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.

rust: add tracepoint support

Make it possible to have Rust code call into tracepoints defined by C
code. It is still required that the tracepoint is declared in a C
header, and that this header is included in the input to bindgen.

Instead of calling __DO_TRACE directly, the exported rust_do_trace_
function calls an inline helper function. This is because the `cond`
argument does not exist at the callsite of DEFINE_RUST_DO_TRACE.

__DECLARE_TRACE always emits an inline static and an extern declaration
that is only used when CREATE_RUST_TRACE_POINTS is set. These should not
end up in the final binary so it is not a problem that they sometimes
are emitted without a user.

Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: Alex Gaynor <alex.gaynor@gmail.com>
Cc: Wedson Almeida Filho <wedsonaf@gmail.com>
Cc: " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " <bjorn3_gh@protonmail.com>
Cc: Benno Lossin <benno.lossin@proton.me>
Cc: Andreas Hindborg <a.hindborg@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Uros Bizjak <ubizjak@gmail.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oliver.upton@linux.dev>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Fuad Tabba <tabba@google.com>
Cc: Paul Walmsley <paul.walmsley@sifive.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Anup Patel <apatel@ventanamicro.com>
Cc: Andrew Jones <ajones@ventanamicro.com>
Cc: Alexandre Ghiti <alexghiti@rivosinc.com>
Cc: Conor Dooley <conor.dooley@microchip.com>
Cc: Samuel Holland <samuel.holland@sifive.com>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: WANG Xuerui <kernel@xen0n.name>
Cc: Bibo Mao <maobibo@loongson.cn>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Tianrui Zhao <zhaotianrui@loongson.cn>
Link: https://lore.kernel.org/20241030-tracepoint-v12-2-eec7f0f8ad22@google.com
Reviewed-by: Carlos Llamas <cmllamas@google.com>
Reviewed-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

authored by

Alice Ryhl and committed by
Steven Rostedt (Google)
ad37bcd9 6e59bcc9

+90 -1
+27 -1
include/linux/tracepoint.h
··· 226 226 } while (0) 227 227 228 228 /* 229 + * Declare an exported function that Rust code can call to trigger this 230 + * tracepoint. This function does not include the static branch; that is done 231 + * in Rust to avoid a function call when the tracepoint is disabled. 232 + */ 233 + #define DEFINE_RUST_DO_TRACE(name, proto, args) 234 + #define __DEFINE_RUST_DO_TRACE(name, proto, args) \ 235 + notrace void rust_do_trace_##name(proto) \ 236 + { \ 237 + __rust_do_trace_##name(args); \ 238 + } 239 + 240 + /* 229 241 * Make sure the alignment of the structure in the __tracepoints section will 230 242 * not add unwanted padding between the beginning of the section and the 231 243 * structure. Force alignment to the same alignment as the section start. ··· 252 240 extern int __traceiter_##name(data_proto); \ 253 241 DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \ 254 242 extern struct tracepoint __tracepoint_##name; \ 243 + extern void rust_do_trace_##name(proto); \ 255 244 static inline int \ 256 245 register_trace_##name(void (*probe)(data_proto), void *data) \ 257 246 { \ ··· 284 271 285 272 #define __DECLARE_TRACE(name, proto, args, cond, data_proto) \ 286 273 __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \ 274 + static inline void __rust_do_trace_##name(proto) \ 275 + { \ 276 + __DO_TRACE(name, \ 277 + TP_ARGS(args), \ 278 + TP_CONDITION(cond), 0); \ 279 + } \ 287 280 static inline void trace_##name(proto) \ 288 281 { \ 289 282 if (static_branch_unlikely(&__tracepoint_##name.key)) \ ··· 304 285 305 286 #define __DECLARE_TRACE_SYSCALL(name, proto, args, cond, data_proto) \ 306 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), 1); \ 293 + } \ 307 294 static inline void trace_##name(proto) \ 308 295 { \ 309 296 if (static_branch_unlikely(&__tracepoint_##name.key)) \ ··· 364 339 void __probestub_##_name(void *__data, proto) \ 365 340 { \ 366 341 } \ 367 - DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); 342 + DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); \ 343 + DEFINE_RUST_DO_TRACE(_name, TP_PROTO(proto), TP_ARGS(args)) 368 344 369 345 #define DEFINE_TRACE(name, proto, args) \ 370 346 DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
+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 */
+1
rust/bindings/bindings_helper.h
··· 20 20 #include <linux/refcount.h> 21 21 #include <linux/sched.h> 22 22 #include <linux/slab.h> 23 + #include <linux/tracepoint.h> 23 24 #include <linux/wait.h> 24 25 #include <linux/workqueue.h> 25 26
+1
rust/kernel/lib.rs
··· 54 54 pub mod sync; 55 55 pub mod task; 56 56 pub mod time; 57 + pub mod tracepoint; 57 58 pub mod types; 58 59 pub mod uaccess; 59 60 pub mod workqueue;
+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;