1338f6903SLoGin use alloc::{string::ToString, sync::Arc}; 2338f6903SLoGin use system_error::SystemError; 3338f6903SLoGin 4*f049d1afSLoGin use crate::{ 5*f049d1afSLoGin arch::interrupt::TrapFrame, 6*f049d1afSLoGin driver::clocksource::timer_riscv::{riscv_sbi_timer_irq_desc_init, RiscVSbiTimer}, 7*f049d1afSLoGin exception::{ 8338f6903SLoGin handle::PerCpuDevIdIrqHandler, 9338f6903SLoGin irqchip::{IrqChip, IrqChipFlags}, 10338f6903SLoGin irqdata::IrqData, 11*f049d1afSLoGin irqdesc::{irq_desc_manager, GenericIrqHandler}, 12338f6903SLoGin irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps}, 13338f6903SLoGin HardwareIrqNumber, IrqNumber, 14*f049d1afSLoGin }, 15*f049d1afSLoGin libs::spinlock::{SpinLock, SpinLockGuard}, 16*f049d1afSLoGin sched::{SchedMode, __schedule}, 17338f6903SLoGin }; 18338f6903SLoGin 19338f6903SLoGin static mut RISCV_INTC_DOMAIN: Option<Arc<IrqDomain>> = None; 20338f6903SLoGin static mut RISCV_INTC_CHIP: Option<Arc<RiscvIntcChip>> = None; 21338f6903SLoGin 22338f6903SLoGin #[inline(always)] 23338f6903SLoGin pub fn riscv_intc_domain() -> &'static Option<Arc<IrqDomain>> { 24338f6903SLoGin unsafe { &RISCV_INTC_DOMAIN } 25338f6903SLoGin } 26338f6903SLoGin 27338f6903SLoGin #[inline(always)] 28338f6903SLoGin fn riscv_intc_chip() -> Option<&'static Arc<RiscvIntcChip>> { 29338f6903SLoGin unsafe { RISCV_INTC_CHIP.as_ref() } 30338f6903SLoGin } 31338f6903SLoGin 32338f6903SLoGin #[derive(Debug)] 33*f049d1afSLoGin struct RiscvIntcChip { 34*f049d1afSLoGin inner: SpinLock<InnerIrqChip>, 35*f049d1afSLoGin } 36338f6903SLoGin 37338f6903SLoGin impl IrqChip for RiscvIntcChip { 38338f6903SLoGin fn name(&self) -> &'static str { 39338f6903SLoGin "RISC-V INTC" 40338f6903SLoGin } 41338f6903SLoGin 42338f6903SLoGin fn irq_disable(&self, _irq: &Arc<IrqData>) {} 43338f6903SLoGin 44338f6903SLoGin fn irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> { 45338f6903SLoGin unsafe { riscv::register::sie::clear_bits(1 << irq.hardware_irq().data()) }; 46338f6903SLoGin Ok(()) 47338f6903SLoGin } 48338f6903SLoGin 49338f6903SLoGin fn irq_unmask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> { 50338f6903SLoGin unsafe { riscv::register::sie::set_bits(1 << irq.hardware_irq().data()) }; 51338f6903SLoGin Ok(()) 52338f6903SLoGin } 53338f6903SLoGin 54*f049d1afSLoGin fn irq_ack(&self, _irq: &Arc<IrqData>) {} 55338f6903SLoGin 56338f6903SLoGin fn can_mask_ack(&self) -> bool { 57338f6903SLoGin false 58338f6903SLoGin } 59338f6903SLoGin 60338f6903SLoGin fn irq_eoi(&self, _irq: &Arc<IrqData>) { 61338f6903SLoGin /* 62338f6903SLoGin * The RISC-V INTC driver uses handle_percpu_devid_irq() flow 63338f6903SLoGin * for the per-HART local interrupts and child irqchip drivers 64338f6903SLoGin * (such as PLIC, SBI IPI, CLINT, APLIC, IMSIC, etc) implement 65338f6903SLoGin * chained handlers for the per-HART local interrupts. 66338f6903SLoGin * 67338f6903SLoGin * In the absence of irq_eoi(), the chained_irq_enter() and 68338f6903SLoGin * chained_irq_exit() functions (used by child irqchip drivers) 69338f6903SLoGin * will do unnecessary mask/unmask of per-HART local interrupts 70338f6903SLoGin * at the time of handling interrupts. To avoid this, we provide 71338f6903SLoGin * an empty irq_eoi() callback for RISC-V INTC irqchip. 72338f6903SLoGin */ 73338f6903SLoGin } 74338f6903SLoGin 75338f6903SLoGin fn can_set_affinity(&self) -> bool { 76338f6903SLoGin false 77338f6903SLoGin } 78338f6903SLoGin 79338f6903SLoGin fn can_set_flow_type(&self) -> bool { 80338f6903SLoGin false 81338f6903SLoGin } 82338f6903SLoGin 83338f6903SLoGin fn flags(&self) -> IrqChipFlags { 84*f049d1afSLoGin self.inner().flags 85338f6903SLoGin } 86338f6903SLoGin } 87338f6903SLoGin 88*f049d1afSLoGin impl RiscvIntcChip { 89*f049d1afSLoGin fn new() -> Self { 90*f049d1afSLoGin Self { 91*f049d1afSLoGin inner: SpinLock::new(InnerIrqChip { 92*f049d1afSLoGin flags: IrqChipFlags::empty(), 93*f049d1afSLoGin }), 94*f049d1afSLoGin } 95*f049d1afSLoGin } 96*f049d1afSLoGin fn inner(&self) -> SpinLockGuard<InnerIrqChip> { 97*f049d1afSLoGin self.inner.lock_irqsave() 98*f049d1afSLoGin } 99*f049d1afSLoGin } 100*f049d1afSLoGin 101*f049d1afSLoGin #[derive(Debug)] 102*f049d1afSLoGin struct InnerIrqChip { 103*f049d1afSLoGin flags: IrqChipFlags, 104*f049d1afSLoGin } 105*f049d1afSLoGin 106338f6903SLoGin #[derive(Debug)] 107338f6903SLoGin struct RiscvIntcDomainOps; 108338f6903SLoGin 109338f6903SLoGin impl IrqDomainOps for RiscvIntcDomainOps { 110338f6903SLoGin fn map( 111338f6903SLoGin &self, 112338f6903SLoGin irq_domain: &Arc<IrqDomain>, 113338f6903SLoGin hwirq: HardwareIrqNumber, 114338f6903SLoGin virq: IrqNumber, 115338f6903SLoGin ) -> Result<(), SystemError> { 116338f6903SLoGin irq_desc_manager().set_percpu_devid_all(virq)?; 117338f6903SLoGin irq_domain_manager().domain_set_info( 118338f6903SLoGin irq_domain, 119338f6903SLoGin virq, 120338f6903SLoGin hwirq, 121338f6903SLoGin riscv_intc_chip().unwrap().clone() as Arc<dyn IrqChip>, 122338f6903SLoGin irq_domain.host_data(), 123338f6903SLoGin &PerCpuDevIdIrqHandler, 124338f6903SLoGin None, 125338f6903SLoGin None, 126338f6903SLoGin ); 127338f6903SLoGin 128338f6903SLoGin return Ok(()); 129338f6903SLoGin } 130338f6903SLoGin 131*f049d1afSLoGin fn unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber) { 132338f6903SLoGin todo!("riscv_intc_domain_ops::unmap"); 133338f6903SLoGin } 134338f6903SLoGin } 135338f6903SLoGin 136338f6903SLoGin #[inline(never)] 137338f6903SLoGin pub unsafe fn riscv_intc_init() -> Result<(), SystemError> { 138*f049d1afSLoGin let intc_chip = Arc::new(RiscvIntcChip::new()); 139338f6903SLoGin 140338f6903SLoGin unsafe { 141338f6903SLoGin RISCV_INTC_CHIP = Some(intc_chip); 142338f6903SLoGin } 143338f6903SLoGin 144338f6903SLoGin let intc_domain = irq_domain_manager() 145338f6903SLoGin .create_and_add_linear("riscv-intc".to_string(), &RiscvIntcDomainOps, 64) 146338f6903SLoGin .ok_or_else(|| { 147338f6903SLoGin kerror!("Failed to create riscv-intc domain"); 148338f6903SLoGin SystemError::ENXIO 149338f6903SLoGin })?; 150338f6903SLoGin 151338f6903SLoGin irq_domain_manager().set_default_domain(intc_domain.clone()); 152338f6903SLoGin 153338f6903SLoGin unsafe { 154338f6903SLoGin RISCV_INTC_DOMAIN = Some(intc_domain); 155338f6903SLoGin } 156338f6903SLoGin 157*f049d1afSLoGin riscv_sbi_timer_irq_desc_init(); 158*f049d1afSLoGin 159338f6903SLoGin return Ok(()); 160338f6903SLoGin } 161*f049d1afSLoGin 162*f049d1afSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-riscv-intc.c#23 163*f049d1afSLoGin pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) { 164*f049d1afSLoGin let hwirq = HardwareIrqNumber::new(trap_frame.cause.code() as u32); 165*f049d1afSLoGin kdebug!("riscv64_do_irq: interrupt {hwirq:?}"); 166*f049d1afSLoGin GenericIrqHandler::handle_domain_irq(riscv_intc_domain().clone().unwrap(), hwirq, trap_frame) 167*f049d1afSLoGin .ok(); 168*f049d1afSLoGin if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() { 169*f049d1afSLoGin __schedule(SchedMode::SM_PREEMPT); 170*f049d1afSLoGin } 171*f049d1afSLoGin } 172