Message ID | 20240802-tracepoint-v5-0-faa164494dcb@google.com (mailing list archive) |
---|---|
Headers | show |
Series | Tracepoints and static branch in Rust | expand |
On Fri, Aug 02, 2024 at 09:31:27AM +0000, Alice Ryhl wrote: > Add just enough support for static key so that we can use it from > tracepoints. Tracepoints rely on `static_key_false` even though it is > deprecated, so we add the same functionality to Rust. > > It is not possible to use the existing C implementation of > arch_static_branch because it passes the argument `key` to inline > assembly as an 'i' parameter, so any attempt to add a C helper for this > function will fail to compile because the value of `key` must be known > at compile-time. > > One disadvantage of this patch is that it introduces a fair amount of > duplicated inline assembly. However, this is a limited and temporary > situation: > > 1. Most inline assembly has no reason to be duplicated like this. It is > only needed here due to the use of 'i' parameters. > > 2. Alice will submit a patch along the lines of [1] that removes the > duplication. This will happen as a follow-up to this patch series. You're talking about yourself in the 3rd person? What's the rush, why not do it right first?
On Fri, Aug 2, 2024 at 11:40 AM Peter Zijlstra <peterz@infradead.org> wrote: > > On Fri, Aug 02, 2024 at 09:31:27AM +0000, Alice Ryhl wrote: > > Add just enough support for static key so that we can use it from > > tracepoints. Tracepoints rely on `static_key_false` even though it is > > deprecated, so we add the same functionality to Rust. > > > > It is not possible to use the existing C implementation of > > arch_static_branch because it passes the argument `key` to inline > > assembly as an 'i' parameter, so any attempt to add a C helper for this > > function will fail to compile because the value of `key` must be known > > at compile-time. > > > > One disadvantage of this patch is that it introduces a fair amount of > > duplicated inline assembly. However, this is a limited and temporary > > situation: > > > > 1. Most inline assembly has no reason to be duplicated like this. It is > > only needed here due to the use of 'i' parameters. > > > > 2. Alice will submit a patch along the lines of [1] that removes the > > duplication. This will happen as a follow-up to this patch series. > > You're talking about yourself in the 3rd person? I'm not sure if commit messages are supposed to be a personal message from me, or an impersonal description of the patch. I'm happy to reword. > What's the rush, why not do it right first? Well for one, this version of the series mostly just makes changes to the second patch. But also, maybe I'm being too aggressive about it, but I have large amounts of out-of-tree code that I've been working on upstreaming, and it's a lot of work to keep it all up-to-date and rebased. I want to reduce it as much as I can. I was hoping that I could get the changes to include/linux/tracepoint.h off my plate, even if more work is needed on the static_key side of things. Alice
An important part of a production ready Linux kernel driver is tracepoints. So to write production ready Linux kernel drivers in Rust, we must be able to call tracepoints from Rust code. This patch series adds support for calling tracepoints declared in C from Rust. To use the tracepoint support, you must: 1. Declare the tracepoint in a C header file as usual. 2. Add #define CREATE_RUST_TRACE_POINTS next to your #define CREATE_TRACE_POINTS. 2. Make sure that the header file is visible to bindgen. 3. Use the declare_trace! macro in your Rust code to generate Rust functions that call into the tracepoint. For example, the kernel has a tracepoint called `sched_kthread_stop`. It is declared like this: TRACE_EVENT(sched_kthread_stop, TP_PROTO(struct task_struct *t), TP_ARGS(t), TP_STRUCT__entry( __array( char, comm, TASK_COMM_LEN ) __field( pid_t, pid ) ), TP_fast_assign( memcpy(__entry->comm, t->comm, TASK_COMM_LEN); __entry->pid = t->pid; ), TP_printk("comm=%s pid=%d", __entry->comm, __entry->pid) ); To call the above tracepoint from Rust code, you must first ensure that the Rust helper for the tracepoint is generated. To do this, you would modify kernel/sched/core.c by adding #define CREATE_RUST_TRACE_POINTS. Next, you would include include/trace/events/sched.h in rust/bindings/bindings_helper.h so that the exported C functions are visible to Rust, and then you would declare the tracepoint in Rust: declare_trace! { fn sched_kthread_stop(task: *mut task_struct); } This will define an inline Rust function that checks the static key, calling into rust_do_trace_##name if the tracepoint is active. Since these tracepoints often take raw pointers as arguments, it may be convenient to wrap it in a safe wrapper: mod raw { declare_trace! { /// # Safety /// `task` must point at a valid task for the duration /// of this call. fn sched_kthread_stop(task: *mut task_struct); } } #[inline] pub fn trace_sched_kthread_stop(task: &Task) { // SAFETY: The pointer to `task` is valid. unsafe { raw::sched_kthread_stop(task.as_raw()) } } A future expansion of the tracepoint support could generate these safe versions automatically, but that is left as future work for now. This is intended for use in the Rust Binder driver, which was originally sent as an RFC [1]. The RFC did not include tracepoint support, but you can see how it will be used in Rust Binder at [2]. The author has verified that the tracepoint support works on Android devices. This implementation implements support for static keys in Rust so that the actual static branch happens in the Rust object file. However, the __DO_TRACE body remains in C code. See v1 for an implementation where __DO_TRACE is also implemented in Rust. Link: https://lore.kernel.org/rust-for-linux/20231101-rust-binder-v1-0-08ba9197f637@google.com/ [1] Link: https://r.android.com/3119993 [2] Signed-off-by: Alice Ryhl <aliceryhl@google.com> --- Changes in v5: - Update first patch regarding inline asm duplication. - Add __rust_do_trace helper to support conditions. - Rename DEFINE_RUST_DO_TRACE_REAL to __DEFINE_RUST_DO_TRACE. - Get rid of glob-import in tracepoint macro. - Address safety requirements on tracepoints in docs. - Link to v4: https://lore.kernel.org/rust-for-linux/20240628-tracepoint-v4-0-353d523a9c15@google.com Changes in v4: - Move arch-specific code into rust/kernel/arch. - Restore DEFINE_RUST_DO_TRACE at end of define_trace.h - Link to v3: https://lore.kernel.org/r/20240621-tracepoint-v3-0-9e44eeea2b85@google.com Changes in v3: - Support for Rust static_key on loongarch64 and riscv64. - Avoid failing compilation on architectures that are missing Rust static_key support when the archtectures does not actually use it. - Link to v2: https://lore.kernel.org/r/20240610-tracepoint-v2-0-faebad81b355@google.com Changes in v2: - Call into C code for __DO_TRACE. - Drop static_call patch, as it is no longer needed. - Link to v1: https://lore.kernel.org/r/20240606-tracepoint-v1-0-6551627bf51b@google.com --- Alice Ryhl (2): rust: add static_key_false rust: add tracepoint support arch/arm64/include/asm/jump_label.h | 1 + arch/loongarch/include/asm/jump_label.h | 1 + arch/riscv/include/asm/jump_label.h | 1 + arch/x86/include/asm/jump_label.h | 1 + include/linux/tracepoint.h | 22 +++++++++++++- include/trace/define_trace.h | 12 ++++++++ rust/bindings/bindings_helper.h | 1 + rust/kernel/arch/arm64/jump_label.rs | 34 ++++++++++++++++++++++ rust/kernel/arch/loongarch/jump_label.rs | 35 +++++++++++++++++++++++ rust/kernel/arch/mod.rs | 24 ++++++++++++++++ rust/kernel/arch/riscv/jump_label.rs | 38 +++++++++++++++++++++++++ rust/kernel/arch/x86/jump_label.rs | 35 +++++++++++++++++++++++ rust/kernel/lib.rs | 3 ++ rust/kernel/static_key.rs | 32 +++++++++++++++++++++ rust/kernel/tracepoint.rs | 49 ++++++++++++++++++++++++++++++++ scripts/Makefile.build | 2 +- 16 files changed, 289 insertions(+), 2 deletions(-) --- base-commit: 8400291e289ee6b2bf9779ff1c83a291501f017b change-id: 20240606-tracepoint-31e15b90e471 Best regards,