Browse Source

把irqdesc添加到sysfs (#525)

* 把irqdesc添加到sysfs
LoGin 1 year ago
parent
commit
196b75dc17

+ 7 - 4
kernel/src/driver/acpi/sysfs.rs

@@ -4,7 +4,10 @@ use crate::{
         base::{kobject::KObject, kset::KSet},
     },
     filesystem::{
-        sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, BinAttribute, SysFSOpsSupport},
+        sysfs::{
+            file::sysfs_emit_str, sysfs_instance, Attribute, BinAttribute, SysFSOpsSupport,
+            SYSFS_ATTR_MODE_RO,
+        },
         vfs::syscall::ModeType,
     },
     libs::rwlock::RwLock,
@@ -131,11 +134,11 @@ impl Attribute for AttrForceRemove {
     }
 
     fn mode(&self) -> ModeType {
-        return ModeType::from_bits_truncate(0o444);
+        SYSFS_ATTR_MODE_RO
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        return SysFSOpsSupport::SHOW;
+        return SysFSOpsSupport::ATTR_SHOW;
     }
 
     fn show(&self, _kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
@@ -224,7 +227,7 @@ impl Attribute for AttrAcpiTable {
 
 impl BinAttribute for AttrAcpiTable {
     fn support_battr(&self) -> SysFSOpsSupport {
-        return SysFSOpsSupport::READ;
+        return SysFSOpsSupport::BATTR_READ;
     }
     fn write(
         &self,

+ 8 - 8
kernel/src/driver/base/device/bus.rs

@@ -12,7 +12,7 @@ use crate::{
     filesystem::{
         sysfs::{
             file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps,
-            SysFSOpsSupport,
+            SysFSOpsSupport, SYSFS_ATTR_MODE_RW, SYSFS_ATTR_MODE_WO,
         },
         vfs::syscall::ModeType,
     },
@@ -598,7 +598,7 @@ impl Attribute for BusAttrDriversProbe {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        return SysFSOpsSupport::STORE;
+        return SysFSOpsSupport::ATTR_STORE;
     }
 
     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/bus.c?r=&mo=5649&fi=241#241
@@ -628,7 +628,7 @@ struct BusAttrDriversAutoprobe;
 
 impl Attribute for BusAttrDriversAutoprobe {
     fn mode(&self) -> ModeType {
-        return ModeType::from_bits_truncate(0o644);
+        SYSFS_ATTR_MODE_RW
     }
 
     fn name(&self) -> &str {
@@ -636,7 +636,7 @@ impl Attribute for BusAttrDriversAutoprobe {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        return SysFSOpsSupport::STORE | SysFSOpsSupport::SHOW;
+        return SysFSOpsSupport::ATTR_STORE | SysFSOpsSupport::ATTR_SHOW;
     }
 
     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/bus.c?r=&mo=5649&fi=241#231
@@ -738,7 +738,7 @@ struct DriverAttrUnbind;
 
 impl Attribute for DriverAttrUnbind {
     fn mode(&self) -> ModeType {
-        ModeType::from_bits_truncate(0o200)
+        SYSFS_ATTR_MODE_WO
     }
 
     fn name(&self) -> &str {
@@ -774,7 +774,7 @@ impl Attribute for DriverAttrUnbind {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_STORE
     }
 }
 
@@ -787,7 +787,7 @@ impl Attribute for DriverAttrBind {
     }
 
     fn mode(&self) -> ModeType {
-        ModeType::from_bits_truncate(0o200)
+        SYSFS_ATTR_MODE_WO
     }
 
     /*
@@ -825,7 +825,7 @@ impl Attribute for DriverAttrBind {
         return Err(SystemError::ENODEV);
     }
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_STORE
     }
 }
 

+ 6 - 4
kernel/src/driver/base/device/dd.rs

@@ -6,7 +6,9 @@ use intertrait::cast::CastArc;
 use crate::{
     driver::base::kobject::KObject,
     filesystem::{
-        sysfs::{file::sysfs_emit_str, sysfs_instance, Attribute, SysFSOpsSupport},
+        sysfs::{
+            file::sysfs_emit_str, sysfs_instance, Attribute, SysFSOpsSupport, SYSFS_ATTR_MODE_WO,
+        },
         vfs::syscall::ModeType,
     },
     libs::wait_queue::WaitQueue,
@@ -615,7 +617,7 @@ impl Attribute for DeviceAttrStateSynced {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW
+        SysFSOpsSupport::ATTR_SHOW
     }
 }
 
@@ -628,11 +630,11 @@ impl Attribute for DeviceAttrCoredump {
     }
 
     fn mode(&self) -> ModeType {
-        ModeType::from_bits_truncate(0o200)
+        SYSFS_ATTR_MODE_WO
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_STORE
     }
 
     fn store(&self, kobj: Arc<dyn KObject>, buf: &[u8]) -> Result<usize, SystemError> {

+ 3 - 3
kernel/src/driver/base/device/mod.rs

@@ -711,7 +711,7 @@ impl DeviceManager {
     ) -> Result<(), SystemError> {
         if unlikely(
             attr.mode().contains(ModeType::S_IRUGO)
-                && (!attr.support().contains(SysFSOpsSupport::SHOW)),
+                && (!attr.support().contains(SysFSOpsSupport::ATTR_SHOW)),
         ) {
             kwarn!(
                 "Attribute '{}': read permission without 'show'",
@@ -720,7 +720,7 @@ impl DeviceManager {
         }
         if unlikely(
             attr.mode().contains(ModeType::S_IWUGO)
-                && (!attr.support().contains(SysFSOpsSupport::STORE)),
+                && (!attr.support().contains(SysFSOpsSupport::ATTR_STORE)),
         ) {
             kwarn!(
                 "Attribute '{}': write permission without 'store'",
@@ -847,7 +847,7 @@ impl Attribute for DeviceAttrDev {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW
+        SysFSOpsSupport::ATTR_SHOW
     }
 }
 

+ 3 - 3
kernel/src/driver/video/fbdev/base/fbcon.rs

@@ -268,7 +268,7 @@ impl Attribute for AttrRotate {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
     }
 
     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3226
@@ -297,7 +297,7 @@ impl Attribute for AttrRotateAll {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_STORE
     }
 
     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3204
@@ -320,7 +320,7 @@ impl Attribute for AttrCursorBlink {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
     }
 
     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbcon.c#3245

+ 10 - 10
kernel/src/driver/video/fbdev/base/fbsysfs.rs

@@ -57,7 +57,7 @@ impl Attribute for AttrName {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW
+        SysFSOpsSupport::ATTR_SHOW
     }
 
     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
@@ -81,7 +81,7 @@ impl Attribute for AttrBitsPerPixel {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
     }
 
     fn store(&self, _kobj: Arc<dyn KObject>, _buf: &[u8]) -> Result<usize, SystemError> {
@@ -111,7 +111,7 @@ impl Attribute for AttrBlank {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_STORE
     }
 
     // todo:  https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#309
@@ -134,7 +134,7 @@ impl Attribute for AttrMode {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
     }
 
     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#166
@@ -161,7 +161,7 @@ impl Attribute for AttrModes {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
     }
 
     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/video/fbdev/core/fbsysfs.c#206
@@ -188,7 +188,7 @@ impl Attribute for AttrPan {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
     }
 
     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
@@ -217,7 +217,7 @@ impl Attribute for AttrVirtualSize {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
     }
 
     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
@@ -249,7 +249,7 @@ impl Attribute for AttrStride {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW
+        SysFSOpsSupport::ATTR_SHOW
     }
 
     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
@@ -273,7 +273,7 @@ impl Attribute for AttrRotate {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
     }
 
     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
@@ -303,7 +303,7 @@ impl Attribute for AttrState {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW | SysFSOpsSupport::STORE
+        SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE
     }
 
     fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {

+ 1 - 1
kernel/src/driver/video/fbdev/vesafb.rs

@@ -575,7 +575,7 @@ impl Attribute for AnonAttrPhysAddr {
     }
 
     fn support(&self) -> SysFSOpsSupport {
-        SysFSOpsSupport::SHOW
+        SysFSOpsSupport::ATTR_SHOW
     }
 
     fn show(&self, _kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {

+ 29 - 0
kernel/src/exception/irqdata.rs

@@ -60,6 +60,35 @@ impl IrqData {
     pub fn irq(&self) -> IrqNumber {
         self.irq
     }
+
+    pub fn hardware_irq(&self) -> HardwareIrqNumber {
+        self.inner.lock_irqsave().hwirq
+    }
+
+    pub fn chip(&self) -> Arc<dyn IrqChip> {
+        self.inner.lock_irqsave().chip.clone()
+    }
+
+    /// 是否为电平触发
+    pub fn is_level_type(&self) -> bool {
+        self.inner
+            .lock_irqsave()
+            .common_data
+            .inner
+            .lock()
+            .state
+            .is_level_type()
+    }
+
+    pub fn is_wakeup_set(&self) -> bool {
+        self.inner
+            .lock_irqsave()
+            .common_data
+            .inner
+            .lock()
+            .state
+            .is_wakeup_set()
+    }
 }
 
 #[allow(dead_code)]

+ 102 - 4
kernel/src/exception/irqdesc.rs

@@ -1,8 +1,8 @@
 use core::{any::Any, fmt::Debug};
 
 use alloc::{
-    collections::BTreeMap,
-    string::String,
+    collections::{btree_map, BTreeMap},
+    string::{String, ToString},
     sync::{Arc, Weak},
     vec::Vec,
 };
@@ -27,7 +27,7 @@ use super::{
     dummychip::no_irq_chip,
     handle::bad_irq_handler,
     irqdata::{IrqCommonData, IrqData, IrqStatus},
-    sysfs::IrqKObjType,
+    sysfs::{irq_sysfs_del, IrqKObjType},
     HardwareIrqNumber, InterruptArch, IrqNumber,
 };
 
@@ -65,6 +65,7 @@ impl IrqDesc {
             inner: SpinLock::new(InnerIrqDesc {
                 common_data,
                 irq_data,
+                desc_internal_state: IrqDescState::empty(),
                 actions: Vec::new(),
                 name,
                 parent_irq: None,
@@ -93,9 +94,45 @@ impl IrqDesc {
         self.inner.lock_irqsave()
     }
 
+    pub fn actions(&self) -> Vec<Arc<IrqAction>> {
+        self.inner().actions.clone()
+    }
+
     pub fn irq(&self) -> IrqNumber {
         self.inner().irq_data.irq()
     }
+
+    pub fn hardware_irq(&self) -> HardwareIrqNumber {
+        self.inner().irq_data.hardware_irq()
+    }
+
+    pub fn irq_data(&self) -> Arc<IrqData> {
+        self.inner().irq_data.clone()
+    }
+
+    /// 标记当前irq描述符已经被添加到sysfs
+    pub fn mark_in_sysfs(&self) {
+        self.inner()
+            .desc_internal_state
+            .insert(IrqDescState::IRQS_SYSFS);
+    }
+
+    pub fn mark_not_in_sysfs(&self) {
+        self.inner()
+            .desc_internal_state
+            .remove(IrqDescState::IRQS_SYSFS);
+    }
+
+    /// 判断当前描述符是否已经添加到了sysfs
+    pub fn in_sysfs(&self) -> bool {
+        self.inner()
+            .desc_internal_state
+            .contains(IrqDescState::IRQS_SYSFS)
+    }
+
+    pub fn name(&self) -> Option<String> {
+        self.inner().name.clone()
+    }
 }
 
 #[allow(dead_code)]
@@ -111,6 +148,7 @@ struct InnerIrqDesc {
     depth: u32,
     /// nested wake enables
     wake_depth: u32,
+    desc_internal_state: IrqDescState,
 
     kern_inode: Option<Arc<KernFSInode>>,
     kset: Option<Arc<KSet>>,
@@ -153,7 +191,7 @@ impl KObject for IrqDesc {
     fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {}
 
     fn name(&self) -> String {
-        self.inner().name.clone().unwrap_or_else(|| format!(""))
+        self.inner().irq_data.irq().data().to_string()
     }
 
     fn set_name(&self, _name: String) {}
@@ -171,6 +209,32 @@ impl KObject for IrqDesc {
     }
 }
 
+bitflags! {
+    /// Bit masks for desc->desc_internal_state
+    struct IrqDescState: u32 {
+        /// autodetection in progress
+        const IRQS_AUTODETECT = 0x00000001;
+        /// was disabled due to spurious interrupt detection
+        const IRQS_SPURIOUS_DISABLED = 0x00000002;
+        /// polling in progress
+        const IRQS_POLL_INPROGRESS = 0x00000008;
+        /// irq is not unmasked in primary handler
+        const IRQS_ONESHOT = 0x00000020;
+        /// irq is replayed
+        const IRQS_REPLAY = 0x00000040;
+        /// irq is waiting
+        const IRQS_WAITING = 0x00000080;
+        /// irq is pending and replayed later
+        const IRQS_PENDING = 0x00000200;
+        /// irq is suspended
+        const IRQS_SUSPENDED = 0x00000800;
+        /// irq line is used to deliver NMIs
+        const IRQS_NMI = 0x00002000;
+        /// descriptor has been added to sysfs
+        const IRQS_SYSFS = 0x00004000;
+    }
+}
+
 /// 每个中断的响应动作的描述符
 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/interrupt.h#118
 #[allow(dead_code)]
@@ -201,6 +265,14 @@ impl IrqAction {
 
         return Arc::new(action);
     }
+
+    pub fn name(&self) -> String {
+        self.inner().name.clone()
+    }
+
+    fn inner(&self) -> SpinLockGuard<InnerIrqAction> {
+        self.inner.lock_irqsave()
+    }
 }
 
 #[allow(dead_code)]
@@ -268,9 +340,21 @@ pub(super) fn early_irq_init() -> Result<(), SystemError> {
         manager.insert(IrqNumber::new(i), irq_desc);
     }
 
+    unsafe {
+        IRQ_DESC_MANAGER = Some(manager);
+    }
+
     return CurrentIrqArch::arch_early_irq_init();
 }
 
+static mut IRQ_DESC_MANAGER: Option<IrqDescManager> = None;
+
+/// 获取中断描述符管理器的引用
+#[inline(always)]
+pub(super) fn irq_desc_manager() -> &'static IrqDescManager {
+    return unsafe { IRQ_DESC_MANAGER.as_ref().unwrap() };
+}
+
 pub(super) struct IrqDescManager {
     irq_descs: BTreeMap<IrqNumber, Arc<IrqDesc>>,
 }
@@ -291,4 +375,18 @@ impl IrqDescManager {
     fn insert(&mut self, irq: IrqNumber, desc: Arc<IrqDesc>) {
         self.irq_descs.insert(irq, desc);
     }
+
+    /// 释放中断描述符
+    #[allow(dead_code)]
+    fn free_desc(&mut self, irq: IrqNumber) {
+        if let Some(desc) = self.irq_descs.get(&irq) {
+            irq_sysfs_del(desc);
+            self.irq_descs.remove(&irq);
+        }
+    }
+
+    /// 迭代中断描述符
+    pub fn iter_descs(&self) -> btree_map::Iter<'_, IrqNumber, Arc<IrqDesc>> {
+        self.irq_descs.iter()
+    }
 }

+ 262 - 7
kernel/src/exception/sysfs.rs

@@ -1,16 +1,37 @@
-use alloc::sync::Arc;
+use alloc::{string::ToString, sync::Arc};
 use system_error::SystemError;
 use unified_init::macros::unified_init;
 
 use crate::{
-    driver::base::kobject::{KObjType, KObject, KObjectSysFSOps},
+    driver::base::{
+        kobject::{KObjType, KObject, KObjectManager, KObjectSysFSOps},
+        kset::KSet,
+    },
     filesystem::{
-        sysfs::{Attribute, AttributeGroup, SysFSOps},
+        sysfs::{
+            file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOps, SysFSOpsSupport,
+            SYSFS_ATTR_MODE_RO,
+        },
         vfs::syscall::ModeType,
     },
     init::initcall::INITCALL_POSTCORE,
+    misc::ksysfs::sys_kernel_kset,
+};
+
+use super::{
+    irqdesc::{irq_desc_manager, IrqDesc},
+    IrqNumber,
 };
 
+/// `/sys/kernel/irq`的kset
+static mut SYS_KERNEL_IRQ_KSET_INSTANCE: Option<Arc<KSet>> = None;
+
+#[inline(always)]
+#[allow(dead_code)]
+pub fn sys_kernel_irq_kset() -> Arc<KSet> {
+    unsafe { SYS_KERNEL_IRQ_KSET_INSTANCE.clone().unwrap() }
+}
+
 /// 中断描述符的kobjtype
 ///
 /// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#280
@@ -40,9 +61,20 @@ impl AttributeGroup for IrqAttrGroup {
         None
     }
 
+    /// 所有的属性
+    ///
+    /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#268
     fn attrs(&self) -> &[&'static dyn Attribute] {
-        todo!("irq_attr_group.attrs")
-        // todo: https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdesc.c#268
+        // 每个irq的属性
+        // todo: 添加per_cpu_count属性
+        &[
+            &AttrChipName,
+            &AttrHardwareIrq,
+            &AttrType,
+            &AttrWakeup,
+            &AttrName,
+            &AttrActions,
+        ]
     }
 
     fn is_visible(
@@ -60,6 +92,229 @@ impl AttributeGroup for IrqAttrGroup {
 #[unified_init(INITCALL_POSTCORE)]
 fn irq_sysfs_init() -> Result<(), SystemError> {
     // todo!("irq_sysfs_init");
-    kwarn!("Unimplemented: irq_sysfs_init");
-    Ok(())
+
+    let irq_kset = KSet::new("irq".to_string());
+    irq_kset
+        .register(Some(sys_kernel_kset()))
+        .expect("register irq kset failed");
+    unsafe {
+        SYS_KERNEL_IRQ_KSET_INSTANCE = Some(irq_kset);
+    }
+
+    // 把所有的irq都注册到/sys/kernel/irq下
+    for (irq, desc) in irq_desc_manager().iter_descs() {
+        irq_sysfs_add(irq, desc);
+    }
+
+    return Ok(());
+}
+
+/// 把irqdesc添加到sysfs
+fn irq_sysfs_add(irq: &IrqNumber, desc: &Arc<IrqDesc>) {
+    if unsafe { SYS_KERNEL_IRQ_KSET_INSTANCE.is_none() } {
+        return;
+    }
+
+    let kset = sys_kernel_irq_kset();
+    KObjectManager::add_kobj(desc.clone() as Arc<dyn KObject>, Some(kset)).unwrap_or_else(|e| {
+        kwarn!("Failed to add irq({irq:?}) kobject to sysfs: {:?}", e);
+    });
+
+    desc.mark_in_sysfs();
+}
+
+/// 从sysfs中删除irqdesc
+#[allow(dead_code)]
+pub(super) fn irq_sysfs_del(desc: &Arc<IrqDesc>) {
+    if desc.in_sysfs() {
+        KObjectManager::remove_kobj(desc.clone() as Arc<dyn KObject>);
+        desc.mark_not_in_sysfs();
+    }
+}
+#[derive(Debug)]
+struct AttrChipName;
+
+impl Attribute for AttrChipName {
+    fn name(&self) -> &str {
+        "chip_name"
+    }
+
+    fn mode(&self) -> ModeType {
+        SYSFS_ATTR_MODE_RO
+    }
+
+    fn support(&self) -> SysFSOpsSupport {
+        SysFSOpsSupport::ATTR_SHOW
+    }
+
+    fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
+        let irq_desc = kobj
+            .arc_any()
+            .downcast::<IrqDesc>()
+            .map_err(|_| SystemError::EINVAL)?;
+        let chip = irq_desc.irq_data().chip();
+        let name = chip.name();
+        let len = core::cmp::min(name.len() + 1, buf.len());
+        let name = format!("{}\n", name);
+        buf[..len].copy_from_slice(name.as_bytes());
+        return Ok(len);
+    }
+}
+
+#[derive(Debug)]
+struct AttrHardwareIrq;
+
+impl Attribute for AttrHardwareIrq {
+    fn name(&self) -> &str {
+        "hwirq"
+    }
+
+    fn mode(&self) -> ModeType {
+        SYSFS_ATTR_MODE_RO
+    }
+
+    fn support(&self) -> SysFSOpsSupport {
+        SysFSOpsSupport::ATTR_SHOW
+    }
+
+    fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
+        let irq_desc = kobj
+            .arc_any()
+            .downcast::<IrqDesc>()
+            .map_err(|_| SystemError::EINVAL)?;
+        let hwirq = irq_desc.hardware_irq();
+        return sysfs_emit_str(buf, &format!("{}\n", hwirq.data()));
+    }
+}
+
+#[derive(Debug)]
+struct AttrType;
+
+impl Attribute for AttrType {
+    fn name(&self) -> &str {
+        "type"
+    }
+
+    fn mode(&self) -> ModeType {
+        SYSFS_ATTR_MODE_RO
+    }
+
+    fn support(&self) -> SysFSOpsSupport {
+        SysFSOpsSupport::ATTR_SHOW
+    }
+
+    fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
+        let irq_desc = kobj
+            .arc_any()
+            .downcast::<IrqDesc>()
+            .map_err(|_| SystemError::EINVAL)?;
+        let irq_type = if irq_desc.irq_data().is_level_type() {
+            "level"
+        } else {
+            "edge"
+        };
+
+        return sysfs_emit_str(buf, &format!("{}\n", irq_type));
+    }
+}
+
+#[derive(Debug)]
+struct AttrWakeup;
+
+impl Attribute for AttrWakeup {
+    fn name(&self) -> &str {
+        "wakeup"
+    }
+
+    fn mode(&self) -> ModeType {
+        SYSFS_ATTR_MODE_RO
+    }
+
+    fn support(&self) -> SysFSOpsSupport {
+        SysFSOpsSupport::ATTR_SHOW
+    }
+
+    fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
+        let irq_desc = kobj
+            .arc_any()
+            .downcast::<IrqDesc>()
+            .map_err(|_| SystemError::EINVAL)?;
+        let wakeup = irq_desc.irq_data().is_wakeup_set();
+        return sysfs_emit_str(buf, &format!("{}\n", wakeup));
+    }
+}
+
+#[derive(Debug)]
+struct AttrName;
+
+impl Attribute for AttrName {
+    fn name(&self) -> &str {
+        "name"
+    }
+
+    fn mode(&self) -> ModeType {
+        SYSFS_ATTR_MODE_RO
+    }
+
+    fn support(&self) -> SysFSOpsSupport {
+        SysFSOpsSupport::ATTR_SHOW
+    }
+
+    fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
+        let irq_desc = kobj
+            .arc_any()
+            .downcast::<IrqDesc>()
+            .map_err(|_| SystemError::EINVAL)?;
+
+        if let Some(name) = irq_desc.name() {
+            return sysfs_emit_str(buf, &format!("{}\n", name));
+        }
+
+        return Ok(0);
+    }
+}
+
+#[derive(Debug)]
+struct AttrActions;
+
+impl Attribute for AttrActions {
+    fn name(&self) -> &str {
+        "actions"
+    }
+
+    fn mode(&self) -> ModeType {
+        SYSFS_ATTR_MODE_RO
+    }
+
+    fn support(&self) -> SysFSOpsSupport {
+        SysFSOpsSupport::ATTR_SHOW
+    }
+
+    fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
+        let irq_desc = kobj
+            .arc_any()
+            .downcast::<IrqDesc>()
+            .map_err(|_| SystemError::EINVAL)?;
+
+        let actions = irq_desc.actions();
+        let mut len = 0;
+
+        for action in actions {
+            if len != 0 {
+                len += sysfs_emit_str(&mut buf[len..], &format!(",{}", action.name())).unwrap();
+            } else {
+                len += sysfs_emit_str(&mut buf[len..], &format!("{}", action.name())).unwrap();
+            }
+
+            if len >= buf.len() {
+                break;
+            }
+        }
+
+        if len != 0 && len < buf.len() {
+            len += sysfs_emit_str(&mut buf[len..], "\n").unwrap();
+        }
+
+        return Ok(len);
+    }
 }

+ 8 - 8
kernel/src/filesystem/sysfs/file.rs

@@ -139,13 +139,13 @@ impl SysFS {
         let sys_support = sysfs_ops.support(attr);
 
         let kern_callback: &'static dyn KernFSCallback;
-        if sys_support.contains(SysFSOpsSupport::SHOW)
-            && sys_support.contains(SysFSOpsSupport::STORE)
+        if sys_support.contains(SysFSOpsSupport::ATTR_SHOW)
+            && sys_support.contains(SysFSOpsSupport::ATTR_STORE)
         {
             kern_callback = &PreallocKFOpsRW;
-        } else if sys_support.contains(SysFSOpsSupport::SHOW) {
+        } else if sys_support.contains(SysFSOpsSupport::ATTR_SHOW) {
             kern_callback = &PreallocKFOpsReadOnly;
-        } else if sys_support.contains(SysFSOpsSupport::STORE) {
+        } else if sys_support.contains(SysFSOpsSupport::ATTR_STORE) {
             kern_callback = &PreallocKFOpsWriteOnly;
         } else {
             kern_callback = &PreallocKFOpsEmpty;
@@ -250,13 +250,13 @@ impl SysFS {
         let kern_callback: &'static dyn KernFSCallback;
         let bin_support = attr.support_battr();
 
-        if bin_support.contains(SysFSOpsSupport::READ)
-            && bin_support.contains(SysFSOpsSupport::WRITE)
+        if bin_support.contains(SysFSOpsSupport::BATTR_READ)
+            && bin_support.contains(SysFSOpsSupport::BATTR_WRITE)
         {
             kern_callback = &PreallocKFOpsRW;
-        } else if bin_support.contains(SysFSOpsSupport::READ) {
+        } else if bin_support.contains(SysFSOpsSupport::BATTR_READ) {
             kern_callback = &PreallocKFOpsReadOnly;
-        } else if bin_support.contains(SysFSOpsSupport::WRITE) {
+        } else if bin_support.contains(SysFSOpsSupport::BATTR_WRITE) {
             kern_callback = &PreallocKFOpsWriteOnly;
         } else {
             kern_callback = &PreallocKFOpsEmpty;

+ 11 - 4
kernel/src/filesystem/sysfs/mod.rs

@@ -110,6 +110,13 @@ pub trait AttributeGroup: Debug + Send + Sync {
     fn is_visible(&self, kobj: Arc<dyn KObject>, attr: &'static dyn Attribute) -> Option<ModeType>;
 }
 
+/// sysfs只读属性文件的权限
+pub const SYSFS_ATTR_MODE_RO: ModeType = ModeType::from_bits_truncate(0o444);
+/// sysfs只写属性文件的权限
+pub const SYSFS_ATTR_MODE_WO: ModeType = ModeType::from_bits_truncate(0o200);
+/// sysfs读写属性文件的权限
+pub const SYSFS_ATTR_MODE_RW: ModeType = ModeType::from_bits_truncate(0o644);
+
 /// sysfs文件的属性
 pub trait Attribute: Debug + Send + Sync {
     fn name(&self) -> &str;
@@ -178,11 +185,11 @@ pub trait SysFSOps: Debug {
 bitflags! {
     pub struct SysFSOpsSupport: u8{
         // === for attribute ===
-        const SHOW = 1 << 0;
-        const STORE = 1 << 1;
+        const ATTR_SHOW = 1 << 0;
+        const ATTR_STORE = 1 << 1;
         // === for bin attribute ===
-        const READ = 1 << 2;
-        const WRITE = 1 << 3;
+        const BATTR_READ = 1 << 2;
+        const BATTR_WRITE = 1 << 3;
     }
 }
 

+ 1 - 0
kernel/src/lib.rs

@@ -45,6 +45,7 @@ mod exception;
 mod filesystem;
 mod init;
 mod ipc;
+mod misc;
 mod mm;
 mod net;
 mod process;

+ 63 - 0
kernel/src/misc/ksysfs.rs

@@ -0,0 +1,63 @@
+use crate::{
+    driver::base::{kobject::KObject, kset::KSet},
+    filesystem::{
+        sysfs::{sysfs_instance, Attribute, AttributeGroup},
+        vfs::syscall::ModeType,
+    },
+    init::initcall::INITCALL_CORE,
+};
+use alloc::{string::ToString, sync::Arc};
+use system_error::SystemError;
+use unified_init::macros::unified_init;
+
+/// `/sys/kernel`的kset
+static mut KERNEL_KSET_INSTANCE: Option<Arc<KSet>> = None;
+
+#[inline(always)]
+#[allow(dead_code)]
+pub fn sys_kernel_kset() -> Arc<KSet> {
+    unsafe { KERNEL_KSET_INSTANCE.clone().unwrap() }
+}
+
+#[unified_init(INITCALL_CORE)]
+fn ksysfs_init() -> Result<(), SystemError> {
+    let kernel_kset = KSet::new("kernel".to_string());
+    kernel_kset
+        .register(None)
+        .expect("register kernel kset failed");
+
+    sysfs_instance()
+        .create_groups(&kernel_kset.as_kobject(), &[&KernelAttrGroup])
+        .map_err(|e| {
+            kerror!("Failed to create sysfs groups for kernel kset: {:?}", e);
+            kernel_kset.unregister();
+            SystemError::ENOMEM
+        })?;
+
+    unsafe {
+        KERNEL_KSET_INSTANCE = Some(kernel_kset);
+    }
+
+    return Ok(());
+}
+
+#[derive(Debug)]
+struct KernelAttrGroup;
+
+impl AttributeGroup for KernelAttrGroup {
+    fn name(&self) -> Option<&str> {
+        None
+    }
+
+    fn attrs(&self) -> &[&'static dyn Attribute] {
+        &[]
+    }
+
+    fn is_visible(
+        &self,
+        _kobj: Arc<dyn KObject>,
+        attr: &'static dyn Attribute,
+    ) -> Option<ModeType> {
+        Some(attr.mode())
+    }
+}

+ 1 - 0
kernel/src/misc/mod.rs

@@ -0,0 +1 @@
+pub mod ksysfs;