Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental tracepoint support #1084

Open
wants to merge 3 commits into
base: rust-next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
rust: add static_call support
Add static_call support by mirroring how C does. When the platform does
not support static calls (right now, that means that it is not x86),
then the function pointer is loaded from a global and called. Otherwise,
we generate a call to a trampoline function, and objtool is used to make
these calls patchable at runtime.

Signed-off-by: Alice Ryhl <[email protected]>
  • Loading branch information
Darksonn committed Jun 6, 2024
commit f791f34fc4837a0974048e92f5f08da4a053aa81
1 change: 1 addition & 0 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub mod net;
pub mod prelude;
pub mod print;
mod static_assert;
pub mod static_call;
#[doc(hidden)]
pub mod std_vendor;
pub mod str;
Expand Down
90 changes: 90 additions & 0 deletions rust/kernel/static_call.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: GPL-2.0

// Copyright (C) 2024 Google LLC.

//! Logic for static calls.

#[macro_export]
#[doc(hidden)]
macro_rules! ty_underscore_for {
($arg:expr) => {
_
};
}

#[doc(hidden)]
#[repr(transparent)]
pub struct AddressableStaticCallKey {
Darksonn marked this conversation as resolved.
Show resolved Hide resolved
_ptr: *const bindings::static_call_key,
}
unsafe impl Sync for AddressableStaticCallKey {}
impl AddressableStaticCallKey {
pub const fn new(ptr: *const bindings::static_call_key) -> Self {
Self { _ptr: ptr }
}
}

#[cfg(CONFIG_HAVE_STATIC_CALL)]
#[doc(hidden)]
#[macro_export]
macro_rules! _static_call {
($name:ident($($args:expr),* $(,)?)) => {{
// Symbol mangling will give this symbol a unique name.
#[cfg(CONFIG_HAVE_STATIC_CALL_INLINE)]
#[link_section = ".discard.addressable"]
#[used]
static __ADDRESSABLE: $crate::static_call::AddressableStaticCallKey = unsafe {
$crate::static_call::AddressableStaticCallKey::new(::core::ptr::addr_of!(
$crate::macros::paste! { $crate::bindings:: [<__SCK__ $name >]; }
))
};

let fn_ptr: unsafe extern "C" fn($($crate::static_call::ty_underscore_for!($args)),*) -> _ =
$crate::macros::paste! { $crate::bindings:: [<__SCT__ $name >]; };
(fn_ptr)($($args),*)
}};
}

#[cfg(not(CONFIG_HAVE_STATIC_CALL))]
#[doc(hidden)]
#[macro_export]
macro_rules! _static_call {
($name:ident($($args:expr),* $(,)?)) => {{
let void_ptr_fn: *mut ::core::ffi::c_void = $crate::macros::paste! { $crate::bindings:: [<__SCK__ $name >]; }.func;

let fn_ptr: unsafe extern "C" fn($($crate::static_call::ty_underscore_for!($args)),*) -> _ = if true {
::core::mem::transmute(void_ptr_fn)
} else {
// This is dead code, but it influences type inference on `fn_ptr` so that we transmute
// the function pointer to the right type.
$crate::macros::paste! { $crate::bindings:: [<__SCT__ $name >]; }
};

(fn_ptr)($($args),*)
}};
}

/// Statically call a global function.
///
/// # Safety
///
/// This macro will call the provided function. It is up to the caller to uphold the safety
/// guarantees of the function.
///
/// # Examples
///
/// ```ignore
/// fn call_static() {
/// unsafe {
/// static_call! { your_static_call() };
/// }
/// }
/// ```
#[macro_export]
macro_rules! static_call {
// Forward to the real implementation. Separated like this so that we don't have to duplicate
// the documentation.
($($args:tt)*) => { $crate::static_call::_static_call! { $($args)* } };
}

pub use {_static_call, static_call, ty_underscore_for};