ANDROID: rust_binder: add back tracepoints
Tracepoints were removed from the the vendor module version of Rust Binder as it required either fixing b/394605825 or hard-coding the tracepoint declarations as created by bindgen. As we are moving Rust Binder back into common/, this no longer depends on invoking bindgen from the DDK. Thus, revert these changes. Bug: 394605825 Bug: 388786466 Change-Id: I81fe5b2b4c92826c6478606cd78c8fccd8a5c7e4 Signed-off-by: Alice Ryhl <aliceryhl@google.com>
This commit is contained in:
committed by
Matthew Maurer
parent
dac7c66bc9
commit
bf40001347
@@ -175,6 +175,14 @@ struct NodeInner {
|
||||
refs: List<NodeRefInfo, { NodeRefInfo::LIST_NODE }>,
|
||||
}
|
||||
|
||||
use core::mem::offset_of;
|
||||
use kernel::bindings::rb_node_layout;
|
||||
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,
|
||||
|
||||
@@ -383,6 +383,13 @@ impl ProcessNodeRefs {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
142
drivers/android/binder/rust_binder.h
Normal file
142
drivers/android/binder/rust_binder.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LINUX_RUST_BINDER_H
|
||||
#define _LINUX_RUST_BINDER_H
|
||||
|
||||
#include <uapi/linux/android/binder.h>
|
||||
#include <uapi/linux/android/binderfs.h>
|
||||
|
||||
/*
|
||||
* These symbols are exposed by `rust_binderfs.c` and exist here so that Rust
|
||||
* Binder can call them.
|
||||
*/
|
||||
int init_rust_binderfs(void);
|
||||
|
||||
struct dentry;
|
||||
struct inode;
|
||||
struct dentry *rust_binderfs_create_proc_file(struct inode *nodp, int pid);
|
||||
void rust_binderfs_remove_file(struct dentry *dentry);
|
||||
|
||||
typedef void *rust_binder_context;
|
||||
/**
|
||||
* struct binder_device - information about a binder device node
|
||||
* @minor: the minor number used by this device
|
||||
* @ctx: the Rust Context used by this device, or null for binder-control
|
||||
*
|
||||
* This is used as the private data for files directly in binderfs, but not
|
||||
* files in the binder_logs subdirectory. This struct owns a refcount on `ctx`
|
||||
* and the entry for `minor` in `binderfs_minors`. For binder-control `ctx` is
|
||||
* null.
|
||||
*/
|
||||
struct binder_device {
|
||||
int minor;
|
||||
rust_binder_context ctx;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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_thread;
|
||||
typedef void *rust_binder_process;
|
||||
typedef void *rust_binder_node;
|
||||
typedef void *rust_binder_ref_data;
|
||||
|
||||
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_thread_layout {
|
||||
size_t arc_offset;
|
||||
size_t process;
|
||||
size_t id;
|
||||
};
|
||||
|
||||
struct rb_process_layout {
|
||||
size_t arc_offset;
|
||||
size_t task;
|
||||
};
|
||||
|
||||
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_thread_layout th;
|
||||
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 p;
|
||||
}
|
||||
|
||||
static inline rust_binder_thread rust_binder_transaction_from_thread(rust_binder_transaction t)
|
||||
{
|
||||
void *p = * (void **) (t + RUST_BINDER_LAYOUT.t.from_thread);
|
||||
return p + RUST_BINDER_LAYOUT.th.arc_offset;
|
||||
}
|
||||
|
||||
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 rust_binder_process rust_binder_thread_proc(rust_binder_thread t)
|
||||
{
|
||||
void *p = * (void **) (t + RUST_BINDER_LAYOUT.th.process);
|
||||
return p + RUST_BINDER_LAYOUT.p.arc_offset;
|
||||
}
|
||||
|
||||
static inline s32 rust_binder_thread_id(rust_binder_thread t)
|
||||
{
|
||||
return * (s32 *) (t + RUST_BINDER_LAYOUT.th.id);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static inline binder_uintptr_t rust_binder_node_ptr(rust_binder_node t)
|
||||
{
|
||||
return * (binder_uintptr_t *) (t + RUST_BINDER_LAYOUT.n.ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -83,6 +83,15 @@ module! {
|
||||
license: "GPL",
|
||||
}
|
||||
|
||||
use kernel::bindings::rust_binder_layout;
|
||||
#[no_mangle]
|
||||
static RUST_BINDER_LAYOUT: rust_binder_layout = rust_binder_layout {
|
||||
t: transaction::TRANSACTION_LAYOUT,
|
||||
th: thread::THREAD_LAYOUT,
|
||||
p: process::PROCESS_LAYOUT,
|
||||
n: node::NODE_LAYOUT,
|
||||
};
|
||||
|
||||
fn next_debug_id() -> usize {
|
||||
static NEXT_DEBUG_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* Copyright 2024 Google LLC
|
||||
*/
|
||||
|
||||
#include "rust_binder.h"
|
||||
|
||||
const char * const binder_command_strings[] = {
|
||||
"BC_TRANSACTION",
|
||||
"BC_REPLY",
|
||||
@@ -51,3 +53,7 @@ const char * const binder_return_strings[] = {
|
||||
"BR_ONEWAY_SPAM_SUSPECT",
|
||||
"BR_TRANSACTION_PENDING_FROZEN"
|
||||
};
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#define CREATE_RUST_TRACE_POINTS
|
||||
#include "rust_binder_events.h"
|
||||
|
||||
387
drivers/android/binder/rust_binder_events.h
Normal file
387
drivers/android/binder/rust_binder_events.h
Normal file
@@ -0,0 +1,387 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2024 Google, Inc.
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_SYSTEM rust_binder
|
||||
#define TRACE_INCLUDE_FILE rust_binder_events
|
||||
#define TRACE_INCLUDE_PATH ../drivers/android/binder
|
||||
|
||||
#if !defined(_RUST_BINDER_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _RUST_BINDER_TRACE_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
TRACE_EVENT(rust_binder_ioctl,
|
||||
TP_PROTO(unsigned int cmd, unsigned long arg),
|
||||
TP_ARGS(cmd, arg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, cmd)
|
||||
__field(unsigned long, arg)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->cmd = cmd;
|
||||
__entry->arg = arg;
|
||||
),
|
||||
TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(rust_binder_function_return_class,
|
||||
TP_PROTO(int ret),
|
||||
TP_ARGS(ret),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, ret)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->ret = ret;
|
||||
),
|
||||
TP_printk("ret=%d", __entry->ret)
|
||||
);
|
||||
|
||||
#define DEFINE_RBINDER_FUNCTION_RETURN_EVENT(name) \
|
||||
DEFINE_EVENT(rust_binder_function_return_class, name, \
|
||||
TP_PROTO(int ret), \
|
||||
TP_ARGS(ret))
|
||||
|
||||
DEFINE_RBINDER_FUNCTION_RETURN_EVENT(rust_binder_ioctl_done);
|
||||
DEFINE_RBINDER_FUNCTION_RETURN_EVENT(rust_binder_read_done);
|
||||
DEFINE_RBINDER_FUNCTION_RETURN_EVENT(rust_binder_write_done);
|
||||
|
||||
TRACE_EVENT(rust_binder_set_priority,
|
||||
TP_PROTO(struct task_struct *thread, int desired_prio, int new_prio),
|
||||
TP_ARGS(thread, desired_prio, new_prio),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(int, proc)
|
||||
__field(int, thread)
|
||||
__field(unsigned int, old_prio)
|
||||
__field(unsigned int, new_prio)
|
||||
__field(unsigned int, desired_prio)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->proc = thread->tgid;
|
||||
__entry->thread = thread->pid;
|
||||
__entry->old_prio = thread->normal_prio;
|
||||
__entry->new_prio = new_prio;
|
||||
__entry->desired_prio = desired_prio;
|
||||
),
|
||||
TP_printk("proc=%d thread=%d old=%d => new=%d desired=%d",
|
||||
__entry->proc, __entry->thread, __entry->old_prio,
|
||||
__entry->new_prio, __entry->desired_prio)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rust_binder_wait_for_work,
|
||||
TP_PROTO(bool proc_work, bool transaction_stack, bool thread_todo),
|
||||
TP_ARGS(proc_work, transaction_stack, thread_todo),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(bool, proc_work)
|
||||
__field(bool, transaction_stack)
|
||||
__field(bool, thread_todo)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->proc_work = proc_work;
|
||||
__entry->transaction_stack = transaction_stack;
|
||||
__entry->thread_todo = thread_todo;
|
||||
),
|
||||
TP_printk("proc_work=%d transaction_stack=%d thread_todo=%d",
|
||||
__entry->proc_work, __entry->transaction_stack,
|
||||
__entry->thread_todo)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rust_binder_transaction,
|
||||
TP_PROTO(bool reply, rust_binder_transaction t),
|
||||
TP_ARGS(reply, t),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, debug_id)
|
||||
__field(int, target_node)
|
||||
__field(int, from_proc)
|
||||
__field(int, to_proc)
|
||||
__field(int, reply)
|
||||
__field(unsigned int, code)
|
||||
__field(unsigned int, flags)
|
||||
),
|
||||
TP_fast_assign(
|
||||
rust_binder_thread from_thread = rust_binder_transaction_from_thread(t);
|
||||
rust_binder_process from = rust_binder_thread_proc(from_thread);
|
||||
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->from_proc = rust_binder_process_task(from)->pid;
|
||||
__entry->to_proc = rust_binder_process_task(to)->pid;
|
||||
__entry->reply = reply;
|
||||
__entry->code = rust_binder_transaction_code(t);
|
||||
__entry->flags = rust_binder_transaction_flags(t);
|
||||
),
|
||||
TP_printk("transaction=%d target_node=%d dest_proc=%d from_proc=%d reply=%d flags=0x%x code=0x%x",
|
||||
__entry->debug_id, __entry->target_node, __entry->to_proc,
|
||||
__entry->from_proc, __entry->reply, __entry->flags,
|
||||
__entry->code)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rust_binder_transaction_thread_selected,
|
||||
TP_PROTO(rust_binder_transaction t, rust_binder_thread thread),
|
||||
TP_ARGS(t, thread),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, debug_id)
|
||||
__field(int, to_thread)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->debug_id = rust_binder_transaction_debug_id(t);
|
||||
__entry->to_thread = rust_binder_thread_id(thread);
|
||||
),
|
||||
TP_printk("transaction=%d thread=%d", __entry->debug_id, __entry->to_thread)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rust_binder_transaction_received,
|
||||
TP_PROTO(rust_binder_transaction t),
|
||||
TP_ARGS(t),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, debug_id)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->debug_id = rust_binder_transaction_debug_id(t);
|
||||
),
|
||||
TP_printk("transaction=%d", __entry->debug_id)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rust_binder_transaction_node_send,
|
||||
TP_PROTO(int t_debug_id, rust_binder_node node,
|
||||
const struct flat_binder_object *original,
|
||||
const struct flat_binder_object *translated),
|
||||
TP_ARGS(t_debug_id, node, original, translated),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(int, debug_id)
|
||||
__field(int, node_debug_id)
|
||||
__field(binder_uintptr_t, node_ptr)
|
||||
__field(int, types)
|
||||
__field(int, original_handle)
|
||||
__field(int, translated_handle)
|
||||
),
|
||||
TP_fast_assign(
|
||||
int orig_is_handle = original->hdr.type == BINDER_TYPE_HANDLE || original->hdr.type == BINDER_TYPE_WEAK_HANDLE;
|
||||
int orig_is_strong = original->hdr.type == BINDER_TYPE_HANDLE || original->hdr.type == BINDER_TYPE_BINDER;
|
||||
int tran_is_handle = translated->hdr.type == BINDER_TYPE_HANDLE || translated->hdr.type == BINDER_TYPE_WEAK_HANDLE;
|
||||
int tran_is_strong = translated->hdr.type == BINDER_TYPE_HANDLE || translated->hdr.type == BINDER_TYPE_BINDER;
|
||||
|
||||
__entry->debug_id = t_debug_id;
|
||||
__entry->node_debug_id = rust_binder_node_debug_id(node);
|
||||
__entry->node_ptr = rust_binder_node_debug_id(node);
|
||||
__entry->types =
|
||||
(orig_is_handle << 0) |
|
||||
(tran_is_handle << 1) |
|
||||
(orig_is_strong << 2) |
|
||||
(tran_is_strong << 3);
|
||||
__entry->original_handle = orig_is_handle ? original->handle : 0;
|
||||
__entry->translated_handle = tran_is_handle ? original->handle : 0;
|
||||
),
|
||||
TP_printk("transaction=%d node=%d ptr=0x%016llx: %s%s [%d] ==> %s%s [%d]",
|
||||
__entry->debug_id, __entry->node_debug_id,
|
||||
(u64)__entry->node_ptr,
|
||||
(__entry->types & (1<<2)) ? "" : "weak ",
|
||||
(__entry->types & (1<<0)) ? "handle" : "binder",
|
||||
__entry->original_handle,
|
||||
(__entry->types & (1<<3)) ? "" : "weak ",
|
||||
(__entry->types & (1<<1)) ? "handle" : "binder",
|
||||
__entry->translated_handle)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rust_binder_transaction_fd_send,
|
||||
TP_PROTO(int t_debug_id, int fd, size_t offset),
|
||||
TP_ARGS(t_debug_id, fd, offset),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(int, debug_id)
|
||||
__field(int, fd)
|
||||
__field(size_t, offset)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->debug_id = t_debug_id;
|
||||
__entry->fd = fd;
|
||||
__entry->offset = offset;
|
||||
),
|
||||
TP_printk("transaction=%d src_fd=%d offset=%zu",
|
||||
__entry->debug_id, __entry->fd, __entry->offset)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rust_binder_transaction_fd_recv,
|
||||
TP_PROTO(int t_debug_id, int fd, size_t offset),
|
||||
TP_ARGS(t_debug_id, fd, offset),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(int, debug_id)
|
||||
__field(int, fd)
|
||||
__field(size_t, offset)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->debug_id = t_debug_id;
|
||||
__entry->fd = fd;
|
||||
__entry->offset = offset;
|
||||
),
|
||||
TP_printk("transaction=%d dest_fd=%d offset=%zu",
|
||||
__entry->debug_id, __entry->fd, __entry->offset)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rust_binder_transaction_alloc_buf,
|
||||
TP_PROTO(int debug_id, const struct binder_transaction_data_sg *data),
|
||||
TP_ARGS(debug_id, data),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(int, debug_id)
|
||||
__field(size_t, data_size)
|
||||
__field(size_t, offsets_size)
|
||||
__field(size_t, extra_buffers_size)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->debug_id = debug_id;
|
||||
__entry->data_size = data->transaction_data.data_size;
|
||||
__entry->offsets_size = data->transaction_data.offsets_size;
|
||||
__entry->extra_buffers_size = data->buffers_size;
|
||||
),
|
||||
TP_printk("transaction=%d data_size=%zd offsets_size=%zd extra_buffers_size=%zd",
|
||||
__entry->debug_id, __entry->data_size, __entry->offsets_size,
|
||||
__entry->extra_buffers_size)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(rust_binder_buffer_release_class,
|
||||
TP_PROTO(int debug_id),
|
||||
TP_ARGS(debug_id),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, debug_id)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->debug_id = debug_id;
|
||||
),
|
||||
TP_printk("transaction=%d", __entry->debug_id)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(rust_binder_buffer_release_class, rust_binder_transaction_buffer_release,
|
||||
TP_PROTO(int debug_id),
|
||||
TP_ARGS(debug_id));
|
||||
|
||||
DEFINE_EVENT(rust_binder_buffer_release_class, rust_binder_transaction_failed_buffer_release,
|
||||
TP_PROTO(int debug_id),
|
||||
TP_ARGS(debug_id));
|
||||
|
||||
DEFINE_EVENT(rust_binder_buffer_release_class, rust_binder_transaction_update_buffer_release,
|
||||
TP_PROTO(int debug_id),
|
||||
TP_ARGS(debug_id));
|
||||
|
||||
TRACE_EVENT(rust_binder_update_page_range,
|
||||
TP_PROTO(int pid, bool allocate, size_t start, size_t end),
|
||||
TP_ARGS(pid, allocate, start, end),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, proc)
|
||||
__field(bool, allocate)
|
||||
__field(size_t, offset)
|
||||
__field(size_t, size)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->proc = pid;
|
||||
__entry->allocate = allocate;
|
||||
__entry->offset = start;
|
||||
__entry->size = end - start;
|
||||
),
|
||||
TP_printk("proc=%d allocate=%d offset=%zu size=%zu",
|
||||
__entry->proc, __entry->allocate,
|
||||
__entry->offset, __entry->size)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(rust_binder_lru_page_class,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, proc)
|
||||
__field(size_t, page_index)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->proc = pid;
|
||||
__entry->page_index = page_index;
|
||||
),
|
||||
TP_printk("proc=%d page_index=%zu",
|
||||
__entry->proc, __entry->page_index)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_alloc_lru_start,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index));
|
||||
|
||||
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_alloc_lru_end,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index));
|
||||
|
||||
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_free_lru_start,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index));
|
||||
|
||||
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_free_lru_end,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index));
|
||||
|
||||
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_alloc_page_start,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index));
|
||||
|
||||
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_alloc_page_end,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index));
|
||||
|
||||
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_unmap_user_start,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index));
|
||||
|
||||
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_unmap_user_end,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index));
|
||||
|
||||
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_unmap_kernel_start,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index));
|
||||
|
||||
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_unmap_kernel_end,
|
||||
TP_PROTO(int pid, size_t page_index),
|
||||
TP_ARGS(pid, page_index));
|
||||
|
||||
TRACE_EVENT(rust_binder_command,
|
||||
TP_PROTO(uint32_t cmd),
|
||||
TP_ARGS(cmd),
|
||||
TP_STRUCT__entry(
|
||||
__field(uint32_t, cmd)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->cmd = cmd;
|
||||
),
|
||||
TP_printk("cmd=0x%x %s",
|
||||
__entry->cmd,
|
||||
_IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_command_strings) ?
|
||||
binder_command_strings[_IOC_NR(__entry->cmd)] :
|
||||
"unknown")
|
||||
);
|
||||
|
||||
TRACE_EVENT(rust_binder_return,
|
||||
TP_PROTO(uint32_t ret),
|
||||
TP_ARGS(ret),
|
||||
TP_STRUCT__entry(
|
||||
__field(uint32_t, ret)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->ret = ret;
|
||||
),
|
||||
TP_printk("ret=0x%x %s",
|
||||
__entry->ret,
|
||||
_IOC_NR(__entry->ret) < ARRAY_SIZE(binder_return_strings) ?
|
||||
binder_return_strings[_IOC_NR(__entry->ret)] :
|
||||
"unknown")
|
||||
);
|
||||
|
||||
#endif /* _RUST_BINDER_TRACE_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
||||
@@ -6,14 +6,14 @@
|
||||
* Copyright 2024 Google LLC
|
||||
*/
|
||||
|
||||
#include <linux/rust_binder.h>
|
||||
#include "rust_binder.h"
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#define CREATE_RUST_TRACE_POINTS
|
||||
#include <trace/hooks/vendor_hooks.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
#include <trace/hooks/rust_binder.h>
|
||||
#include "rust_binder_hooks.h"
|
||||
|
||||
/*
|
||||
* Export tracepoints that act as a bare tracehook (ie: have no trace event
|
||||
|
||||
33
drivers/android/binder/rust_binder_hooks.h
Normal file
33
drivers/android/binder/rust_binder_hooks.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2024 Google, Inc.
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_SYSTEM rust_binder
|
||||
#define TRACE_INCLUDE_FILE rust_binder_hooks
|
||||
#define TRACE_INCLUDE_PATH ../drivers/android/binder
|
||||
|
||||
#if !defined(_RUST_BINDER_HOOK_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _RUST_BINDER_HOOK_H
|
||||
|
||||
#include <trace/hooks/vendor_hooks.h>
|
||||
|
||||
/*
|
||||
* Following tracepoints are not exported in tracefs and provide a
|
||||
* mechanism for vendor modules to hook and extend functionality
|
||||
*/
|
||||
|
||||
DECLARE_HOOK(android_vh_rust_binder_set_priority,
|
||||
TP_PROTO(rust_binder_transaction t, struct task_struct *task),
|
||||
TP_ARGS(t, task));
|
||||
DECLARE_HOOK(android_vh_rust_binder_restore_priority,
|
||||
TP_PROTO(struct task_struct *task),
|
||||
TP_ARGS(task));
|
||||
|
||||
#endif /* _RUST_BINDER_HOOK_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
||||
@@ -411,6 +411,14 @@ pub(crate) struct ThreadPrioState {
|
||||
pub(crate) next: BinderPriority,
|
||||
}
|
||||
|
||||
use core::mem::offset_of;
|
||||
use kernel::bindings::rb_thread_layout;
|
||||
pub(crate) const THREAD_LAYOUT: rb_thread_layout = rb_thread_layout {
|
||||
arc_offset: Arc::<Thread>::DATA_OFFSET,
|
||||
process: offset_of!(Thread, process),
|
||||
id: offset_of!(Thread, id),
|
||||
};
|
||||
|
||||
/// This represents a thread that's used with binder.
|
||||
#[pin_data]
|
||||
pub(crate) struct Thread {
|
||||
|
||||
@@ -2,88 +2,210 @@
|
||||
|
||||
// Copyright (C) 2024 Google LLC.
|
||||
|
||||
#![allow(unused_variables)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use crate::{defs::BinderTransactionDataSg, node::Node, thread::Thread, transaction::Transaction};
|
||||
|
||||
use kernel::bindings::{
|
||||
binder_transaction_data_sg, flat_binder_object, rust_binder_node, rust_binder_thread,
|
||||
rust_binder_transaction, task_struct,
|
||||
};
|
||||
use kernel::error::Result;
|
||||
use kernel::task::{Pid, Task};
|
||||
use kernel::tracepoint::declare_trace;
|
||||
use kernel::uapi::flat_binder_object;
|
||||
use kernel::uapi;
|
||||
|
||||
use core::ffi::{c_int, c_uint, c_ulong};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {}
|
||||
declare_trace! {
|
||||
unsafe fn rust_binder_ioctl(cmd: c_uint, arg: c_ulong);
|
||||
unsafe fn rust_binder_ioctl_done(ret: c_int);
|
||||
unsafe fn rust_binder_read_done(ret: c_int);
|
||||
unsafe fn rust_binder_write_done(ret: c_int);
|
||||
unsafe fn rust_binder_set_priority(thread: *mut task_struct, desired_prio: c_int, new_prio: c_int);
|
||||
unsafe fn android_vh_rust_binder_set_priority(t: rust_binder_transaction, task: *mut task_struct);
|
||||
unsafe fn android_vh_rust_binder_restore_priority(task: *mut task_struct);
|
||||
unsafe fn rust_binder_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool);
|
||||
unsafe fn rust_binder_transaction(reply: bool, t: rust_binder_transaction);
|
||||
unsafe fn rust_binder_transaction_received(t: rust_binder_transaction);
|
||||
unsafe fn rust_binder_transaction_thread_selected(t: rust_binder_transaction, thread: rust_binder_thread);
|
||||
unsafe fn rust_binder_transaction_node_send(t_debug_id: c_int, n: rust_binder_node,
|
||||
orig: *const flat_binder_object,
|
||||
trans: *const flat_binder_object);
|
||||
unsafe fn rust_binder_transaction_fd_send(t_debug_id: c_int, fd: c_int, offset: usize);
|
||||
unsafe fn rust_binder_transaction_fd_recv(t_debug_id: c_int, fd: c_int, offset: usize);
|
||||
unsafe fn rust_binder_transaction_alloc_buf(debug_id: c_int, data: *const binder_transaction_data_sg);
|
||||
unsafe fn rust_binder_transaction_buffer_release(debug_id: c_int);
|
||||
unsafe fn rust_binder_transaction_failed_buffer_release(debug_id: c_int);
|
||||
unsafe fn rust_binder_transaction_update_buffer_release(debug_id: c_int);
|
||||
unsafe fn rust_binder_update_page_range(pid: c_int, allocate: bool, start: usize, end: usize);
|
||||
unsafe fn rust_binder_alloc_lru_start(pid: c_int, page_index: usize);
|
||||
unsafe fn rust_binder_alloc_lru_end(pid: c_int, page_index: usize);
|
||||
unsafe fn rust_binder_free_lru_start(pid: c_int, page_index: usize);
|
||||
unsafe fn rust_binder_free_lru_end(pid: c_int, page_index: usize);
|
||||
unsafe fn rust_binder_alloc_page_start(pid: c_int, page_index: usize);
|
||||
unsafe fn rust_binder_alloc_page_end(pid: c_int, page_index: usize);
|
||||
unsafe fn rust_binder_unmap_user_start(pid: c_int, page_index: usize);
|
||||
unsafe fn rust_binder_unmap_user_end(pid: c_int, page_index: usize);
|
||||
unsafe fn rust_binder_unmap_kernel_start(pid: c_int, page_index: usize);
|
||||
unsafe fn rust_binder_unmap_kernel_end(pid: c_int, page_index: usize);
|
||||
unsafe fn rust_binder_command(cmd: u32);
|
||||
unsafe fn rust_binder_return(ret: u32);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_ioctl_done(ret: Result) {}
|
||||
fn raw_transaction(t: &Transaction) -> rust_binder_transaction {
|
||||
t as *const Transaction as rust_binder_transaction
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_read_done(ret: Result) {}
|
||||
fn raw_thread(t: &Thread) -> rust_binder_thread {
|
||||
t as *const Thread as rust_binder_thread
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_write_done(ret: Result) {}
|
||||
fn raw_node(n: &Node) -> rust_binder_node {
|
||||
n as *const Node as rust_binder_node
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_set_priority(thread: &Task, desired_prio: c_int, new_prio: c_int) {}
|
||||
fn to_errno(ret: Result) -> i32 {
|
||||
match ret {
|
||||
Ok(()) => 0,
|
||||
Err(err) => err.to_errno(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn vh_set_priority(t: &Transaction, task: &Task) {}
|
||||
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 vh_restore_priority(task: &Task) {}
|
||||
pub(crate) fn trace_ioctl_done(ret: Result) {
|
||||
// SAFETY: Always safe to call.
|
||||
unsafe { rust_binder_ioctl_done(to_errno(ret)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool) {}
|
||||
pub(crate) fn trace_read_done(ret: Result) {
|
||||
// SAFETY: Always safe to call.
|
||||
unsafe { rust_binder_read_done(to_errno(ret)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction(reply: bool, t: &Transaction) {}
|
||||
pub(crate) fn trace_write_done(ret: Result) {
|
||||
// SAFETY: Always safe to call.
|
||||
unsafe { rust_binder_write_done(to_errno(ret)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_received(t: &Transaction) {}
|
||||
pub(crate) fn trace_set_priority(thread: &Task, desired_prio: c_int, new_prio: c_int) {
|
||||
// SAFETY: The pointer to the task is valid for the duration of this call.
|
||||
unsafe { rust_binder_set_priority(thread.as_ptr(), desired_prio, new_prio) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_thread_selected(t: &Transaction, th: &Thread) {}
|
||||
pub(crate) fn vh_set_priority(t: &Transaction, task: &Task) {
|
||||
// SAFETY: The pointers to `t` and `task` are valid.
|
||||
unsafe { android_vh_rust_binder_set_priority(raw_transaction(t), task.as_ptr()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn vh_restore_priority(task: &Task) {
|
||||
// SAFETY: The pointer to `task` is valid.
|
||||
unsafe { android_vh_rust_binder_restore_priority(task.as_ptr()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool) {
|
||||
// SAFETY: Always safe to call.
|
||||
unsafe { rust_binder_wait_for_work(proc_work, transaction_stack, thread_todo) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction(reply: bool, t: &Transaction) {
|
||||
// SAFETY: The raw transaction is valid for the duration of this call.
|
||||
unsafe { rust_binder_transaction(reply, raw_transaction(t)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_received(t: &Transaction) {
|
||||
// SAFETY: The raw transaction is valid for the duration of this call.
|
||||
unsafe { rust_binder_transaction_received(raw_transaction(t)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_thread_selected(t: &Transaction, th: &Thread) {
|
||||
// SAFETY: The raw transaction is valid for the duration of this call.
|
||||
unsafe { rust_binder_transaction_thread_selected(raw_transaction(t), raw_thread(th)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_node_send(
|
||||
t_debug_id: usize,
|
||||
n: &Node,
|
||||
orig: &flat_binder_object,
|
||||
trans: &flat_binder_object,
|
||||
orig: &uapi::flat_binder_object,
|
||||
trans: &uapi::flat_binder_object,
|
||||
) {
|
||||
// CAST: Types are identical.
|
||||
let orig = orig as *const uapi::flat_binder_object as *const flat_binder_object;
|
||||
// CAST: Types are identical.
|
||||
let trans = trans as *const uapi::flat_binder_object as *const flat_binder_object;
|
||||
|
||||
// SAFETY: The pointers are valid for the duration of this call.
|
||||
unsafe { rust_binder_transaction_node_send(t_debug_id as c_int, raw_node(n), orig, trans) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize) {}
|
||||
pub(crate) fn trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize) {
|
||||
// SAFETY: This function is always safe to call.
|
||||
unsafe { rust_binder_transaction_fd_send(t_debug_id as c_int, fd as c_int, offset) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize) {}
|
||||
pub(crate) fn trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize) {
|
||||
// SAFETY: This function is always safe to call.
|
||||
unsafe { rust_binder_transaction_fd_recv(t_debug_id as c_int, fd as c_int, offset) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_alloc_buf(debug_id: usize, data: &BinderTransactionDataSg) {
|
||||
let data = data as *const BinderTransactionDataSg;
|
||||
// SAFETY: The `data` pointer is valid.
|
||||
unsafe { rust_binder_transaction_alloc_buf(debug_id as c_int, data.cast()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_buffer_release(debug_id: usize) {}
|
||||
pub(crate) fn trace_transaction_buffer_release(debug_id: usize) {
|
||||
// SAFETY: Always safe to call.
|
||||
unsafe { rust_binder_transaction_buffer_release(debug_id as c_int) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_failed_buffer_release(debug_id: usize) {}
|
||||
pub(crate) fn trace_transaction_failed_buffer_release(debug_id: usize) {
|
||||
// SAFETY: Always safe to call.
|
||||
unsafe { rust_binder_transaction_failed_buffer_release(debug_id as c_int) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_transaction_update_buffer_release(debug_id: usize) {}
|
||||
pub(crate) fn trace_transaction_update_buffer_release(debug_id: usize) {
|
||||
// SAFETY: Always safe to call.
|
||||
unsafe { rust_binder_transaction_update_buffer_release(debug_id as c_int) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_update_page_range(pid: Pid, allocate: bool, start: usize, end: usize) {}
|
||||
pub(crate) fn trace_update_page_range(pid: Pid, allocate: bool, start: usize, end: usize) {
|
||||
// SAFETY: Always safe to call.
|
||||
unsafe { rust_binder_update_page_range(pid as c_int, allocate, start, end) }
|
||||
}
|
||||
|
||||
macro_rules! define_wrapper_lru_page_class {
|
||||
($(fn $name:ident;)*) => {$(
|
||||
kernel::macros::paste! {
|
||||
#[inline]
|
||||
pub(crate) fn [< trace_ $name >](pid: Pid, page_index: usize) {
|
||||
// SAFETY: Always safe to call.
|
||||
unsafe { [< rust_binder_ $name >](pid as c_int, page_index) }
|
||||
}
|
||||
}
|
||||
)*}
|
||||
@@ -103,7 +225,13 @@ define_wrapper_lru_page_class! {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_command(cmd: u32) {}
|
||||
pub(crate) fn trace_command(cmd: u32) {
|
||||
// SAFETY: Trivially safe to call with primitive u32.
|
||||
unsafe { rust_binder_command(cmd) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn trace_return(ret: u32) {}
|
||||
pub(crate) fn trace_return(ret: u32) {
|
||||
// SAFETY: Trivially safe to call with primitive u32.
|
||||
unsafe { rust_binder_return(ret) }
|
||||
}
|
||||
|
||||
@@ -25,6 +25,17 @@ use crate::{
|
||||
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,
|
||||
|
||||
@@ -58,3 +58,9 @@ const blk_features_t RUST_CONST_HELPER_BLK_FEAT_ROTATIONAL = BLK_FEAT_ROTATIONAL
|
||||
const size_t RUST_CONST_HELPER_ASHMEM_NAME_PREFIX_LEN = ASHMEM_NAME_PREFIX_LEN;
|
||||
const size_t RUST_CONST_HELPER_ASHMEM_FULL_NAME_LEN = ASHMEM_FULL_NAME_LEN;
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_RUST)
|
||||
#include "../../drivers/android/binder/rust_binder.h"
|
||||
#include "../../drivers/android/binder/rust_binder_hooks.h"
|
||||
#include "../../drivers/android/binder/rust_binder_events.h"
|
||||
#endif
|
||||
|
||||
@@ -206,6 +206,9 @@ impl<T> Arc<T> {
|
||||
// `Arc` object.
|
||||
Ok(unsafe { Self::from_inner(KBox::leak(inner).into()) })
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
|
||||
Reference in New Issue
Block a user