Skip to content

Commit ad37bcd

Browse files
Darksonnrostedt
authored andcommitted
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>
1 parent 6e59bcc commit ad37bcd

File tree

5 files changed

+90
-1
lines changed

5 files changed

+90
-1
lines changed

include/linux/tracepoint.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,18 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
225225
preempt_enable_notrace(); \
226226
} while (0)
227227

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+
228240
/*
229241
* Make sure the alignment of the structure in the __tracepoints section will
230242
* not add unwanted padding between the beginning of the section and the
@@ -240,6 +252,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
240252
extern int __traceiter_##name(data_proto); \
241253
DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \
242254
extern struct tracepoint __tracepoint_##name; \
255+
extern void rust_do_trace_##name(proto); \
243256
static inline int \
244257
register_trace_##name(void (*probe)(data_proto), void *data) \
245258
{ \
@@ -271,6 +284,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
271284

272285
#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
273286
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \
287+
static inline void __rust_do_trace_##name(proto) \
288+
{ \
289+
__DO_TRACE(name, \
290+
TP_ARGS(args), \
291+
TP_CONDITION(cond), 0); \
292+
} \
274293
static inline void trace_##name(proto) \
275294
{ \
276295
if (static_branch_unlikely(&__tracepoint_##name.key)) \
@@ -285,6 +304,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
285304

286305
#define __DECLARE_TRACE_SYSCALL(name, proto, args, cond, data_proto) \
287306
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \
307+
static inline void __rust_do_trace_##name(proto) \
308+
{ \
309+
__DO_TRACE(name, \
310+
TP_ARGS(args), \
311+
TP_CONDITION(cond), 1); \
312+
} \
288313
static inline void trace_##name(proto) \
289314
{ \
290315
if (static_branch_unlikely(&__tracepoint_##name.key)) \
@@ -339,7 +364,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
339364
void __probestub_##_name(void *__data, proto) \
340365
{ \
341366
} \
342-
DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
367+
DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); \
368+
DEFINE_RUST_DO_TRACE(_name, TP_PROTO(proto), TP_ARGS(args))
343369

344370
#define DEFINE_TRACE(name, proto, args) \
345371
DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));

include/trace/define_trace.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@
7676
#define DECLARE_TRACE(name, proto, args) \
7777
DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
7878

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+
7986
#undef TRACE_INCLUDE
8087
#undef __TRACE_INCLUDE
8188

@@ -134,6 +141,11 @@
134141
# undef UNDEF_TRACE_INCLUDE_PATH
135142
#endif
136143

144+
#ifdef CREATE_RUST_TRACE_POINTS
145+
# undef DEFINE_RUST_DO_TRACE
146+
# define DEFINE_RUST_DO_TRACE(name, proto, args)
147+
#endif
148+
137149
/* We may be processing more files */
138150
#define CREATE_TRACE_POINTS
139151

rust/bindings/bindings_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/refcount.h>
2121
#include <linux/sched.h>
2222
#include <linux/slab.h>
23+
#include <linux/tracepoint.h>
2324
#include <linux/wait.h>
2425
#include <linux/workqueue.h>
2526

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub mod str;
5454
pub mod sync;
5555
pub mod task;
5656
pub mod time;
57+
pub mod tracepoint;
5758
pub mod types;
5859
pub mod uaccess;
5960
pub mod workqueue;

rust/kernel/tracepoint.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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;

0 commit comments

Comments
 (0)