1338f6903SLoGin use alloc::{string::ToString, sync::Arc};
2*2eab6dd7S曾俊 use log::error;
3338f6903SLoGin use system_error::SystemError;
4338f6903SLoGin
5f049d1afSLoGin use crate::{
6f049d1afSLoGin arch::interrupt::TrapFrame,
7f049d1afSLoGin driver::clocksource::timer_riscv::{riscv_sbi_timer_irq_desc_init, RiscVSbiTimer},
8f049d1afSLoGin exception::{
9338f6903SLoGin handle::PerCpuDevIdIrqHandler,
10338f6903SLoGin irqchip::{IrqChip, IrqChipFlags},
11338f6903SLoGin irqdata::IrqData,
12f049d1afSLoGin irqdesc::{irq_desc_manager, GenericIrqHandler},
13338f6903SLoGin irqdomain::{irq_domain_manager, IrqDomain, IrqDomainOps},
140722a06aSLoGin softirq::do_softirq,
15338f6903SLoGin HardwareIrqNumber, IrqNumber,
16f049d1afSLoGin },
17f049d1afSLoGin libs::spinlock::{SpinLock, SpinLockGuard},
18f049d1afSLoGin sched::{SchedMode, __schedule},
19338f6903SLoGin };
20338f6903SLoGin
210102d69fSLoGin use super::riscv_sifive_plic::do_plic_irq;
220102d69fSLoGin
23338f6903SLoGin static mut RISCV_INTC_DOMAIN: Option<Arc<IrqDomain>> = None;
24338f6903SLoGin static mut RISCV_INTC_CHIP: Option<Arc<RiscvIntcChip>> = None;
25338f6903SLoGin
26338f6903SLoGin #[inline(always)]
riscv_intc_domain() -> &'static Option<Arc<IrqDomain>>27338f6903SLoGin pub fn riscv_intc_domain() -> &'static Option<Arc<IrqDomain>> {
28338f6903SLoGin unsafe { &RISCV_INTC_DOMAIN }
29338f6903SLoGin }
30338f6903SLoGin
31338f6903SLoGin #[inline(always)]
riscv_intc_chip() -> Option<&'static Arc<RiscvIntcChip>>32338f6903SLoGin fn riscv_intc_chip() -> Option<&'static Arc<RiscvIntcChip>> {
33338f6903SLoGin unsafe { RISCV_INTC_CHIP.as_ref() }
34338f6903SLoGin }
35338f6903SLoGin
360102d69fSLoGin /// RISC-V INTC虚拟中断号的起始值(192映射物理的0)
370102d69fSLoGin pub const RISCV_INTC_VIRQ_START: u32 = 192;
380102d69fSLoGin
39338f6903SLoGin #[derive(Debug)]
40f049d1afSLoGin struct RiscvIntcChip {
41f049d1afSLoGin inner: SpinLock<InnerIrqChip>,
42f049d1afSLoGin }
43338f6903SLoGin
44338f6903SLoGin impl IrqChip for RiscvIntcChip {
name(&self) -> &'static str45338f6903SLoGin fn name(&self) -> &'static str {
46338f6903SLoGin "RISC-V INTC"
47338f6903SLoGin }
48338f6903SLoGin
irq_disable(&self, _irq: &Arc<IrqData>)49338f6903SLoGin fn irq_disable(&self, _irq: &Arc<IrqData>) {}
50338f6903SLoGin
irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError>51338f6903SLoGin fn irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
52338f6903SLoGin unsafe { riscv::register::sie::clear_bits(1 << irq.hardware_irq().data()) };
53338f6903SLoGin Ok(())
54338f6903SLoGin }
55338f6903SLoGin
irq_unmask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError>56338f6903SLoGin fn irq_unmask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
57338f6903SLoGin unsafe { riscv::register::sie::set_bits(1 << irq.hardware_irq().data()) };
58338f6903SLoGin Ok(())
59338f6903SLoGin }
60338f6903SLoGin
irq_ack(&self, _irq: &Arc<IrqData>)61f049d1afSLoGin fn irq_ack(&self, _irq: &Arc<IrqData>) {}
62338f6903SLoGin
can_mask_ack(&self) -> bool63338f6903SLoGin fn can_mask_ack(&self) -> bool {
64338f6903SLoGin false
65338f6903SLoGin }
66338f6903SLoGin
irq_eoi(&self, _irq: &Arc<IrqData>)67338f6903SLoGin fn irq_eoi(&self, _irq: &Arc<IrqData>) {
68338f6903SLoGin /*
69338f6903SLoGin * The RISC-V INTC driver uses handle_percpu_devid_irq() flow
70338f6903SLoGin * for the per-HART local interrupts and child irqchip drivers
71338f6903SLoGin * (such as PLIC, SBI IPI, CLINT, APLIC, IMSIC, etc) implement
72338f6903SLoGin * chained handlers for the per-HART local interrupts.
73338f6903SLoGin *
74338f6903SLoGin * In the absence of irq_eoi(), the chained_irq_enter() and
75338f6903SLoGin * chained_irq_exit() functions (used by child irqchip drivers)
76338f6903SLoGin * will do unnecessary mask/unmask of per-HART local interrupts
77338f6903SLoGin * at the time of handling interrupts. To avoid this, we provide
78338f6903SLoGin * an empty irq_eoi() callback for RISC-V INTC irqchip.
79338f6903SLoGin */
80338f6903SLoGin }
81338f6903SLoGin
can_set_affinity(&self) -> bool82338f6903SLoGin fn can_set_affinity(&self) -> bool {
83338f6903SLoGin false
84338f6903SLoGin }
85338f6903SLoGin
can_set_flow_type(&self) -> bool86338f6903SLoGin fn can_set_flow_type(&self) -> bool {
87338f6903SLoGin false
88338f6903SLoGin }
89338f6903SLoGin
flags(&self) -> IrqChipFlags90338f6903SLoGin fn flags(&self) -> IrqChipFlags {
91f049d1afSLoGin self.inner().flags
92338f6903SLoGin }
93338f6903SLoGin }
94338f6903SLoGin
95f049d1afSLoGin impl RiscvIntcChip {
960102d69fSLoGin const IRQ_SIZE: u32 = 64;
new() -> Self97f049d1afSLoGin fn new() -> Self {
98f049d1afSLoGin Self {
99f049d1afSLoGin inner: SpinLock::new(InnerIrqChip {
100f049d1afSLoGin flags: IrqChipFlags::empty(),
101f049d1afSLoGin }),
102f049d1afSLoGin }
103f049d1afSLoGin }
inner(&self) -> SpinLockGuard<InnerIrqChip>104f049d1afSLoGin fn inner(&self) -> SpinLockGuard<InnerIrqChip> {
105f049d1afSLoGin self.inner.lock_irqsave()
106f049d1afSLoGin }
107f049d1afSLoGin }
108f049d1afSLoGin
109f049d1afSLoGin #[derive(Debug)]
110f049d1afSLoGin struct InnerIrqChip {
111f049d1afSLoGin flags: IrqChipFlags,
112f049d1afSLoGin }
113f049d1afSLoGin
114338f6903SLoGin #[derive(Debug)]
115338f6903SLoGin struct RiscvIntcDomainOps;
116338f6903SLoGin
117338f6903SLoGin impl IrqDomainOps for RiscvIntcDomainOps {
map( &self, irq_domain: &Arc<IrqDomain>, hwirq: HardwareIrqNumber, virq: IrqNumber, ) -> Result<(), SystemError>118338f6903SLoGin fn map(
119338f6903SLoGin &self,
120338f6903SLoGin irq_domain: &Arc<IrqDomain>,
121338f6903SLoGin hwirq: HardwareIrqNumber,
122338f6903SLoGin virq: IrqNumber,
123338f6903SLoGin ) -> Result<(), SystemError> {
124338f6903SLoGin irq_desc_manager().set_percpu_devid_all(virq)?;
125338f6903SLoGin irq_domain_manager().domain_set_info(
126338f6903SLoGin irq_domain,
127338f6903SLoGin virq,
128338f6903SLoGin hwirq,
129338f6903SLoGin riscv_intc_chip().unwrap().clone() as Arc<dyn IrqChip>,
130338f6903SLoGin irq_domain.host_data(),
131338f6903SLoGin &PerCpuDevIdIrqHandler,
132338f6903SLoGin None,
133338f6903SLoGin None,
134338f6903SLoGin );
135338f6903SLoGin
136338f6903SLoGin return Ok(());
137338f6903SLoGin }
138338f6903SLoGin
unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber)139f049d1afSLoGin fn unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber) {
140338f6903SLoGin todo!("riscv_intc_domain_ops::unmap");
141338f6903SLoGin }
142338f6903SLoGin }
143338f6903SLoGin
144338f6903SLoGin #[inline(never)]
riscv_intc_init() -> Result<(), SystemError>145338f6903SLoGin pub unsafe fn riscv_intc_init() -> Result<(), SystemError> {
146f049d1afSLoGin let intc_chip = Arc::new(RiscvIntcChip::new());
147338f6903SLoGin
148338f6903SLoGin unsafe {
149338f6903SLoGin RISCV_INTC_CHIP = Some(intc_chip);
150338f6903SLoGin }
151338f6903SLoGin
152338f6903SLoGin let intc_domain = irq_domain_manager()
1530102d69fSLoGin .create_and_add_linear(
1540102d69fSLoGin "riscv-intc".to_string(),
1550102d69fSLoGin &RiscvIntcDomainOps,
1560102d69fSLoGin RiscvIntcChip::IRQ_SIZE,
1570102d69fSLoGin )
158338f6903SLoGin .ok_or_else(|| {
159*2eab6dd7S曾俊 error!("Failed to create riscv-intc domain");
160338f6903SLoGin SystemError::ENXIO
161338f6903SLoGin })?;
162338f6903SLoGin
163338f6903SLoGin irq_domain_manager().set_default_domain(intc_domain.clone());
164338f6903SLoGin
165338f6903SLoGin unsafe {
1660102d69fSLoGin RISCV_INTC_DOMAIN = Some(intc_domain.clone());
167338f6903SLoGin }
168338f6903SLoGin
169f049d1afSLoGin riscv_sbi_timer_irq_desc_init();
170f049d1afSLoGin
171338f6903SLoGin return Ok(());
172338f6903SLoGin }
173f049d1afSLoGin
1740102d69fSLoGin /// 把硬件中断号转换为riscv intc芯片的中断域的虚拟中断号
riscv_intc_hwirq_to_virq(hwirq: HardwareIrqNumber) -> Option<IrqNumber>1750102d69fSLoGin pub const fn riscv_intc_hwirq_to_virq(hwirq: HardwareIrqNumber) -> Option<IrqNumber> {
1760102d69fSLoGin if hwirq.data() < RiscvIntcChip::IRQ_SIZE {
1770102d69fSLoGin Some(IrqNumber::new(hwirq.data() + RISCV_INTC_VIRQ_START))
1780102d69fSLoGin } else {
1790102d69fSLoGin None
1800102d69fSLoGin }
1810102d69fSLoGin }
1820102d69fSLoGin
1830102d69fSLoGin /// 把riscv intc芯片的的中断域的虚拟中断号转换为硬件中断号
1840102d69fSLoGin #[allow(dead_code)]
riscv_intc_virq_to_hwirq(virq: IrqNumber) -> Option<HardwareIrqNumber>1850102d69fSLoGin pub const fn riscv_intc_virq_to_hwirq(virq: IrqNumber) -> Option<HardwareIrqNumber> {
1860102d69fSLoGin if virq.data() >= RISCV_INTC_VIRQ_START
1870102d69fSLoGin && virq.data() < RISCV_INTC_VIRQ_START + RiscvIntcChip::IRQ_SIZE
1880102d69fSLoGin {
1890102d69fSLoGin Some(HardwareIrqNumber::new(virq.data() - RISCV_INTC_VIRQ_START))
1900102d69fSLoGin } else {
1910102d69fSLoGin None
1920102d69fSLoGin }
1930102d69fSLoGin }
1940102d69fSLoGin
1950102d69fSLoGin /// 将硬件中断号与riscv intc芯片的虚拟中断号关联
riscv_intc_assicate_irq(hwirq: HardwareIrqNumber) -> Option<IrqNumber>1960102d69fSLoGin pub fn riscv_intc_assicate_irq(hwirq: HardwareIrqNumber) -> Option<IrqNumber> {
1970102d69fSLoGin let virq = riscv_intc_hwirq_to_virq(hwirq)?;
1980102d69fSLoGin irq_domain_manager()
1990102d69fSLoGin .domain_associate(
2000102d69fSLoGin riscv_intc_domain().as_ref().or_else(|| {
201*2eab6dd7S曾俊 error!("riscv_intc_domain is None");
2020102d69fSLoGin None
2030102d69fSLoGin })?,
2040102d69fSLoGin virq,
2050102d69fSLoGin hwirq,
2060102d69fSLoGin )
2070102d69fSLoGin .ok();
2080102d69fSLoGin
2090102d69fSLoGin Some(virq)
2100102d69fSLoGin }
2110102d69fSLoGin
212f049d1afSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/irqchip/irq-riscv-intc.c#23
riscv_intc_irq(trap_frame: &mut TrapFrame)213f049d1afSLoGin pub fn riscv_intc_irq(trap_frame: &mut TrapFrame) {
214f049d1afSLoGin let hwirq = HardwareIrqNumber::new(trap_frame.cause.code() as u32);
2150102d69fSLoGin if hwirq.data() == 9 {
2160102d69fSLoGin // external interrupt
2170102d69fSLoGin do_plic_irq(trap_frame);
2180102d69fSLoGin } else {
2190102d69fSLoGin GenericIrqHandler::handle_domain_irq(
2200102d69fSLoGin riscv_intc_domain().clone().unwrap(),
2210102d69fSLoGin hwirq,
2220102d69fSLoGin trap_frame,
2230102d69fSLoGin )
224f049d1afSLoGin .ok();
2250102d69fSLoGin }
2260722a06aSLoGin do_softirq();
227f049d1afSLoGin if hwirq.data() == RiscVSbiTimer::TIMER_IRQ.data() {
228f049d1afSLoGin __schedule(SchedMode::SM_PREEMPT);
229f049d1afSLoGin }
230f049d1afSLoGin }
231