xref: /DragonOS/kernel/src/exception/mod.rs (revision 55e6f0b65f91b32638fd56581f711a816eccdcd1)
1 use core::ops::Add;
2 
3 use system_error::SystemError;
4 
5 use crate::arch::CurrentIrqArch;
6 
7 pub mod debug;
8 pub mod dummychip;
9 pub mod ebreak;
10 pub mod handle;
11 pub mod init;
12 pub mod ipi;
13 pub mod irqchip;
14 pub mod irqdata;
15 pub mod irqdesc;
16 pub mod irqdomain;
17 pub mod manage;
18 pub mod msi;
19 mod resend;
20 pub mod softirq;
21 pub mod sysfs;
22 
23 /// 中断的架构相关的trait
24 pub trait InterruptArch: Send + Sync {
25     /// 架构相关的中断初始化
26     unsafe fn arch_irq_init() -> Result<(), SystemError>;
27     /// 使能中断
28     unsafe fn interrupt_enable();
29     /// 禁止中断
30     unsafe fn interrupt_disable();
31     /// 检查中断是否被禁止
32     fn is_irq_enabled() -> bool;
33 
34     /// 保存当前中断状态,并且禁止中断
35     unsafe fn save_and_disable_irq() -> IrqFlagsGuard;
36     unsafe fn restore_irq(flags: IrqFlags);
37 
38     /// 检测系统支持的中断总数
39     fn probe_total_irq_num() -> u32;
40 
41     fn arch_early_irq_init() -> Result<(), SystemError> {
42         Ok(())
43     }
44 
45     /// ap启动时的中断初始化
46     fn arch_ap_early_irq_init() -> Result<(), SystemError> {
47         Ok(())
48     }
49 
50     /// 响应未注册的中断
51     fn ack_bad_irq(irq: IrqNumber);
52 }
53 
54 #[derive(Debug, Clone, Copy)]
55 pub struct IrqFlags {
56     flags: usize,
57 }
58 
59 impl IrqFlags {
60     pub fn new(flags: usize) -> Self {
61         IrqFlags { flags }
62     }
63 
64     pub fn flags(&self) -> usize {
65         self.flags
66     }
67 }
68 
69 /// @brief 当前中断状态的保护器,当该对象被drop时,会恢复之前的中断状态
70 ///
71 /// # Example
72 ///
73 /// ```
74 /// use crate::arch::CurrentIrqArch;
75 ///
76 /// // disable irq and save irq state (这是唯一的获取IrqFlagsGuard的方法)
77 /// let guard = unsafe{CurrentIrqArch::save_and_disable_irq()};
78 ///
79 /// // do something
80 ///
81 /// // 销毁guard时,会恢复之前的中断状态
82 /// drop(guard);
83 ///
84 /// ```
85 #[derive(Debug)]
86 pub struct IrqFlagsGuard {
87     flags: IrqFlags,
88 }
89 
90 impl IrqFlagsGuard {
91     /// @brief 创建IrqFlagsGuard对象
92     ///
93     /// # Safety
94     ///
95     /// 该函数不安全,因为它不会检查flags是否是一个有效的IrqFlags对象, 而当它被drop时,会恢复flags中的中断状态
96     ///
97     /// 该函数只应被`CurrentIrqArch::save_and_disable_irq`调用
98     pub unsafe fn new(flags: IrqFlags) -> Self {
99         IrqFlagsGuard { flags }
100     }
101 }
102 impl Drop for IrqFlagsGuard {
103     fn drop(&mut self) {
104         unsafe {
105             CurrentIrqArch::restore_irq(self.flags);
106         }
107     }
108 }
109 
110 // 定义中断号结构体
111 // 用于表示软件逻辑视角的中断号,全局唯一
112 int_like!(IrqNumber, u32);
113 
114 impl IrqNumber {
115     /// 如果一个(PCI)设备中断没有被连接,我们将设置irqnumber为IRQ_NOTCONNECTED。
116     /// 这导致request_irq()失败,返回-ENOTCONN,这样我们就可以区分这种情况和其他错误返回。
117     pub const IRQ_NOTCONNECTED: IrqNumber = IrqNumber::new(u32::MAX);
118 }
119 
120 // 硬件中断号
121 // 用于表示在某个IrqDomain中的中断号
122 int_like!(HardwareIrqNumber, u32);
123 
124 impl Add<u32> for HardwareIrqNumber {
125     type Output = HardwareIrqNumber;
126 
127     fn add(self, rhs: u32) -> HardwareIrqNumber {
128         HardwareIrqNumber::new(self.0 + rhs)
129     }
130 }
131 
132 impl Add<u32> for IrqNumber {
133     type Output = IrqNumber;
134 
135     fn add(self, rhs: u32) -> IrqNumber {
136         IrqNumber::new(self.0 + rhs)
137     }
138 }
139