xref: /DragonOS/kernel/src/driver/irqchip/riscv_intc.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
1338f6903SLoGin use alloc::{string::ToString, sync::Arc};
2*2eab6dd7S曾俊 use log::error;
3338f6903SLoGin use system_error::SystemError;
4338f6903SLoGin 
5f049d1afSLoGin use crate::{
6f049d1afSLoGin     arch::interrupt::TrapFrame,
7f049d1afSLoGin     driver::clocksource::timer_riscv::{riscv_sbi_timer_irq_desc_init, RiscVSbiTimer},
8f049d1afSLoGin     exception::{
9338f6903SLoGin         handle::PerCpuDevIdIrqHandler,
10338f6903SLoGin         irqchip::{IrqChip, IrqChipFlags},
11338f6903SLoGin         irqdata::IrqData,
12f049d1afSLoGin         irqdesc::{irq_desc_manager, GenericIrqHandler},
13338f6903SLoGin         irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps},
140722a06aSLoGin         softirq::do_softirq,
15338f6903SLoGin         HardwareIrqNumber, IrqNumber,
16f049d1afSLoGin     },
17f049d1afSLoGin     libs::spinlock::{SpinLock, SpinLockGuard},
18f049d1afSLoGin     sched::{SchedMode, __schedule},
19338f6903SLoGin };
20338f6903SLoGin 
210102d69fSLoGin use super::riscv_sifive_plic::do_plic_irq;
220102d69fSLoGin 
23338f6903SLoGin static mut RISCV_INTC_DOMAIN: Option<Arc<IrqDomain>> = None;
24338f6903SLoGin static mut RISCV_INTC_CHIP: Option<Arc<RiscvIntcChip>> = None;
25338f6903SLoGin 
26338f6903SLoGin #[inline(always)]
riscv_intc_domain() -> &'static Option<Arc<IrqDomain>>27338f6903SLoGin pub fn riscv_intc_domain() -> &'static Option<Arc<IrqDomain>> {
28338f6903SLoGin     unsafe { &RISCV_INTC_DOMAIN }
29338f6903SLoGin }
30338f6903SLoGin 
31338f6903SLoGin #[inline(always)]
riscv_intc_chip() -> Option<&'static Arc<RiscvIntcChip>>32338f6903SLoGin fn riscv_intc_chip() -> Option<&'static Arc<RiscvIntcChip>> {
33338f6903SLoGin     unsafe { RISCV_INTC_CHIP.as_ref() }
34338f6903SLoGin }
35338f6903SLoGin 
360102d69fSLoGin /// RISC-V INTC虚拟中断号的起始值(192映射物理的0)
370102d69fSLoGin pub const RISCV_INTC_VIRQ_START: u32 = 192;
380102d69fSLoGin 
39338f6903SLoGin #[derive(Debug)]
40f049d1afSLoGin struct RiscvIntcChip {
41f049d1afSLoGin     inner: SpinLock<InnerIrqChip>,
42f049d1afSLoGin }
43338f6903SLoGin 
44338f6903SLoGin impl IrqChip for RiscvIntcChip {
name(&self) -> &'static str45338f6903SLoGin     fn name(&self) -> &'static str {
46338f6903SLoGin         "RISC-V INTC"
47338f6903SLoGin     }
48338f6903SLoGin 
irq_disable(&self, _irq: &Arc<IrqData>)49338f6903SLoGin     fn irq_disable(&self, _irq: &Arc<IrqData>) {}
50338f6903SLoGin 
irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError>51338f6903SLoGin     fn irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
52338f6903SLoGin         unsafe { riscv::register::sie::clear_bits(1 << irq.hardware_irq().data()) };
53338f6903SLoGin         Ok(())
54338f6903SLoGin     }
55338f6903SLoGin 
irq_unmask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError>56338f6903SLoGin     fn irq_unmask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
57338f6903SLoGin         unsafe { riscv::register::sie::set_bits(1 << irq.hardware_irq().data()) };
58338f6903SLoGin         Ok(())
59338f6903SLoGin     }
60338f6903SLoGin 
irq_ack(&self, _irq: &Arc<IrqData>)61f049d1afSLoGin     fn irq_ack(&self, _irq: &Arc<IrqData>) {}
62338f6903SLoGin 
can_mask_ack(&self) -> bool63338f6903SLoGin     fn can_mask_ack(&self) -> bool {
64338f6903SLoGin         false
65338f6903SLoGin     }
66338f6903SLoGin 
irq_eoi(&self, _irq: &Arc<IrqData>)67338f6903SLoGin     fn irq_eoi(&self, _irq: &Arc<IrqData>) {
68338f6903SLoGin         /*
69338f6903SLoGin          * The RISC-V INTC driver uses handle_percpu_devid_irq() flow
70338f6903SLoGin          * for the per-HART local interrupts and child irqchip drivers
71338f6903SLoGin          * (such as PLIC, SBI IPI, CLINT, APLIC, IMSIC, etc) implement
72338f6903SLoGin          * chained handlers for the per-HART local interrupts.
73338f6903SLoGin          *
74338f6903SLoGin          * In the absence of irq_eoi(), the chained_irq_enter() and
75338f6903SLoGin          * chained_irq_exit() functions (used by child irqchip drivers)
76338f6903SLoGin          * will do unnecessary mask/unmask of per-HART local interrupts
77338f6903SLoGin          * at the time of handling interrupts. To avoid this, we provide
78338f6903SLoGin          * an empty irq_eoi() callback for RISC-V INTC irqchip.
79338f6903SLoGin          */
80338f6903SLoGin     }
81338f6903SLoGin 
can_set_affinity(&self) -> bool82338f6903SLoGin     fn can_set_affinity(&self) -> bool {
83338f6903SLoGin         false
84338f6903SLoGin     }
85338f6903SLoGin 
can_set_flow_type(&self) -> bool86338f6903SLoGin     fn can_set_flow_type(&self) -> bool {
87338f6903SLoGin         false
88338f6903SLoGin     }
89338f6903SLoGin 
flags(&self) -> IrqChipFlags90338f6903SLoGin     fn flags(&self) -> IrqChipFlags {
91f049d1afSLoGin         self.inner().flags
92338f6903SLoGin     }
93338f6903SLoGin }
94338f6903SLoGin 
95f049d1afSLoGin impl RiscvIntcChip {
960102d69fSLoGin     const IRQ_SIZE: u32 = 64;
new() -> Self97f049d1afSLoGin     fn new() -> Self {
98f049d1afSLoGin         Self {
99f049d1afSLoGin             inner: SpinLock::new(InnerIrqChip {
100f049d1afSLoGin                 flags: IrqChipFlags::empty(),
101f049d1afSLoGin             }),
102f049d1afSLoGin         }
103f049d1afSLoGin     }
inner(&self) -> SpinLockGuard<InnerIrqChip>104f049d1afSLoGin     fn inner(&self) -> SpinLockGuard<InnerIrqChip> {
105f049d1afSLoGin         self.inner.lock_irqsave()
106f049d1afSLoGin     }
107f049d1afSLoGin }
108f049d1afSLoGin 
109f049d1afSLoGin #[derive(Debug)]
110f049d1afSLoGin struct InnerIrqChip {
111f049d1afSLoGin     flags: IrqChipFlags,
112f049d1afSLoGin }
113f049d1afSLoGin 
114338f6903SLoGin #[derive(Debug)]
115338f6903SLoGin struct RiscvIntcDomainOps;
116338f6903SLoGin 
117338f6903SLoGin impl IrqDomainOps for RiscvIntcDomainOps {
map( &self, irq_domain: &Arc<IrqDomain>, hwirq: HardwareIrqNumber, virq: IrqNumber, ) -> Result<(), SystemError>118338f6903SLoGin     fn map(
119338f6903SLoGin         &self,
120338f6903SLoGin         irq_domain: &Arc<IrqDomain>,
121338f6903SLoGin         hwirq: HardwareIrqNumber,
122338f6903SLoGin         virq: IrqNumber,
123338f6903SLoGin     ) -> Result<(), SystemError> {
124338f6903SLoGin         irq_desc_manager().set_percpu_devid_all(virq)?;
125338f6903SLoGin         irq_domain_manager().domain_set_info(
126338f6903SLoGin             irq_domain,
127338f6903SLoGin             virq,
128338f6903SLoGin             hwirq,
129338f6903SLoGin             riscv_intc_chip().unwrap().clone() as Arc<dyn IrqChip>,
130338f6903SLoGin             irq_domain.host_data(),
131338f6903SLoGin             &PerCpuDevIdIrqHandler,
132338f6903SLoGin             None,
133338f6903SLoGin             None,
134338f6903SLoGin         );
135338f6903SLoGin 
136338f6903SLoGin         return Ok(());
137338f6903SLoGin     }
138338f6903SLoGin 
unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber)139f049d1afSLoGin     fn unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber) {
140338f6903SLoGin         todo!("riscv_intc_domain_ops::unmap");
141338f6903SLoGin     }
142338f6903SLoGin }
143338f6903SLoGin 
144338f6903SLoGin #[inline(never)]
riscv_intc_init() -> Result<(), SystemError>145338f6903SLoGin pub unsafe fn riscv_intc_init() -> Result<(), SystemError> {
146f049d1afSLoGin     let intc_chip = Arc::new(RiscvIntcChip::new());
147338f6903SLoGin 
148338f6903SLoGin     unsafe {
149338f6903SLoGin         RISCV_INTC_CHIP = Some(intc_chip);
150338f6903SLoGin     }
151338f6903SLoGin 
152338f6903SLoGin     let intc_domain = irq_domain_manager()
1530102d69fSLoGin         .create_and_add_linear(
1540102d69fSLoGin             "riscv-intc".to_string(),
1550102d69fSLoGin             &RiscvIntcDomainOps,
1560102d69fSLoGin             RiscvIntcChip::IRQ_SIZE,
1570102d69fSLoGin         )
158338f6903SLoGin         .ok_or_else(|| {
159*2eab6dd7S曾俊             error!("Failed to create riscv-intc domain");
160338f6903SLoGin             SystemError::ENXIO
161338f6903SLoGin         })?;
162338f6903SLoGin 
163338f6903SLoGin     irq_domain_manager().set_default_domain(intc_domain.clone());
164338f6903SLoGin 
165338f6903SLoGin     unsafe {
1660102d69fSLoGin         RISCV_INTC_DOMAIN = Some(intc_domain.clone());
167338f6903SLoGin     }
168338f6903SLoGin 
169f049d1afSLoGin     riscv_sbi_timer_irq_desc_init();
170f049d1afSLoGin 
171338f6903SLoGin     return Ok(());
172338f6903SLoGin }
173f049d1afSLoGin 
1740102d69fSLoGin /// 把硬件中断号转换为riscv intc芯片的中断域的虚拟中断号
riscv_intc_hwirq_to_virq(hwirq: HardwareIrqNumber) -> Option<IrqNumber>1750102d69fSLoGin pub const fn riscv_intc_hwirq_to_virq(hwirq: HardwareIrqNumber) -> Option<IrqNumber> {
1760102d69fSLoGin     if hwirq.data() < RiscvIntcChip::IRQ_SIZE {
1770102d69fSLoGin         Some(IrqNumber::new(hwirq.data() + RISCV_INTC_VIRQ_START))
1780102d69fSLoGin     } else {
1790102d69fSLoGin         None
1800102d69fSLoGin     }
1810102d69fSLoGin }
1820102d69fSLoGin 
1830102d69fSLoGin /// 把riscv intc芯片的的中断域的虚拟中断号转换为硬件中断号
1840102d69fSLoGin #[allow(dead_code)]
riscv_intc_virq_to_hwirq(virq: IrqNumber) -> Option<HardwareIrqNumber>1850102d69fSLoGin pub const fn riscv_intc_virq_to_hwirq(virq: IrqNumber) -> Option<HardwareIrqNumber> {
1860102d69fSLoGin     if virq.data() >= RISCV_INTC_VIRQ_START
1870102d69fSLoGin         && virq.data() < RISCV_INTC_VIRQ_START + RiscvIntcChip::IRQ_SIZE
1880102d69fSLoGin     {
1890102d69fSLoGin         Some(HardwareIrqNumber::new(virq.data() - RISCV_INTC_VIRQ_START))
1900102d69fSLoGin     } else {
1910102d69fSLoGin         None
1920102d69fSLoGin     }
1930102d69fSLoGin }
1940102d69fSLoGin 
1950102d69fSLoGin /// 将硬件中断号与riscv intc芯片的虚拟中断号关联
riscv_intc_assicate_irq(hwirq: HardwareIrqNumber) -> Option<IrqNumber>1960102d69fSLoGin pub fn riscv_intc_assicate_irq(hwirq: HardwareIrqNumber) -> Option<IrqNumber> {
1970102d69fSLoGin     let virq = riscv_intc_hwirq_to_virq(hwirq)?;
1980102d69fSLoGin     irq_domain_manager()
1990102d69fSLoGin         .domain_associate(
2000102d69fSLoGin             riscv_intc_domain().as_ref().or_else(|| {
201*2eab6dd7S曾俊                 error!("riscv_intc_domain is None");
2020102d69fSLoGin                 None
2030102d69fSLoGin             })?,
2040102d69fSLoGin             virq,
2050102d69fSLoGin             hwirq,
2060102d69fSLoGin         )
2070102d69fSLoGin         .ok();
2080102d69fSLoGin 
2090102d69fSLoGin     Some(virq)
2100102d69fSLoGin }
2110102d69fSLoGin 
212f049d1afSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-riscv-intc.c#23
riscv_intc_irq(trap_frame: &mut TrapFrame)213f049d1afSLoGin pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) {
214f049d1afSLoGin     let hwirq = HardwareIrqNumber::new(trap_frame.cause.code() as u32);
2150102d69fSLoGin     if hwirq.data() == 9 {
2160102d69fSLoGin         // external interrupt
2170102d69fSLoGin         do_plic_irq(trap_frame);
2180102d69fSLoGin     } else {
2190102d69fSLoGin         GenericIrqHandler::handle_domain_irq(
2200102d69fSLoGin             riscv_intc_domain().clone().unwrap(),
2210102d69fSLoGin             hwirq,
2220102d69fSLoGin             trap_frame,
2230102d69fSLoGin         )
224f049d1afSLoGin         .ok();
2250102d69fSLoGin     }
2260722a06aSLoGin     do_softirq();
227f049d1afSLoGin     if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() {
228f049d1afSLoGin         __schedule(SchedMode::SM_PREEMPT);
229f049d1afSLoGin     }
230f049d1afSLoGin }
231