1 // SPDX-License-Identifier: GPL-2.0
2
3 // Copyright (C) 2024 Google LLC.
4
5 use crate::{defs::BinderTransactionDataSg, node::Node, thread::Thread, transaction::Transaction};
6
7 use kernel::bindings::{
8 binder_transaction_data_sg, flat_binder_object, rust_binder_node, rust_binder_thread,
9 rust_binder_transaction, task_struct,
10 };
11 use kernel::error::Result;
12 use kernel::ffi::{c_int, c_uint, c_ulong};
13 use kernel::task::{Pid, Task};
14 use kernel::tracepoint::declare_trace;
15 use kernel::uapi;
16
17 declare_trace! {
18 unsafe fn rust_binder_ioctl(cmd: c_uint, arg: c_ulong);
19 unsafe fn rust_binder_ioctl_done(ret: c_int);
20 unsafe fn rust_binder_read_done(ret: c_int);
21 unsafe fn rust_binder_write_done(ret: c_int);
22 unsafe fn rust_binder_set_priority(thread: *mut task_struct, desired_prio: c_int, new_prio: c_int);
23 unsafe fn android_vh_rust_binder_set_priority(t: rust_binder_transaction, task: *mut task_struct);
24 unsafe fn android_vh_rust_binder_restore_priority(task: *mut task_struct);
25 unsafe fn rust_binder_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool);
26 unsafe fn rust_binder_transaction(reply: bool, t: rust_binder_transaction);
27 unsafe fn rust_binder_transaction_received(t: rust_binder_transaction);
28 unsafe fn rust_binder_transaction_thread_selected(t: rust_binder_transaction, thread: rust_binder_thread);
29 unsafe fn rust_binder_transaction_node_send(t_debug_id: c_int, n: rust_binder_node,
30 orig: *const flat_binder_object,
31 trans: *const flat_binder_object);
32 unsafe fn rust_binder_transaction_fd_send(t_debug_id: c_int, fd: c_int, offset: usize);
33 unsafe fn rust_binder_transaction_fd_recv(t_debug_id: c_int, fd: c_int, offset: usize);
34 unsafe fn rust_binder_transaction_alloc_buf(debug_id: c_int, data: *const binder_transaction_data_sg);
35 unsafe fn rust_binder_transaction_buffer_release(debug_id: c_int);
36 unsafe fn rust_binder_transaction_failed_buffer_release(debug_id: c_int);
37 unsafe fn rust_binder_transaction_update_buffer_release(debug_id: c_int);
38 unsafe fn rust_binder_update_page_range(pid: c_int, allocate: bool, start: usize, end: usize);
39 unsafe fn rust_binder_alloc_lru_start(pid: c_int, page_index: usize);
40 unsafe fn rust_binder_alloc_lru_end(pid: c_int, page_index: usize);
41 unsafe fn rust_binder_free_lru_start(pid: c_int, page_index: usize);
42 unsafe fn rust_binder_free_lru_end(pid: c_int, page_index: usize);
43 unsafe fn rust_binder_alloc_page_start(pid: c_int, page_index: usize);
44 unsafe fn rust_binder_alloc_page_end(pid: c_int, page_index: usize);
45 unsafe fn rust_binder_unmap_user_start(pid: c_int, page_index: usize);
46 unsafe fn rust_binder_unmap_user_end(pid: c_int, page_index: usize);
47 unsafe fn rust_binder_unmap_kernel_start(pid: c_int, page_index: usize);
48 unsafe fn rust_binder_unmap_kernel_end(pid: c_int, page_index: usize);
49 unsafe fn rust_binder_command(cmd: u32);
50 unsafe fn rust_binder_return(ret: u32);
51 }
52
53 #[inline]
raw_transaction(t: &Transaction) -> rust_binder_transaction54 fn raw_transaction(t: &Transaction) -> rust_binder_transaction {
55 t as *const Transaction as rust_binder_transaction
56 }
57
58 #[inline]
raw_thread(t: &Thread) -> rust_binder_thread59 fn raw_thread(t: &Thread) -> rust_binder_thread {
60 t as *const Thread as rust_binder_thread
61 }
62
63 #[inline]
raw_node(n: &Node) -> rust_binder_node64 fn raw_node(n: &Node) -> rust_binder_node {
65 n as *const Node as rust_binder_node
66 }
67
68 #[inline]
to_errno(ret: Result) -> i3269 fn to_errno(ret: Result) -> i32 {
70 match ret {
71 Ok(()) => 0,
72 Err(err) => err.to_errno(),
73 }
74 }
75
76 #[inline]
trace_ioctl(cmd: u32, arg: usize)77 pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {
78 // SAFETY: Always safe to call.
79 unsafe { rust_binder_ioctl(cmd, arg as c_ulong) }
80 }
81
82 #[inline]
trace_ioctl_done(ret: Result)83 pub(crate) fn trace_ioctl_done(ret: Result) {
84 // SAFETY: Always safe to call.
85 unsafe { rust_binder_ioctl_done(to_errno(ret)) }
86 }
87
88 #[inline]
trace_read_done(ret: Result)89 pub(crate) fn trace_read_done(ret: Result) {
90 // SAFETY: Always safe to call.
91 unsafe { rust_binder_read_done(to_errno(ret)) }
92 }
93
94 #[inline]
trace_write_done(ret: Result)95 pub(crate) fn trace_write_done(ret: Result) {
96 // SAFETY: Always safe to call.
97 unsafe { rust_binder_write_done(to_errno(ret)) }
98 }
99
100 #[inline]
trace_set_priority(thread: &Task, desired_prio: c_int, new_prio: c_int)101 pub(crate) fn trace_set_priority(thread: &Task, desired_prio: c_int, new_prio: c_int) {
102 // SAFETY: The pointer to the task is valid for the duration of this call.
103 unsafe { rust_binder_set_priority(thread.as_ptr(), desired_prio, new_prio) }
104 }
105
106 #[inline]
vh_set_priority(t: &Transaction, task: &Task)107 pub(crate) fn vh_set_priority(t: &Transaction, task: &Task) {
108 // SAFETY: The pointers to `t` and `task` are valid.
109 unsafe { android_vh_rust_binder_set_priority(raw_transaction(t), task.as_ptr()) }
110 }
111
112 #[inline]
vh_restore_priority(task: &Task)113 pub(crate) fn vh_restore_priority(task: &Task) {
114 // SAFETY: The pointer to `task` is valid.
115 unsafe { android_vh_rust_binder_restore_priority(task.as_ptr()) }
116 }
117
118 #[inline]
trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool)119 pub(crate) fn trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool) {
120 // SAFETY: Always safe to call.
121 unsafe { rust_binder_wait_for_work(proc_work, transaction_stack, thread_todo) }
122 }
123
124 #[inline]
trace_transaction(reply: bool, t: &Transaction)125 pub(crate) fn trace_transaction(reply: bool, t: &Transaction) {
126 // SAFETY: The raw transaction is valid for the duration of this call.
127 unsafe { rust_binder_transaction(reply, raw_transaction(t)) }
128 }
129
130 #[inline]
trace_transaction_received(t: &Transaction)131 pub(crate) fn trace_transaction_received(t: &Transaction) {
132 // SAFETY: The raw transaction is valid for the duration of this call.
133 unsafe { rust_binder_transaction_received(raw_transaction(t)) }
134 }
135
136 #[inline]
trace_transaction_thread_selected(t: &Transaction, th: &Thread)137 pub(crate) fn trace_transaction_thread_selected(t: &Transaction, th: &Thread) {
138 // SAFETY: The raw transaction is valid for the duration of this call.
139 unsafe { rust_binder_transaction_thread_selected(raw_transaction(t), raw_thread(th)) }
140 }
141
142 #[inline]
trace_transaction_node_send( t_debug_id: usize, n: &Node, orig: &uapi::flat_binder_object, trans: &uapi::flat_binder_object, )143 pub(crate) fn trace_transaction_node_send(
144 t_debug_id: usize,
145 n: &Node,
146 orig: &uapi::flat_binder_object,
147 trans: &uapi::flat_binder_object,
148 ) {
149 // CAST: Types are identical.
150 let orig = orig as *const uapi::flat_binder_object as *const flat_binder_object;
151 // CAST: Types are identical.
152 let trans = trans as *const uapi::flat_binder_object as *const flat_binder_object;
153
154 // SAFETY: The pointers are valid for the duration of this call.
155 unsafe { rust_binder_transaction_node_send(t_debug_id as c_int, raw_node(n), orig, trans) }
156 }
157
158 #[inline]
trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize)159 pub(crate) fn trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize) {
160 // SAFETY: This function is always safe to call.
161 unsafe { rust_binder_transaction_fd_send(t_debug_id as c_int, fd as c_int, offset) }
162 }
163
164 #[inline]
trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize)165 pub(crate) fn trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize) {
166 // SAFETY: This function is always safe to call.
167 unsafe { rust_binder_transaction_fd_recv(t_debug_id as c_int, fd as c_int, offset) }
168 }
169
170 #[inline]
trace_transaction_alloc_buf(debug_id: usize, data: &BinderTransactionDataSg)171 pub(crate) fn trace_transaction_alloc_buf(debug_id: usize, data: &BinderTransactionDataSg) {
172 let data = data as *const BinderTransactionDataSg;
173 // SAFETY: The `data` pointer is valid.
174 unsafe { rust_binder_transaction_alloc_buf(debug_id as c_int, data.cast()) }
175 }
176
177 #[inline]
trace_transaction_buffer_release(debug_id: usize)178 pub(crate) fn trace_transaction_buffer_release(debug_id: usize) {
179 // SAFETY: Always safe to call.
180 unsafe { rust_binder_transaction_buffer_release(debug_id as c_int) }
181 }
182
183 #[inline]
trace_transaction_failed_buffer_release(debug_id: usize)184 pub(crate) fn trace_transaction_failed_buffer_release(debug_id: usize) {
185 // SAFETY: Always safe to call.
186 unsafe { rust_binder_transaction_failed_buffer_release(debug_id as c_int) }
187 }
188
189 #[inline]
trace_transaction_update_buffer_release(debug_id: usize)190 pub(crate) fn trace_transaction_update_buffer_release(debug_id: usize) {
191 // SAFETY: Always safe to call.
192 unsafe { rust_binder_transaction_update_buffer_release(debug_id as c_int) }
193 }
194
195 #[inline]
trace_update_page_range(pid: Pid, allocate: bool, start: usize, end: usize)196 pub(crate) fn trace_update_page_range(pid: Pid, allocate: bool, start: usize, end: usize) {
197 // SAFETY: Always safe to call.
198 unsafe { rust_binder_update_page_range(pid as c_int, allocate, start, end) }
199 }
200
201 macro_rules! define_wrapper_lru_page_class {
202 ($(fn $name:ident;)*) => {$(
203 kernel::macros::paste! {
204 #[inline]
205 pub(crate) fn [< trace_ $name >](pid: Pid, page_index: usize) {
206 // SAFETY: Always safe to call.
207 unsafe { [< rust_binder_ $name >](pid as c_int, page_index) }
208 }
209 }
210 )*}
211 }
212
213 define_wrapper_lru_page_class! {
214 fn alloc_lru_start;
215 fn alloc_lru_end;
216 fn free_lru_start;
217 fn free_lru_end;
218 fn alloc_page_start;
219 fn alloc_page_end;
220 fn unmap_user_start;
221 fn unmap_user_end;
222 fn unmap_kernel_start;
223 fn unmap_kernel_end;
224 }
225
226 #[inline]
trace_command(cmd: u32)227 pub(crate) fn trace_command(cmd: u32) {
228 // SAFETY: Trivially safe to call with primitive u32.
229 unsafe { rust_binder_command(cmd) }
230 }
231
232 #[inline]
trace_return(ret: u32)233 pub(crate) fn trace_return(ret: u32) {
234 // SAFETY: Trivially safe to call with primitive u32.
235 unsafe { rust_binder_return(ret) }
236 }
237