xref: /DragonOS/kernel/src/arch/riscv64/interrupt/mod.rs (revision 55e6f0b65f91b32638fd56581f711a816eccdcd1)
1 use core::any::Any;
2 use kprobe::ProbeArgs;
3 use riscv::register::{scause::Scause, sstatus::Sstatus};
4 use system_error::SystemError;
5 
6 use crate::{
7     driver::irqchip::{riscv_intc::riscv_intc_init, riscv_sifive_plic::riscv_sifive_plic_init},
8     exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
9     libs::align::align_up,
10 };
11 
12 use super::cpu::STACK_ALIGN;
13 
14 pub(super) mod entry;
15 mod handle;
16 pub mod ipi;
17 
18 pub struct RiscV64InterruptArch;
19 
20 impl InterruptArch for RiscV64InterruptArch {
21     unsafe fn arch_irq_init() -> Result<(), SystemError> {
22         Self::interrupt_disable();
23         riscv_sifive_plic_init()?;
24         // 注意,intc的初始化必须在plic之后,不然会导致plic无法关联上中断
25         riscv_intc_init()?;
26 
27         Ok(())
28     }
29     unsafe fn interrupt_enable() {
30         riscv::interrupt::enable();
31     }
32 
33     unsafe fn interrupt_disable() {
34         riscv::interrupt::disable();
35     }
36 
37     fn is_irq_enabled() -> bool {
38         riscv::register::sstatus::read().sie()
39     }
40 
41     unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
42         let sie = riscv::register::sstatus::read().sie();
43         riscv::register::sstatus::clear_sie();
44         IrqFlagsGuard::new(IrqFlags::new(sie.into()))
45     }
46 
47     unsafe fn restore_irq(flags: IrqFlags) {
48         let sie: bool = flags.flags() != 0;
49         if sie {
50             riscv::register::sstatus::set_sie();
51         } else {
52             riscv::register::sstatus::clear_sie();
53         }
54     }
55 
56     fn probe_total_irq_num() -> u32 {
57         // todo: 获取中断总数
58         256
59     }
60 
61     fn ack_bad_irq(irq: IrqNumber) {
62         todo!("ack_bad_irq: {}", irq.data());
63     }
64 }
65 
66 /// 中断栈帧结构体
67 #[repr(C)]
68 #[derive(Debug, Copy, Clone)]
69 pub struct TrapFrame {
70     pub epc: usize,
71     pub ra: usize,
72     pub sp: usize,
73     pub gp: usize,
74     pub tp: usize,
75     pub t0: usize,
76     pub t1: usize,
77     pub t2: usize,
78     pub s0: usize,
79     pub s1: usize,
80     pub a0: usize,
81     pub a1: usize,
82     pub a2: usize,
83     pub a3: usize,
84     pub a4: usize,
85     pub a5: usize,
86     pub a6: usize,
87     pub a7: usize,
88     pub s2: usize,
89     pub s3: usize,
90     pub s4: usize,
91     pub s5: usize,
92     pub s6: usize,
93     pub s7: usize,
94     pub s8: usize,
95     pub s9: usize,
96     pub s10: usize,
97     pub s11: usize,
98     pub t3: usize,
99     pub t4: usize,
100     pub t5: usize,
101     pub t6: usize,
102     // 以下是中断发生时自动保存的寄存器
103     pub status: Sstatus,
104     pub badaddr: usize,
105     pub cause: Scause,
106     /// a0 value before the syscall
107     pub origin_a0: usize,
108 }
109 
110 impl TrapFrame {
111     /// 中断栈帧结构体的大小
112     pub const SIZE: usize = core::mem::size_of::<TrapFrame>();
113 
114     /// 中断栈帧在栈上的大小
115     pub const SIZE_ON_STACK: usize = align_up(Self::SIZE, STACK_ALIGN);
116     /// 判断当前中断是否来自用户模式
117     pub fn is_from_user(&self) -> bool {
118         self.status.spp() == riscv::register::sstatus::SPP::User
119     }
120 
121     pub fn new() -> Self {
122         Self {
123             epc: 0,
124             ra: 0,
125             sp: 0,
126             gp: 0,
127             tp: 0,
128             t0: 0,
129             t1: 0,
130             t2: 0,
131             s0: 0,
132             s1: 0,
133             a0: 0,
134             a1: 0,
135             a2: 0,
136             a3: 0,
137             a4: 0,
138             a5: 0,
139             a6: 0,
140             a7: 0,
141             s2: 0,
142             s3: 0,
143             s4: 0,
144             s5: 0,
145             s6: 0,
146             s7: 0,
147             s8: 0,
148             s9: 0,
149             s10: 0,
150             s11: 0,
151             t3: 0,
152             t4: 0,
153             t5: 0,
154             t6: 0,
155             status: unsafe { core::mem::zeroed() },
156             badaddr: 0,
157             cause: unsafe { core::mem::zeroed() },
158             origin_a0: 0,
159         }
160     }
161 
162     pub fn set_return_value(&mut self, value: usize) {
163         self.a0 = value;
164     }
165 
166     /// 设置当前的程序计数器
167     pub fn set_pc(&mut self, pc: usize) {
168         self.epc = pc;
169     }
170 }
171 
172 impl ProbeArgs for TrapFrame {
173     fn as_any(&self) -> &dyn Any {
174         self
175     }
176     fn break_address(&self) -> usize {
177         self.epc
178     }
179     fn debug_address(&self) -> usize {
180         self.epc
181     }
182 }
183