Skip to content

Commit f244881

Browse files
committed
ANDROID: rust: add static_key_false
This method is deprecated in C, but we are still adding it here because we are mirroring how C implements tracepoints, and tracepoints use static_key_false. Signed-off-by: Alice Ryhl <aliceryhl@google.com>
1 parent 0b5336e commit f244881

File tree

3 files changed

+152
-1
lines changed

3 files changed

+152
-1
lines changed

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub mod prelude;
3939
pub mod print;
4040
mod static_assert;
4141
pub mod static_call;
42+
pub mod static_key;
4243
#[doc(hidden)]
4344
pub mod std_vendor;
4445
pub mod str;

rust/kernel/static_key.rs

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
// Copyright (C) 2024 Google LLC.
4+
5+
//! Logic for static keys.
6+
7+
use crate::bindings::*;
8+
9+
#[doc(hidden)]
10+
#[macro_export]
11+
#[cfg(target_arch = "x86_64")]
12+
#[cfg(not(CONFIG_HAVE_RUST_ASM_GOTO))]
13+
macro_rules! _static_key_false {
14+
($key:path, $keytyp:ty, $field:ident) => {{
15+
let mut output = 1u32;
16+
17+
core::arch::asm!(
18+
r#"
19+
1: .byte 0x0f,0x1f,0x44,0x00,0x00
20+
21+
.pushsection __jump_table, "aw"
22+
.balign 8
23+
.long 1b - .
24+
.long 3f - .
25+
.quad {0} + {1} - .
26+
.popsection
27+
28+
2: mov {2:e}, 0
29+
3:
30+
"#,
31+
sym $key,
32+
const ::core::mem::offset_of!($keytyp, $field),
33+
inout(reg) output,
34+
);
35+
36+
output != 0
37+
}};
38+
}
39+
40+
#[doc(hidden)]
41+
#[macro_export]
42+
#[cfg(target_arch = "x86_64")]
43+
#[cfg(CONFIG_HAVE_RUST_ASM_GOTO)]
44+
macro_rules! _static_key_false {
45+
($key:path, $keytyp:ty, $field:ident) => {'my_label: {
46+
core::arch::asm!(
47+
r#"
48+
1: .byte 0x0f,0x1f,0x44,0x00,0x00
49+
50+
.pushsection __jump_table, "aw"
51+
.balign 8
52+
.long 1b - .
53+
.long {0} - .
54+
.quad {1} + {2} - .
55+
.popsection
56+
"#,
57+
label {
58+
break 'my_label true;
59+
},
60+
sym $key,
61+
const ::core::mem::offset_of!($keytyp, $field),
62+
);
63+
64+
break 'my_label false;
65+
}};
66+
}
67+
68+
#[doc(hidden)]
69+
#[macro_export]
70+
#[cfg(target_arch = "aarch64")]
71+
#[cfg(not(CONFIG_HAVE_RUST_ASM_GOTO))]
72+
macro_rules! _static_key_false {
73+
($key:path, $keytyp:ty, $field:ident) => {{
74+
let mut output = 1u32;
75+
76+
core::arch::asm!(
77+
r#"
78+
1: nop
79+
80+
.pushsection __jump_table, "aw"
81+
.align 3
82+
.long 1b - ., 3f - .
83+
.quad {0} + {1} - .
84+
.popsection
85+
86+
2: mov {2:w}, 0
87+
3:
88+
"#,
89+
sym $key,
90+
const ::core::mem::offset_of!($keytyp, $field),
91+
inout(reg) output
92+
);
93+
94+
output != 0
95+
}};
96+
}
97+
98+
#[doc(hidden)]
99+
#[macro_export]
100+
#[cfg(target_arch = "aarch64")]
101+
#[cfg(CONFIG_HAVE_RUST_ASM_GOTO)]
102+
macro_rules! _static_key_false {
103+
($key:path, $keytyp:ty, $field:ident) => {'my_label: {
104+
core::arch::asm!(
105+
r#"
106+
1: nop
107+
108+
.pushsection __jump_table, "aw"
109+
.align 3
110+
.long 1b - ., {0} - .
111+
.quad {1} + {2} - .
112+
.popsection
113+
"#,
114+
label {
115+
break 'my_label true;
116+
},
117+
sym $key,
118+
const ::core::mem::offset_of!($keytyp, $field),
119+
);
120+
121+
break 'my_label false;
122+
}};
123+
}
124+
125+
/// Branch based on a static key.
126+
///
127+
/// Takes three arguments:
128+
///
129+
/// * `key` - the path to the static variable containing the `static_key`.
130+
/// * `keytyp` - the type of `key`.
131+
/// * `field` - the name of the field of `key` that contains the `static_key`.
132+
#[macro_export]
133+
macro_rules! static_key_false {
134+
// Forward to the real implementation. Separated like this so that we don't have to duplicate
135+
// the documentation.
136+
($key:path, $keytyp:ty, $field:ident) => {{
137+
// Assert that `$key` has type `$keytyp` and that `$key.$field` has type `static_key`.
138+
//
139+
// SAFETY: We know that `$key` is a static because otherwise the inline assembly will not
140+
// compile. The raw pointers created in this block are in-bounds of `$key`.
141+
static _TY_ASSERT: () = unsafe {
142+
let key: *const $keytyp = ::core::ptr::addr_of!($key);
143+
let _: *const $crate::bindings::static_key = ::core::ptr::addr_of!((*key).$field);
144+
};
145+
146+
$crate::static_key::_static_key_false! { $key, $keytyp, $field }
147+
}};
148+
}
149+
150+
pub use {_static_key_false, static_key_false};

scripts/Makefile.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ $(obj)/%.lst: $(obj)/%.c FORCE
263263
# Compile Rust sources (.rs)
264264
# ---------------------------------------------------------------------------
265265

266-
rust_allowed_features := new_uninit
266+
rust_allowed_features := asm_const,asm_goto,new_uninit
267267

268268
# `--out-dir` is required to avoid temporaries being created by `rustc` in the
269269
# current working directory, which may be not accessible in the out-of-tree

0 commit comments

Comments
 (0)