mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-28 16:53:49 +00:00
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>
This commit is contained in:
parent
6e59bcc9c8
commit
ad37bcd965
@ -225,6 +225,18 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
|
||||
preempt_enable_notrace(); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Declare an exported function that Rust code can call to trigger this
|
||||
* tracepoint. This function does not include the static branch; that is done
|
||||
* in Rust to avoid a function call when the tracepoint is disabled.
|
||||
*/
|
||||
#define DEFINE_RUST_DO_TRACE(name, proto, args)
|
||||
#define __DEFINE_RUST_DO_TRACE(name, proto, args) \
|
||||
notrace void rust_do_trace_##name(proto) \
|
||||
{ \
|
||||
__rust_do_trace_##name(args); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the alignment of the structure in the __tracepoints section will
|
||||
* 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)
|
||||
extern int __traceiter_##name(data_proto); \
|
||||
DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \
|
||||
extern struct tracepoint __tracepoint_##name; \
|
||||
extern void rust_do_trace_##name(proto); \
|
||||
static inline int \
|
||||
register_trace_##name(void (*probe)(data_proto), void *data) \
|
||||
{ \
|
||||
@ -271,6 +284,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
|
||||
|
||||
#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
|
||||
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \
|
||||
static inline void __rust_do_trace_##name(proto) \
|
||||
{ \
|
||||
__DO_TRACE(name, \
|
||||
TP_ARGS(args), \
|
||||
TP_CONDITION(cond), 0); \
|
||||
} \
|
||||
static inline void trace_##name(proto) \
|
||||
{ \
|
||||
if (static_branch_unlikely(&__tracepoint_##name.key)) \
|
||||
@ -285,6 +304,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
|
||||
|
||||
#define __DECLARE_TRACE_SYSCALL(name, proto, args, cond, data_proto) \
|
||||
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \
|
||||
static inline void __rust_do_trace_##name(proto) \
|
||||
{ \
|
||||
__DO_TRACE(name, \
|
||||
TP_ARGS(args), \
|
||||
TP_CONDITION(cond), 1); \
|
||||
} \
|
||||
static inline void trace_##name(proto) \
|
||||
{ \
|
||||
if (static_branch_unlikely(&__tracepoint_##name.key)) \
|
||||
@ -339,7 +364,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
|
||||
void __probestub_##_name(void *__data, proto) \
|
||||
{ \
|
||||
} \
|
||||
DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
|
||||
DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); \
|
||||
DEFINE_RUST_DO_TRACE(_name, TP_PROTO(proto), TP_ARGS(args))
|
||||
|
||||
#define DEFINE_TRACE(name, proto, args) \
|
||||
DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args));
|
||||
|
@ -76,6 +76,13 @@
|
||||
#define DECLARE_TRACE(name, proto, args) \
|
||||
DEFINE_TRACE(name, PARAMS(proto), PARAMS(args))
|
||||
|
||||
/* If requested, create helpers for calling these tracepoints from Rust. */
|
||||
#ifdef CREATE_RUST_TRACE_POINTS
|
||||
#undef DEFINE_RUST_DO_TRACE
|
||||
#define DEFINE_RUST_DO_TRACE(name, proto, args) \
|
||||
__DEFINE_RUST_DO_TRACE(name, PARAMS(proto), PARAMS(args))
|
||||
#endif
|
||||
|
||||
#undef TRACE_INCLUDE
|
||||
#undef __TRACE_INCLUDE
|
||||
|
||||
@ -134,6 +141,11 @@
|
||||
# undef UNDEF_TRACE_INCLUDE_PATH
|
||||
#endif
|
||||
|
||||
#ifdef CREATE_RUST_TRACE_POINTS
|
||||
# undef DEFINE_RUST_DO_TRACE
|
||||
# define DEFINE_RUST_DO_TRACE(name, proto, args)
|
||||
#endif
|
||||
|
||||
/* We may be processing more files */
|
||||
#define CREATE_TRACE_POINTS
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/tracepoint.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
||||
pub mod sync;
|
||||
pub mod task;
|
||||
pub mod time;
|
||||
pub mod tracepoint;
|
||||
pub mod types;
|
||||
pub mod uaccess;
|
||||
pub mod workqueue;
|
||||
|
49
rust/kernel/tracepoint.rs
Normal file
49
rust/kernel/tracepoint.rs
Normal file
@ -0,0 +1,49 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
// Copyright (C) 2024 Google LLC.
|
||||
|
||||
//! Logic for tracepoints.
|
||||
|
||||
/// Declare the Rust entry point for a tracepoint.
|
||||
///
|
||||
/// This macro generates an unsafe function that calls into C, and its safety requirements will be
|
||||
/// whatever the relevant C code requires. To document these safety requirements, you may add
|
||||
/// doc-comments when invoking the macro.
|
||||
#[macro_export]
|
||||
macro_rules! declare_trace {
|
||||
($($(#[$attr:meta])* $pub:vis unsafe fn $name:ident($($argname:ident : $argtyp:ty),* $(,)?);)*) => {$(
|
||||
$( #[$attr] )*
|
||||
#[inline(always)]
|
||||
$pub unsafe fn $name($($argname : $argtyp),*) {
|
||||
#[cfg(CONFIG_TRACEPOINTS)]
|
||||
{
|
||||
// SAFETY: It's always okay to query the static key for a tracepoint.
|
||||
let should_trace = unsafe {
|
||||
$crate::macros::paste! {
|
||||
$crate::jump_label::static_branch_unlikely!(
|
||||
$crate::bindings::[< __tracepoint_ $name >],
|
||||
$crate::bindings::tracepoint,
|
||||
key
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
if should_trace {
|
||||
$crate::macros::paste! {
|
||||
// SAFETY: The caller guarantees that it is okay to call this tracepoint.
|
||||
unsafe { $crate::bindings::[< rust_do_trace_ $name >]($($argname),*) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(CONFIG_TRACEPOINTS))]
|
||||
{
|
||||
// If tracepoints are disabled, insert a trivial use of each argument
|
||||
// to avoid unused argument warnings.
|
||||
$( let _unused = $argname; )*
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
pub use declare_trace;
|
Loading…
Reference in New Issue
Block a user