xref: /DragonOS/kernel/src/exception/mod.rs (revision 3bc96fa4a9c01d91cddeb152fe78d6408351c29f)
1f2022a8aSLoGin use system_error::SystemError;
2f2022a8aSLoGin 
3f678331aShanjiezhou use crate::arch::CurrentIrqArch;
4f678331aShanjiezhou 
5*3bc96fa4SLoGin pub mod dummychip;
6*3bc96fa4SLoGin pub mod handle;
7f2022a8aSLoGin pub mod init;
8aa0367d6SLoGin pub mod ipi;
9ce5850adSLoGin pub mod irqchip;
10ce5850adSLoGin pub mod irqdata;
11*3bc96fa4SLoGin pub mod irqdesc;
12ce5850adSLoGin pub mod irqdomain;
13ce5850adSLoGin pub mod msi;
1462e46139SGou Ngai pub mod softirq;
15*3bc96fa4SLoGin pub mod sysfs;
16f678331aShanjiezhou 
17f2022a8aSLoGin /// 中断的架构相关的trait
18f678331aShanjiezhou pub trait InterruptArch: Send + Sync {
19f2022a8aSLoGin     /// 架构相关的中断初始化
20f2022a8aSLoGin     unsafe fn arch_irq_init() -> Result<(), SystemError>;
21f2022a8aSLoGin     /// 使能中断
22f678331aShanjiezhou     unsafe fn interrupt_enable();
23f2022a8aSLoGin     /// 禁止中断
24f678331aShanjiezhou     unsafe fn interrupt_disable();
25f2022a8aSLoGin     /// 检查中断是否被禁止
26f678331aShanjiezhou     fn is_irq_enabled() -> bool;
27f678331aShanjiezhou 
28f2022a8aSLoGin     /// 保存当前中断状态,并且禁止中断
29f678331aShanjiezhou     unsafe fn save_and_disable_irq() -> IrqFlagsGuard;
30f678331aShanjiezhou     unsafe fn restore_irq(flags: IrqFlags);
31*3bc96fa4SLoGin 
32*3bc96fa4SLoGin     /// 检测系统支持的中断总数
33*3bc96fa4SLoGin     fn probe_total_irq_num() -> u32;
34*3bc96fa4SLoGin 
35*3bc96fa4SLoGin     fn arch_early_irq_init() -> Result<(), SystemError> {
36*3bc96fa4SLoGin         Ok(())
37*3bc96fa4SLoGin     }
38*3bc96fa4SLoGin 
39*3bc96fa4SLoGin     /// 响应未注册的中断
40*3bc96fa4SLoGin     fn ack_bad_irq(irq: IrqNumber);
41f678331aShanjiezhou }
42f678331aShanjiezhou 
43f678331aShanjiezhou #[derive(Debug, Clone, Copy)]
44f678331aShanjiezhou pub struct IrqFlags {
4540fe15e0SLoGin     flags: usize,
46f678331aShanjiezhou }
47f678331aShanjiezhou 
48f678331aShanjiezhou impl IrqFlags {
4940fe15e0SLoGin     pub fn new(flags: usize) -> Self {
50f678331aShanjiezhou         IrqFlags { flags }
51f678331aShanjiezhou     }
52f678331aShanjiezhou 
5340fe15e0SLoGin     pub fn flags(&self) -> usize {
54f678331aShanjiezhou         self.flags
55f678331aShanjiezhou     }
56f678331aShanjiezhou }
57f678331aShanjiezhou 
58f678331aShanjiezhou /// @brief 当前中断状态的保护器,当该对象被drop时,会恢复之前的中断状态
59f678331aShanjiezhou ///
60f678331aShanjiezhou /// # Example
61f678331aShanjiezhou ///
62f678331aShanjiezhou /// ```
63f678331aShanjiezhou /// use crate::arch::CurrentIrqArch;
64f678331aShanjiezhou ///
65f678331aShanjiezhou /// // disable irq and save irq state (这是唯一的获取IrqFlagsGuard的方法)
66f678331aShanjiezhou /// let guard = unsafe{CurrentIrqArch::save_and_disable_irq()};
67f678331aShanjiezhou ///
68f678331aShanjiezhou /// // do something
69f678331aShanjiezhou ///
70f678331aShanjiezhou /// // 销毁guard时,会恢复之前的中断状态
71f678331aShanjiezhou /// drop(guard);
72f678331aShanjiezhou ///
73f678331aShanjiezhou /// ```
74f678331aShanjiezhou #[derive(Debug)]
75f678331aShanjiezhou pub struct IrqFlagsGuard {
76f678331aShanjiezhou     flags: IrqFlags,
77f678331aShanjiezhou }
78f678331aShanjiezhou 
79f678331aShanjiezhou impl IrqFlagsGuard {
80f678331aShanjiezhou     /// @brief 创建IrqFlagsGuard对象
81f678331aShanjiezhou     ///
82f678331aShanjiezhou     /// # Safety
83f678331aShanjiezhou     ///
84f678331aShanjiezhou     /// 该函数不安全,因为它不会检查flags是否是一个有效的IrqFlags对象, 而当它被drop时,会恢复flags中的中断状态
85f678331aShanjiezhou     ///
86f678331aShanjiezhou     /// 该函数只应被`CurrentIrqArch::save_and_disable_irq`调用
87f678331aShanjiezhou     pub unsafe fn new(flags: IrqFlags) -> Self {
88f678331aShanjiezhou         IrqFlagsGuard { flags }
89f678331aShanjiezhou     }
90f678331aShanjiezhou }
91f678331aShanjiezhou impl Drop for IrqFlagsGuard {
92f678331aShanjiezhou     fn drop(&mut self) {
93f678331aShanjiezhou         unsafe {
94f678331aShanjiezhou             CurrentIrqArch::restore_irq(self.flags);
95f678331aShanjiezhou         }
96f678331aShanjiezhou     }
97f678331aShanjiezhou }
98ce5850adSLoGin 
99ce5850adSLoGin // 定义中断号结构体
100ce5850adSLoGin // 用于表示软件逻辑视角的中断号,全局唯一
101ce5850adSLoGin int_like!(IrqNumber, u32);
102ce5850adSLoGin 
103ce5850adSLoGin // 硬件中断号
104ce5850adSLoGin // 用于表示在某个IrqDomain中的中断号
105ce5850adSLoGin int_like!(HardwareIrqNumber, u32);
106