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