Browse Source

feat:Add tracepoint prototype (#1088)

* feat:Add tracepoint prototype

Signed-off-by: Godones <chenlinfeng25@outlook.com>
linfeng 2 ngày trước cách đây
mục cha
commit
50bbcae01a

+ 144 - 11
kernel/Cargo.lock

@@ -212,7 +212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fe05a1a3c09033e9e87f7ba13af35cf2508148d3a97fb6b16475df84207993fa"
 dependencies = [
  "libc",
- "windows",
+ "windows 0.58.0",
 ]
 
 [[package]]
@@ -1498,14 +1498,14 @@ dependencies = [
 
 [[package]]
 name = "static-keys"
-version = "0.6.1"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ae6eb9d5e3c88a62145a3f2edd2e45c296bad8ef3e31b06d654acff70272744"
+checksum = "aa784228d57f9f47a0f5837289ba92296239c2273f146d97b35bbd8538806777"
 dependencies = [
  "clear-cache",
  "libc",
  "mach2",
- "windows",
+ "windows 0.59.0",
 ]
 
 [[package]]
@@ -1972,23 +1972,46 @@ version = "0.58.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
 dependencies = [
- "windows-core",
+ "windows-core 0.58.0",
  "windows-targets 0.52.6",
 ]
 
+[[package]]
+name = "windows"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1"
+dependencies = [
+ "windows-core 0.59.0",
+ "windows-targets 0.53.0",
+]
+
 [[package]]
 name = "windows-core"
 version = "0.58.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
 dependencies = [
- "windows-implement",
- "windows-interface",
- "windows-result",
- "windows-strings",
+ "windows-implement 0.58.0",
+ "windows-interface 0.58.0",
+ "windows-result 0.2.0",
+ "windows-strings 0.1.0",
  "windows-targets 0.52.6",
 ]
 
+[[package]]
+name = "windows-core"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce"
+dependencies = [
+ "windows-implement 0.59.0",
+ "windows-interface 0.59.1",
+ "windows-result 0.3.2",
+ "windows-strings 0.3.1",
+ "windows-targets 0.53.0",
+]
+
 [[package]]
 name = "windows-implement"
 version = "0.58.0"
@@ -2000,6 +2023,17 @@ dependencies = [
  "syn 2.0.100",
 ]
 
+[[package]]
+name = "windows-implement"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+]
+
 [[package]]
 name = "windows-interface"
 version = "0.58.0"
@@ -2011,6 +2045,23 @@ dependencies = [
  "syn 2.0.100",
 ]
 
+[[package]]
+name = "windows-interface"
+version = "0.59.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.100",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
+
 [[package]]
 name = "windows-result"
 version = "0.2.0"
@@ -2020,16 +2071,34 @@ dependencies = [
  "windows-targets 0.52.6",
 ]
 
+[[package]]
+name = "windows-result"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
+dependencies = [
+ "windows-link",
+]
+
 [[package]]
 name = "windows-strings"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
 dependencies = [
- "windows-result",
+ "windows-result 0.2.0",
  "windows-targets 0.52.6",
 ]
 
+[[package]]
+name = "windows-strings"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
+dependencies = [
+ "windows-link",
+]
+
 [[package]]
 name = "windows-sys"
 version = "0.48.0"
@@ -2072,13 +2141,29 @@ dependencies = [
  "windows_aarch64_gnullvm 0.52.6",
  "windows_aarch64_msvc 0.52.6",
  "windows_i686_gnu 0.52.6",
- "windows_i686_gnullvm",
+ "windows_i686_gnullvm 0.52.6",
  "windows_i686_msvc 0.52.6",
  "windows_x86_64_gnu 0.52.6",
  "windows_x86_64_gnullvm 0.52.6",
  "windows_x86_64_msvc 0.52.6",
 ]
 
+[[package]]
+name = "windows-targets"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
+dependencies = [
+ "windows_aarch64_gnullvm 0.53.0",
+ "windows_aarch64_msvc 0.53.0",
+ "windows_i686_gnu 0.53.0",
+ "windows_i686_gnullvm 0.53.0",
+ "windows_i686_msvc 0.53.0",
+ "windows_x86_64_gnu 0.53.0",
+ "windows_x86_64_gnullvm 0.53.0",
+ "windows_x86_64_msvc 0.53.0",
+]
+
 [[package]]
 name = "windows_aarch64_gnullvm"
 version = "0.48.5"
@@ -2091,6 +2176,12 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
 
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
+
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.48.5"
@@ -2103,6 +2194,12 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
 
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
+
 [[package]]
 name = "windows_i686_gnu"
 version = "0.48.5"
@@ -2115,12 +2212,24 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
 
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
+
 [[package]]
 name = "windows_i686_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
 
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
+
 [[package]]
 name = "windows_i686_msvc"
 version = "0.48.5"
@@ -2133,6 +2242,12 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
 
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
+
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.48.5"
@@ -2145,6 +2260,12 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
+
 [[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.48.5"
@@ -2157,6 +2278,12 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
 
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
+
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.48.5"
@@ -2169,6 +2296,12 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
+
 [[package]]
 name = "winnow"
 version = "0.7.4"

+ 1 - 1
kernel/Cargo.toml

@@ -75,7 +75,7 @@ lru = "0.12.3"
 rbpf = { path = "crates/rbpf" }
 printf-compat = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/printf-compat", rev = "5f5c9cc363", default-features = false }
 
-static-keys = "=0.6.1"
+static-keys = { version = "=0.7" }
 
 defer = "0.2.1"
 cfg-if = { version = "1.0.0" }

+ 10 - 0
kernel/src/arch/loongarch64/link.ld

@@ -66,6 +66,16 @@ SECTIONS
 	}
 
 	. = ALIGN(32768);
+	
+	trace_point_start_pa = .;
+	.tracepoint (trace_point_start_pa): AT(trace_point_start_pa - KERNEL_VMA)
+    {
+        _tracepoint = .;
+        *(.tracepoint)
+        *(.tracepoint.*)
+        _etracepoint = .;
+    }
+    . = ALIGN(32768);
 
 	init_proc_union_start_pa = .;
 	.data.init_proc_union (init_proc_union_start_pa):

+ 10 - 0
kernel/src/arch/riscv64/link.ld

@@ -68,6 +68,16 @@ SECTIONS
 
 	. = ALIGN(32768);
 
+	trace_point_start_pa = .;
+	.tracepoint (trace_point_start_pa): AT(trace_point_start_pa - KERNEL_VMA)
+    {
+        _tracepoint = .;
+        *(.tracepoint)
+        *(.tracepoint.*)
+        _etracepoint = .;
+    }
+    . = ALIGN(32768);
+
 	init_proc_union_start_pa = .;
 	.data.init_proc_union (init_proc_union_start_pa): AT(init_proc_union_start_pa - KERNEL_VMA)
 	 { *(.data.init_proc_union) }

+ 10 - 0
kernel/src/arch/x86_64/link.lds

@@ -67,6 +67,16 @@ SECTIONS
 
 	. = ALIGN(32768);
 
+	trace_point_start_pa = .;
+	.tracepoint (trace_point_start_pa): AT(trace_point_start_pa - KERNEL_VMA)
+    {
+        _tracepoint = .;
+        *(.tracepoint)
+        *(.tracepoint.*)
+        _etracepoint = .;
+    }
+    . = ALIGN(32768);
+
 	init_proc_union_start_pa = .;
 	.data.init_proc_union (init_proc_union_start_pa): AT(init_proc_union_start_pa - KERNEL_VMA)
 	 { *(.data.init_proc_union) }

+ 2 - 1
kernel/src/debug/.gitignore

@@ -1,2 +1,3 @@
 gen_kallsyms
-kallsyms.S
+kallsyms.S
+kallsyms

+ 2 - 0
kernel/src/debug/mod.rs

@@ -2,4 +2,6 @@ pub mod jump_label;
 pub mod klog;
 pub mod kprobe;
 pub mod panic;
+pub mod sysfs;
 pub mod traceback;
+pub mod tracing;

+ 28 - 0
kernel/src/debug/sysfs/mod.rs

@@ -0,0 +1,28 @@
+use crate::driver::base::kset::KSet;
+use crate::init::initcall::INITCALL_POSTCORE;
+use crate::misc::ksysfs::sys_kernel_kset;
+use alloc::string::ToString;
+use alloc::sync::Arc;
+use system_error::SystemError;
+use unified_init::macros::unified_init;
+
+/// `/sys/kernel/debug`的kset
+static mut SYS_KERNEL_DEBUG_KSET_INSTANCE: Option<Arc<KSet>> = None;
+
+/// 初始化debug模块在sysfs中的目录
+#[unified_init(INITCALL_POSTCORE)]
+fn debugfs_init() -> Result<(), SystemError> {
+    let debug_kset = KSet::new("debug".to_string());
+    debug_kset
+        .register(Some(sys_kernel_kset()))
+        .expect("register debug kset failed");
+    unsafe {
+        SYS_KERNEL_DEBUG_KSET_INSTANCE = Some(debug_kset);
+    }
+    super::tracing::init_debugfs_tracing()?;
+    return Ok(());
+}
+
+pub fn debugfs_kset() -> Arc<KSet> {
+    unsafe { SYS_KERNEL_DEBUG_KSET_INSTANCE.clone().unwrap() }
+}

+ 239 - 0
kernel/src/debug/tracing/events.rs

@@ -0,0 +1,239 @@
+use crate::debug::tracing::tracepoint::{CommonTracePointMeta, TracePoint};
+use crate::debug::tracing::TracingDirCallBack;
+use crate::filesystem::kernfs::callback::{KernCallbackData, KernFSCallback, KernInodePrivateData};
+use crate::filesystem::kernfs::KernFSInode;
+use crate::filesystem::vfs::syscall::ModeType;
+use crate::filesystem::vfs::PollStatus;
+use crate::libs::spinlock::SpinLock;
+use alloc::boxed::Box;
+use alloc::collections::BTreeMap;
+use alloc::string::{String, ToString};
+use alloc::sync::Arc;
+use system_error::SystemError;
+
+#[derive(Debug)]
+pub struct TracingEventsManager {
+    root: Arc<KernFSInode>,
+    subsystems: SpinLock<BTreeMap<String, Arc<EventsSubsystem>>>,
+}
+
+impl TracingEventsManager {
+    pub fn new(root: Arc<KernFSInode>) -> Self {
+        Self {
+            root,
+            subsystems: SpinLock::new(BTreeMap::new()),
+        }
+    }
+
+    /// Create a subsystem by name
+    ///
+    /// If the subsystem already exists, return the existing subsystem.
+    pub fn create_subsystem(
+        &self,
+        subsystem_name: &str,
+    ) -> Result<Arc<EventsSubsystem>, SystemError> {
+        if self.subsystems.lock().contains_key(subsystem_name) {
+            return Ok(self.get_subsystem(subsystem_name).unwrap());
+        }
+        let dir = self.root.add_dir(
+            subsystem_name.to_string(),
+            ModeType::from_bits_truncate(0o755),
+            None,
+            Some(&TracingDirCallBack),
+        )?;
+        let subsystem = Arc::new(EventsSubsystem::new(dir));
+        self.subsystems
+            .lock()
+            .insert(subsystem_name.to_string(), subsystem.clone());
+        Ok(subsystem)
+    }
+
+    /// Get the subsystem by name
+    pub fn get_subsystem(&self, subsystem_name: &str) -> Option<Arc<EventsSubsystem>> {
+        self.subsystems.lock().get(subsystem_name).cloned()
+    }
+}
+
+#[derive(Debug)]
+pub struct EventsSubsystem {
+    root: Arc<KernFSInode>,
+    events: SpinLock<BTreeMap<String, Arc<EventInfo>>>,
+}
+
+impl EventsSubsystem {
+    pub fn new(root: Arc<KernFSInode>) -> Self {
+        Self {
+            root,
+            events: SpinLock::new(BTreeMap::new()),
+        }
+    }
+
+    /// Insert a new event into the subsystem
+    pub fn insert_event(
+        &self,
+        event_name: &str,
+        event_info: Arc<EventInfo>,
+    ) -> Result<(), SystemError> {
+        self.events
+            .lock()
+            .insert(event_name.to_string(), event_info);
+        Ok(())
+    }
+
+    /// Get the event by name
+    #[allow(unused)]
+    pub fn get_event(&self, event_name: &str) -> Option<Arc<EventInfo>> {
+        self.events.lock().get(event_name).cloned()
+    }
+
+    /// Get the root inode of the subsystem
+    pub fn root(&self) -> Arc<KernFSInode> {
+        self.root.clone()
+    }
+}
+
+#[derive(Debug)]
+pub struct EventInfo {
+    #[allow(unused)]
+    enable: Arc<KernFSInode>,
+    // filter: Arc<KernFSInode>,
+    // trigger: Arc<KernFSInode>,
+}
+
+impl EventInfo {
+    pub fn new(tracepoint: &'static TracePoint, subsystem: Arc<KernFSInode>) -> Arc<Self> {
+        let trace_dir = subsystem
+            .add_dir(
+                tracepoint.name().to_string(),
+                ModeType::from_bits_truncate(0o755),
+                None,
+                Some(&TracingDirCallBack),
+            )
+            .expect("add tracepoint dir failed");
+        let enable_inode = trace_dir
+            .add_file(
+                "enable".to_string(),
+                ModeType::from_bits_truncate(0o644),
+                None,
+                Some(KernInodePrivateData::DebugFS(tracepoint)),
+                Some(&EnableCallBack),
+            )
+            .expect("add enable file failed");
+
+        Arc::new(Self {
+            enable: enable_inode,
+        })
+    }
+}
+
+impl Drop for EventInfo {
+    fn drop(&mut self) {}
+}
+
+#[derive(Debug)]
+struct EnableCallBack;
+
+impl KernFSCallback for EnableCallBack {
+    fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> {
+        Ok(())
+    }
+
+    fn read(
+        &self,
+        data: KernCallbackData,
+        buf: &mut [u8],
+        offset: usize,
+    ) -> Result<usize, SystemError> {
+        if offset > 0 {
+            return Ok(0);
+        }
+        let pri_data = data.private_data();
+        match pri_data {
+            Some(pri_data) => {
+                let tracepoint = pri_data.debugfs_tracepoint().ok_or(SystemError::EINVAL)?;
+                let buf_value = if tracepoint.is_enabled() { b"1" } else { b"0" };
+                let len = buf.len().min(buf_value.len());
+                buf[..len].copy_from_slice(&buf_value[..len]);
+                Ok(len)
+            }
+            None => {
+                return Err(SystemError::EINVAL);
+            }
+        }
+    }
+
+    fn write(
+        &self,
+        data: KernCallbackData,
+        buf: &[u8],
+        _offset: usize,
+    ) -> Result<usize, SystemError> {
+        let pri_data = data.private_data();
+        match pri_data {
+            Some(pri_data) => {
+                let tracepoint = pri_data.debugfs_tracepoint().ok_or(SystemError::EINVAL)?;
+                let value = core::str::from_utf8(buf)
+                    .map_err(|_| SystemError::EINVAL)?
+                    .trim();
+                match value {
+                    "0" => {
+                        tracepoint.disable();
+                    }
+                    "1" => {
+                        tracepoint.enable();
+                    }
+                    _ => {
+                        log::info!("EnableCallBack invalid value: {}", value);
+                        return Err(SystemError::EINVAL);
+                    }
+                }
+                Ok(buf.len())
+            }
+            None => {
+                return Err(SystemError::EINVAL);
+            }
+        }
+    }
+
+    fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> {
+        Err(SystemError::ENOSYS)
+    }
+}
+
+static mut TRACING_EVENTS_MANAGER: Option<TracingEventsManager> = None;
+
+/// Initialize the tracing events
+pub fn init_events(events_root: Arc<KernFSInode>) -> Result<(), SystemError> {
+    let events_manager = TracingEventsManager::new(events_root);
+    let tracepoint_data_start = _tracepoint as usize as *const CommonTracePointMeta;
+    let tracepoint_data_end = _etracepoint as usize as *const CommonTracePointMeta;
+    let tracepoint_data_len = (tracepoint_data_end as usize - tracepoint_data_start as usize)
+        / size_of::<CommonTracePointMeta>();
+    let tracepoint_data =
+        unsafe { core::slice::from_raw_parts(tracepoint_data_start, tracepoint_data_len) };
+    for tracepoint_meta in tracepoint_data {
+        let tracepoint = tracepoint_meta.trace_point;
+        tracepoint.register(tracepoint_meta.print_func, Box::new(()));
+        log::info!(
+            "tracepoint name: {}, module path: {}",
+            tracepoint.name(),
+            tracepoint.module_path()
+        );
+        // kernel::{subsystem}::
+        let mut subsys_name = tracepoint.module_path().split("::");
+        let subsys_name = subsys_name.nth(1).ok_or(SystemError::EINVAL)?;
+        let subsys = events_manager.create_subsystem(subsys_name)?;
+        let event_info = EventInfo::new(tracepoint, subsys.root());
+        subsys.insert_event(tracepoint.name(), event_info)?;
+    }
+
+    unsafe {
+        TRACING_EVENTS_MANAGER = Some(events_manager);
+    }
+
+    Ok(())
+}
+extern "C" {
+    fn _tracepoint();
+    fn _etracepoint();
+}

+ 97 - 0
kernel/src/debug/tracing/mod.rs

@@ -0,0 +1,97 @@
+mod events;
+pub mod trace_pipe;
+pub mod tracepoint;
+
+use crate::debug::sysfs::debugfs_kset;
+use crate::debug::tracing::trace_pipe::TRACE_PIPE_MAX_RECORD;
+use crate::driver::base::kobject::KObject;
+use crate::filesystem::kernfs::callback::{KernCallbackData, KernFSCallback, KernInodePrivateData};
+use crate::filesystem::kernfs::KernFSInode;
+use crate::filesystem::vfs::syscall::ModeType;
+use crate::filesystem::vfs::PollStatus;
+use alloc::string::ToString;
+use alloc::sync::Arc;
+use system_error::SystemError;
+use tracepoint::TracePoint;
+
+static mut TRACING_ROOT_INODE: Option<Arc<KernFSInode>> = None;
+
+#[allow(unused)]
+fn tracing_root_inode() -> Arc<KernFSInode> {
+    unsafe { TRACING_ROOT_INODE.clone().unwrap() }
+}
+
+/// Initialize the debugfs tracing directory
+pub fn init_debugfs_tracing() -> Result<(), SystemError> {
+    let debugfs = debugfs_kset();
+    let root_dir = debugfs.inode().ok_or(SystemError::ENOENT)?;
+    let tracing_root = root_dir.add_dir(
+        "tracing".to_string(),
+        ModeType::from_bits_truncate(0o555),
+        None,
+        Some(&TracingDirCallBack),
+    )?;
+    let events_root = tracing_root.add_dir(
+        "events".to_string(),
+        ModeType::from_bits_truncate(0o755),
+        None,
+        Some(&TracingDirCallBack),
+    )?;
+
+    tracing_root.add_file(
+        "trace_pipe".to_string(),
+        ModeType::from_bits_truncate(0o444),
+        Some(TRACE_PIPE_MAX_RECORD),
+        None,
+        Some(&trace_pipe::TracePipeCallBack),
+    )?;
+
+    trace_pipe::init_trace_pipe();
+
+    events::init_events(events_root)?;
+
+    unsafe {
+        TRACING_ROOT_INODE = Some(tracing_root);
+    }
+    Ok(())
+}
+
+#[derive(Debug)]
+pub struct TracingDirCallBack;
+
+impl KernFSCallback for TracingDirCallBack {
+    fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> {
+        Ok(())
+    }
+
+    fn read(
+        &self,
+        _data: KernCallbackData,
+        _buf: &mut [u8],
+        _offset: usize,
+    ) -> Result<usize, SystemError> {
+        Err(SystemError::EISDIR)
+    }
+
+    fn write(
+        &self,
+        _data: KernCallbackData,
+        _buf: &[u8],
+        _offset: usize,
+    ) -> Result<usize, SystemError> {
+        Err(SystemError::EISDIR)
+    }
+
+    fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> {
+        Err(SystemError::EISDIR)
+    }
+}
+
+impl KernInodePrivateData {
+    pub fn debugfs_tracepoint(&self) -> Option<&'static TracePoint> {
+        return match self {
+            KernInodePrivateData::DebugFS(tracepoint) => Some(tracepoint),
+            _ => None,
+        };
+    }
+}

+ 123 - 0
kernel/src/debug/tracing/trace_pipe.rs

@@ -0,0 +1,123 @@
+use crate::filesystem::kernfs::callback::{KernCallbackData, KernFSCallback};
+use crate::filesystem::vfs::PollStatus;
+use crate::libs::spinlock::SpinLock;
+use alloc::string::String;
+use alloc::vec::Vec;
+use core::fmt::Debug;
+use system_error::SystemError;
+
+static mut TRACE_PIPE: Option<TracePipe> = None;
+
+pub const TRACE_PIPE_MAX_RECORD: usize = 4096;
+
+pub fn init_trace_pipe() {
+    unsafe {
+        TRACE_PIPE = Some(TracePipe::new(TRACE_PIPE_MAX_RECORD));
+    }
+}
+
+pub fn trace_pipe() -> &'static TracePipe {
+    unsafe { TRACE_PIPE.as_ref().unwrap() }
+}
+
+/// Push a record to trace pipe
+pub fn trace_pipe_push_record(record: String) {
+    trace_pipe().push_record(record);
+}
+
+pub struct TracePipe {
+    buf: SpinLock<TracePipeBuf>,
+}
+
+struct TracePipeBuf {
+    size: usize,
+    max_record: usize,
+    buf: Vec<String>,
+}
+
+impl TracePipeBuf {
+    pub const fn new(max_record: usize) -> Self {
+        Self {
+            max_record,
+            size: 0,
+            buf: Vec::new(),
+        }
+    }
+
+    pub fn push_str(&mut self, record: String) {
+        let record_size = record.len();
+        if self.size + record_size > self.max_record {
+            let mut i = 0;
+            while i < record_size {
+                let t = self.buf.pop().unwrap();
+                self.size -= t.len();
+                i += t.len();
+            }
+        }
+        self.buf.push(record);
+        self.size += record_size;
+    }
+
+    pub fn read_at(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
+        if offset == self.size {
+            return Ok(0);
+        }
+        if buf.len() < self.size {
+            return Err(SystemError::EINVAL);
+        }
+        let mut count = 0;
+        for line in self.buf.iter() {
+            let line = line.as_bytes();
+            buf[count..count + line.len()].copy_from_slice(line);
+            count += line.len();
+        }
+        Ok(count)
+    }
+}
+
+impl TracePipe {
+    pub const fn new(max_record: usize) -> Self {
+        Self {
+            buf: SpinLock::new(TracePipeBuf::new(max_record)),
+        }
+    }
+    pub fn push_record(&self, record: String) {
+        self.buf.lock().push_str(record);
+    }
+
+    pub fn read_at(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
+        self.buf.lock().read_at(buf, offset)
+    }
+}
+
+#[derive(Debug)]
+pub struct TracePipeCallBack;
+
+impl KernFSCallback for TracePipeCallBack {
+    fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> {
+        Ok(())
+    }
+
+    fn read(
+        &self,
+        _data: KernCallbackData,
+        buf: &mut [u8],
+        offset: usize,
+    ) -> Result<usize, SystemError> {
+        let trace_pipe = trace_pipe();
+        trace_pipe.read_at(buf, offset)
+    }
+
+    fn write(
+        &self,
+        _data: KernCallbackData,
+        _buf: &[u8],
+        _offset: usize,
+    ) -> Result<usize, SystemError> {
+        Err(SystemError::EPERM)
+    }
+
+    fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> {
+        Ok(PollStatus::READ)
+    }
+}

