xref: /DragonOS/kernel/src/arch/riscv64/interrupt/mod.rs (revision 0102d69fdd231e472d7bb3d609a41ae56a3799ee)
15c4224e5SLoGin use riscv::register::{scause::Scause, sstatus::Sstatus};
2f2022a8aSLoGin use system_error::SystemError;
3f2022a8aSLoGin 
4338f6903SLoGin use crate::{
5*0102d69fSLoGin     driver::irqchip::{riscv_intc::riscv_intc_init, riscv_sifive_plic::riscv_sifive_plic_init},
6338f6903SLoGin     exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
75c4224e5SLoGin     libs::align::align_up,
8338f6903SLoGin };
94fda81ceSLoGin 
105c4224e5SLoGin use super::cpu::STACK_ALIGN;
115c4224e5SLoGin 
125c4224e5SLoGin pub(super) mod entry;
135c4224e5SLoGin mod handle;
144fda81ceSLoGin pub mod ipi;
154fda81ceSLoGin 
164fda81ceSLoGin pub struct RiscV64InterruptArch;
174fda81ceSLoGin 
184fda81ceSLoGin impl InterruptArch for RiscV64InterruptArch {
19f2022a8aSLoGin     unsafe fn arch_irq_init() -> Result<(), SystemError> {
20*0102d69fSLoGin         Self::interrupt_disable();
21*0102d69fSLoGin         riscv_sifive_plic_init()?;
22*0102d69fSLoGin         // 注意,intc的初始化必须在plic之后,不然会导致plic无法关联上中断
23338f6903SLoGin         riscv_intc_init()?;
24338f6903SLoGin 
25338f6903SLoGin         Ok(())
26f2022a8aSLoGin     }
274fda81ceSLoGin     unsafe fn interrupt_enable() {
287a29d4fcSLoGin         riscv::interrupt::enable();
294fda81ceSLoGin     }
304fda81ceSLoGin 
314fda81ceSLoGin     unsafe fn interrupt_disable() {
327a29d4fcSLoGin         riscv::interrupt::disable();
334fda81ceSLoGin     }
344fda81ceSLoGin 
354fda81ceSLoGin     fn is_irq_enabled() -> bool {
367a29d4fcSLoGin         riscv::register::sstatus::read().sie()
374fda81ceSLoGin     }
384fda81ceSLoGin 
394fda81ceSLoGin     unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
407a29d4fcSLoGin         let sie = riscv::register::sstatus::read().sie();
419621ab16SLoGin         riscv::register::sstatus::clear_sie();
427a29d4fcSLoGin         IrqFlagsGuard::new(IrqFlags::new(sie.into()))
434fda81ceSLoGin     }
444fda81ceSLoGin 
454fda81ceSLoGin     unsafe fn restore_irq(flags: IrqFlags) {
467a29d4fcSLoGin         let sie: bool = flags.flags() != 0;
477a29d4fcSLoGin         if sie {
487a29d4fcSLoGin             riscv::register::sstatus::set_sie();
497a29d4fcSLoGin         } else {
507a29d4fcSLoGin             riscv::register::sstatus::clear_sie();
517a29d4fcSLoGin         }
524fda81ceSLoGin     }
533bc96fa4SLoGin 
543bc96fa4SLoGin     fn probe_total_irq_num() -> u32 {
553bc96fa4SLoGin         // todo: 获取中断总数
563bc96fa4SLoGin         256
573bc96fa4SLoGin     }
583bc96fa4SLoGin 
593bc96fa4SLoGin     fn ack_bad_irq(irq: IrqNumber) {
603bc96fa4SLoGin         todo!("ack_bad_irq: {}", irq.data());
613bc96fa4SLoGin     }
624fda81ceSLoGin }
634fda81ceSLoGin 
644fda81ceSLoGin /// 中断栈帧结构体
654fda81ceSLoGin #[repr(C)]
664fda81ceSLoGin #[derive(Debug, Copy, Clone)]
674fda81ceSLoGin pub struct TrapFrame {
689b96c5b5SLoGin     pub epc: usize,
699b96c5b5SLoGin     pub ra: usize,
709b96c5b5SLoGin     pub sp: usize,
719b96c5b5SLoGin     pub gp: usize,
729b96c5b5SLoGin     pub tp: usize,
739b96c5b5SLoGin     pub t0: usize,
749b96c5b5SLoGin     pub t1: usize,
759b96c5b5SLoGin     pub t2: usize,
769b96c5b5SLoGin     pub s0: usize,
779b96c5b5SLoGin     pub s1: usize,
789b96c5b5SLoGin     pub a0: usize,
799b96c5b5SLoGin     pub a1: usize,
809b96c5b5SLoGin     pub a2: usize,
819b96c5b5SLoGin     pub a3: usize,
829b96c5b5SLoGin     pub a4: usize,
839b96c5b5SLoGin     pub a5: usize,
849b96c5b5SLoGin     pub a6: usize,
859b96c5b5SLoGin     pub a7: usize,
869b96c5b5SLoGin     pub s2: usize,
879b96c5b5SLoGin     pub s3: usize,
889b96c5b5SLoGin     pub s4: usize,
899b96c5b5SLoGin     pub s5: usize,
909b96c5b5SLoGin     pub s6: usize,
919b96c5b5SLoGin     pub s7: usize,
929b96c5b5SLoGin     pub s8: usize,
939b96c5b5SLoGin     pub s9: usize,
949b96c5b5SLoGin     pub s10: usize,
959b96c5b5SLoGin     pub s11: usize,
969b96c5b5SLoGin     pub t3: usize,
979b96c5b5SLoGin     pub t4: usize,
989b96c5b5SLoGin     pub t5: usize,
999b96c5b5SLoGin     pub t6: usize,
1005c4224e5SLoGin     // 以下是中断发生时自动保存的寄存器
1019b96c5b5SLoGin     pub status: Sstatus,
1029b96c5b5SLoGin     pub badaddr: usize,
1039b96c5b5SLoGin     pub cause: Scause,
1045c4224e5SLoGin     /// a0 value before the syscall
1059b96c5b5SLoGin     pub origin_a0: usize,
1064fda81ceSLoGin }
1074fda81ceSLoGin 
1084fda81ceSLoGin impl TrapFrame {
1095c4224e5SLoGin     /// 中断栈帧结构体的大小
1105c4224e5SLoGin     pub const SIZE: usize = core::mem::size_of::<TrapFrame>();
1115c4224e5SLoGin 
1125c4224e5SLoGin     /// 中断栈帧在栈上的大小
1135c4224e5SLoGin     pub const SIZE_ON_STACK: usize = align_up(Self::SIZE, STACK_ALIGN);
1144fda81ceSLoGin     /// 判断当前中断是否来自用户模式
115b5b571e0SLoGin     pub fn is_from_user(&self) -> bool {
1165c4224e5SLoGin         self.status.spp() == riscv::register::sstatus::SPP::User
1174fda81ceSLoGin     }
118e8eab1acSLoGin 
119e8eab1acSLoGin     pub fn new() -> Self {
120e8eab1acSLoGin         Self {
121e8eab1acSLoGin             epc: 0,
122e8eab1acSLoGin             ra: 0,
123e8eab1acSLoGin             sp: 0,
124e8eab1acSLoGin             gp: 0,
125e8eab1acSLoGin             tp: 0,
126e8eab1acSLoGin             t0: 0,
127e8eab1acSLoGin             t1: 0,
128e8eab1acSLoGin             t2: 0,
129e8eab1acSLoGin             s0: 0,
130e8eab1acSLoGin             s1: 0,
131e8eab1acSLoGin             a0: 0,
132e8eab1acSLoGin             a1: 0,
133e8eab1acSLoGin             a2: 0,
134e8eab1acSLoGin             a3: 0,
135e8eab1acSLoGin             a4: 0,
136e8eab1acSLoGin             a5: 0,
137e8eab1acSLoGin             a6: 0,
138e8eab1acSLoGin             a7: 0,
139e8eab1acSLoGin             s2: 0,
140e8eab1acSLoGin             s3: 0,
141e8eab1acSLoGin             s4: 0,
142e8eab1acSLoGin             s5: 0,
143e8eab1acSLoGin             s6: 0,
144e8eab1acSLoGin             s7: 0,
145e8eab1acSLoGin             s8: 0,
146e8eab1acSLoGin             s9: 0,
147e8eab1acSLoGin             s10: 0,
148e8eab1acSLoGin             s11: 0,
149e8eab1acSLoGin             t3: 0,
150e8eab1acSLoGin             t4: 0,
151e8eab1acSLoGin             t5: 0,
152e8eab1acSLoGin             t6: 0,
153e8eab1acSLoGin             status: unsafe { core::mem::zeroed() },
154e8eab1acSLoGin             badaddr: 0,
155e8eab1acSLoGin             cause: unsafe { core::mem::zeroed() },
156e8eab1acSLoGin             origin_a0: 0,
157e8eab1acSLoGin         }
158e8eab1acSLoGin     }
159e8eab1acSLoGin 
160e8eab1acSLoGin     pub fn set_return_value(&mut self, value: usize) {
161e8eab1acSLoGin         self.a0 = value;
162e8eab1acSLoGin     }
1634fda81ceSLoGin }
164