Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'trace-rust-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull rust trace event support from Steven Rostedt:
"Allow Rust code to have trace events

Trace events is a popular way to debug what is happening inside the
kernel or just to find out what is happening. Rust code is being added
to the Linux kernel but it currently does not support the tracing
infrastructure. Add support of trace events inside Rust code"

* tag 'trace-rust-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
rust: jump_label: skip formatting generated file
jump_label: rust: pass a mut ptr to `static_key_count`
samples: rust: fix `rust_print` build making it a combined module
rust: add arch_static_branch
jump_label: adjust inline asm to be consistent
rust: samples: add tracepoint to Rust sample
rust: add tracepoint support
rust: add static_branch_unlikely for static_key_false

+375 -64
+1
MAINTAINERS
··· 20348 20348 P: https://rust-for-linux.com/contributing 20349 20349 T: git https://github.com/Rust-for-Linux/linux.git rust-next 20350 20350 F: Documentation/rust/ 20351 + F: include/trace/events/rust_sample.h 20351 20352 F: rust/ 20352 20353 F: samples/rust/ 20353 20354 F: scripts/*rust*
+9 -5
arch/arm/include/asm/jump_label.h
··· 9 9 10 10 #define JUMP_LABEL_NOP_SIZE 4 11 11 12 + /* This macro is also expanded on the Rust side. */ 13 + #define ARCH_STATIC_BRANCH_ASM(key, label) \ 14 + "1:\n\t" \ 15 + WASM(nop) "\n\t" \ 16 + ".pushsection __jump_table, \"aw\"\n\t" \ 17 + ".word 1b, " label ", " key "\n\t" \ 18 + ".popsection\n\t" \ 19 + 12 20 static __always_inline bool arch_static_branch(struct static_key *key, bool branch) 13 21 { 14 - asm goto("1:\n\t" 15 - WASM(nop) "\n\t" 16 - ".pushsection __jump_table, \"aw\"\n\t" 17 - ".word 1b, %l[l_yes], %c0\n\t" 18 - ".popsection\n\t" 22 + asm goto(ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]") 19 23 : : "i" (&((char *)key)[branch]) : : l_yes); 20 24 21 25 return false;
+13 -7
arch/arm64/include/asm/jump_label.h
··· 19 19 #define JUMP_TABLE_ENTRY(key, label) \ 20 20 ".pushsection __jump_table, \"aw\"\n\t" \ 21 21 ".align 3\n\t" \ 22 - ".long 1b - ., %l["#label"] - .\n\t" \ 23 - ".quad %c0 - .\n\t" \ 24 - ".popsection\n\t" \ 25 - : : "i"(key) : : label 22 + ".long 1b - ., " label " - .\n\t" \ 23 + ".quad " key " - .\n\t" \ 24 + ".popsection\n\t" 25 + 26 + /* This macro is also expanded on the Rust side. */ 27 + #define ARCH_STATIC_BRANCH_ASM(key, label) \ 28 + "1: nop\n\t" \ 29 + JUMP_TABLE_ENTRY(key, label) 26 30 27 31 static __always_inline bool arch_static_branch(struct static_key * const key, 28 32 const bool branch) ··· 34 30 char *k = &((char *)key)[branch]; 35 31 36 32 asm goto( 37 - "1: nop \n\t" 38 - JUMP_TABLE_ENTRY(k, l_yes) 33 + ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]") 34 + : : "i"(k) : : l_yes 39 35 ); 40 36 41 37 return false; ··· 47 43 const bool branch) 48 44 { 49 45 char *k = &((char *)key)[branch]; 46 + 50 47 asm goto( 51 48 "1: b %l[l_yes] \n\t" 52 - JUMP_TABLE_ENTRY(k, l_yes) 49 + JUMP_TABLE_ENTRY("%c0", "%l[l_yes]") 50 + : : "i"(k) : : l_yes 53 51 ); 54 52 return false; 55 53 l_yes:
+10 -6
arch/loongarch/include/asm/jump_label.h
··· 13 13 14 14 #define JUMP_LABEL_NOP_SIZE 4 15 15 16 - #define JUMP_TABLE_ENTRY \ 16 + /* This macro is also expanded on the Rust side. */ 17 + #define JUMP_TABLE_ENTRY(key, label) \ 17 18 ".pushsection __jump_table, \"aw\" \n\t" \ 18 19 ".align 3 \n\t" \ 19 - ".long 1b - ., %l[l_yes] - . \n\t" \ 20 - ".quad %0 - . \n\t" \ 20 + ".long 1b - ., " label " - . \n\t" \ 21 + ".quad " key " - . \n\t" \ 21 22 ".popsection \n\t" 23 + 24 + #define ARCH_STATIC_BRANCH_ASM(key, label) \ 25 + "1: nop \n\t" \ 26 + JUMP_TABLE_ENTRY(key, label) 22 27 23 28 static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch) 24 29 { 25 30 asm goto( 26 - "1: nop \n\t" 27 - JUMP_TABLE_ENTRY 31 + ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]") 28 32 : : "i"(&((char *)key)[branch]) : : l_yes); 29 33 30 34 return false; ··· 41 37 { 42 38 asm goto( 43 39 "1: b %l[l_yes] \n\t" 44 - JUMP_TABLE_ENTRY 40 + JUMP_TABLE_ENTRY("%0", "%l[l_yes]") 45 41 : : "i"(&((char *)key)[branch]) : : l_yes); 46 42 47 43 return false;
+28 -22
arch/riscv/include/asm/jump_label.h
··· 16 16 17 17 #define JUMP_LABEL_NOP_SIZE 4 18 18 19 + #define JUMP_TABLE_ENTRY(key, label) \ 20 + ".pushsection __jump_table, \"aw\" \n\t" \ 21 + ".align " RISCV_LGPTR " \n\t" \ 22 + ".long 1b - ., " label " - . \n\t" \ 23 + "" RISCV_PTR " " key " - . \n\t" \ 24 + ".popsection \n\t" 25 + 26 + /* This macro is also expanded on the Rust side. */ 27 + #define ARCH_STATIC_BRANCH_ASM(key, label) \ 28 + " .align 2 \n\t" \ 29 + " .option push \n\t" \ 30 + " .option norelax \n\t" \ 31 + " .option norvc \n\t" \ 32 + "1: nop \n\t" \ 33 + " .option pop \n\t" \ 34 + JUMP_TABLE_ENTRY(key, label) 35 + 19 36 static __always_inline bool arch_static_branch(struct static_key * const key, 20 37 const bool branch) 21 38 { 22 39 asm goto( 23 - " .align 2 \n\t" 24 - " .option push \n\t" 25 - " .option norelax \n\t" 26 - " .option norvc \n\t" 27 - "1: nop \n\t" 28 - " .option pop \n\t" 29 - " .pushsection __jump_table, \"aw\" \n\t" 30 - " .align " RISCV_LGPTR " \n\t" 31 - " .long 1b - ., %l[label] - . \n\t" 32 - " " RISCV_PTR " %0 - . \n\t" 33 - " .popsection \n\t" 40 + ARCH_STATIC_BRANCH_ASM("%0", "%l[label]") 34 41 : : "i"(&((char *)key)[branch]) : : label); 35 42 36 43 return false; ··· 45 38 return true; 46 39 } 47 40 41 + #define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \ 42 + " .align 2 \n\t" \ 43 + " .option push \n\t" \ 44 + " .option norelax \n\t" \ 45 + " .option norvc \n\t" \ 46 + "1: j " label " \n\t" \ 47 + " .option pop \n\t" \ 48 + JUMP_TABLE_ENTRY(key, label) 49 + 48 50 static __always_inline bool arch_static_branch_jump(struct static_key * const key, 49 51 const bool branch) 50 52 { 51 53 asm goto( 52 - " .align 2 \n\t" 53 - " .option push \n\t" 54 - " .option norelax \n\t" 55 - " .option norvc \n\t" 56 - "1: j %l[label] \n\t" 57 - " .option pop \n\t" 58 - " .pushsection __jump_table, \"aw\" \n\t" 59 - " .align " RISCV_LGPTR " \n\t" 60 - " .long 1b - ., %l[label] - . \n\t" 61 - " " RISCV_PTR " %0 - . \n\t" 62 - " .popsection \n\t" 54 + ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[label]") 63 55 : : "i"(&((char *)key)[branch]) : : label); 64 56 65 57 return false;
+13 -22
arch/x86/include/asm/jump_label.h
··· 12 12 #include <linux/stringify.h> 13 13 #include <linux/types.h> 14 14 15 - #define JUMP_TABLE_ENTRY \ 15 + #define JUMP_TABLE_ENTRY(key, label) \ 16 16 ".pushsection __jump_table, \"aw\" \n\t" \ 17 17 _ASM_ALIGN "\n\t" \ 18 18 ".long 1b - . \n\t" \ 19 - ".long %l[l_yes] - . \n\t" \ 20 - _ASM_PTR "%c0 + %c1 - .\n\t" \ 19 + ".long " label " - . \n\t" \ 20 + _ASM_PTR " " key " - . \n\t" \ 21 21 ".popsection \n\t" 22 22 23 + /* This macro is also expanded on the Rust side. */ 23 24 #ifdef CONFIG_HAVE_JUMP_LABEL_HACK 24 - 25 - static __always_inline bool arch_static_branch(struct static_key *key, bool branch) 26 - { 27 - asm goto("1:" 28 - "jmp %l[l_yes] # objtool NOPs this \n\t" 29 - JUMP_TABLE_ENTRY 30 - : : "i" (key), "i" (2 | branch) : : l_yes); 31 - 32 - return false; 33 - l_yes: 34 - return true; 35 - } 36 - 25 + #define ARCH_STATIC_BRANCH_ASM(key, label) \ 26 + "1: jmp " label " # objtool NOPs this \n\t" \ 27 + JUMP_TABLE_ENTRY(key " + 2", label) 37 28 #else /* !CONFIG_HAVE_JUMP_LABEL_HACK */ 29 + #define ARCH_STATIC_BRANCH_ASM(key, label) \ 30 + "1: .byte " __stringify(BYTES_NOP5) "\n\t" \ 31 + JUMP_TABLE_ENTRY(key, label) 32 + #endif /* CONFIG_HAVE_JUMP_LABEL_HACK */ 38 33 39 34 static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch) 40 35 { 41 - asm goto("1:" 42 - ".byte " __stringify(BYTES_NOP5) "\n\t" 43 - JUMP_TABLE_ENTRY 36 + asm goto(ARCH_STATIC_BRANCH_ASM("%c0 + %c1", "%l[l_yes]") 44 37 : : "i" (key), "i" (branch) : : l_yes); 45 38 46 39 return false; ··· 41 48 return true; 42 49 } 43 50 44 - #endif /* CONFIG_HAVE_JUMP_LABEL_HACK */ 45 - 46 51 static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch) 47 52 { 48 53 asm goto("1:" 49 54 "jmp %l[l_yes]\n\t" 50 - JUMP_TABLE_ENTRY 55 + JUMP_TABLE_ENTRY("%c0 + %c1", "%l[l_yes]") 51 56 : : "i" (key), "i" (branch) : : l_yes); 52 57 53 58 return false;
+27 -1
include/linux/tracepoint.h
··· 240 240 } while (0) 241 241 242 242 /* 243 + * Declare an exported function that Rust code can call to trigger this 244 + * tracepoint. This function does not include the static branch; that is done 245 + * in Rust to avoid a function call when the tracepoint is disabled. 246 + */ 247 + #define DEFINE_RUST_DO_TRACE(name, proto, args) 248 + #define __DEFINE_RUST_DO_TRACE(name, proto, args) \ 249 + notrace void rust_do_trace_##name(proto) \ 250 + { \ 251 + __rust_do_trace_##name(args); \ 252 + } 253 + 254 + /* 243 255 * Make sure the alignment of the structure in the __tracepoints section will 244 256 * not add unwanted padding between the beginning of the section and the 245 257 * structure. Force alignment to the same alignment as the section start. ··· 266 254 extern int __traceiter_##name(data_proto); \ 267 255 DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \ 268 256 extern struct tracepoint __tracepoint_##name; \ 257 + extern void rust_do_trace_##name(proto); \ 269 258 static inline int \ 270 259 register_trace_##name(void (*probe)(data_proto), void *data) \ 271 260 { \ ··· 298 285 299 286 #define __DECLARE_TRACE(name, proto, args, cond, data_proto) \ 300 287 __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \ 288 + static inline void __rust_do_trace_##name(proto) \ 289 + { \ 290 + __DO_TRACE(name, \ 291 + TP_ARGS(args), \ 292 + TP_CONDITION(cond), 0); \ 293 + } \ 301 294 static inline void trace_##name(proto) \ 302 295 { \ 303 296 if (static_branch_unlikely(&__tracepoint_##name.key)) \ ··· 318 299 319 300 #define __DECLARE_TRACE_SYSCALL(name, proto, args, cond, data_proto) \ 320 301 __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \ 302 + static inline void __rust_do_trace_##name(proto) \ 303 + { \ 304 + __DO_TRACE(name, \ 305 + TP_ARGS(args), \ 306 + TP_CONDITION(cond), 1); \ 307 + } \ 321 308 static inline void trace_##name(proto) \ 322 309 { \ 323 310 might_fault(); \ ··· 379 354 void __probestub_##_name(void *__data, proto) \ 380 355 { \ 381 356 } \ 382 - DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); 357 + DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); \ 358 + DEFINE_RUST_DO_TRACE(_name, TP_PROTO(proto), TP_ARGS(args)) 383 359 384 360 #define DEFINE_TRACE_FN(_name, _reg, _unreg, _proto, _args) \ 385 361 static struct tracepoint_ext __tracepoint_ext_##_name = { \
+12
include/trace/define_trace.h
··· 76 76 #define DECLARE_TRACE(name, proto, args) \ 77 77 DEFINE_TRACE(name, PARAMS(proto), PARAMS(args)) 78 78 79 + /* If requested, create helpers for calling these tracepoints from Rust. */ 80 + #ifdef CREATE_RUST_TRACE_POINTS 81 + #undef DEFINE_RUST_DO_TRACE 82 + #define DEFINE_RUST_DO_TRACE(name, proto, args) \ 83 + __DEFINE_RUST_DO_TRACE(name, PARAMS(proto), PARAMS(args)) 84 + #endif 85 + 79 86 #undef TRACE_INCLUDE 80 87 #undef __TRACE_INCLUDE 81 88 ··· 139 132 #ifdef UNDEF_TRACE_INCLUDE_PATH 140 133 # undef TRACE_INCLUDE_PATH 141 134 # undef UNDEF_TRACE_INCLUDE_PATH 135 + #endif 136 + 137 + #ifdef CREATE_RUST_TRACE_POINTS 138 + # undef DEFINE_RUST_DO_TRACE 139 + # define DEFINE_RUST_DO_TRACE(name, proto, args) 142 140 #endif 143 141 144 142 /* We may be processing more files */
+31
include/trace/events/rust_sample.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Tracepoints for `samples/rust/rust_print.rs`. 4 + * 5 + * Copyright (C) 2024 Google, Inc. 6 + */ 7 + 8 + #undef TRACE_SYSTEM 9 + #define TRACE_SYSTEM rust_sample 10 + 11 + #if !defined(_RUST_SAMPLE_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) 12 + #define _RUST_SAMPLE_TRACE_H 13 + 14 + #include <linux/tracepoint.h> 15 + 16 + TRACE_EVENT(rust_sample_loaded, 17 + TP_PROTO(int magic_number), 18 + TP_ARGS(magic_number), 19 + TP_STRUCT__entry( 20 + __field(int, magic_number) 21 + ), 22 + TP_fast_assign( 23 + __entry->magic_number = magic_number; 24 + ), 25 + TP_printk("magic=%d", __entry->magic_number) 26 + ); 27 + 28 + #endif /* _RUST_SAMPLE_TRACE_H */ 29 + 30 + /* This part must be outside protection */ 31 + #include <trace/define_trace.h>
+6
rust/Makefile
··· 36 36 obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.o 37 37 obj-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.o 38 38 39 + always-$(subst y,$(CONFIG_RUST),$(CONFIG_JUMP_LABEL)) += kernel/generated_arch_static_branch_asm.rs 40 + 39 41 # Avoids running `$(RUSTC)` for the sysroot when it may not be available. 40 42 ifdef CONFIG_RUST 41 43 ··· 425 423 $(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/alloc.o $(obj)/build_error.o \ 426 424 $(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE 427 425 +$(call if_changed_rule,rustc_library) 426 + 427 + ifdef CONFIG_JUMP_LABEL 428 + $(obj)/kernel.o: $(obj)/kernel/generated_arch_static_branch_asm.rs 429 + endif 428 430 429 431 endif # CONFIG_RUST
+3
rust/bindings/bindings_helper.h
··· 17 17 #include <linux/firmware.h> 18 18 #include <linux/fs.h> 19 19 #include <linux/jiffies.h> 20 + #include <linux/jump_label.h> 20 21 #include <linux/mdio.h> 21 22 #include <linux/phy.h> 22 23 #include <linux/pid_namespace.h> ··· 26 25 #include <linux/sched.h> 27 26 #include <linux/security.h> 28 27 #include <linux/slab.h> 28 + #include <linux/tracepoint.h> 29 29 #include <linux/wait.h> 30 30 #include <linux/workqueue.h> 31 + #include <trace/events/rust_sample.h> 31 32 32 33 /* `bindgen` gets confused at certain things. */ 33 34 const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
+1
rust/helpers/helpers.c
··· 14 14 #include "cred.c" 15 15 #include "err.c" 16 16 #include "fs.c" 17 + #include "jump_label.c" 17 18 #include "kunit.c" 18 19 #include "mutex.c" 19 20 #include "page.c"
+14
rust/helpers/jump_label.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + /* 4 + * Copyright (C) 2024 Google LLC. 5 + */ 6 + 7 + #include <linux/jump_label.h> 8 + 9 + #ifndef CONFIG_JUMP_LABEL 10 + int rust_helper_static_key_count(struct static_key *key) 11 + { 12 + return static_key_count(key); 13 + } 14 + #endif
+3
rust/kernel/.gitignore
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + /generated_arch_static_branch_asm.rs
+7
rust/kernel/generated_arch_static_branch_asm.rs.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #include <linux/jump_label.h> 4 + 5 + // Cut here. 6 + 7 + ::kernel::concat_literals!(ARCH_STATIC_BRANCH_ASM("{symb} + {off} + {branch}", "{l_yes}"))
+74
rust/kernel/jump_label.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + // Copyright (C) 2024 Google LLC. 4 + 5 + //! Logic for static keys. 6 + //! 7 + //! C header: [`include/linux/jump_label.h`](srctree/include/linux/jump_label.h). 8 + 9 + /// Branch based on a static key. 10 + /// 11 + /// Takes three arguments: 12 + /// 13 + /// * `key` - the path to the static variable containing the `static_key`. 14 + /// * `keytyp` - the type of `key`. 15 + /// * `field` - the name of the field of `key` that contains the `static_key`. 16 + /// 17 + /// # Safety 18 + /// 19 + /// The macro must be used with a real static key defined by C. 20 + #[macro_export] 21 + macro_rules! static_branch_unlikely { 22 + ($key:path, $keytyp:ty, $field:ident) => {{ 23 + let _key: *const $keytyp = ::core::ptr::addr_of!($key); 24 + let _key: *const $crate::bindings::static_key_false = ::core::ptr::addr_of!((*_key).$field); 25 + let _key: *const $crate::bindings::static_key = _key.cast(); 26 + 27 + #[cfg(not(CONFIG_JUMP_LABEL))] 28 + { 29 + $crate::bindings::static_key_count(_key.cast_mut()) > 0 30 + } 31 + 32 + #[cfg(CONFIG_JUMP_LABEL)] 33 + $crate::jump_label::arch_static_branch! { $key, $keytyp, $field, false } 34 + }}; 35 + } 36 + pub use static_branch_unlikely; 37 + 38 + /// Assert that the assembly block evaluates to a string literal. 39 + #[cfg(CONFIG_JUMP_LABEL)] 40 + const _: &str = include!(concat!( 41 + env!("OBJTREE"), 42 + "/rust/kernel/generated_arch_static_branch_asm.rs" 43 + )); 44 + 45 + #[macro_export] 46 + #[doc(hidden)] 47 + #[cfg(CONFIG_JUMP_LABEL)] 48 + macro_rules! arch_static_branch { 49 + ($key:path, $keytyp:ty, $field:ident, $branch:expr) => {'my_label: { 50 + $crate::asm!( 51 + include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_static_branch_asm.rs")); 52 + l_yes = label { 53 + break 'my_label true; 54 + }, 55 + symb = sym $key, 56 + off = const ::core::mem::offset_of!($keytyp, $field), 57 + branch = const $crate::jump_label::bool_to_int($branch), 58 + ); 59 + 60 + break 'my_label false; 61 + }}; 62 + } 63 + 64 + #[cfg(CONFIG_JUMP_LABEL)] 65 + pub use arch_static_branch; 66 + 67 + /// A helper used by inline assembly to pass a boolean to as a `const` parameter. 68 + /// 69 + /// Using this function instead of a cast lets you assert that the input is a boolean, and not some 70 + /// other type that can also be cast to an integer. 71 + #[doc(hidden)] 72 + pub const fn bool_to_int(b: bool) -> i32 { 73 + b as i32 74 + }
+37
rust/kernel/lib.rs
··· 38 38 pub mod fs; 39 39 pub mod init; 40 40 pub mod ioctl; 41 + pub mod jump_label; 41 42 #[cfg(CONFIG_KUNIT)] 42 43 pub mod kunit; 43 44 pub mod list; ··· 58 57 pub mod sync; 59 58 pub mod task; 60 59 pub mod time; 60 + pub mod tracepoint; 61 61 pub mod types; 62 62 pub mod uaccess; 63 63 pub mod workqueue; ··· 151 149 let offset: usize = ::core::mem::offset_of!($type, $($f)*); 152 150 ptr.sub(offset) as *const $type 153 151 }} 152 + } 153 + 154 + /// Helper for `.rs.S` files. 155 + #[doc(hidden)] 156 + #[macro_export] 157 + macro_rules! concat_literals { 158 + ($( $asm:literal )* ) => { 159 + ::core::concat!($($asm),*) 160 + }; 161 + } 162 + 163 + /// Wrapper around `asm!` configured for use in the kernel. 164 + /// 165 + /// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!` 166 + /// syntax. 167 + // For x86, `asm!` uses intel syntax by default, but we want to use at&t syntax in the kernel. 168 + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 169 + #[macro_export] 170 + macro_rules! asm { 171 + ($($asm:expr),* ; $($rest:tt)*) => { 172 + ::core::arch::asm!( $($asm)*, options(att_syntax), $($rest)* ) 173 + }; 174 + } 175 + 176 + /// Wrapper around `asm!` configured for use in the kernel. 177 + /// 178 + /// Uses a semicolon to avoid parsing ambiguities, even though this does not match native `asm!` 179 + /// syntax. 180 + // For non-x86 arches we just pass through to `asm!`. 181 + #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] 182 + #[macro_export] 183 + macro_rules! asm { 184 + ($($asm:expr),* ; $($rest:tt)*) => { 185 + ::core::arch::asm!( $($asm)*, $($rest)* ) 186 + }; 154 187 }
+49
rust/kernel/tracepoint.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + // Copyright (C) 2024 Google LLC. 4 + 5 + //! Logic for tracepoints. 6 + 7 + /// Declare the Rust entry point for a tracepoint. 8 + /// 9 + /// This macro generates an unsafe function that calls into C, and its safety requirements will be 10 + /// whatever the relevant C code requires. To document these safety requirements, you may add 11 + /// doc-comments when invoking the macro. 12 + #[macro_export] 13 + macro_rules! declare_trace { 14 + ($($(#[$attr:meta])* $pub:vis unsafe fn $name:ident($($argname:ident : $argtyp:ty),* $(,)?);)*) => {$( 15 + $( #[$attr] )* 16 + #[inline(always)] 17 + $pub unsafe fn $name($($argname : $argtyp),*) { 18 + #[cfg(CONFIG_TRACEPOINTS)] 19 + { 20 + // SAFETY: It's always okay to query the static key for a tracepoint. 21 + let should_trace = unsafe { 22 + $crate::macros::paste! { 23 + $crate::jump_label::static_branch_unlikely!( 24 + $crate::bindings::[< __tracepoint_ $name >], 25 + $crate::bindings::tracepoint, 26 + key 27 + ) 28 + } 29 + }; 30 + 31 + if should_trace { 32 + $crate::macros::paste! { 33 + // SAFETY: The caller guarantees that it is okay to call this tracepoint. 34 + unsafe { $crate::bindings::[< rust_do_trace_ $name >]($($argname),*) }; 35 + } 36 + } 37 + } 38 + 39 + #[cfg(not(CONFIG_TRACEPOINTS))] 40 + { 41 + // If tracepoints are disabled, insert a trivial use of each argument 42 + // to avoid unused argument warnings. 43 + $( let _unused = $argname; )* 44 + } 45 + } 46 + )*} 47 + } 48 + 49 + pub use declare_trace;
+3
samples/rust/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 + ccflags-y += -I$(src) # needed for trace events 2 3 3 4 obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o 4 5 obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o 6 + 7 + rust_print-y := rust_print_main.o rust_print_events.o 5 8 6 9 subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs
+18
samples/rust/rust_print.rs samples/rust/rust_print_main.rs
··· 69 69 70 70 arc_print()?; 71 71 72 + trace::trace_rust_sample_loaded(42); 73 + 72 74 Ok(RustPrint) 73 75 } 74 76 } ··· 78 76 impl Drop for RustPrint { 79 77 fn drop(&mut self) { 80 78 pr_info!("Rust printing macros sample (exit)\n"); 79 + } 80 + } 81 + 82 + mod trace { 83 + use core::ffi::c_int; 84 + 85 + kernel::declare_trace! { 86 + /// # Safety 87 + /// 88 + /// Always safe to call. 89 + unsafe fn rust_sample_loaded(magic: c_int); 90 + } 91 + 92 + pub(crate) fn trace_rust_sample_loaded(magic: i32) { 93 + // SAFETY: Always safe to call. 94 + unsafe { rust_sample_loaded(magic as c_int) } 81 95 } 82 96 }
+8
samples/rust/rust_print_events.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2024 Google LLC 4 + */ 5 + 6 + #define CREATE_TRACE_POINTS 7 + #define CREATE_RUST_TRACE_POINTS 8 + #include <trace/events/rust_sample.h>
+8 -1
scripts/Makefile.build
··· 248 248 # Compile Rust sources (.rs) 249 249 # --------------------------------------------------------------------------- 250 250 251 - rust_allowed_features := new_uninit 251 + rust_allowed_features := asm_const,asm_goto,new_uninit 252 252 253 253 # `--out-dir` is required to avoid temporaries being created by `rustc` in the 254 254 # current working directory, which may be not accessible in the out-of-tree 255 255 # modules case. 256 256 rust_common_cmd = \ 257 + OBJTREE=$(abspath $(objtree)) \ 257 258 RUST_MODFILE=$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \ 258 259 -Zallow-features=$(rust_allowed_features) \ 259 260 -Zcrate-attr=no_std \ ··· 303 302 304 303 $(obj)/%.ll: $(obj)/%.rs FORCE 305 304 +$(call if_changed_dep,rustc_ll_rs) 305 + 306 + quiet_cmd_rustc_rs_rs_S = RSCPP $(quiet_modtag) $@ 307 + cmd_rustc_rs_rs_S = $(CPP) $(c_flags) -xc -C -P $< | sed '1,/^\/\/ Cut here.$$/d' >$@ 308 + 309 + $(obj)/%.rs: $(obj)/%.rs.S FORCE 310 + +$(call if_changed_dep,rustc_rs_rs_S) 306 311 307 312 # Compile assembler sources (.S) 308 313 # ---------------------------------------------------------------------------