xref: /DragonOS/kernel/src/perf/kprobe.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
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