+ 187 - 0
kernel/src/debug/tracing/tracepoint.rs

@@ -0,0 +1,187 @@
+use crate::libs::spinlock::{SpinLock, SpinLockGuard};
+use alloc::boxed::Box;
+use alloc::collections::BTreeMap;
+use core::any::Any;
+use core::fmt::Debug;
+use static_keys::StaticFalseKey;
+
+pub struct TracePoint {
+    name: &'static str,
+    module_path: &'static str,
+    key: &'static StaticFalseKey,
+    register: Option<fn()>,
+    unregister: Option<fn()>,
+    callback: SpinLock<BTreeMap<usize, TracePointFunc>>,
+}
+
+impl Debug for TracePoint {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        f.debug_struct("TracePoint")
+            .field("name", &self.name)
+            .finish()
+    }
+}
+
+#[derive(Debug)]
+#[repr(C)]
+pub struct CommonTracePointMeta {
+    pub trace_point: &'static TracePoint,
+    pub print_func: fn(),
+}
+
+#[derive(Debug)]
+pub struct TracePointFunc {
+    pub func: fn(),
+    pub data: Box<dyn Any + Send + Sync>,
+}
+
+impl TracePoint {
+    pub const fn new(
+        key: &'static StaticFalseKey,
+        name: &'static str,
+        module_path: &'static str,
+        register: Option<fn()>,
+        unregister: Option<fn()>,
+    ) -> Self {
+        Self {
+            name,
+            module_path,
+            key,
+            register,
+            unregister,
+            callback: SpinLock::new(BTreeMap::new()),
+        }
+    }
+
+    pub fn name(&self) -> &'static str {
+        self.name
+    }
+
+    pub fn module_path(&self) -> &'static str {
+        self.module_path
+    }
+
+    /// Register a callback function to the tracepoint
+    pub fn register(&self, func: fn(), data: Box<dyn Any + Sync + Send>) {
+        let trace_point_func = TracePointFunc { func, data };
+        let mut funcs = self.callback.lock();
+        if let Some(register) = self.register {
+            register();
+        }
+        let ptr = func as usize;
+        funcs.entry(ptr).or_insert(trace_point_func);
+    }
+
+    /// Unregister a callback function from the tracepoint
+    pub fn unregister(&self, func: fn()) {
+        let mut funcs = self.callback.lock();
+        if let Some(unregister) = self.unregister {
+            unregister();
+        }
+        let func_ptr = func as usize;
+        funcs.remove(&func_ptr);
+    }
+
+    /// Get the callback list
+    pub fn callback_list(&self) -> SpinLockGuard<BTreeMap<usize, TracePointFunc>> {
+        self.callback.lock()
+    }
+
+    /// Enable the tracepoint
+    pub fn enable(&self) {
+        unsafe {
+            self.key.enable();
+        }
+    }
+
+    /// Disable the tracepoint
+    pub fn disable(&self) {
+        unsafe {
+            self.key.disable();
+        }
+    }
+
+    /// Check if the tracepoint is enabled
+    pub fn is_enabled(&self) -> bool {
+        self.key.is_enabled()
+    }
+}
+
+/// Define a tracepoint
+///
+/// User should call register_trace_\$name to register a callback function to the tracepoint and
+/// call trace_\$name to trigger the callback function
+#[macro_export]
+macro_rules! define_trace_point {
+    ($name:ident $(,$arg:ident:$arg_type:ty),*) => {
+        paste::paste!{
+            static_keys::define_static_key_false!([<__ $name _KEY>]);
+            #[allow(non_upper_case_globals)]
+            #[used]
+            static [<__ $name>]: $crate::debug::tracing::tracepoint::TracePoint = $crate::debug::tracing::tracepoint::TracePoint::new(&[<__ $name _KEY>],stringify!($name), module_path!(),None,None);
+
+            #[inline(always)]
+            #[allow(non_snake_case)]
+            pub fn [<TRACE_ $name>]( $($arg:$arg_type),* ){
+
+                if static_keys::static_branch_unlikely!([<__ $name _KEY>]){
+                    let mut funcs = [<__ $name>].callback_list();
+                    for trace_func in funcs.values_mut(){
+                        let func = trace_func.func;
+                        let data = trace_func.data.as_mut();
+                        let func = unsafe{core::mem::transmute::<fn(),fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*)>(func)};
+                        func(data $(,$arg)*);
+                    }
+                }
+
+            }
+
+            #[allow(unused,non_snake_case)]
+            pub fn [<register_trace_ $name>](func:fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),data:alloc::boxed::Box<dyn core::any::Any+Send+Sync>){
+                let func = unsafe{core::mem::transmute::<fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),fn()>(func)};
+                [<__ $name>].register(func,data);
+            }
+
+            #[allow(unused,non_snake_case)]
+            pub fn [<unregister_trace_ $name>](func:fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*)){
+                let func = unsafe{core::mem::transmute::<fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),fn()>(func)};
+                [<__ $name>].unregister(func);
+            }
+
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! define_event_trace{
+    ($name:ident,
+        ($($arg:ident:$arg_type:ty),*),
+        $fmt:expr) =>{
+        define_trace_point!($name $(,$arg:$arg_type),*);
+        paste::paste!{
+            #[derive(Debug)]
+            #[repr(C)]
+            #[allow(non_snake_case)]
+
+            struct [<__ $name _TracePointMeta>]{
+                trace_point: &'static $crate::debug::tracing::tracepoint::TracePoint,
+                print_func: fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),
+            }
+             #[allow(non_upper_case_globals)]
+             #[link_section = ".tracepoint"]
+             #[used]
+            static [<__ $name _meta>]: [<__ $name _TracePointMeta>] = [<__ $name _TracePointMeta>]{
+                trace_point:&[<__ $name>],
+                print_func:[<TRACE_PRINT_ $name>],
+            };
+            #[allow(non_snake_case)]
+            pub fn [<TRACE_PRINT_ $name>](_data:&mut (dyn core::any::Any+Send+Sync),$($arg:$arg_type),* ){
+                 let time = $crate::time::Instant::now();
+                 let cpu_id = $crate::arch::cpu::current_cpu_id().data();
+                 let current_pid = $crate::process::ProcessManager::current_pcb().pid().data();
+                 let format = format!("[{}][{}][{}] {}\n",time,cpu_id,current_pid,$fmt);
+                 $crate::debug::tracing::trace_pipe::trace_pipe_push_record(format);
+            }
+        }
+    };
+}

