xref: /DragonOS/kernel/src/driver/irqchip/riscv_sifive_plic.rs (revision 0102d69fdd231e472d7bb3d609a41ae56a3799ee)
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