public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: "Alice Ryhl" <aliceryhl@google.com>,
	"Steven Rostedt" <rostedt@goodmis.org>,
	"Masami Hiramatsu" <mhiramat@kernel.org>,
	"Peter Zijlstra" <peterz@infradead.org>,
	"Josh Poimboeuf" <jpoimboe@kernel.org>,
	"Jason Baron" <jbaron@akamai.com>,
	"Ard Biesheuvel" <ardb@kernel.org>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Wedson Almeida Filho" <wedsonaf@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <benno.lossin@proton.me>,
	"Andreas Hindborg" <a.hindborg@samsung.com>
Cc: linux-trace-kernel@vger.kernel.org,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 0/3] Tracepoints and static branch/call in Rust
Date: Thu, 6 Jun 2024 11:25:49 -0400	[thread overview]
Message-ID: <cd4a58d9-3e0a-49d1-8a74-bc9d53fc2dfd@efficios.com> (raw)
In-Reply-To: <20240606-tracepoint-v1-0-6551627bf51b@google.com>

On 2024-06-06 11:05, Alice Ryhl wrote:
> 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.

I'm glad to see progress on this front ! Please see feedback below.

> 
> To use the tracepoint support, you must:
> 
> 1. Declare the tracepoint in a C header file as usual.
> 2. Make sure that the header file is visible to bindgen so that Rust
>     bindings are generated for the symbols that the tracepoint macro
>     emits.
> 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 would add the relevant
> header file to rust/bindings/bindings_helper.h and add the following
> invocation somewhere in your Rust code:
> 
> 	declare_trace! {
> 	    fn sched_kthread_stop(task: *mut task_struct);
> 	}
> 
> This will define a Rust function of the given name that you can call
> like any other Rust function. Since these tracepoints often take raw
> pointers as arguments, it may be convenient to wrap it in a safe
> wrapper:
> 
> 	mod raw {
> 	    declare_trace! {
> 	        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 will end up in the Rust object file. However,
> it would also be possible to just wrap the trace_##name generated by
> __DECLARE_TRACE in an extern C function and then call that from Rust.
> This will simplify the Rust code by removing the need for static
> branches and calls, but it places the static branch behind an external
> call, which has performance implications.

The tracepoints try very hard to minimize overhead of dormant tracepoints
so it is not frowned-upon to have them built into production binaries.
This is needed to make sure distribution vendors keep those tracepoints
in the kernel binaries that reach end-users.

Adding a function call before evaluation of the static branch goes against
this major goal.

> 
> A possible middle ground would be to place just the __DO_TRACE body in
> an extern C function and to implement the Rust wrapper by doing the
> static branch in Rust, and then calling into C the code that contains
> __DO_TRACE when the tracepoint is active. However, this would need some
> changes to include/linux/tracepoint.h to generate and export a function
> containing the body of __DO_TRACE when the tracepoint should be callable
> from Rust.

This tradeoff is more acceptable than having a function call before
evaluation of the static branch, but I wonder what is the upside of
this tradeoff compared to inlining the whole __DO_TRACE in Rust ?

> So in general, there is a tradeoff between placing parts of the
> tracepoint (which is perf sensitive) behind an external call, and having
> code duplicated in both C and Rust (which must be kept in sync when
> changes are made). This is an important point that I would like feedback
> on from the C maintainers.

I don't see how the duplication happens there: __DO_TRACE is meant to be
inlined into each C tracepoint caller site, so the code is already meant
to be duplicated. Having an explicit function wrapping the tracepoint
for Rust would just create an extra instance of __DO_TRACE if it happens
to be also inlined into C code.

Or do you meant you would like to prevent having to duplicate the
implementation of __DO_TRACE in both C and Rust ?

I'm not sure if you mean to prevent source code duplication between
C and Rust or duplication of binary code (instructions).

Thanks,

Mathieu


> 
> Link: https://lore.kernel.org/rust-for-linux/20231101-rust-binder-v1-0-08ba9197f637@google.com/ [1]
> Link: https://r.android.com/3110088 [2]
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> ---
> Alice Ryhl (3):
>        rust: add static_call support
>        rust: add static_key_false
>        rust: add tracepoint support
> 
>   rust/bindings/bindings_helper.h |  1 +
>   rust/bindings/lib.rs            | 15 +++++++
>   rust/helpers.c                  | 24 +++++++++++
>   rust/kernel/lib.rs              |  3 ++
>   rust/kernel/static_call.rs      | 92 +++++++++++++++++++++++++++++++++++++++++
>   rust/kernel/static_key.rs       | 87 ++++++++++++++++++++++++++++++++++++++
>   rust/kernel/tracepoint.rs       | 92 +++++++++++++++++++++++++++++++++++++++++
>   scripts/Makefile.build          |  2 +-
>   8 files changed, 315 insertions(+), 1 deletion(-)
> ---
> base-commit: 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0
> change-id: 20240606-tracepoint-31e15b90e471
> 
> Best regards,

-- 
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com


  parent reply	other threads:[~2024-06-06 15:25 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-06 15:05 [PATCH 0/3] Tracepoints and static branch/call in Rust Alice Ryhl
2024-06-06 15:05 ` [PATCH 1/3] rust: add static_call support Alice Ryhl
2024-06-06 17:18   ` Peter Zijlstra
2024-06-06 19:09     ` Miguel Ojeda
2024-06-06 19:33       ` Peter Zijlstra
2024-06-07  9:43         ` Alice Ryhl
2024-06-07 10:52           ` Peter Zijlstra
2024-06-07 11:08             ` Alice Ryhl
2024-06-07 11:46             ` Miguel Ojeda
2024-06-06 15:05 ` [PATCH 2/3] rust: add static_key_false Alice Ryhl
2024-06-06 15:38   ` Mathieu Desnoyers
2024-06-06 16:19     ` Alice Ryhl
2024-06-06 17:23   ` Peter Zijlstra
2024-06-06 15:05 ` [PATCH 3/3] rust: add tracepoint support Alice Ryhl
2024-06-06 15:30   ` Mathieu Desnoyers
2024-06-06 15:49     ` Boqun Feng
2024-06-06 16:18       ` Mathieu Desnoyers
2024-06-06 17:35       ` Peter Zijlstra
2024-06-06 19:00         ` Boqun Feng
2024-06-06 19:29           ` Peter Zijlstra
2024-06-06 23:50             ` Boqun Feng
2024-06-06 16:16     ` Alice Ryhl
2024-06-06 16:21       ` Mathieu Desnoyers
2024-06-06 17:26   ` Peter Zijlstra
2024-06-06 15:25 ` Mathieu Desnoyers [this message]
2024-06-06 15:46   ` [PATCH 0/3] Tracepoints and static branch/call in Rust Alice Ryhl
2024-06-06 16:17     ` Mathieu Desnoyers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cd4a58d9-3e0a-49d1-8a74-bc9d53fc2dfd@efficios.com \
    --to=mathieu.desnoyers@efficios.com \
    --cc=a.hindborg@samsung.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=ardb@kernel.org \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=gary@garyguo.net \
    --cc=jbaron@akamai.com \
    --cc=jpoimboe@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=wedsonaf@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox