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