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