1338f6903SLoGin use alloc::{string::ToString, sync::Arc}; 2338f6903SLoGin use system_error::SystemError; 3338f6903SLoGin 4f049d1afSLoGin use crate::{ 5f049d1afSLoGin arch::interrupt::TrapFrame, 6f049d1afSLoGin driver::clocksource::timer_riscv::{riscv_sbi_timer_irq_desc_init, RiscVSbiTimer}, 7f049d1afSLoGin exception::{ 8338f6903SLoGin handle::PerCpuDevIdIrqHandler, 9338f6903SLoGin irqchip::{IrqChip, IrqChipFlags}, 10338f6903SLoGin irqdata::IrqData, 11f049d1afSLoGin irqdesc::{irq_desc_manager, GenericIrqHandler}, 12338f6903SLoGin irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps}, 130722a06aSLoGin softirq::do_softirq, 14338f6903SLoGin HardwareIrqNumber, IrqNumber, 15f049d1afSLoGin }, 16f049d1afSLoGin libs::spinlock::{SpinLock, SpinLockGuard}, 17f049d1afSLoGin sched::{SchedMode, __schedule}, 18338f6903SLoGin }; 19338f6903SLoGin 20*0102d69fSLoGin use super::riscv_sifive_plic::do_plic_irq; 21*0102d69fSLoGin 22338f6903SLoGin static mut RISCV_INTC_DOMAIN: Option<Arc<IrqDomain>> = None; 23338f6903SLoGin static mut RISCV_INTC_CHIP: Option<Arc<RiscvIntcChip>> = None; 24338f6903SLoGin 25338f6903SLoGin #[inline(always)] 26338f6903SLoGin pub fn riscv_intc_domain() -> &'static Option<Arc<IrqDomain>> { 27338f6903SLoGin unsafe { &RISCV_INTC_DOMAIN } 28338f6903SLoGin } 29338f6903SLoGin 30338f6903SLoGin #[inline(always)] 31338f6903SLoGin fn riscv_intc_chip() -> Option<&'static Arc<RiscvIntcChip>> { 32338f6903SLoGin unsafe { RISCV_INTC_CHIP.as_ref() } 33338f6903SLoGin } 34338f6903SLoGin 35*0102d69fSLoGin /// RISC-V INTC虚拟中断号的起始值(192映射物理的0) 36*0102d69fSLoGin pub const RISCV_INTC_VIRQ_START: u32 = 192; 37*0102d69fSLoGin 38338f6903SLoGin #[derive(Debug)] 39f049d1afSLoGin struct RiscvIntcChip { 40f049d1afSLoGin inner: SpinLock<InnerIrqChip>, 41f049d1afSLoGin } 42338f6903SLoGin 43338f6903SLoGin impl IrqChip for RiscvIntcChip { 44338f6903SLoGin fn name(&self) -> &'static str { 45338f6903SLoGin "RISC-V INTC" 46338f6903SLoGin } 47338f6903SLoGin 48338f6903SLoGin fn irq_disable(&self, _irq: &Arc<IrqData>) {} 49338f6903SLoGin 50338f6903SLoGin fn irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> { 51338f6903SLoGin unsafe { riscv::register::sie::clear_bits(1 << irq.hardware_irq().data()) }; 52338f6903SLoGin Ok(()) 53338f6903SLoGin } 54338f6903SLoGin 55338f6903SLoGin fn irq_unmask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> { 56338f6903SLoGin unsafe { riscv::register::sie::set_bits(1 << irq.hardware_irq().data()) }; 57338f6903SLoGin Ok(()) 58338f6903SLoGin } 59338f6903SLoGin 60f049d1afSLoGin fn irq_ack(&self, _irq: &Arc<IrqData>) {} 61338f6903SLoGin 62338f6903SLoGin fn can_mask_ack(&self) -> bool { 63338f6903SLoGin false 64338f6903SLoGin } 65338f6903SLoGin 66338f6903SLoGin fn irq_eoi(&self, _irq: &Arc<IrqData>) { 67338f6903SLoGin /* 68338f6903SLoGin * The RISC-V INTC driver uses handle_percpu_devid_irq() flow 69338f6903SLoGin * for the per-HART local interrupts and child irqchip drivers 70338f6903SLoGin * (such as PLIC, SBI IPI, CLINT, APLIC, IMSIC, etc) implement 71338f6903SLoGin * chained handlers for the per-HART local interrupts. 72338f6903SLoGin * 73338f6903SLoGin * In the absence of irq_eoi(), the chained_irq_enter() and 74338f6903SLoGin * chained_irq_exit() functions (used by child irqchip drivers) 75338f6903SLoGin * will do unnecessary mask/unmask of per-HART local interrupts 76338f6903SLoGin * at the time of handling interrupts. To avoid this, we provide 77338f6903SLoGin * an empty irq_eoi() callback for RISC-V INTC irqchip. 78338f6903SLoGin */ 79338f6903SLoGin } 80338f6903SLoGin 81338f6903SLoGin fn can_set_affinity(&self) -> bool { 82338f6903SLoGin false 83338f6903SLoGin } 84338f6903SLoGin 85338f6903SLoGin fn can_set_flow_type(&self) -> bool { 86338f6903SLoGin false 87338f6903SLoGin } 88338f6903SLoGin 89338f6903SLoGin fn flags(&self) -> IrqChipFlags { 90f049d1afSLoGin self.inner().flags 91338f6903SLoGin } 92338f6903SLoGin } 93338f6903SLoGin 94f049d1afSLoGin impl RiscvIntcChip { 95*0102d69fSLoGin const IRQ_SIZE: u32 = 64; 96f049d1afSLoGin fn new() -> Self { 97f049d1afSLoGin Self { 98f049d1afSLoGin inner: SpinLock::new(InnerIrqChip { 99f049d1afSLoGin flags: IrqChipFlags::empty(), 100f049d1afSLoGin }), 101f049d1afSLoGin } 102f049d1afSLoGin } 103f049d1afSLoGin fn inner(&self) -> SpinLockGuard<InnerIrqChip> { 104f049d1afSLoGin self.inner.lock_irqsave() 105f049d1afSLoGin } 106f049d1afSLoGin } 107f049d1afSLoGin 108f049d1afSLoGin #[derive(Debug)] 109f049d1afSLoGin struct InnerIrqChip { 110f049d1afSLoGin flags: IrqChipFlags, 111f049d1afSLoGin } 112f049d1afSLoGin 113338f6903SLoGin #[derive(Debug)] 114338f6903SLoGin struct RiscvIntcDomainOps; 115338f6903SLoGin 116338f6903SLoGin impl IrqDomainOps for RiscvIntcDomainOps { 117338f6903SLoGin fn map( 118338f6903SLoGin &self, 119338f6903SLoGin irq_domain: &Arc<IrqDomain>, 120338f6903SLoGin hwirq: HardwareIrqNumber, 121338f6903SLoGin virq: IrqNumber, 122338f6903SLoGin ) -> Result<(), SystemError> { 123338f6903SLoGin irq_desc_manager().set_percpu_devid_all(virq)?; 124338f6903SLoGin irq_domain_manager().domain_set_info( 125338f6903SLoGin irq_domain, 126338f6903SLoGin virq, 127338f6903SLoGin hwirq, 128338f6903SLoGin riscv_intc_chip().unwrap().clone() as Arc<dyn IrqChip>, 129338f6903SLoGin irq_domain.host_data(), 130338f6903SLoGin &PerCpuDevIdIrqHandler, 131338f6903SLoGin None, 132338f6903SLoGin None, 133338f6903SLoGin ); 134338f6903SLoGin 135338f6903SLoGin return Ok(()); 136338f6903SLoGin } 137338f6903SLoGin 138f049d1afSLoGin fn unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber) { 139338f6903SLoGin todo!("riscv_intc_domain_ops::unmap"); 140338f6903SLoGin } 141338f6903SLoGin } 142338f6903SLoGin 143338f6903SLoGin #[inline(never)] 144338f6903SLoGin pub unsafe fn riscv_intc_init() -> Result<(), SystemError> { 145f049d1afSLoGin let intc_chip = Arc::new(RiscvIntcChip::new()); 146338f6903SLoGin 147338f6903SLoGin unsafe { 148338f6903SLoGin RISCV_INTC_CHIP = Some(intc_chip); 149338f6903SLoGin } 150338f6903SLoGin 151338f6903SLoGin let intc_domain = irq_domain_manager() 152*0102d69fSLoGin .create_and_add_linear( 153*0102d69fSLoGin "riscv-intc".to_string(), 154*0102d69fSLoGin &RiscvIntcDomainOps, 155*0102d69fSLoGin RiscvIntcChip::IRQ_SIZE, 156*0102d69fSLoGin ) 157338f6903SLoGin .ok_or_else(|| { 158338f6903SLoGin kerror!("Failed to create riscv-intc domain"); 159338f6903SLoGin SystemError::ENXIO 160338f6903SLoGin })?; 161338f6903SLoGin 162338f6903SLoGin irq_domain_manager().set_default_domain(intc_domain.clone()); 163338f6903SLoGin 164338f6903SLoGin unsafe { 165*0102d69fSLoGin RISCV_INTC_DOMAIN = Some(intc_domain.clone()); 166338f6903SLoGin } 167338f6903SLoGin 168f049d1afSLoGin riscv_sbi_timer_irq_desc_init(); 169f049d1afSLoGin 170338f6903SLoGin return Ok(()); 171338f6903SLoGin } 172f049d1afSLoGin 173*0102d69fSLoGin /// 把硬件中断号转换为riscv intc芯片的中断域的虚拟中断号 174*0102d69fSLoGin pub const fn riscv_intc_hwirq_to_virq(hwirq: HardwareIrqNumber) -> Option<IrqNumber> { 175*0102d69fSLoGin if hwirq.data() < RiscvIntcChip::IRQ_SIZE { 176*0102d69fSLoGin Some(IrqNumber::new(hwirq.data() + RISCV_INTC_VIRQ_START)) 177*0102d69fSLoGin } else { 178*0102d69fSLoGin None 179*0102d69fSLoGin } 180*0102d69fSLoGin } 181*0102d69fSLoGin 182*0102d69fSLoGin /// 把riscv intc芯片的的中断域的虚拟中断号转换为硬件中断号 183*0102d69fSLoGin #[allow(dead_code)] 184*0102d69fSLoGin pub const fn riscv_intc_virq_to_hwirq(virq: IrqNumber) -> Option<HardwareIrqNumber> { 185*0102d69fSLoGin if virq.data() >= RISCV_INTC_VIRQ_START 186*0102d69fSLoGin && virq.data() < RISCV_INTC_VIRQ_START + RiscvIntcChip::IRQ_SIZE 187*0102d69fSLoGin { 188*0102d69fSLoGin Some(HardwareIrqNumber::new(virq.data() - RISCV_INTC_VIRQ_START)) 189*0102d69fSLoGin } else { 190*0102d69fSLoGin None 191*0102d69fSLoGin } 192*0102d69fSLoGin } 193*0102d69fSLoGin 194*0102d69fSLoGin /// 将硬件中断号与riscv intc芯片的虚拟中断号关联 195*0102d69fSLoGin pub fn riscv_intc_assicate_irq(hwirq: HardwareIrqNumber) -> Option<IrqNumber> { 196*0102d69fSLoGin let virq = riscv_intc_hwirq_to_virq(hwirq)?; 197*0102d69fSLoGin irq_domain_manager() 198*0102d69fSLoGin .domain_associate( 199*0102d69fSLoGin riscv_intc_domain().as_ref().or_else(|| { 200*0102d69fSLoGin kerror!("riscv_intc_domain is None"); 201*0102d69fSLoGin None 202*0102d69fSLoGin })?, 203*0102d69fSLoGin virq, 204*0102d69fSLoGin hwirq, 205*0102d69fSLoGin ) 206*0102d69fSLoGin .ok(); 207*0102d69fSLoGin 208*0102d69fSLoGin Some(virq) 209*0102d69fSLoGin } 210*0102d69fSLoGin 211f049d1afSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-riscv-intc.c#23 212f049d1afSLoGin pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) { 213f049d1afSLoGin let hwirq = HardwareIrqNumber::new(trap_frame.cause.code() as u32); 214*0102d69fSLoGin if hwirq.data() == 9 { 215*0102d69fSLoGin // external interrupt 216*0102d69fSLoGin do_plic_irq(trap_frame); 217*0102d69fSLoGin } else { 218*0102d69fSLoGin GenericIrqHandler::handle_domain_irq( 219*0102d69fSLoGin riscv_intc_domain().clone().unwrap(), 220*0102d69fSLoGin hwirq, 221*0102d69fSLoGin trap_frame, 222*0102d69fSLoGin ) 223f049d1afSLoGin .ok(); 224*0102d69fSLoGin } 2250722a06aSLoGin do_softirq(); 226f049d1afSLoGin if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() { 227f049d1afSLoGin __schedule(SchedMode::SM_PREEMPT); 228f049d1afSLoGin } 229f049d1afSLoGin } 230