xref: /DragonOS/kernel/src/driver/irqchip/riscv_sifive_plic.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
10102d69fSLoGin //! 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-sifive-plic.c
20102d69fSLoGin //!
30102d69fSLoGin //!
40102d69fSLoGin //!
50102d69fSLoGin //!  This driver implements a version of the RISC-V PLIC with the actual layout
60102d69fSLoGin //!  specified in chapter 8 of the SiFive U5 Coreplex Series Manual:
70102d69fSLoGin //!
80102d69fSLoGin //!      https://static.dev.sifive.com/U54-MC-RVCoreIP.pdf
90102d69fSLoGin //!
100102d69fSLoGin //!  The largest number supported by devices marked as 'sifive,plic-1.0.0', is
110102d69fSLoGin //!  1024, of which device 0 is defined as non-existent by the RISC-V Privileged
120102d69fSLoGin //!  Spec.
130102d69fSLoGin //!
140102d69fSLoGin 
150102d69fSLoGin use core::{
160102d69fSLoGin     fmt::Debug,
170102d69fSLoGin     ops::Deref,
180102d69fSLoGin     ptr::{read_volatile, write_volatile},
190102d69fSLoGin     sync::atomic::AtomicBool,
200102d69fSLoGin };
210102d69fSLoGin 
220102d69fSLoGin use alloc::{
230102d69fSLoGin     string::ToString,
240102d69fSLoGin     sync::{Arc, Weak},
250102d69fSLoGin };
260102d69fSLoGin use bitmap::AllocBitmap;
270102d69fSLoGin use fdt::node::FdtNode;
28*2eab6dd7S曾俊 use log::{debug, warn};
290102d69fSLoGin use system_error::SystemError;
300102d69fSLoGin 
310102d69fSLoGin use crate::{
320102d69fSLoGin     arch::interrupt::TrapFrame,
330102d69fSLoGin     driver::open_firmware::fdt::open_firmware_fdt_driver,
340102d69fSLoGin     exception::{
350102d69fSLoGin         handle::fast_eoi_irq_handler,
360102d69fSLoGin         irqchip::{IrqChip, IrqChipData, IrqChipFlags, IrqChipSetMaskResult},
370102d69fSLoGin         irqdata::IrqData,
380102d69fSLoGin         irqdesc::{irq_desc_manager, GenericIrqHandler},
390102d69fSLoGin         irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps},
400102d69fSLoGin         manage::irq_manager,
410102d69fSLoGin         HardwareIrqNumber, IrqNumber,
420102d69fSLoGin     },
430102d69fSLoGin     libs::{
440102d69fSLoGin         cpumask::CpuMask,
450102d69fSLoGin         once::Once,
460102d69fSLoGin         spinlock::{SpinLock, SpinLockGuard},
470102d69fSLoGin     },
480102d69fSLoGin     mm::{
490102d69fSLoGin         mmio_buddy::{mmio_pool, MMIOSpaceGuard},
500102d69fSLoGin         percpu::{PerCpu, PerCpuVar},
510102d69fSLoGin         PhysAddr, VirtAddr,
520102d69fSLoGin     },
530102d69fSLoGin     smp::cpu::{smp_cpu_manager, ProcessorId},
540102d69fSLoGin };
550102d69fSLoGin 
560102d69fSLoGin static mut PLIC_HANDLERS: Option<PerCpuVar<PlicHandler>> = None;
570102d69fSLoGin 
580102d69fSLoGin static mut PLIC_IRQ_CHIP: Option<Arc<PlicIrqChip>> = None;
590102d69fSLoGin 
600102d69fSLoGin #[inline(always)]
plic_irq_chip() -> Arc<PlicIrqChip>610102d69fSLoGin fn plic_irq_chip() -> Arc<PlicIrqChip> {
620102d69fSLoGin     unsafe { PLIC_IRQ_CHIP.as_ref().unwrap().clone() }
630102d69fSLoGin }
640102d69fSLoGin 
650102d69fSLoGin #[inline(always)]
plic_handlers() -> &'static PerCpuVar<PlicHandler>660102d69fSLoGin fn plic_handlers() -> &'static PerCpuVar<PlicHandler> {
670102d69fSLoGin     unsafe { PLIC_HANDLERS.as_ref().unwrap() }
680102d69fSLoGin }
690102d69fSLoGin 
700102d69fSLoGin #[allow(dead_code)]
710102d69fSLoGin struct PlicChipData {
720102d69fSLoGin     irq_domain: Weak<IrqDomain>,
730102d69fSLoGin     phandle: u32,
740102d69fSLoGin     lmask: SpinLock<CpuMask>,
750102d69fSLoGin     mmio_guard: Option<MMIOSpaceGuard>,
760102d69fSLoGin     regs: VirtAddr,
770102d69fSLoGin }
780102d69fSLoGin 
790102d69fSLoGin impl PlicChipData {
new( irq_domain: Weak<IrqDomain>, mmio_guard: MMIOSpaceGuard, regs: VirtAddr, phandle: u32, ) -> Arc<Self>800102d69fSLoGin     fn new(
810102d69fSLoGin         irq_domain: Weak<IrqDomain>,
820102d69fSLoGin         mmio_guard: MMIOSpaceGuard,
830102d69fSLoGin         regs: VirtAddr,
840102d69fSLoGin         phandle: u32,
850102d69fSLoGin     ) -> Arc<Self> {
860102d69fSLoGin         let r = Self {
870102d69fSLoGin             irq_domain,
880102d69fSLoGin             lmask: SpinLock::new(CpuMask::new()),
890102d69fSLoGin             mmio_guard: Some(mmio_guard),
900102d69fSLoGin             regs,
910102d69fSLoGin             phandle,
920102d69fSLoGin         };
930102d69fSLoGin 
940102d69fSLoGin         Arc::new(r)
950102d69fSLoGin     }
960102d69fSLoGin 
lmask(&self) -> SpinLockGuard<CpuMask>970102d69fSLoGin     fn lmask(&self) -> SpinLockGuard<CpuMask> {
980102d69fSLoGin         self.lmask.lock()
990102d69fSLoGin     }
1000102d69fSLoGin }
1010102d69fSLoGin 
1020102d69fSLoGin impl Debug for PlicChipData {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result1030102d69fSLoGin     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1040102d69fSLoGin         f.debug_struct("PlicChipData").finish()
1050102d69fSLoGin     }
1060102d69fSLoGin }
1070102d69fSLoGin 
1080102d69fSLoGin impl IrqChipData for PlicChipData {
as_any_ref(&self) -> &dyn core::any::Any1090102d69fSLoGin     fn as_any_ref(&self) -> &dyn core::any::Any {
1100102d69fSLoGin         self
1110102d69fSLoGin     }
1120102d69fSLoGin }
1130102d69fSLoGin 
1140102d69fSLoGin struct PlicHandler {
1150102d69fSLoGin     priv_data: Option<Arc<PlicChipData>>,
1160102d69fSLoGin     present: AtomicBool,
1170102d69fSLoGin     inner: SpinLock<InnerPlicHandler>,
1180102d69fSLoGin }
1190102d69fSLoGin 
1200102d69fSLoGin struct InnerPlicHandler {
1210102d69fSLoGin     hart_base: VirtAddr,
1220102d69fSLoGin     enable_base: VirtAddr,
1230102d69fSLoGin     enable_save: Option<AllocBitmap>,
1240102d69fSLoGin }
1250102d69fSLoGin 
1260102d69fSLoGin impl PlicHandler {
new() -> Self1270102d69fSLoGin     fn new() -> Self {
1280102d69fSLoGin         let inner = InnerPlicHandler {
1290102d69fSLoGin             hart_base: VirtAddr::new(0),
1300102d69fSLoGin             enable_base: VirtAddr::new(0),
1310102d69fSLoGin             enable_save: None,
1320102d69fSLoGin         };
1330102d69fSLoGin         Self {
1340102d69fSLoGin             priv_data: None,
1350102d69fSLoGin             present: AtomicBool::new(false),
1360102d69fSLoGin             inner: SpinLock::new(inner),
1370102d69fSLoGin         }
1380102d69fSLoGin     }
1390102d69fSLoGin 
set_threshold(&self, threshold: u32)1400102d69fSLoGin     fn set_threshold(&self, threshold: u32) {
1410102d69fSLoGin         let inner = self.inner();
1420102d69fSLoGin         unsafe {
1430102d69fSLoGin             /* priority must be > threshold to trigger an interrupt */
1440102d69fSLoGin             core::ptr::write_volatile(
1450102d69fSLoGin                 (inner.hart_base + PlicIrqChip::CONTEXT_THRESHOLD).data() as *mut u32,
1460102d69fSLoGin                 threshold,
1470102d69fSLoGin             );
1480102d69fSLoGin         }
1490102d69fSLoGin     }
1500102d69fSLoGin 
force_set_priv_data(&mut self, priv_data: Arc<PlicChipData>)1510102d69fSLoGin     unsafe fn force_set_priv_data(&mut self, priv_data: Arc<PlicChipData>) {
1520102d69fSLoGin         self.priv_data = Some(priv_data);
1530102d69fSLoGin     }
1540102d69fSLoGin 
priv_data(&self) -> Option<Arc<PlicChipData>>1550102d69fSLoGin     fn priv_data(&self) -> Option<Arc<PlicChipData>> {
1560102d69fSLoGin         self.priv_data.clone()
1570102d69fSLoGin     }
1580102d69fSLoGin 
present(&self) -> bool1590102d69fSLoGin     fn present(&self) -> bool {
1600102d69fSLoGin         self.present.load(core::sync::atomic::Ordering::SeqCst)
1610102d69fSLoGin     }
1620102d69fSLoGin 
set_present(&self, present: bool)1630102d69fSLoGin     fn set_present(&self, present: bool) {
1640102d69fSLoGin         self.present
1650102d69fSLoGin             .store(present, core::sync::atomic::Ordering::SeqCst);
1660102d69fSLoGin     }
1670102d69fSLoGin 
inner(&self) -> SpinLockGuard<InnerPlicHandler>1680102d69fSLoGin     fn inner(&self) -> SpinLockGuard<InnerPlicHandler> {
1690102d69fSLoGin         self.inner.lock()
1700102d69fSLoGin     }
1710102d69fSLoGin 
toggle(&self, hwirq: HardwareIrqNumber, enable: bool)1720102d69fSLoGin     fn toggle(&self, hwirq: HardwareIrqNumber, enable: bool) {
1730102d69fSLoGin         let inner = self.inner();
1740102d69fSLoGin         let reg = (inner.enable_base + ((hwirq.data() / 32) * 4) as usize).data() as *mut u32;
1750102d69fSLoGin         let hwirq_mask = 1 << (hwirq.data() % 32);
1760102d69fSLoGin 
1770102d69fSLoGin         if enable {
1780102d69fSLoGin             unsafe {
1790102d69fSLoGin                 core::ptr::write_volatile(reg, core::ptr::read_volatile(reg) | hwirq_mask);
1800102d69fSLoGin             }
1810102d69fSLoGin         } else {
1820102d69fSLoGin             unsafe {
1830102d69fSLoGin                 core::ptr::write_volatile(reg, core::ptr::read_volatile(reg) & !hwirq_mask);
1840102d69fSLoGin             }
1850102d69fSLoGin         }
1860102d69fSLoGin     }
1870102d69fSLoGin }
1880102d69fSLoGin 
plic_irq_toggle(cpumask: &CpuMask, irq_data: &Arc<IrqData>, enable: bool)1890102d69fSLoGin fn plic_irq_toggle(cpumask: &CpuMask, irq_data: &Arc<IrqData>, enable: bool) {
1900102d69fSLoGin     cpumask.iter_cpu().for_each(|cpu| {
191*2eab6dd7S曾俊         debug!("plic: irq_toggle: cpu: {cpu:?}");
1920102d69fSLoGin         let handler = unsafe { plic_handlers().force_get(cpu) };
1930102d69fSLoGin         handler.toggle(irq_data.hardware_irq(), enable);
1940102d69fSLoGin     });
1950102d69fSLoGin }
1960102d69fSLoGin 
1970102d69fSLoGin /// SiFive PLIC中断控制器
1980102d69fSLoGin ///
1990102d69fSLoGin /// https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-sifive-plic.c#204
2000102d69fSLoGin #[derive(Debug)]
2010102d69fSLoGin struct PlicIrqChip;
2020102d69fSLoGin #[allow(dead_code)]
2030102d69fSLoGin impl PlicIrqChip {
2040102d69fSLoGin     const COMPATIBLE: &'static str = "sifive,plic-1.0.0";
2050102d69fSLoGin 
2060102d69fSLoGin     const MAX_DEVICES: u32 = 1024;
2070102d69fSLoGin     const MAX_CONTEXTS: u32 = 15872;
2080102d69fSLoGin 
2090102d69fSLoGin     /*
2100102d69fSLoGin      * Each interrupt source has a priority register associated with it.
2110102d69fSLoGin      * We always hardwire it to one in Linux.
2120102d69fSLoGin      */
2130102d69fSLoGin     const PRIORITY_BASE: usize = 0;
2140102d69fSLoGin     const PRIORITY_PER_ID: usize = 4;
2150102d69fSLoGin 
2160102d69fSLoGin     /*
2170102d69fSLoGin      * Each hart context has a vector of interrupt enable bits associated with it.
2180102d69fSLoGin      * There's one bit for each interrupt source.
2190102d69fSLoGin      */
2200102d69fSLoGin     const CONTEXT_ENABLE_BASE: usize = 0x2080;
2210102d69fSLoGin     const CONTEXT_ENABLE_SIZE: usize = 0x100;
2220102d69fSLoGin 
2230102d69fSLoGin     /*
2240102d69fSLoGin      * Each hart context has a set of control registers associated with it.  Right
2250102d69fSLoGin      * now there's only two: a source priority threshold over which the hart will
2260102d69fSLoGin      * take an interrupt, and a register to claim interrupts.
2270102d69fSLoGin      */
2280102d69fSLoGin     const CONTEXT_BASE: usize = 0x201000;
2290102d69fSLoGin     const CONTEXT_SIZE: usize = 0x2000;
2300102d69fSLoGin     const CONTEXT_THRESHOLD: usize = 0x00;
2310102d69fSLoGin     const CONTEXT_CLAIM: usize = 0x04;
2320102d69fSLoGin 
2330102d69fSLoGin     const PLIC_DISABLE_THRESHOLD: u32 = 0x7;
2340102d69fSLoGin     const PLIC_ENABLE_THRESHOLD: u32 = 0;
2350102d69fSLoGin 
2360102d69fSLoGin     const PLIC_QUIRK_EDGE_INTERRUPT: u32 = 0;
2370102d69fSLoGin }
2380102d69fSLoGin 
2390102d69fSLoGin impl IrqChip for PlicIrqChip {
name(&self) -> &'static str2400102d69fSLoGin     fn name(&self) -> &'static str {
2410102d69fSLoGin         "SiFive PLIC"
2420102d69fSLoGin     }
irq_enable(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError>2430102d69fSLoGin     fn irq_enable(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
244*2eab6dd7S曾俊         // warn!("plic: irq_enable");
2450102d69fSLoGin         let common_data = irq_data.common_data();
2460102d69fSLoGin         let inner_guard = common_data.inner();
2470102d69fSLoGin         let mask = inner_guard.effective_affinity();
2480102d69fSLoGin 
2490102d69fSLoGin         plic_irq_toggle(mask, irq_data, true);
2500102d69fSLoGin         self.irq_unmask(irq_data).expect("irq_unmask failed");
2510102d69fSLoGin 
2520102d69fSLoGin         Ok(())
2530102d69fSLoGin     }
2540102d69fSLoGin 
irq_unmask(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError>2550102d69fSLoGin     fn irq_unmask(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
256*2eab6dd7S曾俊         // warn!("plic: irq_unmask");
2570102d69fSLoGin 
2580102d69fSLoGin         let chip_data = irq_data
2590102d69fSLoGin             .chip_info_read_irqsave()
2600102d69fSLoGin             .chip_data()
2610102d69fSLoGin             .ok_or(SystemError::EINVAL)?;
2620102d69fSLoGin         let plic_chip_data = chip_data
2630102d69fSLoGin             .as_any_ref()
2640102d69fSLoGin             .downcast_ref::<PlicChipData>()
2650102d69fSLoGin             .ok_or(SystemError::EINVAL)?;
2660102d69fSLoGin 
2670102d69fSLoGin         unsafe {
2680102d69fSLoGin             core::ptr::write_volatile(
2690102d69fSLoGin                 (plic_chip_data.regs
2700102d69fSLoGin                     + PlicIrqChip::PRIORITY_BASE
2710102d69fSLoGin                     + irq_data.hardware_irq().data() as usize * PlicIrqChip::PRIORITY_PER_ID)
2720102d69fSLoGin                     .data() as *mut u32,
2730102d69fSLoGin                 1,
2740102d69fSLoGin             );
2750102d69fSLoGin         }
2760102d69fSLoGin 
2770102d69fSLoGin         Ok(())
2780102d69fSLoGin     }
2790102d69fSLoGin 
irq_mask(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError>2800102d69fSLoGin     fn irq_mask(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
2810102d69fSLoGin         let chip_data = irq_data
2820102d69fSLoGin             .chip_info_read_irqsave()
2830102d69fSLoGin             .chip_data()
2840102d69fSLoGin             .ok_or(SystemError::EINVAL)?;
2850102d69fSLoGin         let plic_chip_data = chip_data
2860102d69fSLoGin             .as_any_ref()
2870102d69fSLoGin             .downcast_ref::<PlicChipData>()
2880102d69fSLoGin             .ok_or(SystemError::EINVAL)?;
2890102d69fSLoGin 
2900102d69fSLoGin         unsafe {
2910102d69fSLoGin             core::ptr::write_volatile(
2920102d69fSLoGin                 (plic_chip_data.regs
2930102d69fSLoGin                     + PlicIrqChip::PRIORITY_BASE
2940102d69fSLoGin                     + irq_data.hardware_irq().data() as usize * PlicIrqChip::PRIORITY_PER_ID)
2950102d69fSLoGin                     .data() as *mut u32,
2960102d69fSLoGin                 0,
2970102d69fSLoGin             );
2980102d69fSLoGin         }
2990102d69fSLoGin 
3000102d69fSLoGin         Ok(())
3010102d69fSLoGin     }
3020102d69fSLoGin 
irq_disable(&self, irq_data: &Arc<IrqData>)3030102d69fSLoGin     fn irq_disable(&self, irq_data: &Arc<IrqData>) {
304*2eab6dd7S曾俊         debug!("plic: irq_disable");
3050102d69fSLoGin         let common_data = irq_data.common_data();
3060102d69fSLoGin         let inner_guard = common_data.inner();
3070102d69fSLoGin         let mask = inner_guard.effective_affinity();
3080102d69fSLoGin         plic_irq_toggle(mask, irq_data, false);
3090102d69fSLoGin     }
3100102d69fSLoGin 
irq_eoi(&self, irq_data: &Arc<IrqData>)3110102d69fSLoGin     fn irq_eoi(&self, irq_data: &Arc<IrqData>) {
3120102d69fSLoGin         let handler = plic_handlers().get();
3130102d69fSLoGin 
3140102d69fSLoGin         if core::intrinsics::unlikely(irq_data.common_data().disabled()) {
3150102d69fSLoGin             handler.toggle(irq_data.hardware_irq(), true);
3160102d69fSLoGin             unsafe {
3170102d69fSLoGin                 write_volatile(
3180102d69fSLoGin                     (handler.inner().hart_base + PlicIrqChip::CONTEXT_CLAIM).data() as *mut u32,
3190102d69fSLoGin                     irq_data.hardware_irq().data(),
3200102d69fSLoGin                 );
3210102d69fSLoGin             }
3220102d69fSLoGin 
3230102d69fSLoGin             handler.toggle(irq_data.hardware_irq(), false);
3240102d69fSLoGin         } else {
325*2eab6dd7S曾俊             // debug!("plic: irq_eoi: hwirq: {:?}", irq_data.hardware_irq());
3260102d69fSLoGin             unsafe {
3270102d69fSLoGin                 write_volatile(
3280102d69fSLoGin                     (handler.inner().hart_base + PlicIrqChip::CONTEXT_CLAIM).data() as *mut u32,
3290102d69fSLoGin                     irq_data.hardware_irq().data(),
3300102d69fSLoGin                 );
3310102d69fSLoGin             }
3320102d69fSLoGin         }
3330102d69fSLoGin     }
3340102d69fSLoGin 
irq_ack(&self, _irq: &Arc<IrqData>)3350102d69fSLoGin     fn irq_ack(&self, _irq: &Arc<IrqData>) {
3360102d69fSLoGin         todo!()
3370102d69fSLoGin     }
3380102d69fSLoGin 
can_mask_ack(&self) -> bool3390102d69fSLoGin     fn can_mask_ack(&self) -> bool {
3400102d69fSLoGin         false
3410102d69fSLoGin     }
3420102d69fSLoGin 
can_set_affinity(&self) -> bool3430102d69fSLoGin     fn can_set_affinity(&self) -> bool {
3440102d69fSLoGin         true
3450102d69fSLoGin     }
3460102d69fSLoGin 
3470102d69fSLoGin     /// 设置中断的亲和性
3480102d69fSLoGin     ///
3490102d69fSLoGin     /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-sifive-plic.c#161
irq_set_affinity( &self, irq_data: &Arc<IrqData>, mask_val: &CpuMask, force: bool, ) -> Result<IrqChipSetMaskResult, SystemError>3500102d69fSLoGin     fn irq_set_affinity(
3510102d69fSLoGin         &self,
3520102d69fSLoGin         irq_data: &Arc<IrqData>,
3530102d69fSLoGin         mask_val: &CpuMask,
3540102d69fSLoGin         force: bool,
3550102d69fSLoGin     ) -> Result<IrqChipSetMaskResult, SystemError> {
3560102d69fSLoGin         let chip_data = irq_data
3570102d69fSLoGin             .chip_info_read_irqsave()
3580102d69fSLoGin             .chip_data()
3590102d69fSLoGin             .ok_or(SystemError::EINVAL)?;
3600102d69fSLoGin         let plic_chip_data = chip_data
3610102d69fSLoGin             .as_any_ref()
3620102d69fSLoGin             .downcast_ref::<PlicChipData>()
3630102d69fSLoGin             .ok_or(SystemError::EINVAL)?;
3640102d69fSLoGin 
3650102d69fSLoGin         let mut amask = plic_chip_data.lmask().deref() & mask_val;
3660102d69fSLoGin         let cpu = if force {
3670102d69fSLoGin             mask_val.first()
3680102d69fSLoGin         } else {
3690102d69fSLoGin             amask.bitand_assign(smp_cpu_manager().possible_cpus());
3700102d69fSLoGin             // todo: 随机选择一个CPU
3710102d69fSLoGin             amask.first()
3720102d69fSLoGin         }
3730102d69fSLoGin         .ok_or(SystemError::EINVAL)?;
3740102d69fSLoGin 
3750102d69fSLoGin         if cpu.data() > smp_cpu_manager().present_cpus_count() {
3760102d69fSLoGin             return Err(SystemError::EINVAL);
3770102d69fSLoGin         }
3780102d69fSLoGin 
3790102d69fSLoGin         self.irq_disable(irq_data);
3800102d69fSLoGin         irq_data
3810102d69fSLoGin             .common_data()
3820102d69fSLoGin             .set_effective_affinity(CpuMask::from_cpu(cpu));
3830102d69fSLoGin         if !irq_data.common_data().disabled() {
3840102d69fSLoGin             self.irq_enable(irq_data).ok();
3850102d69fSLoGin         }
3860102d69fSLoGin 
3870102d69fSLoGin         Ok(IrqChipSetMaskResult::Done)
3880102d69fSLoGin     }
3890102d69fSLoGin 
can_set_flow_type(&self) -> bool3900102d69fSLoGin     fn can_set_flow_type(&self) -> bool {
3910102d69fSLoGin         false
3920102d69fSLoGin     }
3930102d69fSLoGin 
flags(&self) -> IrqChipFlags3940102d69fSLoGin     fn flags(&self) -> IrqChipFlags {
3950102d69fSLoGin         IrqChipFlags::empty()
3960102d69fSLoGin     }
3970102d69fSLoGin }
3980102d69fSLoGin 
3990102d69fSLoGin #[inline(never)]
riscv_sifive_plic_init() -> Result<(), SystemError>4000102d69fSLoGin pub fn riscv_sifive_plic_init() -> Result<(), SystemError> {
4010102d69fSLoGin     static INIT_PLIC_IRQ_CHIP_ONCE: Once = Once::new();
4020102d69fSLoGin     INIT_PLIC_IRQ_CHIP_ONCE.call_once(|| unsafe {
4030102d69fSLoGin         PLIC_IRQ_CHIP = Some(Arc::new(PlicIrqChip));
4040102d69fSLoGin 
4050102d69fSLoGin         PLIC_HANDLERS = Some(
4060102d69fSLoGin             PerCpuVar::new(
4070102d69fSLoGin                 (0..PerCpu::MAX_CPU_NUM)
4080102d69fSLoGin                     .map(|_| PlicHandler::new())
4090102d69fSLoGin                     .collect(),
4100102d69fSLoGin             )
4110102d69fSLoGin             .unwrap(),
4120102d69fSLoGin         );
4130102d69fSLoGin     });
4140102d69fSLoGin 
4150102d69fSLoGin     let fdt = open_firmware_fdt_driver().fdt_ref()?;
4160102d69fSLoGin     let all_plics = fdt.all_nodes().filter(|x| {
4170102d69fSLoGin         if let Some(compatible) = x.compatible() {
4180102d69fSLoGin             compatible
4190102d69fSLoGin                 .all()
4200102d69fSLoGin                 .any(|x| x == PlicIrqChip::COMPATIBLE || x == "riscv,plic0")
4210102d69fSLoGin         } else {
4220102d69fSLoGin             false
4230102d69fSLoGin         }
4240102d69fSLoGin     });
4250102d69fSLoGin     for node in all_plics {
4260102d69fSLoGin         if let Err(e) = do_riscv_sifive_plic_init(&node) {
427*2eab6dd7S曾俊             warn!("Failed to init SiFive PLIC: node: {node:?} {e:?}");
4280102d69fSLoGin         }
4290102d69fSLoGin     }
4300102d69fSLoGin 
4310102d69fSLoGin     unsafe { riscv::register::sie::set_sext() };
4320102d69fSLoGin     Ok(())
4330102d69fSLoGin }
4340102d69fSLoGin 
4350102d69fSLoGin /// 初始化SiFive PLIC
4360102d69fSLoGin ///
4370102d69fSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-sifive-plic.c#415
do_riscv_sifive_plic_init(fdt_node: &FdtNode) -> Result<(), SystemError>4380102d69fSLoGin fn do_riscv_sifive_plic_init(fdt_node: &FdtNode) -> Result<(), SystemError> {
4390102d69fSLoGin     let reg = fdt_node
4400102d69fSLoGin         .reg()
4410102d69fSLoGin         .ok_or(SystemError::EINVAL)?
4420102d69fSLoGin         .next()
4430102d69fSLoGin         .ok_or(SystemError::EIO)?;
4440102d69fSLoGin     let paddr = PhysAddr::new(reg.starting_address as usize);
4450102d69fSLoGin     let size = reg.size.ok_or(SystemError::EINVAL)?;
4460102d69fSLoGin     let mmio_guard = mmio_pool().create_mmio(size)?;
4470102d69fSLoGin     let vaddr = unsafe { mmio_guard.map_any_phys(paddr, size) }?;
4480102d69fSLoGin 
4490102d69fSLoGin     let phandle = fdt_node
4500102d69fSLoGin         .property("phandle")
4510102d69fSLoGin         .ok_or(SystemError::EINVAL)?
4520102d69fSLoGin         .as_usize()
4530102d69fSLoGin         .ok_or(SystemError::EINVAL)?;
4540102d69fSLoGin 
4550102d69fSLoGin     // 中断数量
4560102d69fSLoGin     let irq_num = fdt_node
4570102d69fSLoGin         .property("riscv,ndev")
4580102d69fSLoGin         .ok_or(SystemError::EINVAL)?
4590102d69fSLoGin         .as_usize()
4600102d69fSLoGin         .ok_or(SystemError::EINVAL)?;
461*2eab6dd7S曾俊     debug!(
4620102d69fSLoGin         "plic: node: {}, irq_num: {irq_num}, paddr: {paddr:?}, size: {size}",
4630102d69fSLoGin         fdt_node.name
4640102d69fSLoGin     );
4650102d69fSLoGin     let nr_contexts = fdt_node
4660102d69fSLoGin         .interrupts_extended()
4670102d69fSLoGin         .ok_or(SystemError::EINVAL)?
4680102d69fSLoGin         .count();
469*2eab6dd7S曾俊     debug!("plic: nr_contexts: {nr_contexts}");
4700102d69fSLoGin 
4710102d69fSLoGin     let irq_domain = irq_domain_manager()
4720102d69fSLoGin         .create_and_add_linear(
4730102d69fSLoGin             fdt_node.name.to_string(),
4740102d69fSLoGin             &PlicIrqDomainOps,
4750102d69fSLoGin             (irq_num + 1) as u32,
4760102d69fSLoGin         )
4770102d69fSLoGin         .ok_or(SystemError::EINVAL)?;
478*2eab6dd7S曾俊     // debug!("plic: irq_domain: {irq_domain:?}");
4790102d69fSLoGin 
4800102d69fSLoGin     let priv_data = PlicChipData::new(
4810102d69fSLoGin         Arc::downgrade(&irq_domain),
4820102d69fSLoGin         mmio_guard,
4830102d69fSLoGin         vaddr,
4840102d69fSLoGin         phandle as u32,
4850102d69fSLoGin     );
4860102d69fSLoGin     irq_domain.set_host_data(Some(priv_data.clone() as Arc<dyn IrqChipData>));
4870102d69fSLoGin 
4880102d69fSLoGin     let loop_done_setup = |irq_handler: &PlicHandler| {
4890102d69fSLoGin         for x in 1..=irq_num {
4900102d69fSLoGin             irq_handler.toggle(HardwareIrqNumber::new(x as u32), false);
4910102d69fSLoGin 
4920102d69fSLoGin             unsafe {
4930102d69fSLoGin                 core::ptr::write_volatile(
4940102d69fSLoGin                     (priv_data.regs + PlicIrqChip::PRIORITY_BASE + x * PlicIrqChip::PRIORITY_PER_ID)
4950102d69fSLoGin                         .data() as *mut u32,
4960102d69fSLoGin                     1,
4970102d69fSLoGin                 )
4980102d69fSLoGin             };
4990102d69fSLoGin         }
5000102d69fSLoGin     };
5010102d69fSLoGin 
5020102d69fSLoGin     // todo: 学习linux那样处理,获取到hartid,这里暂时糊代码
5030102d69fSLoGin     // linux: https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-sifive-plic.c#458
5040102d69fSLoGin     for i in smp_cpu_manager().present_cpus().iter_cpu() {
5050102d69fSLoGin         let i = i.data() as usize;
5060102d69fSLoGin 
5070102d69fSLoGin         let cpu = ProcessorId::new(i as u32);
5080102d69fSLoGin         let handler = unsafe { plic_handlers().force_get(cpu) };
5090102d69fSLoGin         if handler.present() {
510*2eab6dd7S曾俊             warn!("plic: handler {i} already present.");
5110102d69fSLoGin             handler.set_threshold(PlicIrqChip::PLIC_ENABLE_THRESHOLD);
5120102d69fSLoGin             loop_done_setup(handler);
5130102d69fSLoGin             continue;
5140102d69fSLoGin         }
5150102d69fSLoGin 
516*2eab6dd7S曾俊         debug!("plic: setup lmask {cpu:?}.");
5170102d69fSLoGin         priv_data.lmask().set(cpu, true);
5180102d69fSLoGin         let mut handler_inner = handler.inner();
5190102d69fSLoGin         handler_inner.hart_base =
5200102d69fSLoGin             priv_data.regs + PlicIrqChip::CONTEXT_BASE + i * PlicIrqChip::CONTEXT_SIZE;
5210102d69fSLoGin         handler_inner.enable_base = priv_data.regs
5220102d69fSLoGin             + PlicIrqChip::CONTEXT_ENABLE_BASE
5230102d69fSLoGin             + i * PlicIrqChip::CONTEXT_ENABLE_SIZE;
5240102d69fSLoGin         handler.set_present(true);
5250102d69fSLoGin         unsafe {
5260102d69fSLoGin             plic_handlers()
5270102d69fSLoGin                 .force_get_mut(cpu)
5280102d69fSLoGin                 .force_set_priv_data(priv_data.clone())
5290102d69fSLoGin         };
5300102d69fSLoGin 
5310102d69fSLoGin         handler_inner.enable_save = Some(AllocBitmap::new(irq_num as usize));
5320102d69fSLoGin 
5330102d69fSLoGin         drop(handler_inner);
5340102d69fSLoGin         handler.set_threshold(PlicIrqChip::PLIC_ENABLE_THRESHOLD);
5350102d69fSLoGin 
5360102d69fSLoGin         loop_done_setup(handler);
5370102d69fSLoGin     }
5380102d69fSLoGin 
5390102d69fSLoGin     // 把外部设备的中断与PLIC关联起来
5400102d69fSLoGin     associate_irq_with_plic_domain(&irq_domain, phandle as u32).ok();
5410102d69fSLoGin 
5420102d69fSLoGin     Ok(())
5430102d69fSLoGin }
5440102d69fSLoGin 
5450102d69fSLoGin /// 把设备的中断与PLIC的关联起来
associate_irq_with_plic_domain( irq_domain: &Arc<IrqDomain>, plic_phandle: u32, ) -> Result<(), SystemError>5460102d69fSLoGin fn associate_irq_with_plic_domain(
5470102d69fSLoGin     irq_domain: &Arc<IrqDomain>,
5480102d69fSLoGin     plic_phandle: u32,
5490102d69fSLoGin ) -> Result<(), SystemError> {
5500102d69fSLoGin     let fdt_ref = open_firmware_fdt_driver().fdt_ref()?;
5510102d69fSLoGin     let nodes = fdt_ref.all_nodes().filter(|x| {
5520102d69fSLoGin         if let Some(pa) = x.property("interrupt-parent").and_then(|x| x.as_usize()) {
5530102d69fSLoGin             pa as u32 == plic_phandle
5540102d69fSLoGin         } else {
5550102d69fSLoGin             false
5560102d69fSLoGin         }
5570102d69fSLoGin     });
5580102d69fSLoGin 
5590102d69fSLoGin     for node in nodes {
5600102d69fSLoGin         if let Some(irq) = node.interrupts().and_then(|mut x| x.next()) {
5610102d69fSLoGin             let irq = irq as u32;
5620102d69fSLoGin             let virq = IrqNumber::new(irq);
5630102d69fSLoGin             let hwirq = HardwareIrqNumber::new(irq);
564*2eab6dd7S曾俊             debug!("plic: associate irq: {irq}, virq: {virq:?}, hwirq: {hwirq:?}");
5650102d69fSLoGin             irq_domain_manager()
5660102d69fSLoGin                 .domain_associate(irq_domain, virq, hwirq)
5670102d69fSLoGin                 .ok();
5680102d69fSLoGin         }
5690102d69fSLoGin     }
5700102d69fSLoGin 
5710102d69fSLoGin     Ok(())
5720102d69fSLoGin }
5730102d69fSLoGin #[derive(Debug)]
5740102d69fSLoGin struct PlicIrqDomainOps;
5750102d69fSLoGin 
5760102d69fSLoGin impl IrqDomainOps for PlicIrqDomainOps {
unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber)5770102d69fSLoGin     fn unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber) {
5780102d69fSLoGin         todo!()
5790102d69fSLoGin     }
5800102d69fSLoGin 
map( &self, irq_domain: &Arc<IrqDomain>, hwirq: HardwareIrqNumber, virq: IrqNumber, ) -> Result<(), SystemError>5810102d69fSLoGin     fn map(
5820102d69fSLoGin         &self,
5830102d69fSLoGin         irq_domain: &Arc<IrqDomain>,
5840102d69fSLoGin         hwirq: HardwareIrqNumber,
5850102d69fSLoGin         virq: IrqNumber,
5860102d69fSLoGin     ) -> Result<(), SystemError> {
587*2eab6dd7S曾俊         // debug!("plic: map: virq: {virq:?}, hwirq: {hwirq:?}");
5880102d69fSLoGin 
5890102d69fSLoGin         let chip_data = irq_domain.host_data().ok_or(SystemError::EINVAL)?;
5900102d69fSLoGin         let plic_chip_data = chip_data
5910102d69fSLoGin             .as_any_ref()
5920102d69fSLoGin             .downcast_ref::<PlicChipData>()
5930102d69fSLoGin             .ok_or(SystemError::EINVAL)?;
5940102d69fSLoGin         irq_domain_manager().domain_set_info(
5950102d69fSLoGin             irq_domain,
5960102d69fSLoGin             virq,
5970102d69fSLoGin             hwirq,
5980102d69fSLoGin             plic_irq_chip(),
5990102d69fSLoGin             irq_domain.host_data(),
6000102d69fSLoGin             fast_eoi_irq_handler(),
6010102d69fSLoGin             None,
6020102d69fSLoGin             None,
6030102d69fSLoGin         );
6040102d69fSLoGin         let irq_desc = irq_desc_manager().lookup(virq).unwrap();
6050102d69fSLoGin         irq_desc.set_noprobe();
6060102d69fSLoGin         let mask = plic_chip_data.lmask().clone();
6070102d69fSLoGin         irq_manager().irq_set_affinity(&irq_desc.irq_data(), &irq_desc.inner(), &mask)?;
6080102d69fSLoGin         Ok(())
6090102d69fSLoGin     }
6100102d69fSLoGin 
activate( &self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>, _reserve: bool, ) -> Result<(), SystemError>6110102d69fSLoGin     fn activate(
6120102d69fSLoGin         &self,
6130102d69fSLoGin         _domain: &Arc<IrqDomain>,
6140102d69fSLoGin         _irq_data: &Arc<IrqData>,
6150102d69fSLoGin         _reserve: bool,
6160102d69fSLoGin     ) -> Result<(), SystemError> {
617*2eab6dd7S曾俊         warn!("plic: activate");
6180102d69fSLoGin         loop {}
6190102d69fSLoGin     }
6200102d69fSLoGin 
deactivate(&self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>)6210102d69fSLoGin     fn deactivate(&self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>) {}
6220102d69fSLoGin }
6230102d69fSLoGin 
6240102d69fSLoGin /// 处理PLIC中断
do_plic_irq(trap_frame: &mut TrapFrame)6250102d69fSLoGin pub(super) fn do_plic_irq(trap_frame: &mut TrapFrame) {
626*2eab6dd7S曾俊     // debug!("plic: do_plic_irq");
6270102d69fSLoGin 
6280102d69fSLoGin     let handler = plic_handlers().get();
6290102d69fSLoGin     let priv_data = handler.priv_data();
6300102d69fSLoGin     if priv_data.is_none() {
6310102d69fSLoGin         return;
6320102d69fSLoGin     }
6330102d69fSLoGin 
6340102d69fSLoGin     let domain = priv_data.unwrap().irq_domain.upgrade();
6350102d69fSLoGin     if domain.is_none() {
6360102d69fSLoGin         return;
6370102d69fSLoGin     }
6380102d69fSLoGin 
6390102d69fSLoGin     let domain = domain.unwrap();
6400102d69fSLoGin 
6410102d69fSLoGin     // 循环处理中断
6420102d69fSLoGin     loop {
6430102d69fSLoGin         let claim = unsafe {
6440102d69fSLoGin             read_volatile(
6450102d69fSLoGin                 (handler.inner().hart_base + PlicIrqChip::CONTEXT_CLAIM).data() as *const u32,
6460102d69fSLoGin             )
6470102d69fSLoGin         };
6480102d69fSLoGin 
6490102d69fSLoGin         if claim == 0 {
6500102d69fSLoGin             break;
6510102d69fSLoGin         }
652*2eab6dd7S曾俊         debug!("plic: claim: {claim:?}");
6530102d69fSLoGin 
6540102d69fSLoGin         let hwirq = HardwareIrqNumber::new(claim);
6550102d69fSLoGin         if let Err(e) = GenericIrqHandler::handle_domain_irq(domain.clone(), hwirq, trap_frame) {
656*2eab6dd7S曾俊             warn!("plic: can't find mapping for hwirq {hwirq:?}, {e:?}");
6570102d69fSLoGin         }
6580102d69fSLoGin     }
6590102d69fSLoGin }
660