-
Notifications
You must be signed in to change notification settings - Fork 456
Experimental tracepoint support #1084
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
base: rust-next
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 { | ||
_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}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
Darksonn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Copyright (C) 2024 Google LLC. | ||
|
||
//! Logic for static keys. | ||
|
||
use crate::bindings::*; | ||
|
||
#[doc(hidden)] | ||
#[macro_export] | ||
#[cfg(target_arch = "x86_64")] | ||
#[cfg(not(CONFIG_HAVE_RUST_ASM_GOTO))] | ||
macro_rules! _static_key_false { | ||
($key:path, $keytyp:ty, $field:ident) => {{ | ||
let mut output = 1u32; | ||
|
||
core::arch::asm!( | ||
r#" | ||
1: .byte 0x0f,0x1f,0x44,0x00,0x00 | ||
|
||
.pushsection __jump_table, "aw" | ||
.balign 8 | ||
.long 1b - . | ||
.long 3f - . | ||
.quad {0} + {1} - . | ||
.popsection | ||
|
||
2: mov {2:e}, 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you may want to use att_syntax ;-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you show me how to do that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
unsafe fn i32_xadd(v: *mut i32, mut i: i32) -> i32 {
// SAFETY: Per function safety requirement, the address of `v` is valid for "xadd".
unsafe {
asm!(
lock_instr!("xaddl {i:e}, ({v})"),
i = inout(reg) i,
v = in(reg) v,
options(att_syntax, preserves_flags),
);
}
i
} in https://lore.kernel.org/rust-for-linux/[email protected]/ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Kernel developers will prefer that, yeah... :) Sadly, specifying every single time that may be painful. Perhaps we could have our own There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added to our wishlist. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks Gary, then we should probably do it soon if we are going to start adding more |
||
3: | ||
"#, | ||
sym $key, | ||
const ::core::mem::offset_of!($keytyp, $field), | ||
Darksonn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
inout(reg) output, | ||
); | ||
|
||
output != 0 | ||
}}; | ||
} | ||
|
||
#[doc(hidden)] | ||
#[macro_export] | ||
#[cfg(target_arch = "x86_64")] | ||
#[cfg(CONFIG_HAVE_RUST_ASM_GOTO)] | ||
macro_rules! _static_key_false { | ||
($key:path, $keytyp:ty, $field:ident) => {'my_label: { | ||
core::arch::asm!( | ||
r#" | ||
1: .byte 0x0f,0x1f,0x44,0x00,0x00 | ||
|
||
.pushsection __jump_table, "aw" | ||
.balign 8 | ||
.long 1b - . | ||
.long {0} - . | ||
.quad {1} + {2} - . | ||
.popsection | ||
"#, | ||
label { | ||
break 'my_label true; | ||
}, | ||
sym $key, | ||
const ::core::mem::offset_of!($keytyp, $field), | ||
); | ||
|
||
break 'my_label false; | ||
}}; | ||
} | ||
|
||
#[doc(hidden)] | ||
#[macro_export] | ||
#[cfg(target_arch = "aarch64")] | ||
#[cfg(not(CONFIG_HAVE_RUST_ASM_GOTO))] | ||
macro_rules! _static_key_false { | ||
($key:path, $keytyp:ty, $field:ident) => {{ | ||
let mut output = 1u32; | ||
|
||
core::arch::asm!( | ||
r#" | ||
1: nop | ||
|
||
.pushsection __jump_table, "aw" | ||
.align 3 | ||
.long 1b - ., 3f - . | ||
.quad {0} + {1} - . | ||
.popsection | ||
|
||
2: mov {2:w}, 0 | ||
3: | ||
"#, | ||
sym $key, | ||
const ::core::mem::offset_of!($keytyp, $field), | ||
inout(reg) output | ||
); | ||
|
||
output != 0 | ||
}}; | ||
} | ||
|
||
#[doc(hidden)] | ||
#[macro_export] | ||
#[cfg(target_arch = "aarch64")] | ||
#[cfg(CONFIG_HAVE_RUST_ASM_GOTO)] | ||
macro_rules! _static_key_false { | ||
($key:path, $keytyp:ty, $field:ident) => {'my_label: { | ||
core::arch::asm!( | ||
r#" | ||
1: nop | ||
|
||
.pushsection __jump_table, "aw" | ||
.align 3 | ||
.long 1b - ., {0} - . | ||
.quad {1} + {2} - . | ||
.popsection | ||
"#, | ||
label { | ||
break 'my_label true; | ||
}, | ||
sym $key, | ||
const ::core::mem::offset_of!($keytyp, $field), | ||
); | ||
|
||
break 'my_label false; | ||
}}; | ||
} | ||
|
||
/// Branch based on a static key. | ||
/// | ||
/// Takes three arguments: | ||
/// | ||
/// * `key` - the path to the static variable containing the `static_key`. | ||
/// * `keytyp` - the type of `key`. | ||
/// * `field` - the name of the field of `key` that contains the `static_key`. | ||
#[macro_export] | ||
macro_rules! static_key_false { | ||
// Forward to the real implementation. Separated like this so that we don't have to duplicate | ||
// the documentation. | ||
($key:path, $keytyp:ty, $field:ident) => {{ | ||
// Assert that `$key` has type `$keytyp` and that `$key.$field` has type `static_key`. | ||
// | ||
// SAFETY: We know that `$key` is a static because otherwise the inline assembly will not | ||
// compile. The raw pointers created in this block are in-bounds of `$key`. | ||
static _TY_ASSERT: () = unsafe { | ||
let key: *const $keytyp = ::core::ptr::addr_of!($key); | ||
let _: *const $crate::bindings::static_key = ::core::ptr::addr_of!((*key).$field); | ||
}; | ||
|
||
$crate::static_key::_static_key_false! { $key, $keytyp, $field } | ||
}}; | ||
} | ||
|
||
pub use {_static_key_false, static_key_false}; |
Uh oh!
There was an error while loading. Please reload this page.