lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <df3a68334760b2b254219a69426982bf858dee39.1762221537.git.chenmiao@openatom.club>
Date: Tue,  4 Nov 2025 02:04:17 +0000
From: "chenmiao" <chenmiao@...natom.club>
To: <ojeda@...nel.org>
Cc: "Alex Gaynor" <alex.gaynor@...il.com>, 
	"Boqun Feng" <boqun.feng@...il.com>, "Gary Guo" <gary@...yguo.net>, 
	Björn Roy Baron <bjorn3_gh@...tonmail.com>, 
	"Benno Lossin" <lossin@...nel.org>, 
	"Andreas Hindborg" <a.hindborg@...nel.org>, 
	"Alice Ryhl" <aliceryhl@...gle.com>, "Trevor Gross" <tmgross@...ch.edu>, 
	"Danilo Krummrich" <dakr@...nel.org>, 
	"Steven Rostedt (Google)" <rostedt@...dmis.org>, 
	"open list:RUST" <rust-for-linux@...r.kernel.org>, 
	"open list" <linux-kernel@...r.kernel.org>
Subject: [PATCH] rust: kernel: Support more jump_label api

The initial implementation of arch_static_branch was achieved by accessing
the offset from the original type. However, this approach extended the
path and introduced redundant calculations when dealing with types like
`static_key_true/false`, as shown below:

```
static_brach_unlikely(tp, tracepoint, key)
  => tracepoint->key->key
  => &tracepoint->key(static_key_false) == &tracepoint->key.key(static_key)
  => off: tracepoint->key - tracepoint
```

In practice, the implementation of `arch_static_branch` overlooked many
detailed descriptions. To improve clarity, additional comments have been
added to the original logic. The approach has been modified to directly
locate the corresponding `static_key` instead of using offsets, thereby
reducing  computational overhead.

If finding the offset from the primitive type is necessary for this
implementation, I will abandon this change.

Additionally, support for the `static_branch_enable/disable` APIs has been
introduced.

Signed-off-by: chenmiao <chenmiao@...natom.club>
---
 .../generated_arch_static_branch_asm.rs.S     |   2 +-
 rust/kernel/jump_label.rs                     | 169 ++++++++++++++++--
 2 files changed, 155 insertions(+), 16 deletions(-)

diff --git a/rust/kernel/generated_arch_static_branch_asm.rs.S b/rust/kernel/generated_arch_static_branch_asm.rs.S
index 2afb638708db3..08603dc2d61e7 100644
--- a/rust/kernel/generated_arch_static_branch_asm.rs.S
+++ b/rust/kernel/generated_arch_static_branch_asm.rs.S
@@ -4,4 +4,4 @@
 
 // Cut here.
 
-::kernel::concat_literals!(ARCH_STATIC_BRANCH_ASM("{symb} + {off} + {branch}", "{l_yes}"))
+::kernel::concat_literals!(ARCH_STATIC_BRANCH_ASM("{real_key} + {branch}", "{l_yes}"))
diff --git a/rust/kernel/jump_label.rs b/rust/kernel/jump_label.rs
index 4e974c768dbd5..12ae78f95c761 100644
--- a/rust/kernel/jump_label.rs
+++ b/rust/kernel/jump_label.rs
@@ -6,22 +6,63 @@
 //!
 //! C header: [`include/linux/jump_label.h`](srctree/include/linux/jump_label.h).
 
-/// Branch based on a static key.
+/// The key used for the static_key_false/true.
 ///
-/// Takes three arguments:
+/// If the key just contains a static_key, like: `struct tracepoint`;
 ///
-/// * `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`.
+/// ```
+/// pub struct tracepoint {
+///     ...,
+///     key: static_key,
+///     ...,
+/// }
 ///
-/// # Safety
+/// // When you use the tracepoint as the parameter.
+/// if static_branch_unlikely!(tp, tracepoint, key) {
+///     // Do something
+/// }
 ///
