* [PATCH 0/2] Access Rust fields from TP_fast_assign in TRACE_EVENT
@ 2025-12-03 14:48 Alice Ryhl
2025-12-03 14:48 ` [PATCH 1/2] rust: sync: add Arc::DATA_OFFSET Alice Ryhl
2025-12-03 14:48 ` [PATCH 2/2] rust_binder: add binder_transaction tracepoint Alice Ryhl
0 siblings, 2 replies; 4+ messages in thread
From: Alice Ryhl @ 2025-12-03 14:48 UTC (permalink / raw)
To: Greg Kroah-Hartman, Carlos Llamas, Steven Rostedt
Cc: Masami Hiramatsu, Mathieu Desnoyers, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Arve Hjønnevåg,
Todd Kjos, Martijn Coenen, Joel Fernandes, Christian Brauner,
Suren Baghdasaryan, rust-for-linux, linux-trace-kernel,
linux-kernel, Alice Ryhl
This patch shows one possible mechanism for accessing Rust fields from
the TP_fast_assign() body of a trace event. The idea is to have the
driver expose the offsets of the relevant fields, and to have the C code
use those offsets to access the data.
I'm currently using this mechanism in the Rust Binder driver on
Android's fork of 6.12.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
Alice Ryhl (2):
rust: sync: add Arc::DATA_OFFSET
rust_binder: add binder_transaction tracepoint
drivers/android/binder/node.rs | 8 +++
drivers/android/binder/process.rs | 7 +++
drivers/android/binder/rust_binder.h | 79 +++++++++++++++++++++++++++++
drivers/android/binder/rust_binder_events.h | 30 +++++++++++
drivers/android/binder/rust_binder_main.rs | 8 +++
drivers/android/binder/thread.rs | 1 +
drivers/android/binder/trace.rs | 21 ++++++++
drivers/android/binder/transaction.rs | 14 +++++
rust/kernel/sync/arc.rs | 3 ++
9 files changed, 171 insertions(+)
---
base-commit: 211ddde0823f1442e4ad052a2f30f050145ccada
change-id: 20251113-binder-trace1-b2d369f63e30
Best regards,
--
Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] rust: sync: add Arc::DATA_OFFSET
2025-12-03 14:48 [PATCH 0/2] Access Rust fields from TP_fast_assign in TRACE_EVENT Alice Ryhl
@ 2025-12-03 14:48 ` Alice Ryhl
2025-12-04 13:32 ` Daniel Almeida
2025-12-03 14:48 ` [PATCH 2/2] rust_binder: add binder_transaction tracepoint Alice Ryhl
1 sibling, 1 reply; 4+ messages in thread
From: Alice Ryhl @ 2025-12-03 14:48 UTC (permalink / raw)
To: Greg Kroah-Hartman, Carlos Llamas, Steven Rostedt
Cc: Masami Hiramatsu, Mathieu Desnoyers, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Arve Hjønnevåg,
Todd Kjos, Martijn Coenen, Joel Fernandes, Christian Brauner,
Suren Baghdasaryan, rust-for-linux, linux-trace-kernel,
linux-kernel, Alice Ryhl
This constant will be used to expose some offset constants from the Rust
Binder driver to tracepoints which are implemented in C. The constant is
usually equal to sizeof(refcount_t), but may be larger if T has a large
alignment.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
rust/kernel/sync/arc.rs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index 289f77abf415a2a52e039a2c0291413eda01217c..921e19333b895f0d971591c4753047d0248a3029 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -240,6 +240,9 @@ pub fn new(contents: T, flags: Flags) -> Result<Self, AllocError> {
// `Arc` object.
Ok(unsafe { Self::from_inner(inner) })
}
+
+ /// The offset that the value is stored at.
+ pub const DATA_OFFSET: usize = core::mem::offset_of!(ArcInner<T>, data);
}
impl<T: ?Sized> Arc<T> {
--
2.52.0.158.g65b55ccf14-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] rust_binder: add binder_transaction tracepoint
2025-12-03 14:48 [PATCH 0/2] Access Rust fields from TP_fast_assign in TRACE_EVENT Alice Ryhl
2025-12-03 14:48 ` [PATCH 1/2] rust: sync: add Arc::DATA_OFFSET Alice Ryhl
@ 2025-12-03 14:48 ` Alice Ryhl
1 sibling, 0 replies; 4+ messages in thread
From: Alice Ryhl @ 2025-12-03 14:48 UTC (permalink / raw)
To: Greg Kroah-Hartman, Carlos Llamas, Steven Rostedt
Cc: Masami Hiramatsu, Mathieu Desnoyers, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Arve Hjønnevåg,
Todd Kjos, Martijn Coenen, Joel Fernandes, Christian Brauner,
Suren Baghdasaryan, rust-for-linux, linux-trace-kernel,
linux-kernel, Alice Ryhl
This patch adds the binder_transaction tracepoint to Rust Binder. This
was chosen as the next tracepoint to add as it is the most complex
tracepoint. (And it's also an important tracepoint known to perfetto.)
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
drivers/android/binder/node.rs | 8 +++
drivers/android/binder/process.rs | 7 +++
drivers/android/binder/rust_binder.h | 79 +++++++++++++++++++++++++++++
drivers/android/binder/rust_binder_events.h | 30 +++++++++++
drivers/android/binder/rust_binder_main.rs | 8 +++
drivers/android/binder/thread.rs | 1 +
drivers/android/binder/trace.rs | 21 ++++++++
drivers/android/binder/transaction.rs | 14 +++++
8 files changed, 168 insertions(+)
diff --git a/drivers/android/binder/node.rs b/drivers/android/binder/node.rs
index ade895ef791ec5746f9f5c1bfc15f47d59829455..7e6c94c7c3373461520d52d0b1fe8c1fc871fbd8 100644
--- a/drivers/android/binder/node.rs
+++ b/drivers/android/binder/node.rs
@@ -178,6 +178,14 @@ struct NodeInner {
refs: List<NodeRefInfo, { NodeRefInfo::LIST_NODE }>,
}
+use kernel::bindings::rb_node_layout;
+use mem::offset_of;
+pub(crate) const NODE_LAYOUT: rb_node_layout = rb_node_layout {
+ arc_offset: Arc::<Node>::DATA_OFFSET + offset_of!(DTRWrap<Node>, wrapped),
+ debug_id: offset_of!(Node, debug_id),
+ ptr: offset_of!(Node, ptr),
+};
+
#[pin_data]
pub(crate) struct Node {
pub(crate) debug_id: usize,
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index f13a747e784c84a0fb09cbf47442712106eba07c..c4c8a0ba93366f3e2ec426fb5950f48edb0610ae 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -387,6 +387,13 @@ fn new() -> Self {
}
}
+use core::mem::offset_of;
+use kernel::bindings::rb_process_layout;
+pub(crate) const PROCESS_LAYOUT: rb_process_layout = rb_process_layout {
+ arc_offset: Arc::<Process>::DATA_OFFSET,
+ task: offset_of!(Process, task),
+};
+
/// A process using binder.
///
/// Strictly speaking, there can be multiple of these per process. There is one for each binder fd
diff --git a/drivers/android/binder/rust_binder.h b/drivers/android/binder/rust_binder.h
index 31806890ed1a278793ae7178f9d76ca4d591a954..e68ba7a23c34de4688fa7d34341b0585b5dba7e9 100644
--- a/drivers/android/binder/rust_binder.h
+++ b/drivers/android/binder/rust_binder.h
@@ -20,4 +20,83 @@ struct inode;
struct dentry *rust_binderfs_create_proc_file(struct inode *nodp, int pid);
void rust_binderfs_remove_file(struct dentry *dentry);
+/*
+ * The internal data types in the Rust Binder driver are opaque to C, so we use
+ * void pointer typedefs for these types.
+ */
+
+typedef void *rust_binder_transaction;
+typedef void *rust_binder_process;
+typedef void *rust_binder_node;
+
+struct rb_process_layout {
+ size_t arc_offset;
+ size_t task;
+};
+
+struct rb_transaction_layout {
+ size_t debug_id;
+ size_t code;
+ size_t flags;
+ size_t from_thread;
+ size_t to_proc;
+ size_t target_node;
+};
+
+struct rb_node_layout {
+ size_t arc_offset;
+ size_t debug_id;
+ size_t ptr;
+};
+
+struct rust_binder_layout {
+ struct rb_transaction_layout t;
+ struct rb_process_layout p;
+ struct rb_node_layout n;
+};
+
+extern const struct rust_binder_layout RUST_BINDER_LAYOUT;
+
+static inline size_t rust_binder_transaction_debug_id(rust_binder_transaction t)
+{
+ return *(size_t *) (t + RUST_BINDER_LAYOUT.t.debug_id);
+}
+
+static inline u32 rust_binder_transaction_code(rust_binder_transaction t)
+{
+ return *(u32 *) (t + RUST_BINDER_LAYOUT.t.code);
+}
+
+static inline u32 rust_binder_transaction_flags(rust_binder_transaction t)
+{
+ return *(u32 *) (t + RUST_BINDER_LAYOUT.t.flags);
+}
+
+// Nullable!
+static inline rust_binder_node rust_binder_transaction_target_node(rust_binder_transaction t)
+{
+ void *p = *(void **) (t + RUST_BINDER_LAYOUT.t.target_node);
+
+ if (p)
+ p = p + RUST_BINDER_LAYOUT.n.arc_offset;
+ return NULL;
+}
+
+static inline rust_binder_process rust_binder_transaction_to_proc(rust_binder_transaction t)
+{
+ void *p = *(void **) (t + RUST_BINDER_LAYOUT.t.to_proc);
+
+ return p + RUST_BINDER_LAYOUT.p.arc_offset;
+}
+
+static inline struct task_struct *rust_binder_process_task(rust_binder_process t)
+{
+ return *(struct task_struct **) (t + RUST_BINDER_LAYOUT.p.task);
+}
+
+static inline size_t rust_binder_node_debug_id(rust_binder_node t)
+{
+ return *(size_t *) (t + RUST_BINDER_LAYOUT.n.debug_id);
+}
+
#endif
diff --git a/drivers/android/binder/rust_binder_events.h b/drivers/android/binder/rust_binder_events.h
index 2f3efbf9dba68e6415f0f09ff5c8255dc5c5bc00..8ad785c6bd0f5783df1e764a8827fed41afbcb00 100644
--- a/drivers/android/binder/rust_binder_events.h
+++ b/drivers/android/binder/rust_binder_events.h
@@ -30,6 +30,36 @@ TRACE_EVENT(rust_binder_ioctl,
TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg)
);
+TRACE_EVENT(rust_binder_transaction,
+ TP_PROTO(bool reply, rust_binder_transaction t, struct task_struct *thread),
+ TP_ARGS(reply, t, thread),
+ TP_STRUCT__entry(
+ __field(int, debug_id)
+ __field(int, target_node)
+ __field(int, to_proc)
+ __field(int, to_thread)
+ __field(int, reply)
+ __field(unsigned int, code)
+ __field(unsigned int, flags)
+ ),
+ TP_fast_assign(
+ rust_binder_process to = rust_binder_transaction_to_proc(t);
+ rust_binder_node target_node = rust_binder_transaction_target_node(t);
+
+ __entry->debug_id = rust_binder_transaction_debug_id(t);
+ __entry->target_node = target_node ? rust_binder_node_debug_id(target_node) : 0;
+ __entry->to_proc = rust_binder_process_task(to)->pid;
+ __entry->to_thread = thread ? thread->pid : 0;
+ __entry->reply = reply;
+ __entry->code = rust_binder_transaction_code(t);
+ __entry->flags = rust_binder_transaction_flags(t);
+ ),
+ TP_printk("transaction=%d dest_node=%d dest_proc=%d dest_thread=%d reply=%d flags=0x%x code=0x%x",
+ __entry->debug_id, __entry->target_node,
+ __entry->to_proc, __entry->to_thread,
+ __entry->reply, __entry->flags, __entry->code)
+);
+
#endif /* _RUST_BINDER_TRACE_H */
/* This part must be outside protection */
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index 6773b7c273ec9634057300954d67b51ca9b54f6f..3799b4707ed4e0505a3d3370e3dd1e74f974b641 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -89,6 +89,14 @@ fn default() -> Self {
license: "GPL",
}
+use kernel::bindings::rust_binder_layout;
+#[no_mangle]
+static RUST_BINDER_LAYOUT: rust_binder_layout = rust_binder_layout {
+ t: transaction::TRANSACTION_LAYOUT,
+ p: process::PROCESS_LAYOUT,
+ n: node::NODE_LAYOUT,
+};
+
fn next_debug_id() -> usize {
static NEXT_DEBUG_ID: AtomicUsize = AtomicUsize::new(0);
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 7e34ccd394f8049bab88562ffb4601739aea670a..0874e2793e276e075802d97ea9bb02a4c2fc8c72 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -1117,6 +1117,7 @@ fn deliver_single_reply(
transaction: &DArc<Transaction>,
) -> bool {
if let Ok(transaction) = &reply {
+ crate::trace::trace_transaction(true, transaction, Some(&self.task));
transaction.set_outstanding(&mut self.process.inner.lock());
}
diff --git a/drivers/android/binder/trace.rs b/drivers/android/binder/trace.rs
index af0e4392805e7ef2a39b7c1e557ea233dcd810ab..9839901c7151590defed297b091f1339603c09df 100644
--- a/drivers/android/binder/trace.rs
+++ b/drivers/android/binder/trace.rs
@@ -2,11 +2,21 @@
// Copyright (C) 2025 Google LLC.
+use crate::transaction::Transaction;
+
+use kernel::bindings::{rust_binder_transaction, task_struct};
use kernel::ffi::{c_uint, c_ulong};
+use kernel::task::Task;
use kernel::tracepoint::declare_trace;
declare_trace! {
unsafe fn rust_binder_ioctl(cmd: c_uint, arg: c_ulong);
+ unsafe fn rust_binder_transaction(reply: bool, t: rust_binder_transaction, thread: *mut task_struct);
+}
+
+#[inline]
+fn raw_transaction(t: &Transaction) -> rust_binder_transaction {
+ t as *const Transaction as rust_binder_transaction
}
#[inline]
@@ -14,3 +24,14 @@ pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {
// SAFETY: Always safe to call.
unsafe { rust_binder_ioctl(cmd, arg as c_ulong) }
}
+
+#[inline]
+pub(crate) fn trace_transaction(reply: bool, t: &Transaction, thread: Option<&Task>) {
+ let thread = match thread {
+ Some(thread) => thread.as_ptr(),
+ None => core::ptr::null_mut(),
+ };
+ // SAFETY: The raw transaction is valid for the duration of this call. The thread pointer is
+ // valid or null.
+ unsafe { rust_binder_transaction(reply, raw_transaction(t), thread) }
+}
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index 02512175d6229535373f2d3e543ba8c91ecd72f0..6a12064a53ad4c477d8b6cb016333f5a10ec399a 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -24,6 +24,17 @@
BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead,
};
+use core::mem::offset_of;
+use kernel::bindings::rb_transaction_layout;
+pub(crate) const TRANSACTION_LAYOUT: rb_transaction_layout = rb_transaction_layout {
+ debug_id: offset_of!(Transaction, debug_id),
+ code: offset_of!(Transaction, code),
+ flags: offset_of!(Transaction, flags),
+ from_thread: offset_of!(Transaction, from),
+ to_proc: offset_of!(Transaction, to),
+ target_node: offset_of!(Transaction, target_node),
+};
+
#[pin_data(PinnedDrop)]
pub(crate) struct Transaction {
pub(crate) debug_id: usize,
@@ -249,6 +260,7 @@ pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
if oneway {
if let Some(target_node) = self.target_node.clone() {
+ crate::trace::trace_transaction(false, &self, None);
if process_inner.is_frozen {
process_inner.async_recv = true;
if self.flags & TF_UPDATE_TXN != 0 {
@@ -286,11 +298,13 @@ pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
}
let res = if let Some(thread) = self.find_target_thread() {
+ crate::trace::trace_transaction(false, &self, Some(&thread.task));
match thread.push_work(self) {
PushWorkRes::Ok => Ok(()),
PushWorkRes::FailedDead(me) => Err((BinderError::new_dead(), me)),
}
} else {
+ crate::trace::trace_transaction(false, &self, None);
process_inner.push_work(self)
};
drop(process_inner);
--
2.52.0.158.g65b55ccf14-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] rust: sync: add Arc::DATA_OFFSET
2025-12-03 14:48 ` [PATCH 1/2] rust: sync: add Arc::DATA_OFFSET Alice Ryhl
@ 2025-12-04 13:32 ` Daniel Almeida
0 siblings, 0 replies; 4+ messages in thread
From: Daniel Almeida @ 2025-12-04 13:32 UTC (permalink / raw)
To: Alice Ryhl
Cc: Greg Kroah-Hartman, Carlos Llamas, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Miguel Ojeda, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Arve Hjønnevåg,
Todd Kjos, Martijn Coenen, Joel Fernandes, Christian Brauner,
Suren Baghdasaryan, rust-for-linux, linux-trace-kernel,
linux-kernel
> On 3 Dec 2025, at 08:48, Alice Ryhl <aliceryhl@google.com> wrote:
>
> This constant will be used to expose some offset constants from the Rust
> Binder driver to tracepoints which are implemented in C. The constant is
> usually equal to sizeof(refcount_t), but may be larger if T has a large
> alignment.
>
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> ---
> rust/kernel/sync/arc.rs | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
> index 289f77abf415a2a52e039a2c0291413eda01217c..921e19333b895f0d971591c4753047d0248a3029 100644
> --- a/rust/kernel/sync/arc.rs
> +++ b/rust/kernel/sync/arc.rs
> @@ -240,6 +240,9 @@ pub fn new(contents: T, flags: Flags) -> Result<Self, AllocError> {
> // `Arc` object.
> Ok(unsafe { Self::from_inner(inner) })
> }
> +
> + /// The offset that the value is stored at.
> + pub const DATA_OFFSET: usize = core::mem::offset_of!(ArcInner<T>, data);
> }
>
> impl<T: ?Sized> Arc<T> {
>
> --
> 2.52.0.158.g65b55ccf14-goog
>
>
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-12-04 13:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-03 14:48 [PATCH 0/2] Access Rust fields from TP_fast_assign in TRACE_EVENT Alice Ryhl
2025-12-03 14:48 ` [PATCH 1/2] rust: sync: add Arc::DATA_OFFSET Alice Ryhl
2025-12-04 13:32 ` Daniel Almeida
2025-12-03 14:48 ` [PATCH 2/2] rust_binder: add binder_transaction tracepoint Alice Ryhl
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).