11mod bpf;
22mod kprobe;
3+ mod tracepoint;
34
4- use alloc:: { boxed:: Box , sync:: Arc } ;
5+ use alloc:: {
6+ boxed:: Box ,
7+ sync:: { Arc , Weak } ,
8+ } ;
59use core:: { any:: Any , ffi:: c_void, fmt:: Debug } ;
610
711use axerrno:: { AxError , AxResult } ;
812use axio:: Pollable ;
13+ use hashbrown:: HashMap ;
914use kbpf_basic:: {
1015 linux_bpf:: { perf_event_attr, perf_type_id} ,
1116 perf:: { PerfEventIoc , PerfProbeArgs } ,
1217} ;
1318use kspin:: { SpinNoPreempt , SpinNoPreemptGuard } ;
19+ use lazyinit:: LazyInit ;
1420
1521use crate :: {
1622 bpf:: tansform:: EbpfKernelAuxiliary ,
1723 file:: { FileLike , Kstat , add_file_like, get_file_like} ,
18- perf:: { bpf:: BpfPerfEventWrapper , kprobe :: KprobePerfEvent } ,
24+ perf:: bpf:: BpfPerfEventWrapper ,
1925} ;
2026
2127pub trait PerfEventOps : Pollable + Send + Sync + Debug {
@@ -26,7 +32,9 @@ pub trait PerfEventOps: Pollable + Send + Sync + Debug {
2632 fn custom_mmap ( & self ) -> bool {
2733 false
2834 }
29-
35+ fn set_bpf_prog ( & mut self , _bpf_prog : Arc < dyn FileLike > ) -> AxResult < ( ) > {
36+ Err ( AxError :: OperationNotSupported )
37+ }
3038 fn mmap (
3139 & mut self ,
3240 _aspace : & mut axmm:: AddrSpace ,
@@ -104,11 +112,7 @@ impl FileLike for PerfEvent {
104112 let file = get_file_like ( bpf_prog_fd as _ ) ?;
105113
106114 let mut event = self . event . lock ( ) ;
107- let kprobe_event = event
108- . as_any_mut ( )
109- . downcast_mut :: < KprobePerfEvent > ( )
110- . ok_or ( AxError :: InvalidInput ) ?;
111- kprobe_event. set_bpf_prog ( file) ?;
115+ event. set_bpf_prog ( file) ?;
112116 }
113117 }
114118 Ok ( 0 )
@@ -143,7 +147,7 @@ pub fn perf_event_open(
143147 let args =
144148 PerfProbeArgs :: try_from_perf_attr :: < EbpfKernelAuxiliary > ( attr, pid, cpu, group_fd, flags)
145149 . unwrap ( ) ;
146- axlog:: warn !( "perf_event_process: {:#?}" , args) ;
150+ axlog:: info !( "perf_event_process: {:#?}" , args) ;
147151 let event: Box < dyn PerfEventOps > = match args. type_ {
148152 // Kprobe
149153 // See /sys/bus/event_source/devices/kprobe/type
@@ -155,21 +159,49 @@ pub fn perf_event_open(
155159 let bpf_event = bpf:: perf_event_open_bpf ( args) ;
156160 Box :: new ( bpf_event)
157161 }
162+ perf_type_id:: PERF_TYPE_TRACEPOINT => {
163+ let tracepoint_event = tracepoint:: perf_event_open_tracepoint ( args) ?;
164+ Box :: new ( tracepoint_event)
165+ }
158166 _ => {
159167 unimplemented ! ( "perf_event_process: unknown type: {:?}" , args) ;
160168 }
161169 } ;
162- let event = Arc :: new ( PerfEvent :: new ( event) ) ;
163- let fd = add_file_like ( event, false ) . map ( |fd| fd as _ ) ;
164- fd
170+ let event = Arc :: new ( PerfEvent :: new ( event) ) as Arc < dyn FileLike > ;
171+ let fd = add_file_like ( event. clone ( ) , false ) . map ( |fd| fd as _ ) ?;
172+
173+ PERF_FILE
174+ . get ( )
175+ . unwrap ( )
176+ . lock ( )
177+ . insert ( fd, Arc :: downgrade ( & event) ) ;
178+
179+ axlog:: info!( "perf_event_open: fd: {:?}" , fd) ;
180+ Ok ( fd as _ )
181+ }
182+
183+ static PERF_FILE : LazyInit < SpinNoPreempt < HashMap < usize , Weak < dyn FileLike > > > > = LazyInit :: new ( ) ;
184+
185+ pub fn perf_event_init ( ) {
186+ PERF_FILE . init_once ( SpinNoPreempt :: new ( HashMap :: new ( ) ) ) ;
165187}
166188
167189pub fn perf_event_output ( _ctx : * mut c_void , fd : usize , _flags : u32 , data : & [ u8 ] ) -> AxResult < ( ) > {
168- // axlog::error!("perf_event_output: fd: {}, data: {:?}", fd, data.len());
169- let file = get_file_like ( fd as _ ) ?;
190+ let mut perf_file_map = PERF_FILE . get ( ) . unwrap ( ) . lock ( ) ;
191+ let perf_file_weak = perf_file_map. get ( & fd) . ok_or ( AxError :: NotFound ) ?;
192+
193+ let Some ( file) = perf_file_weak. upgrade ( ) else {
194+ // The file has been dropped, remove the weak reference from the map
195+ perf_file_map. remove ( & fd) ;
196+ return Err ( AxError :: NotFound ) ;
197+ } ;
198+
170199 let bpf_event_file = file. into_any ( ) . downcast :: < PerfEvent > ( ) . unwrap ( ) ;
171200 let mut event = bpf_event_file. event ( ) ;
172- let event = event. as_any_mut ( ) . downcast_mut :: < BpfPerfEventWrapper > ( ) . unwrap ( ) ;
201+ let event = event
202+ . as_any_mut ( )
203+ . downcast_mut :: < BpfPerfEventWrapper > ( )
204+ . unwrap ( ) ;
173205 event. write_event ( data) . unwrap ( ) ;
174206 Ok ( ( ) )
175207}
0 commit comments