1*fae6e9adSlinfeng use super::Result;
2*fae6e9adSlinfeng use crate::arch::interrupt::TrapFrame;
3*fae6e9adSlinfeng use crate::arch::kprobe::KProbeContext;
4*fae6e9adSlinfeng use crate::bpf::helper::BPF_HELPER_FUN_SET;
5*fae6e9adSlinfeng use crate::bpf::prog::BpfProg;
6*fae6e9adSlinfeng use crate::debug::kprobe::args::KprobeInfo;
7*fae6e9adSlinfeng use crate::debug::kprobe::{register_kprobe, unregister_kprobe, LockKprobe};
8*fae6e9adSlinfeng use crate::filesystem::vfs::file::{File, PageCache};
9*fae6e9adSlinfeng use crate::filesystem::vfs::{FilePrivateData, FileSystem, IndexNode};
10*fae6e9adSlinfeng use crate::libs::casting::DowncastArc;
11*fae6e9adSlinfeng use crate::libs::spinlock::SpinLockGuard;
12*fae6e9adSlinfeng use crate::perf::util::PerfProbeArgs;
13*fae6e9adSlinfeng use crate::perf::PerfEventOps;
14*fae6e9adSlinfeng use alloc::boxed::Box;
15*fae6e9adSlinfeng use alloc::string::String;
16*fae6e9adSlinfeng use alloc::sync::Arc;
17*fae6e9adSlinfeng use alloc::vec::Vec;
18*fae6e9adSlinfeng use core::any::Any;
19*fae6e9adSlinfeng use core::fmt::Debug;
20*fae6e9adSlinfeng use kprobe::{CallBackFunc, ProbeArgs};
21*fae6e9adSlinfeng use rbpf::EbpfVmRawOwned;
22*fae6e9adSlinfeng use system_error::SystemError;
23*fae6e9adSlinfeng #[derive(Debug)]
24*fae6e9adSlinfeng pub struct KprobePerfEvent {
25*fae6e9adSlinfeng _args: PerfProbeArgs,
26*fae6e9adSlinfeng kprobe: LockKprobe,
27*fae6e9adSlinfeng }
28*fae6e9adSlinfeng
29*fae6e9adSlinfeng impl Drop for KprobePerfEvent {
drop(&mut self)30*fae6e9adSlinfeng fn drop(&mut self) {
31*fae6e9adSlinfeng unregister_kprobe(self.kprobe.clone());
32*fae6e9adSlinfeng }
33*fae6e9adSlinfeng }
34*fae6e9adSlinfeng
35*fae6e9adSlinfeng impl KprobePerfEvent {
do_set_bpf_prog(&self, prog_file: Arc<File>) -> Result<()>36*fae6e9adSlinfeng pub fn do_set_bpf_prog(&self, prog_file: Arc<File>) -> Result<()> {
37*fae6e9adSlinfeng let file = prog_file
38*fae6e9adSlinfeng .inode()
39*fae6e9adSlinfeng .downcast_arc::<BpfProg>()
40*fae6e9adSlinfeng .ok_or(SystemError::EINVAL)?;
41*fae6e9adSlinfeng let prog_slice = file.insns();
42*fae6e9adSlinfeng let mut vm =
43*fae6e9adSlinfeng EbpfVmRawOwned::new(Some(prog_slice.to_vec())).map_err(|_| SystemError::EINVAL)?;
44*fae6e9adSlinfeng vm.register_helper_set(BPF_HELPER_FUN_SET.get())
45*fae6e9adSlinfeng .map_err(|_| SystemError::EINVAL)?;
46*fae6e9adSlinfeng // create a callback to execute the ebpf prog
47*fae6e9adSlinfeng let callback = Box::new(KprobePerfCallBack::new(file, vm));
48*fae6e9adSlinfeng // update callback for kprobe
49*fae6e9adSlinfeng self.kprobe.write().update_event_callback(callback);
50*fae6e9adSlinfeng Ok(())
51*fae6e9adSlinfeng }
52*fae6e9adSlinfeng }
53*fae6e9adSlinfeng
54*fae6e9adSlinfeng pub struct KprobePerfCallBack {
55*fae6e9adSlinfeng _bpf_prog_file: Arc<BpfProg>,
56*fae6e9adSlinfeng vm: EbpfVmRawOwned,
57*fae6e9adSlinfeng }
58*fae6e9adSlinfeng
59*fae6e9adSlinfeng impl KprobePerfCallBack {
new(bpf_prog_file: Arc<BpfProg>, vm: EbpfVmRawOwned) -> Self60*fae6e9adSlinfeng fn new(bpf_prog_file: Arc<BpfProg>, vm: EbpfVmRawOwned) -> Self {
61*fae6e9adSlinfeng Self {
62*fae6e9adSlinfeng _bpf_prog_file: bpf_prog_file,
63*fae6e9adSlinfeng vm,
64*fae6e9adSlinfeng }
65*fae6e9adSlinfeng }
66*fae6e9adSlinfeng }
67*fae6e9adSlinfeng
68*fae6e9adSlinfeng impl CallBackFunc for KprobePerfCallBack {
call(&self, trap_frame: &dyn ProbeArgs)69*fae6e9adSlinfeng fn call(&self, trap_frame: &dyn ProbeArgs) {
70*fae6e9adSlinfeng let trap_frame = trap_frame.as_any().downcast_ref::<TrapFrame>().unwrap();
71*fae6e9adSlinfeng let pt_regs = KProbeContext::from(trap_frame);
72*fae6e9adSlinfeng let probe_context = unsafe {
73*fae6e9adSlinfeng core::slice::from_raw_parts_mut(
74*fae6e9adSlinfeng &pt_regs as *const KProbeContext as *mut u8,
75*fae6e9adSlinfeng size_of::<KProbeContext>(),
76*fae6e9adSlinfeng )
77*fae6e9adSlinfeng };
78*fae6e9adSlinfeng let _res = self
79*fae6e9adSlinfeng .vm
80*fae6e9adSlinfeng .execute_program(probe_context)
81*fae6e9adSlinfeng .map_err(|_| SystemError::EINVAL);
82*fae6e9adSlinfeng }
83*fae6e9adSlinfeng }
84*fae6e9adSlinfeng
85*fae6e9adSlinfeng impl IndexNode for KprobePerfEvent {
read_at( &self, _offset: usize, _len: usize, _buf: &mut [u8], _data: SpinLockGuard<FilePrivateData>, ) -> Result<usize>86*fae6e9adSlinfeng fn read_at(
87*fae6e9adSlinfeng &self,
88*fae6e9adSlinfeng _offset: usize,
89*fae6e9adSlinfeng _len: usize,
90*fae6e9adSlinfeng _buf: &mut [u8],
91*fae6e9adSlinfeng _data: SpinLockGuard<FilePrivateData>,
92*fae6e9adSlinfeng ) -> Result<usize> {
93*fae6e9adSlinfeng panic!("read_at not implemented for PerfEvent");
94*fae6e9adSlinfeng }
95*fae6e9adSlinfeng
write_at( &self, _offset: usize, _len: usize, _buf: &[u8], _data: SpinLockGuard<FilePrivateData>, ) -> Result<usize>96*fae6e9adSlinfeng fn write_at(
97*fae6e9adSlinfeng &self,
98*fae6e9adSlinfeng _offset: usize,
99*fae6e9adSlinfeng _len: usize,
100*fae6e9adSlinfeng _buf: &[u8],
101*fae6e9adSlinfeng _data: SpinLockGuard<FilePrivateData>,
102*fae6e9adSlinfeng ) -> Result<usize> {
103*fae6e9adSlinfeng panic!("write_at not implemented for PerfEvent");
104*fae6e9adSlinfeng }
105*fae6e9adSlinfeng
fs(&self) -> Arc<dyn FileSystem>106*fae6e9adSlinfeng fn fs(&self) -> Arc<dyn FileSystem> {
107*fae6e9adSlinfeng panic!("fs not implemented for PerfEvent");
108*fae6e9adSlinfeng }
109*fae6e9adSlinfeng
as_any_ref(&self) -> &dyn Any110*fae6e9adSlinfeng fn as_any_ref(&self) -> &dyn Any {
111*fae6e9adSlinfeng self
112*fae6e9adSlinfeng }
113*fae6e9adSlinfeng
list(&self) -> Result<Vec<String>>114*fae6e9adSlinfeng fn list(&self) -> Result<Vec<String>> {
115*fae6e9adSlinfeng Err(SystemError::ENOSYS)
116*fae6e9adSlinfeng }
117*fae6e9adSlinfeng
page_cache(&self) -> Option<Arc<PageCache>>118*fae6e9adSlinfeng fn page_cache(&self) -> Option<Arc<PageCache>> {
119*fae6e9adSlinfeng None
120*fae6e9adSlinfeng }
121*fae6e9adSlinfeng }
122*fae6e9adSlinfeng
123*fae6e9adSlinfeng impl PerfEventOps for KprobePerfEvent {
set_bpf_prog(&self, bpf_prog: Arc<File>) -> Result<()>124*fae6e9adSlinfeng fn set_bpf_prog(&self, bpf_prog: Arc<File>) -> Result<()> {
125*fae6e9adSlinfeng self.do_set_bpf_prog(bpf_prog)
126*fae6e9adSlinfeng }
enable(&self) -> Result<()>127*fae6e9adSlinfeng fn enable(&self) -> Result<()> {
128*fae6e9adSlinfeng self.kprobe.write().enable();
129*fae6e9adSlinfeng Ok(())
130*fae6e9adSlinfeng }
disable(&self) -> Result<()>131*fae6e9adSlinfeng fn disable(&self) -> Result<()> {
132*fae6e9adSlinfeng self.kprobe.write().disable();
133*fae6e9adSlinfeng Ok(())
134*fae6e9adSlinfeng }
135*fae6e9adSlinfeng
readable(&self) -> bool136*fae6e9adSlinfeng fn readable(&self) -> bool {
137*fae6e9adSlinfeng true
138*fae6e9adSlinfeng }
139*fae6e9adSlinfeng }
140*fae6e9adSlinfeng
perf_event_open_kprobe(args: PerfProbeArgs) -> KprobePerfEvent141*fae6e9adSlinfeng pub fn perf_event_open_kprobe(args: PerfProbeArgs) -> KprobePerfEvent {
142*fae6e9adSlinfeng let symbol = args.name.clone();
143*fae6e9adSlinfeng log::info!("create kprobe for symbol: {symbol}");
144*fae6e9adSlinfeng let kprobe_info = KprobeInfo {
145*fae6e9adSlinfeng pre_handler: |_| {},
146*fae6e9adSlinfeng post_handler: |_| {},
147*fae6e9adSlinfeng fault_handler: None,
148*fae6e9adSlinfeng event_callback: None,
149*fae6e9adSlinfeng symbol: Some(symbol),
150*fae6e9adSlinfeng addr: None,
151*fae6e9adSlinfeng offset: 0,
152*fae6e9adSlinfeng enable: false,
153*fae6e9adSlinfeng };
154*fae6e9adSlinfeng let kprobe = register_kprobe(kprobe_info).expect("create kprobe failed");
155*fae6e9adSlinfeng KprobePerfEvent {
156*fae6e9adSlinfeng _args: args,
157*fae6e9adSlinfeng kprobe,
158*fae6e9adSlinfeng }
159*fae6e9adSlinfeng }
160