+ 11 - 12
kernel/src/filesystem/kernfs/callback.rs

@@ -1,3 +1,5 @@
+use super::KernFSInode;
+use crate::debug::tracing::tracepoint::TracePoint;
 use crate::{
     filesystem::{sysfs::SysFSKernPrivateData, vfs::PollStatus},
     libs::spinlock::SpinLockGuard,
@@ -6,8 +8,6 @@ use alloc::sync::Arc;
 use core::fmt::Debug;
 use system_error::SystemError;
 
-use super::KernFSInode;
-
 /// KernFS文件的回调接口
 ///
 /// 当用户态程序打开、读取、写入、关闭文件时,kernfs会调用相应的回调函数。
@@ -86,24 +86,23 @@ impl<'a> KernCallbackData<'a> {
 #[derive(Debug)]
 pub enum KernInodePrivateData {
     SysFS(SysFSKernPrivateData),
+    DebugFS(&'static TracePoint),
 }
 
 impl KernInodePrivateData {
     #[inline(always)]
     pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
-        match self {
-            KernInodePrivateData::SysFS(private_data) => {
-                return private_data.callback_read(buf, offset);
-            }
-        }
+        return match self {
+            KernInodePrivateData::SysFS(private_data) => private_data.callback_read(buf, offset),
+            _ => Err(SystemError::ENOSYS),
+        };
     }
 
     #[inline(always)]
     pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result<usize, SystemError> {
-        match self {
-            KernInodePrivateData::SysFS(private_data) => {
-                return private_data.callback_write(buf, offset);
-            }
-        }
+        return match self {
+            KernInodePrivateData::SysFS(private_data) => private_data.callback_write(buf, offset),
+            _ => Err(SystemError::ENOSYS),
+        };
     }
 }

+ 5 - 1
kernel/src/filesystem/vfs/core.rs

@@ -5,6 +5,7 @@ use log::{error, info};
 use system_error::SystemError;
 
 use crate::{
+    define_event_trace, define_trace_point,
     driver::base::block::{gendisk::GenDisk, manager::block_dev_manager},
     filesystem::{
         devfs::devfs_init,
@@ -155,7 +156,7 @@ pub fn mount_root_fs() -> Result<(), SystemError> {
     let fatfs: Arc<FATFileSystem> = fatfs.unwrap();
     let r = migrate_virtual_filesystem(fatfs);
     if r.is_err() {
-        error!("Failed to migrate virtual filesystem to FAT32!");
+        error!("Failed to migrate virtual filesyst  em to FAT32!");
         loop {
             spin_loop();
         }
@@ -165,12 +166,15 @@ pub fn mount_root_fs() -> Result<(), SystemError> {
     return Ok(());
 }
 
+define_event_trace!(DO_MKDIR_AT,(path:&str,mode:FileMode),
+    format_args!("mkdir at {} with mode {:?}",path, mode));
 /// @brief 创建文件/文件夹
 pub fn do_mkdir_at(
     dirfd: i32,
     path: &str,
     mode: FileMode,
 ) -> Result<Arc<dyn IndexNode>, SystemError> {
+    TRACE_DO_MKDIR_AT(path, mode);
     // debug!("Call do mkdir at");
     let (mut current_inode, path) =
         user_path_at(&ProcessManager::current_pcb(), dirfd, path.trim())?;