1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2025 Google LLC. 4 5 use crate::transaction::Transaction; 6 7 use kernel::bindings::{rust_binder_transaction, task_struct}; 8 use kernel::error::Result; 9 use kernel::ffi::{c_int, c_uint, c_ulong}; 10 use kernel::task::Task; 11 use kernel::tracepoint::declare_trace; 12 13 declare_trace! { 14 unsafe fn binder_ioctl(cmd: c_uint, arg: c_ulong); 15 unsafe fn binder_ioctl_done(ret: c_int); 16 unsafe fn binder_read_done(ret: c_int); 17 unsafe fn binder_write_done(ret: c_int); 18 unsafe fn binder_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool); 19 unsafe fn binder_transaction(reply: bool, t: rust_binder_transaction, thread: *mut task_struct); 20 unsafe fn binder_transaction_received(t: rust_binder_transaction); 21 unsafe fn binder_transaction_fd_send(t_debug_id: c_int, fd: c_int, offset: usize); 22 unsafe fn binder_transaction_fd_recv(t_debug_id: c_int, fd: c_int, offset: usize); 23 unsafe fn binder_command(cmd: u32); 24 unsafe fn binder_return(ret: u32); 25 } 26 27 #[inline] 28 fn raw_transaction(t: &Transaction) -> rust_binder_transaction { 29 t as *const Transaction as rust_binder_transaction 30 } 31 32 #[inline] 33 fn to_errno(ret: Result) -> i32 { 34 match ret { 35 Ok(()) => 0, 36 Err(err) => err.to_errno(), 37 } 38 } 39 40 #[inline] 41 pub(crate) fn trace_ioctl(cmd: u32, arg: usize) { 42 // SAFETY: Always safe to call. 43 unsafe { binder_ioctl(cmd, arg as c_ulong) } 44 } 45 46 #[inline] 47 pub(crate) fn trace_ioctl_done(ret: Result) { 48 // SAFETY: Always safe to call. 49 unsafe { binder_ioctl_done(to_errno(ret)) } 50 } 51 #[inline] 52 pub(crate) fn trace_read_done(ret: Result) { 53 // SAFETY: Always safe to call. 54 unsafe { binder_read_done(to_errno(ret)) } 55 } 56 #[inline] 57 pub(crate) fn trace_write_done(ret: Result) { 58 // SAFETY: Always safe to call. 59 unsafe { binder_write_done(to_errno(ret)) } 60 } 61 62 #[inline] 63 pub(crate) fn trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool) { 64 // SAFETY: Always safe to call. 65 unsafe { binder_wait_for_work(proc_work, transaction_stack, thread_todo) } 66 } 67 68 #[inline] 69 pub(crate) fn trace_transaction(reply: bool, t: &Transaction, thread: Option<&Task>) { 70 let thread = match thread { 71 Some(thread) => thread.as_ptr(), 72 None => core::ptr::null_mut(), 73 }; 74 // SAFETY: The raw transaction is valid for the duration of this call. The thread pointer is 75 // valid or null. 76 unsafe { binder_transaction(reply, raw_transaction(t), thread) } 77 } 78 79 #[inline] 80 pub(crate) fn trace_transaction_received(t: &Transaction) { 81 // SAFETY: The raw transaction is valid for the duration of this call. 82 unsafe { binder_transaction_received(raw_transaction(t)) } 83 } 84 85 #[inline] 86 pub(crate) fn trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize) { 87 // SAFETY: This function is always safe to call. 88 unsafe { binder_transaction_fd_send(t_debug_id as c_int, fd as c_int, offset) } 89 } 90 #[inline] 91 pub(crate) fn trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize) { 92 // SAFETY: This function is always safe to call. 93 unsafe { binder_transaction_fd_recv(t_debug_id as c_int, fd as c_int, offset) } 94 } 95 96 #[inline] 97 pub(crate) fn trace_command(cmd: u32) { 98 // SAFETY: This function is always safe to call. 99 unsafe { binder_command(cmd) } 100 } 101 #[inline] 102 pub(crate) fn trace_return(ret: u32) { 103 // SAFETY: This function is always safe to call. 104 unsafe { binder_return(ret) } 105 } 106