1*0102d69fSLoGin //! 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-sifive-plic.c 2*0102d69fSLoGin //! 3*0102d69fSLoGin //! 4*0102d69fSLoGin //! 5*0102d69fSLoGin //! This driver implements a version of the RISC-V PLIC with the actual layout 6*0102d69fSLoGin //! specified in chapter 8 of the SiFive U5 Coreplex Series Manual: 7*0102d69fSLoGin //! 8*0102d69fSLoGin //! https://static.dev.sifive.com/U54-MC-RVCoreIP.pdf 9*0102d69fSLoGin //! 10*0102d69fSLoGin //! The largest number supported by devices marked as 'sifive,plic-1.0.0', is 11*0102d69fSLoGin //! 1024, of which device 0 is defined as non-existent by the RISC-V Privileged 12*0102d69fSLoGin //! Spec. 13*0102d69fSLoGin //! 14*0102d69fSLoGin 15*0102d69fSLoGin use core::{ 16*0102d69fSLoGin fmt::Debug, 17*0102d69fSLoGin ops::Deref, 18*0102d69fSLoGin ptr::{read_volatile, write_volatile}, 19*0102d69fSLoGin sync::atomic::AtomicBool, 20*0102d69fSLoGin }; 21*0102d69fSLoGin 22*0102d69fSLoGin use alloc::{ 23*0102d69fSLoGin string::ToString, 24*0102d69fSLoGin sync::{Arc, Weak}, 25*0102d69fSLoGin }; 26*0102d69fSLoGin use bitmap::AllocBitmap; 27*0102d69fSLoGin use fdt::node::FdtNode; 28*0102d69fSLoGin use system_error::SystemError; 29*0102d69fSLoGin 30*0102d69fSLoGin use crate::{ 31*0102d69fSLoGin arch::interrupt::TrapFrame, 32*0102d69fSLoGin driver::open_firmware::fdt::open_firmware_fdt_driver, 33*0102d69fSLoGin exception::{ 34*0102d69fSLoGin handle::fast_eoi_irq_handler, 35*0102d69fSLoGin irqchip::{IrqChip, IrqChipData, IrqChipFlags, IrqChipSetMaskResult}, 36*0102d69fSLoGin irqdata::IrqData, 37*0102d69fSLoGin irqdesc::{irq_desc_manager, GenericIrqHandler}, 38*0102d69fSLoGin irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps}, 39*0102d69fSLoGin manage::irq_manager, 40*0102d69fSLoGin HardwareIrqNumber, IrqNumber, 41*0102d69fSLoGin }, 42*0102d69fSLoGin libs::{ 43*0102d69fSLoGin cpumask::CpuMask, 44*0102d69fSLoGin once::Once, 45*0102d69fSLoGin spinlock::{SpinLock, SpinLockGuard}, 46*0102d69fSLoGin }, 47*0102d69fSLoGin mm::{ 48*0102d69fSLoGin mmio_buddy::{mmio_pool, MMIOSpaceGuard}, 49*0102d69fSLoGin percpu::{PerCpu, PerCpuVar}, 50*0102d69fSLoGin PhysAddr, VirtAddr, 51*0102d69fSLoGin }, 52*0102d69fSLoGin smp::cpu::{smp_cpu_manager, ProcessorId}, 53*0102d69fSLoGin }; 54*0102d69fSLoGin 55*0102d69fSLoGin static mut PLIC_HANDLERS: Option<PerCpuVar<PlicHandler>> = None; 56*0102d69fSLoGin 57*0102d69fSLoGin static mut PLIC_IRQ_CHIP: Option<Arc<PlicIrqChip>> = None; 58*0102d69fSLoGin 59*0102d69fSLoGin #[inline(always)] 60*0102d69fSLoGin fn plic_irq_chip() -> Arc<PlicIrqChip> { 61*0102d69fSLoGin unsafe { PLIC_IRQ_CHIP.as_ref().unwrap().clone() } 62*0102d69fSLoGin } 63*0102d69fSLoGin 64*0102d69fSLoGin #[inline(always)] 65*0102d69fSLoGin fn plic_handlers() -> &'static PerCpuVar<PlicHandler> { 66*0102d69fSLoGin unsafe { PLIC_HANDLERS.as_ref().unwrap() } 67*0102d69fSLoGin } 68*0102d69fSLoGin 69*0102d69fSLoGin #[allow(dead_code)] 70*0102d69fSLoGin struct PlicChipData { 71*0102d69fSLoGin irq_domain: Weak<IrqDomain>, 72*0102d69fSLoGin phandle: u32, 73*0102d69fSLoGin lmask: SpinLock<CpuMask>, 74*0102d69fSLoGin mmio_guard: Option<MMIOSpaceGuard>, 75*0102d69fSLoGin regs: VirtAddr, 76*0102d69fSLoGin } 77*0102d69fSLoGin 78*0102d69fSLoGin impl PlicChipData { 79*0102d69fSLoGin fn new( 80*0102d69fSLoGin irq_domain: Weak<IrqDomain>, 81*0102d69fSLoGin mmio_guard: MMIOSpaceGuard, 82*0102d69fSLoGin regs: VirtAddr, 83*0102d69fSLoGin phandle: u32, 84*0102d69fSLoGin ) -> Arc<Self> { 85*0102d69fSLoGin let r = Self { 86*0102d69fSLoGin irq_domain, 87*0102d69fSLoGin lmask: SpinLock::new(CpuMask::new()), 88*0102d69fSLoGin mmio_guard: Some(mmio_guard), 89*0102d69fSLoGin regs, 90*0102d69fSLoGin phandle, 91*0102d69fSLoGin }; 92*0102d69fSLoGin 93*0102d69fSLoGin Arc::new(r) 94*0102d69fSLoGin } 95*0102d69fSLoGin 96*0102d69fSLoGin fn lmask(&self) -> SpinLockGuard<CpuMask> { 97*0102d69fSLoGin self.lmask.lock() 98*0102d69fSLoGin } 99*0102d69fSLoGin } 100*0102d69fSLoGin 101*0102d69fSLoGin impl Debug for PlicChipData { 102*0102d69fSLoGin fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 103*0102d69fSLoGin f.debug_struct("PlicChipData").finish() 104*0102d69fSLoGin } 105*0102d69fSLoGin } 106*0102d69fSLoGin 107*0102d69fSLoGin impl IrqChipData for PlicChipData { 108*0102d69fSLoGin fn as_any_ref(&self) -> &dyn core::any::Any { 109*0102d69fSLoGin self 110*0102d69fSLoGin } 111*0102d69fSLoGin } 112*0102d69fSLoGin 113*0102d69fSLoGin struct PlicHandler { 114*0102d69fSLoGin priv_data: Option<Arc<PlicChipData>>, 115*0102d69fSLoGin present: AtomicBool, 116*0102d69fSLoGin inner: SpinLock<InnerPlicHandler>, 117*0102d69fSLoGin } 118*0102d69fSLoGin 119*0102d69fSLoGin struct InnerPlicHandler { 120*0102d69fSLoGin hart_base: VirtAddr, 121*0102d69fSLoGin enable_base: VirtAddr, 122*0102d69fSLoGin enable_save: Option<AllocBitmap>, 123*0102d69fSLoGin } 124*0102d69fSLoGin 125*0102d69fSLoGin impl PlicHandler { 126*0102d69fSLoGin fn new() -> Self { 127*0102d69fSLoGin let inner = InnerPlicHandler { 128*0102d69fSLoGin hart_base: VirtAddr::new(0), 129*0102d69fSLoGin enable_base: VirtAddr::new(0), 130*0102d69fSLoGin enable_save: None, 131*0102d69fSLoGin }; 132*0102d69fSLoGin Self { 133*0102d69fSLoGin priv_data: None, 134*0102d69fSLoGin present: AtomicBool::new(false), 135*0102d69fSLoGin inner: SpinLock::new(inner), 136*0102d69fSLoGin } 137*0102d69fSLoGin } 138*0102d69fSLoGin 139*0102d69fSLoGin fn set_threshold(&self, threshold: u32) { 140*0102d69fSLoGin let inner = self.inner(); 141*0102d69fSLoGin unsafe { 142*0102d69fSLoGin /* priority must be > threshold to trigger an interrupt */ 143*0102d69fSLoGin core::ptr::write_volatile( 144*0102d69fSLoGin (inner.hart_base + PlicIrqChip::CONTEXT_THRESHOLD).data() as *mut u32, 145*0102d69fSLoGin threshold, 146*0102d69fSLoGin ); 147*0102d69fSLoGin } 148*0102d69fSLoGin } 149*0102d69fSLoGin 150*0102d69fSLoGin unsafe fn force_set_priv_data(&mut self, priv_data: Arc<PlicChipData>) { 151*0102d69fSLoGin self.priv_data = Some(priv_data); 152*0102d69fSLoGin } 153*0102d69fSLoGin 154*0102d69fSLoGin fn priv_data(&self) -> Option<Arc<PlicChipData>> { 155*0102d69fSLoGin self.priv_data.clone() 156*0102d69fSLoGin } 157*0102d69fSLoGin 158*0102d69fSLoGin fn present(&self) -> bool { 159*0102d69fSLoGin self.present.load(core::sync::atomic::Ordering::SeqCst) 160*0102d69fSLoGin } 161*0102d69fSLoGin 162*0102d69fSLoGin fn set_present(&self, present: bool) { 163*0102d69fSLoGin self.present 164*0102d69fSLoGin .store(present, core::sync::atomic::Ordering::SeqCst); 165*0102d69fSLoGin } 166*0102d69fSLoGin 167*0102d69fSLoGin fn inner(&self) -> SpinLockGuard<InnerPlicHandler> { 168*0102d69fSLoGin self.inner.lock() 169*0102d69fSLoGin } 170*0102d69fSLoGin 171*0102d69fSLoGin fn toggle(&self, hwirq: HardwareIrqNumber, enable: bool) { 172*0102d69fSLoGin let inner = self.inner(); 173*0102d69fSLoGin let reg = (inner.enable_base + ((hwirq.data() / 32) * 4) as usize).data() as *mut u32; 174*0102d69fSLoGin let hwirq_mask = 1 << (hwirq.data() % 32); 175*0102d69fSLoGin 176*0102d69fSLoGin if enable { 177*0102d69fSLoGin unsafe { 178*0102d69fSLoGin core::ptr::write_volatile(reg, core::ptr::read_volatile(reg) | hwirq_mask); 179*0102d69fSLoGin } 180*0102d69fSLoGin } else { 181*0102d69fSLoGin unsafe { 182*0102d69fSLoGin core::ptr::write_volatile(reg, core::ptr::read_volatile(reg) & !hwirq_mask); 183*0102d69fSLoGin } 184*0102d69fSLoGin } 185*0102d69fSLoGin } 186*0102d69fSLoGin } 187*0102d69fSLoGin 188*0102d69fSLoGin fn plic_irq_toggle(cpumask: &CpuMask, irq_data: &Arc<IrqData>, enable: bool) { 189*0102d69fSLoGin cpumask.iter_cpu().for_each(|cpu| { 190*0102d69fSLoGin kdebug!("plic: irq_toggle: cpu: {cpu:?}"); 191*0102d69fSLoGin let handler = unsafe { plic_handlers().force_get(cpu) }; 192*0102d69fSLoGin handler.toggle(irq_data.hardware_irq(), enable); 193*0102d69fSLoGin }); 194*0102d69fSLoGin } 195*0102d69fSLoGin 196*0102d69fSLoGin /// SiFive PLIC中断控制器 197*0102d69fSLoGin /// 198*0102d69fSLoGin /// https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-sifive-plic.c#204 199*0102d69fSLoGin #[derive(Debug)] 200*0102d69fSLoGin struct PlicIrqChip; 201*0102d69fSLoGin #[allow(dead_code)] 202*0102d69fSLoGin impl PlicIrqChip { 203*0102d69fSLoGin const COMPATIBLE: &'static str = "sifive,plic-1.0.0"; 204*0102d69fSLoGin 205*0102d69fSLoGin const MAX_DEVICES: u32 = 1024; 206*0102d69fSLoGin const MAX_CONTEXTS: u32 = 15872; 207*0102d69fSLoGin 208*0102d69fSLoGin /* 209*0102d69fSLoGin * Each interrupt source has a priority register associated with it. 210*0102d69fSLoGin * We always hardwire it to one in Linux. 211*0102d69fSLoGin */ 212*0102d69fSLoGin const PRIORITY_BASE: usize = 0; 213*0102d69fSLoGin const PRIORITY_PER_ID: usize = 4; 214*0102d69fSLoGin 215*0102d69fSLoGin /* 216*0102d69fSLoGin * Each hart context has a vector of interrupt enable bits associated with it. 217*0102d69fSLoGin * There's one bit for each interrupt source. 218*0102d69fSLoGin */ 219*0102d69fSLoGin const CONTEXT_ENABLE_BASE: usize = 0x2080; 220*0102d69fSLoGin const CONTEXT_ENABLE_SIZE: usize = 0x100; 221*0102d69fSLoGin 222*0102d69fSLoGin /* 223*0102d69fSLoGin * Each hart context has a set of control registers associated with it. Right 224*0102d69fSLoGin * now there's only two: a source priority threshold over which the hart will 225*0102d69fSLoGin * take an interrupt, and a register to claim interrupts. 226*0102d69fSLoGin */ 227*0102d69fSLoGin const CONTEXT_BASE: usize = 0x201000; 228*0102d69fSLoGin const CONTEXT_SIZE: usize = 0x2000; 229*0102d69fSLoGin const CONTEXT_THRESHOLD: usize = 0x00; 230*0102d69fSLoGin const CONTEXT_CLAIM: usize = 0x04; 231*0102d69fSLoGin 232*0102d69fSLoGin const PLIC_DISABLE_THRESHOLD: u32 = 0x7; 233*0102d69fSLoGin const PLIC_ENABLE_THRESHOLD: u32 = 0; 234*0102d69fSLoGin 235*0102d69fSLoGin const PLIC_QUIRK_EDGE_INTERRUPT: u32 = 0; 236*0102d69fSLoGin } 237*0102d69fSLoGin 238*0102d69fSLoGin impl IrqChip for PlicIrqChip { 239*0102d69fSLoGin fn name(&self) -> &'static str { 240*0102d69fSLoGin "SiFive PLIC" 241*0102d69fSLoGin } 242*0102d69fSLoGin fn irq_enable(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> { 243*0102d69fSLoGin // kwarn!("plic: irq_enable"); 244*0102d69fSLoGin let common_data = irq_data.common_data(); 245*0102d69fSLoGin let inner_guard = common_data.inner(); 246*0102d69fSLoGin let mask = inner_guard.effective_affinity(); 247*0102d69fSLoGin 248*0102d69fSLoGin plic_irq_toggle(mask, irq_data, true); 249*0102d69fSLoGin self.irq_unmask(irq_data).expect("irq_unmask failed"); 250*0102d69fSLoGin 251*0102d69fSLoGin Ok(()) 252*0102d69fSLoGin } 253*0102d69fSLoGin 254*0102d69fSLoGin fn irq_unmask(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> { 255*0102d69fSLoGin // kwarn!("plic: irq_unmask"); 256*0102d69fSLoGin 257*0102d69fSLoGin let chip_data = irq_data 258*0102d69fSLoGin .chip_info_read_irqsave() 259*0102d69fSLoGin .chip_data() 260*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 261*0102d69fSLoGin let plic_chip_data = chip_data 262*0102d69fSLoGin .as_any_ref() 263*0102d69fSLoGin .downcast_ref::<PlicChipData>() 264*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 265*0102d69fSLoGin 266*0102d69fSLoGin unsafe { 267*0102d69fSLoGin core::ptr::write_volatile( 268*0102d69fSLoGin (plic_chip_data.regs 269*0102d69fSLoGin + PlicIrqChip::PRIORITY_BASE 270*0102d69fSLoGin + irq_data.hardware_irq().data() as usize * PlicIrqChip::PRIORITY_PER_ID) 271*0102d69fSLoGin .data() as *mut u32, 272*0102d69fSLoGin 1, 273*0102d69fSLoGin ); 274*0102d69fSLoGin } 275*0102d69fSLoGin 276*0102d69fSLoGin Ok(()) 277*0102d69fSLoGin } 278*0102d69fSLoGin 279*0102d69fSLoGin fn irq_mask(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> { 280*0102d69fSLoGin let chip_data = irq_data 281*0102d69fSLoGin .chip_info_read_irqsave() 282*0102d69fSLoGin .chip_data() 283*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 284*0102d69fSLoGin let plic_chip_data = chip_data 285*0102d69fSLoGin .as_any_ref() 286*0102d69fSLoGin .downcast_ref::<PlicChipData>() 287*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 288*0102d69fSLoGin 289*0102d69fSLoGin unsafe { 290*0102d69fSLoGin core::ptr::write_volatile( 291*0102d69fSLoGin (plic_chip_data.regs 292*0102d69fSLoGin + PlicIrqChip::PRIORITY_BASE 293*0102d69fSLoGin + irq_data.hardware_irq().data() as usize * PlicIrqChip::PRIORITY_PER_ID) 294*0102d69fSLoGin .data() as *mut u32, 295*0102d69fSLoGin 0, 296*0102d69fSLoGin ); 297*0102d69fSLoGin } 298*0102d69fSLoGin 299*0102d69fSLoGin Ok(()) 300*0102d69fSLoGin } 301*0102d69fSLoGin 302*0102d69fSLoGin fn irq_disable(&self, irq_data: &Arc<IrqData>) { 303*0102d69fSLoGin kdebug!("plic: irq_disable"); 304*0102d69fSLoGin let common_data = irq_data.common_data(); 305*0102d69fSLoGin let inner_guard = common_data.inner(); 306*0102d69fSLoGin let mask = inner_guard.effective_affinity(); 307*0102d69fSLoGin plic_irq_toggle(mask, irq_data, false); 308*0102d69fSLoGin } 309*0102d69fSLoGin 310*0102d69fSLoGin fn irq_eoi(&self, irq_data: &Arc<IrqData>) { 311*0102d69fSLoGin let handler = plic_handlers().get(); 312*0102d69fSLoGin 313*0102d69fSLoGin if core::intrinsics::unlikely(irq_data.common_data().disabled()) { 314*0102d69fSLoGin handler.toggle(irq_data.hardware_irq(), true); 315*0102d69fSLoGin unsafe { 316*0102d69fSLoGin write_volatile( 317*0102d69fSLoGin (handler.inner().hart_base + PlicIrqChip::CONTEXT_CLAIM).data() as *mut u32, 318*0102d69fSLoGin irq_data.hardware_irq().data(), 319*0102d69fSLoGin ); 320*0102d69fSLoGin } 321*0102d69fSLoGin 322*0102d69fSLoGin handler.toggle(irq_data.hardware_irq(), false); 323*0102d69fSLoGin } else { 324*0102d69fSLoGin // kdebug!("plic: irq_eoi: hwirq: {:?}", irq_data.hardware_irq()); 325*0102d69fSLoGin unsafe { 326*0102d69fSLoGin write_volatile( 327*0102d69fSLoGin (handler.inner().hart_base + PlicIrqChip::CONTEXT_CLAIM).data() as *mut u32, 328*0102d69fSLoGin irq_data.hardware_irq().data(), 329*0102d69fSLoGin ); 330*0102d69fSLoGin } 331*0102d69fSLoGin } 332*0102d69fSLoGin } 333*0102d69fSLoGin 334*0102d69fSLoGin fn irq_ack(&self, _irq: &Arc<IrqData>) { 335*0102d69fSLoGin todo!() 336*0102d69fSLoGin } 337*0102d69fSLoGin 338*0102d69fSLoGin fn can_mask_ack(&self) -> bool { 339*0102d69fSLoGin false 340*0102d69fSLoGin } 341*0102d69fSLoGin 342*0102d69fSLoGin fn can_set_affinity(&self) -> bool { 343*0102d69fSLoGin true 344*0102d69fSLoGin } 345*0102d69fSLoGin 346*0102d69fSLoGin /// 设置中断的亲和性 347*0102d69fSLoGin /// 348*0102d69fSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-sifive-plic.c#161 349*0102d69fSLoGin fn irq_set_affinity( 350*0102d69fSLoGin &self, 351*0102d69fSLoGin irq_data: &Arc<IrqData>, 352*0102d69fSLoGin mask_val: &CpuMask, 353*0102d69fSLoGin force: bool, 354*0102d69fSLoGin ) -> Result<IrqChipSetMaskResult, SystemError> { 355*0102d69fSLoGin let chip_data = irq_data 356*0102d69fSLoGin .chip_info_read_irqsave() 357*0102d69fSLoGin .chip_data() 358*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 359*0102d69fSLoGin let plic_chip_data = chip_data 360*0102d69fSLoGin .as_any_ref() 361*0102d69fSLoGin .downcast_ref::<PlicChipData>() 362*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 363*0102d69fSLoGin 364*0102d69fSLoGin let mut amask = plic_chip_data.lmask().deref() & mask_val; 365*0102d69fSLoGin let cpu = if force { 366*0102d69fSLoGin mask_val.first() 367*0102d69fSLoGin } else { 368*0102d69fSLoGin amask.bitand_assign(smp_cpu_manager().possible_cpus()); 369*0102d69fSLoGin // todo: 随机选择一个CPU 370*0102d69fSLoGin amask.first() 371*0102d69fSLoGin } 372*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 373*0102d69fSLoGin 374*0102d69fSLoGin if cpu.data() > smp_cpu_manager().present_cpus_count() { 375*0102d69fSLoGin return Err(SystemError::EINVAL); 376*0102d69fSLoGin } 377*0102d69fSLoGin 378*0102d69fSLoGin self.irq_disable(irq_data); 379*0102d69fSLoGin irq_data 380*0102d69fSLoGin .common_data() 381*0102d69fSLoGin .set_effective_affinity(CpuMask::from_cpu(cpu)); 382*0102d69fSLoGin if !irq_data.common_data().disabled() { 383*0102d69fSLoGin self.irq_enable(irq_data).ok(); 384*0102d69fSLoGin } 385*0102d69fSLoGin 386*0102d69fSLoGin Ok(IrqChipSetMaskResult::Done) 387*0102d69fSLoGin } 388*0102d69fSLoGin 389*0102d69fSLoGin fn can_set_flow_type(&self) -> bool { 390*0102d69fSLoGin false 391*0102d69fSLoGin } 392*0102d69fSLoGin 393*0102d69fSLoGin fn flags(&self) -> IrqChipFlags { 394*0102d69fSLoGin IrqChipFlags::empty() 395*0102d69fSLoGin } 396*0102d69fSLoGin } 397*0102d69fSLoGin 398*0102d69fSLoGin #[inline(never)] 399*0102d69fSLoGin pub fn riscv_sifive_plic_init() -> Result<(), SystemError> { 400*0102d69fSLoGin static INIT_PLIC_IRQ_CHIP_ONCE: Once = Once::new(); 401*0102d69fSLoGin INIT_PLIC_IRQ_CHIP_ONCE.call_once(|| unsafe { 402*0102d69fSLoGin PLIC_IRQ_CHIP = Some(Arc::new(PlicIrqChip)); 403*0102d69fSLoGin 404*0102d69fSLoGin PLIC_HANDLERS = Some( 405*0102d69fSLoGin PerCpuVar::new( 406*0102d69fSLoGin (0..PerCpu::MAX_CPU_NUM) 407*0102d69fSLoGin .map(|_| PlicHandler::new()) 408*0102d69fSLoGin .collect(), 409*0102d69fSLoGin ) 410*0102d69fSLoGin .unwrap(), 411*0102d69fSLoGin ); 412*0102d69fSLoGin }); 413*0102d69fSLoGin 414*0102d69fSLoGin let fdt = open_firmware_fdt_driver().fdt_ref()?; 415*0102d69fSLoGin let all_plics = fdt.all_nodes().filter(|x| { 416*0102d69fSLoGin if let Some(compatible) = x.compatible() { 417*0102d69fSLoGin compatible 418*0102d69fSLoGin .all() 419*0102d69fSLoGin .any(|x| x == PlicIrqChip::COMPATIBLE || x == "riscv,plic0") 420*0102d69fSLoGin } else { 421*0102d69fSLoGin false 422*0102d69fSLoGin } 423*0102d69fSLoGin }); 424*0102d69fSLoGin for node in all_plics { 425*0102d69fSLoGin if let Err(e) = do_riscv_sifive_plic_init(&node) { 426*0102d69fSLoGin kwarn!("Failed to init SiFive PLIC: node: {node:?} {e:?}"); 427*0102d69fSLoGin } 428*0102d69fSLoGin } 429*0102d69fSLoGin 430*0102d69fSLoGin unsafe { riscv::register::sie::set_sext() }; 431*0102d69fSLoGin Ok(()) 432*0102d69fSLoGin } 433*0102d69fSLoGin 434*0102d69fSLoGin /// 初始化SiFive PLIC 435*0102d69fSLoGin /// 436*0102d69fSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-sifive-plic.c#415 437*0102d69fSLoGin fn do_riscv_sifive_plic_init(fdt_node: &FdtNode) -> Result<(), SystemError> { 438*0102d69fSLoGin let reg = fdt_node 439*0102d69fSLoGin .reg() 440*0102d69fSLoGin .ok_or(SystemError::EINVAL)? 441*0102d69fSLoGin .next() 442*0102d69fSLoGin .ok_or(SystemError::EIO)?; 443*0102d69fSLoGin let paddr = PhysAddr::new(reg.starting_address as usize); 444*0102d69fSLoGin let size = reg.size.ok_or(SystemError::EINVAL)?; 445*0102d69fSLoGin let mmio_guard = mmio_pool().create_mmio(size)?; 446*0102d69fSLoGin let vaddr = unsafe { mmio_guard.map_any_phys(paddr, size) }?; 447*0102d69fSLoGin 448*0102d69fSLoGin let phandle = fdt_node 449*0102d69fSLoGin .property("phandle") 450*0102d69fSLoGin .ok_or(SystemError::EINVAL)? 451*0102d69fSLoGin .as_usize() 452*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 453*0102d69fSLoGin 454*0102d69fSLoGin // 中断数量 455*0102d69fSLoGin let irq_num = fdt_node 456*0102d69fSLoGin .property("riscv,ndev") 457*0102d69fSLoGin .ok_or(SystemError::EINVAL)? 458*0102d69fSLoGin .as_usize() 459*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 460*0102d69fSLoGin kdebug!( 461*0102d69fSLoGin "plic: node: {}, irq_num: {irq_num}, paddr: {paddr:?}, size: {size}", 462*0102d69fSLoGin fdt_node.name 463*0102d69fSLoGin ); 464*0102d69fSLoGin let nr_contexts = fdt_node 465*0102d69fSLoGin .interrupts_extended() 466*0102d69fSLoGin .ok_or(SystemError::EINVAL)? 467*0102d69fSLoGin .count(); 468*0102d69fSLoGin kdebug!("plic: nr_contexts: {nr_contexts}"); 469*0102d69fSLoGin 470*0102d69fSLoGin let irq_domain = irq_domain_manager() 471*0102d69fSLoGin .create_and_add_linear( 472*0102d69fSLoGin fdt_node.name.to_string(), 473*0102d69fSLoGin &PlicIrqDomainOps, 474*0102d69fSLoGin (irq_num + 1) as u32, 475*0102d69fSLoGin ) 476*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 477*0102d69fSLoGin // kdebug!("plic: irq_domain: {irq_domain:?}"); 478*0102d69fSLoGin 479*0102d69fSLoGin let priv_data = PlicChipData::new( 480*0102d69fSLoGin Arc::downgrade(&irq_domain), 481*0102d69fSLoGin mmio_guard, 482*0102d69fSLoGin vaddr, 483*0102d69fSLoGin phandle as u32, 484*0102d69fSLoGin ); 485*0102d69fSLoGin irq_domain.set_host_data(Some(priv_data.clone() as Arc<dyn IrqChipData>)); 486*0102d69fSLoGin 487*0102d69fSLoGin let loop_done_setup = |irq_handler: &PlicHandler| { 488*0102d69fSLoGin for x in 1..=irq_num { 489*0102d69fSLoGin irq_handler.toggle(HardwareIrqNumber::new(x as u32), false); 490*0102d69fSLoGin 491*0102d69fSLoGin unsafe { 492*0102d69fSLoGin core::ptr::write_volatile( 493*0102d69fSLoGin (priv_data.regs + PlicIrqChip::PRIORITY_BASE + x * PlicIrqChip::PRIORITY_PER_ID) 494*0102d69fSLoGin .data() as *mut u32, 495*0102d69fSLoGin 1, 496*0102d69fSLoGin ) 497*0102d69fSLoGin }; 498*0102d69fSLoGin } 499*0102d69fSLoGin }; 500*0102d69fSLoGin 501*0102d69fSLoGin // todo: 学习linux那样处理,获取到hartid,这里暂时糊代码 502*0102d69fSLoGin // linux: https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-sifive-plic.c#458 503*0102d69fSLoGin for i in smp_cpu_manager().present_cpus().iter_cpu() { 504*0102d69fSLoGin let i = i.data() as usize; 505*0102d69fSLoGin 506*0102d69fSLoGin let cpu = ProcessorId::new(i as u32); 507*0102d69fSLoGin let handler = unsafe { plic_handlers().force_get(cpu) }; 508*0102d69fSLoGin if handler.present() { 509*0102d69fSLoGin kwarn!("plic: handler {i} already present."); 510*0102d69fSLoGin handler.set_threshold(PlicIrqChip::PLIC_ENABLE_THRESHOLD); 511*0102d69fSLoGin loop_done_setup(handler); 512*0102d69fSLoGin continue; 513*0102d69fSLoGin } 514*0102d69fSLoGin 515*0102d69fSLoGin kdebug!("plic: setup lmask {cpu:?}."); 516*0102d69fSLoGin priv_data.lmask().set(cpu, true); 517*0102d69fSLoGin let mut handler_inner = handler.inner(); 518*0102d69fSLoGin handler_inner.hart_base = 519*0102d69fSLoGin priv_data.regs + PlicIrqChip::CONTEXT_BASE + i * PlicIrqChip::CONTEXT_SIZE; 520*0102d69fSLoGin handler_inner.enable_base = priv_data.regs 521*0102d69fSLoGin + PlicIrqChip::CONTEXT_ENABLE_BASE 522*0102d69fSLoGin + i * PlicIrqChip::CONTEXT_ENABLE_SIZE; 523*0102d69fSLoGin handler.set_present(true); 524*0102d69fSLoGin unsafe { 525*0102d69fSLoGin plic_handlers() 526*0102d69fSLoGin .force_get_mut(cpu) 527*0102d69fSLoGin .force_set_priv_data(priv_data.clone()) 528*0102d69fSLoGin }; 529*0102d69fSLoGin 530*0102d69fSLoGin handler_inner.enable_save = Some(AllocBitmap::new(irq_num as usize)); 531*0102d69fSLoGin 532*0102d69fSLoGin drop(handler_inner); 533*0102d69fSLoGin handler.set_threshold(PlicIrqChip::PLIC_ENABLE_THRESHOLD); 534*0102d69fSLoGin 535*0102d69fSLoGin loop_done_setup(handler); 536*0102d69fSLoGin } 537*0102d69fSLoGin 538*0102d69fSLoGin // 把外部设备的中断与PLIC关联起来 539*0102d69fSLoGin associate_irq_with_plic_domain(&irq_domain, phandle as u32).ok(); 540*0102d69fSLoGin 541*0102d69fSLoGin Ok(()) 542*0102d69fSLoGin } 543*0102d69fSLoGin 544*0102d69fSLoGin /// 把设备的中断与PLIC的关联起来 545*0102d69fSLoGin fn associate_irq_with_plic_domain( 546*0102d69fSLoGin irq_domain: &Arc<IrqDomain>, 547*0102d69fSLoGin plic_phandle: u32, 548*0102d69fSLoGin ) -> Result<(), SystemError> { 549*0102d69fSLoGin let fdt_ref = open_firmware_fdt_driver().fdt_ref()?; 550*0102d69fSLoGin let nodes = fdt_ref.all_nodes().filter(|x| { 551*0102d69fSLoGin if let Some(pa) = x.property("interrupt-parent").and_then(|x| x.as_usize()) { 552*0102d69fSLoGin pa as u32 == plic_phandle 553*0102d69fSLoGin } else { 554*0102d69fSLoGin false 555*0102d69fSLoGin } 556*0102d69fSLoGin }); 557*0102d69fSLoGin 558*0102d69fSLoGin for node in nodes { 559*0102d69fSLoGin if let Some(irq) = node.interrupts().and_then(|mut x| x.next()) { 560*0102d69fSLoGin let irq = irq as u32; 561*0102d69fSLoGin let virq = IrqNumber::new(irq); 562*0102d69fSLoGin let hwirq = HardwareIrqNumber::new(irq); 563*0102d69fSLoGin kdebug!("plic: associate irq: {irq}, virq: {virq:?}, hwirq: {hwirq:?}"); 564*0102d69fSLoGin irq_domain_manager() 565*0102d69fSLoGin .domain_associate(irq_domain, virq, hwirq) 566*0102d69fSLoGin .ok(); 567*0102d69fSLoGin } 568*0102d69fSLoGin } 569*0102d69fSLoGin 570*0102d69fSLoGin Ok(()) 571*0102d69fSLoGin } 572*0102d69fSLoGin #[derive(Debug)] 573*0102d69fSLoGin struct PlicIrqDomainOps; 574*0102d69fSLoGin 575*0102d69fSLoGin impl IrqDomainOps for PlicIrqDomainOps { 576*0102d69fSLoGin fn unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber) { 577*0102d69fSLoGin todo!() 578*0102d69fSLoGin } 579*0102d69fSLoGin 580*0102d69fSLoGin fn map( 581*0102d69fSLoGin &self, 582*0102d69fSLoGin irq_domain: &Arc<IrqDomain>, 583*0102d69fSLoGin hwirq: HardwareIrqNumber, 584*0102d69fSLoGin virq: IrqNumber, 585*0102d69fSLoGin ) -> Result<(), SystemError> { 586*0102d69fSLoGin // kdebug!("plic: map: virq: {virq:?}, hwirq: {hwirq:?}"); 587*0102d69fSLoGin 588*0102d69fSLoGin let chip_data = irq_domain.host_data().ok_or(SystemError::EINVAL)?; 589*0102d69fSLoGin let plic_chip_data = chip_data 590*0102d69fSLoGin .as_any_ref() 591*0102d69fSLoGin .downcast_ref::<PlicChipData>() 592*0102d69fSLoGin .ok_or(SystemError::EINVAL)?; 593*0102d69fSLoGin irq_domain_manager().domain_set_info( 594*0102d69fSLoGin irq_domain, 595*0102d69fSLoGin virq, 596*0102d69fSLoGin hwirq, 597*0102d69fSLoGin plic_irq_chip(), 598*0102d69fSLoGin irq_domain.host_data(), 599*0102d69fSLoGin fast_eoi_irq_handler(), 600*0102d69fSLoGin None, 601*0102d69fSLoGin None, 602*0102d69fSLoGin ); 603*0102d69fSLoGin let irq_desc = irq_desc_manager().lookup(virq).unwrap(); 604*0102d69fSLoGin irq_desc.set_noprobe(); 605*0102d69fSLoGin let mask = plic_chip_data.lmask().clone(); 606*0102d69fSLoGin irq_manager().irq_set_affinity(&irq_desc.irq_data(), &irq_desc.inner(), &mask)?; 607*0102d69fSLoGin Ok(()) 608*0102d69fSLoGin } 609*0102d69fSLoGin 610*0102d69fSLoGin fn activate( 611*0102d69fSLoGin &self, 612*0102d69fSLoGin _domain: &Arc<IrqDomain>, 613*0102d69fSLoGin _irq_data: &Arc<IrqData>, 614*0102d69fSLoGin _reserve: bool, 615*0102d69fSLoGin ) -> Result<(), SystemError> { 616*0102d69fSLoGin kwarn!("plic: activate"); 617*0102d69fSLoGin loop {} 618*0102d69fSLoGin } 619*0102d69fSLoGin 620*0102d69fSLoGin fn deactivate(&self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>) {} 621*0102d69fSLoGin } 622*0102d69fSLoGin 623*0102d69fSLoGin /// 处理PLIC中断 624*0102d69fSLoGin pub(super) fn do_plic_irq(trap_frame: &mut TrapFrame) { 625*0102d69fSLoGin // kdebug!("plic: do_plic_irq"); 626*0102d69fSLoGin 627*0102d69fSLoGin let handler = plic_handlers().get(); 628*0102d69fSLoGin let priv_data = handler.priv_data(); 629*0102d69fSLoGin if priv_data.is_none() { 630*0102d69fSLoGin return; 631*0102d69fSLoGin } 632*0102d69fSLoGin 633*0102d69fSLoGin let domain = priv_data.unwrap().irq_domain.upgrade(); 634*0102d69fSLoGin if domain.is_none() { 635*0102d69fSLoGin return; 636*0102d69fSLoGin } 637*0102d69fSLoGin 638*0102d69fSLoGin let domain = domain.unwrap(); 639*0102d69fSLoGin 640*0102d69fSLoGin // 循环处理中断 641*0102d69fSLoGin loop { 642*0102d69fSLoGin let claim = unsafe { 643*0102d69fSLoGin read_volatile( 644*0102d69fSLoGin (handler.inner().hart_base + PlicIrqChip::CONTEXT_CLAIM).data() as *const u32, 645*0102d69fSLoGin ) 646*0102d69fSLoGin }; 647*0102d69fSLoGin 648*0102d69fSLoGin if claim == 0 { 649*0102d69fSLoGin break; 650*0102d69fSLoGin } 651*0102d69fSLoGin kdebug!("plic: claim: {claim:?}"); 652*0102d69fSLoGin 653*0102d69fSLoGin let hwirq = HardwareIrqNumber::new(claim); 654*0102d69fSLoGin if let Err(e) = GenericIrqHandler::handle_domain_irq(domain.clone(), hwirq, trap_frame) { 655*0102d69fSLoGin kwarn!("plic: can't find mapping for hwirq {hwirq:?}, {e:?}"); 656*0102d69fSLoGin } 657*0102d69fSLoGin } 658*0102d69fSLoGin } 659