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