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