-/// The macro must be used with a real static key defined by C.
-#[macro_export]
-macro_rules! static_branch_unlikely {
-    ($key:path, $keytyp:ty, $field:ident) => {{
+/// // It just like:
+/// let _key: *const crate::bindings::tracepoint = ::core::ptr::addr_of!($key);
+/// let _key: *const crate::bindings::static_key_false = ::core::ptr::addr_of!((*_key).key);
+/// let _key: *const crate::bindings::static_key = _key.cast();
+/// ```
+///
+/// If the key just contains a single static_key, like: `struct static_key_false`;
+///
+/// ```
+/// pub struct static_key_false {
+///     key: static_key,
+/// }
+///
+/// // When you use the static_key_false as the parameter.
+/// if static_branch_unlikely!(key) {
+///     // Do something
+/// }
+///
+/// // It just like:
+/// let _key: *const crate::bindings::static_key_false = ::core::ptr::addr_of!($key);
+/// let _key: *const crate::bindings::static_key = _key.cast();
+/// ```
+///
+macro_rules! __static_branch_base {
+    ($basety:ty, $branch:expr, $key:path) => {{
+        let _key: *const $basety = ::core::ptr::addr_of!($key);
+        let _key: *const $crate::bindings::static_key = _key.cast();
+
+        #[cfg(not(CONFIG_JUMP_LABEL))]
+        {
+            $crate::bindings::static_key_count(_key.cast_mut()) > 0
+        }
+
+        #[cfg(CONFIG_JUMP_LABEL)]
+        {
+            $crate::jump_label::arch_static_branch! { _key, $branch }
+        }
+    }};
+    ($basety:ty, $branch:expr, $key:path, $keytyp:ty, $field:ident) => {{
         let _key: *const $keytyp = ::core::ptr::addr_of!($key);
-        let _key: *const $crate::bindings::static_key_false = ::core::ptr::addr_of!((*_key).$field);
+        let _key: *const $basety = ::core::ptr::addr_of!((*_key).$field);
         let _key: *const $crate::bindings::static_key = _key.cast();
 
         #[cfg(not(CONFIG_JUMP_LABEL))]
@@ -30,7 +71,88 @@ macro_rules! static_branch_unlikely {
         }
 
         #[cfg(CONFIG_JUMP_LABEL)]
-        $crate::jump_label::arch_static_branch! { $key, $keytyp, $field, false }
+        {
+            $crate::jump_label::arch_static_branch! { _key, $branch }
+        }
+    }};
+}
+
+/// Branch based on a static key.
+///
+/// Takes two type arguments:
+///
+/// First Type takes one argument:
+///
+/// * `key` - the static variable containing the `static_key`.
+///
+/// Second Type 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`.
+///
+/// # Safety
+///
+/// ```
+/// let tp: tracepoint = tracepoint::new();
+/// if static_key_likely!(tp, tracepoint, key) {
+///     // Do something
+/// }
+///
+/// let key: static_key_false = static_key_true::new();
+/// if static_key_likely!(key) {
+///     // Do something
+/// }
+/// ```
+///
+/// The macro must be used with a real static key defined by C.
+#[macro_export]
+macro_rules! static_branch_likely {
+    ($key:path) => {{
+        __static_branch_base! { $crate::bindings::static_key_true, true, $key }
+    }};
+    ($key:path, $keytyp:ty, $field:ident) => {{
+        __static_branch_base! { $crate::bindings::static_key_true, true, $key, $keytyp, $field }
+    }};
+}
+pub use static_branch_likely;
+
+/// Branch based on a static key.
+///
+/// Takes two type arguments:
+///
+/// First Type takes one argument:
+///
+/// * `key` - the static variable containing the `static_key`.
+///
+/// Second Type 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`.
+///
+/// # Safety
+///
+/// ```
+/// let tp: tracepoint = tracepoint::new();
+/// if static_key_unlikely!(tp, tracepoint, key) {
+///     // Do something
+/// }
+///
+/// let key: static_key_false = static_key_false::new();
+/// if static_key_unlikely!(key) {
+///     // Do something
+/// }
+/// ```
+///
+/// The macro must be used with a real static key defined by C.
+#[macro_export]
+macro_rules! static_branch_unlikely {
+    ($key:path) => {{
+        static_branch_base! { $crate::bindings::static_key_false, false, $key }
+    }};
+    ($key:path, $keytyp:ty, $field:ident) => {{
+        static_branch_base! { $crate::bindings::static_key_false, false, $key, $keytyp, $field }
     }};
 }
 pub use static_branch_unlikely;
@@ -46,14 +168,13 @@ macro_rules! static_branch_unlikely {
 #[doc(hidden)]
 #[cfg(CONFIG_JUMP_LABEL)]
 macro_rules! arch_static_branch {
-    ($key:path, $keytyp:ty, $field:ident, $branch:expr) => {'my_label: {
+    ($key:path, $branch:expr) => {'my_label: {
         $crate::asm!(
             include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_static_branch_asm.rs"));
             l_yes = label {
                 break 'my_label true;
             },
-            symb = sym $key,
-            off = const ::core::mem::offset_of!($keytyp, $field),
+            real_key = sym $key,
             branch = const $crate::jump_label::bool_to_int($branch),
         );
 
@@ -72,3 +193,21 @@ macro_rules! arch_static_branch {
 pub const fn bool_to_int(b: bool) -> i32 {
     b as i32
 }
+
+/// Enable a static branch.
+#[macro_export]
+macro_rules! static_branch_enable {
+    ($key:path) => {{
+        let _key: *const $crate::bindings::static_key = ::core::ptr::addr_of!($key);
+        $crate::bindings::static_key_enable(_key.cast_mut());
+    }};
+}
+
+/// Disable a static branch.
+#[macro_export]
+macro_rules! static_branch_disable {
+    ($key:path) => {{
+        let _key: *const $crate::bindings::static_key = ::core::ptr::addr_of!($key);
+        $crate::bindings::static_key_disable(_key.cast_mut());
+    }};
+}
-- 
2.43.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