Commit c1ea3120 authored by Alice Ryhl's avatar Alice Ryhl Committed by Greg Kroah-Hartman
Browse files

rust_binder: add binder_transaction tracepoint



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: default avatarAlice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251203-binder-trace1-v1-2-22d3ffddb44e@google.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c1093b85
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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,
+7 −0
Original line number Diff line number Diff line
@@ -418,6 +418,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
+79 −0
Original line number Diff line number Diff line
@@ -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
+30 −0
Original line number Diff line number Diff line
@@ -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 */
+8 −0
Original line number Diff line number Diff line
@@ -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);

Loading