xref: /DragonOS/kernel/src/exception/handle.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
1e2841179SLoGin use core::{intrinsics::unlikely, ops::BitAnd};
23bc96fa4SLoGin 
3e2841179SLoGin use alloc::sync::Arc;
4*2eab6dd7S曾俊 use log::{debug, error, warn};
5e2841179SLoGin use system_error::SystemError;
6e2841179SLoGin 
7e2841179SLoGin use crate::{
8e2841179SLoGin     arch::{interrupt::TrapFrame, CurrentIrqArch},
90102d69fSLoGin     exception::{irqchip::IrqChipFlags, irqdesc::InnerIrqDesc},
10338f6903SLoGin     libs::{once::Once, spinlock::SpinLockGuard},
11e2841179SLoGin     process::{ProcessFlags, ProcessManager},
12338f6903SLoGin     smp::core::smp_get_processor_id,
13e2841179SLoGin };
143bc96fa4SLoGin 
153bc96fa4SLoGin use super::{
160102d69fSLoGin     irqchip::IrqChip,
17e2841179SLoGin     irqdata::{IrqData, IrqHandlerData, IrqStatus},
18e2841179SLoGin     irqdesc::{
19e2841179SLoGin         InnerIrqAction, IrqDesc, IrqDescState, IrqFlowHandler, IrqReturn, ThreadedHandlerFlags,
20e2841179SLoGin     },
21e2841179SLoGin     manage::{irq_manager, IrqManager},
22e2841179SLoGin     InterruptArch, IrqNumber,
233bc96fa4SLoGin };
243bc96fa4SLoGin 
253bc96fa4SLoGin /// 获取用于处理错误的中断的处理程序
263bc96fa4SLoGin #[inline(always)]
bad_irq_handler() -> &'static dyn IrqFlowHandler273bc96fa4SLoGin pub fn bad_irq_handler() -> &'static dyn IrqFlowHandler {
283bc96fa4SLoGin     &HandleBadIrq
293bc96fa4SLoGin }
303bc96fa4SLoGin 
31e2841179SLoGin /// 获取用于处理快速EOI的中断的处理程序
32e2841179SLoGin #[inline(always)]
fast_eoi_irq_handler() -> &'static dyn IrqFlowHandler33e2841179SLoGin pub fn fast_eoi_irq_handler() -> &'static dyn IrqFlowHandler {
34e2841179SLoGin     &FastEOIIrqHandler
35e2841179SLoGin }
36e2841179SLoGin 
37e2841179SLoGin /// 获取用于处理边沿触发中断的处理程序
38e2841179SLoGin #[inline(always)]
390102d69fSLoGin #[allow(dead_code)]
edge_irq_handler() -> &'static dyn IrqFlowHandler40e2841179SLoGin pub fn edge_irq_handler() -> &'static dyn IrqFlowHandler {
41e2841179SLoGin     &EdgeIrqHandler
42e2841179SLoGin }
43e2841179SLoGin 
443bc96fa4SLoGin /// handle spurious and unhandled irqs
453bc96fa4SLoGin #[derive(Debug)]
463bc96fa4SLoGin struct HandleBadIrq;
473bc96fa4SLoGin 
483bc96fa4SLoGin impl IrqFlowHandler for HandleBadIrq {
493bc96fa4SLoGin     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/handle.c?fi=handle_bad_irq#33
handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame)50e2841179SLoGin     fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
513bc96fa4SLoGin         // todo: print_irq_desc
523bc96fa4SLoGin         // todo: 增加kstat计数
533bc96fa4SLoGin         CurrentIrqArch::ack_bad_irq(irq_desc.irq());
543bc96fa4SLoGin     }
553bc96fa4SLoGin }
56e2841179SLoGin 
57e2841179SLoGin #[derive(Debug)]
58e2841179SLoGin struct FastEOIIrqHandler;
59e2841179SLoGin 
60e2841179SLoGin impl IrqFlowHandler for FastEOIIrqHandler {
610102d69fSLoGin     /// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/chip.c?r=&mo=17578&fi=689#689
handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame)620102d69fSLoGin     fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
630102d69fSLoGin         let chip = irq_desc.irq_data().chip_info_read_irqsave().chip();
640102d69fSLoGin 
650102d69fSLoGin         let mut desc_inner = irq_desc.inner();
660102d69fSLoGin         let out = |din: SpinLockGuard<InnerIrqDesc>| {
670102d69fSLoGin             if !chip.flags().contains(IrqChipFlags::IRQCHIP_EOI_IF_HANDLED) {
680102d69fSLoGin                 chip.irq_eoi(din.irq_data());
690102d69fSLoGin             }
700102d69fSLoGin         };
710102d69fSLoGin         if !irq_may_run(&desc_inner) {
720102d69fSLoGin             out(desc_inner);
730102d69fSLoGin             return;
740102d69fSLoGin         }
750102d69fSLoGin 
760102d69fSLoGin         desc_inner
770102d69fSLoGin             .internal_state_mut()
780102d69fSLoGin             .remove(IrqDescState::IRQS_REPLAY | IrqDescState::IRQS_WAITING);
790102d69fSLoGin 
800102d69fSLoGin         if desc_inner.actions().is_empty() || desc_inner.common_data().disabled() {
810102d69fSLoGin             desc_inner
820102d69fSLoGin                 .internal_state_mut()
830102d69fSLoGin                 .insert(IrqDescState::IRQS_PENDING);
840102d69fSLoGin             mask_irq(desc_inner.irq_data());
850102d69fSLoGin             out(desc_inner);
860102d69fSLoGin             return;
870102d69fSLoGin         }
880102d69fSLoGin 
890102d69fSLoGin         desc_inner = handle_irq_event(irq_desc, desc_inner);
900102d69fSLoGin         cond_unmask_eoi_irq(&desc_inner, &chip);
910102d69fSLoGin 
920102d69fSLoGin         return;
93e2841179SLoGin     }
94e2841179SLoGin }
95e2841179SLoGin 
96e2841179SLoGin #[derive(Debug)]
97e2841179SLoGin struct EdgeIrqHandler;
98e2841179SLoGin 
99e2841179SLoGin impl IrqFlowHandler for EdgeIrqHandler {
100e2841179SLoGin     // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/chip.c?fi=handle_edge_irq#775
handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame)101e2841179SLoGin     fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
102e2841179SLoGin         let mut desc_inner_guard: SpinLockGuard<'_, InnerIrqDesc> = irq_desc.inner();
103e2841179SLoGin         if !irq_may_run(&desc_inner_guard) {
104*2eab6dd7S曾俊             // debug!("!irq_may_run");
105e2841179SLoGin             desc_inner_guard
106e2841179SLoGin                 .internal_state_mut()
107e2841179SLoGin                 .insert(IrqDescState::IRQS_PENDING);
108e2841179SLoGin             mask_ack_irq(desc_inner_guard.irq_data());
109e2841179SLoGin             return;
110e2841179SLoGin         }
111e2841179SLoGin 
112e2841179SLoGin         if desc_inner_guard.common_data().disabled() {
113*2eab6dd7S曾俊             // debug!("desc_inner_guard.common_data().disabled()");
114e2841179SLoGin             desc_inner_guard
115e2841179SLoGin                 .internal_state_mut()
116e2841179SLoGin                 .insert(IrqDescState::IRQS_PENDING);
117e2841179SLoGin             mask_ack_irq(desc_inner_guard.irq_data());
118e2841179SLoGin             return;
119e2841179SLoGin         }
120e2841179SLoGin 
121e2841179SLoGin         let irq_data = desc_inner_guard.irq_data().clone();
122e2841179SLoGin 
123e2841179SLoGin         irq_data.chip_info_read_irqsave().chip().irq_ack(&irq_data);
124e2841179SLoGin 
125e2841179SLoGin         loop {
126e2841179SLoGin             if unlikely(desc_inner_guard.actions().is_empty()) {
127*2eab6dd7S曾俊                 debug!("no action for irq {}", irq_data.irq().data());
128e2841179SLoGin                 irq_manager().mask_irq(&irq_data);
129e2841179SLoGin                 return;
130e2841179SLoGin             }
131e2841179SLoGin 
132e2841179SLoGin             // 当我们在处理一个中断时,如果另一个中断到来,我们本可以屏蔽它.
133e2841179SLoGin             // 如果在此期间没有被禁用,请重新启用它。
134e2841179SLoGin             if desc_inner_guard
135e2841179SLoGin                 .internal_state()
136e2841179SLoGin                 .contains(IrqDescState::IRQS_PENDING)
137e2841179SLoGin             {
138e2841179SLoGin                 let status = desc_inner_guard.common_data().status();
139b5b571e0SLoGin                 if !status.disabled() && status.masked() {
140*2eab6dd7S曾俊                     // debug!("re-enable irq");
141e2841179SLoGin                     irq_manager().unmask_irq(&desc_inner_guard);
142e2841179SLoGin                 }
143e2841179SLoGin             }
144e2841179SLoGin 
145*2eab6dd7S曾俊             // debug!("handle_irq_event");
146e2841179SLoGin 
1470102d69fSLoGin             desc_inner_guard = handle_irq_event(irq_desc, desc_inner_guard);
148e2841179SLoGin 
149b5b571e0SLoGin             if !desc_inner_guard
150e2841179SLoGin                 .internal_state()
151e2841179SLoGin                 .contains(IrqDescState::IRQS_PENDING)
152b5b571e0SLoGin                 || desc_inner_guard.common_data().disabled()
153e2841179SLoGin             {
154e2841179SLoGin                 break;
155e2841179SLoGin             }
156e2841179SLoGin         }
157e2841179SLoGin     }
158e2841179SLoGin }
159e2841179SLoGin 
160e2841179SLoGin /// 判断中断是否可以运行
irq_may_run(desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>) -> bool161e2841179SLoGin fn irq_may_run(desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>) -> bool {
162e2841179SLoGin     let mask = IrqStatus::IRQD_IRQ_INPROGRESS | IrqStatus::IRQD_WAKEUP_ARMED;
163e2841179SLoGin     let status = desc_inner_guard.common_data().status();
164e2841179SLoGin 
165e2841179SLoGin     // 如果中断不在处理中并且没有被唤醒,则可以运行
166e2841179SLoGin     if status.bitand(mask).is_empty() {
167e2841179SLoGin         return true;
168e2841179SLoGin     }
169e2841179SLoGin 
170e2841179SLoGin     // todo: 检查其他处理器是否在轮询当前中断
171e2841179SLoGin     return false;
172e2841179SLoGin }
173e2841179SLoGin 
mask_ack_irq(irq_data: &Arc<IrqData>)174338f6903SLoGin pub(super) fn mask_ack_irq(irq_data: &Arc<IrqData>) {
175e2841179SLoGin     let chip = irq_data.chip_info_read_irqsave().chip();
176e2841179SLoGin     if chip.can_mask_ack() {
177b5b571e0SLoGin         chip.irq_mask_ack(irq_data);
178e2841179SLoGin         irq_data.common_data().set_masked();
179e2841179SLoGin     } else {
180e2841179SLoGin         irq_manager().mask_irq(irq_data);
181b5b571e0SLoGin         chip.irq_ack(irq_data);
182e2841179SLoGin     }
183e2841179SLoGin }
184e2841179SLoGin 
mask_irq(irq_data: &Arc<IrqData>)1850102d69fSLoGin pub(super) fn mask_irq(irq_data: &Arc<IrqData>) {
1860102d69fSLoGin     if irq_data.common_data().masked() {
1870102d69fSLoGin         return;
1880102d69fSLoGin     }
1890102d69fSLoGin 
1900102d69fSLoGin     let chip = irq_data.chip_info_read_irqsave().chip();
1910102d69fSLoGin     if chip.irq_mask(irq_data).is_ok() {
1920102d69fSLoGin         irq_data.irqd_set(IrqStatus::IRQD_IRQ_MASKED);
1930102d69fSLoGin     }
1940102d69fSLoGin }
1950102d69fSLoGin 
unmask_irq(irq_data: &Arc<IrqData>)1960102d69fSLoGin pub(super) fn unmask_irq(irq_data: &Arc<IrqData>) {
1970102d69fSLoGin     if !irq_data.common_data().masked() {
1980102d69fSLoGin         return;
1990102d69fSLoGin     }
2000102d69fSLoGin 
2010102d69fSLoGin     let chip = irq_data.chip_info_read_irqsave().chip();
2020102d69fSLoGin 
2030102d69fSLoGin     if chip.irq_unmask(irq_data).is_ok() {
2040102d69fSLoGin         irq_data.irqd_clear(IrqStatus::IRQD_IRQ_MASKED);
2050102d69fSLoGin     }
2060102d69fSLoGin }
2070102d69fSLoGin 
208e2841179SLoGin impl IrqManager {
do_irq_wake_thread( &self, desc: &Arc<IrqDesc>, action_inner: &mut SpinLockGuard<'_, InnerIrqAction>, )209e2841179SLoGin     pub(super) fn do_irq_wake_thread(
210e2841179SLoGin         &self,
211e2841179SLoGin         desc: &Arc<IrqDesc>,
212e2841179SLoGin         action_inner: &mut SpinLockGuard<'_, InnerIrqAction>,
213e2841179SLoGin     ) {
214e2841179SLoGin         let thread = action_inner.thread();
215e2841179SLoGin 
216e2841179SLoGin         if thread.is_none() {
217e2841179SLoGin             return;
218e2841179SLoGin         }
219e2841179SLoGin 
220e2841179SLoGin         let thread = thread.unwrap();
221e2841179SLoGin         if thread.flags().contains(ProcessFlags::EXITING) {
222e2841179SLoGin             return;
223e2841179SLoGin         }
224e2841179SLoGin 
225e2841179SLoGin         // 如果线程已经在运行,我们不需要唤醒它
226e2841179SLoGin         if action_inner
227e2841179SLoGin             .thread_flags_mut()
228e2841179SLoGin             .test_and_set_bit(ThreadedHandlerFlags::IRQTF_RUNTHREAD)
229e2841179SLoGin         {
230e2841179SLoGin             return;
231e2841179SLoGin         }
232e2841179SLoGin 
233e2841179SLoGin         desc.inc_threads_active();
234e2841179SLoGin 
235e2841179SLoGin         ProcessManager::wakeup(&thread).ok();
236e2841179SLoGin     }
237e2841179SLoGin }
238e2841179SLoGin 
handle_irq_event<'a>( irq_desc: &'a Arc<IrqDesc>, mut desc_inner_guard: SpinLockGuard<'_, InnerIrqDesc>, ) -> SpinLockGuard<'a, InnerIrqDesc>2390102d69fSLoGin fn handle_irq_event<'a>(
2400102d69fSLoGin     irq_desc: &'a Arc<IrqDesc>,
2410102d69fSLoGin     mut desc_inner_guard: SpinLockGuard<'_, InnerIrqDesc>,
2420102d69fSLoGin ) -> SpinLockGuard<'a, InnerIrqDesc> {
2430102d69fSLoGin     desc_inner_guard
2440102d69fSLoGin         .internal_state_mut()
2450102d69fSLoGin         .remove(IrqDescState::IRQS_PENDING);
2460102d69fSLoGin     desc_inner_guard.common_data().set_inprogress();
2470102d69fSLoGin 
2480102d69fSLoGin     drop(desc_inner_guard);
2490102d69fSLoGin 
2500102d69fSLoGin     let _r = do_handle_irq_event(irq_desc);
2510102d69fSLoGin 
2520102d69fSLoGin     let desc_inner_guard = irq_desc.inner();
2530102d69fSLoGin     desc_inner_guard.common_data().clear_inprogress();
2540102d69fSLoGin 
2550102d69fSLoGin     return desc_inner_guard;
2560102d69fSLoGin }
257e2841179SLoGin /// 处理中断事件
258e2841179SLoGin ///
259e2841179SLoGin /// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/handle.c?fi=handle_irq_event#139
260e2841179SLoGin #[inline(never)]
do_handle_irq_event(desc: &Arc<IrqDesc>) -> Result<(), SystemError>261e2841179SLoGin fn do_handle_irq_event(desc: &Arc<IrqDesc>) -> Result<(), SystemError> {
262e2841179SLoGin     let desc_inner_guard = desc.inner();
263e2841179SLoGin     let irq_data = desc_inner_guard.irq_data().clone();
264e2841179SLoGin     let actions = desc_inner_guard.actions().clone();
265e2841179SLoGin     drop(desc_inner_guard);
266e2841179SLoGin 
267e2841179SLoGin     let irq = irq_data.irq();
268e2841179SLoGin     let mut r = Ok(IrqReturn::NotHandled);
269e2841179SLoGin 
270e2841179SLoGin     for action in actions {
271e2841179SLoGin         let mut action_inner: SpinLockGuard<'_, InnerIrqAction> = action.inner();
272*2eab6dd7S曾俊         // debug!("do_handle_irq_event: action: {:?}", action_inner.name());
273e2841179SLoGin         let dynamic_data = action_inner
274e2841179SLoGin             .dev_id()
275e2841179SLoGin             .clone()
276e2841179SLoGin             .map(|d| d as Arc<dyn IrqHandlerData>);
277e2841179SLoGin         r = action_inner
278e2841179SLoGin             .handler()
279e2841179SLoGin             .unwrap()
280e2841179SLoGin             .handle(irq, None, dynamic_data);
281e2841179SLoGin 
282e2841179SLoGin         if let Ok(IrqReturn::WakeThread) = r {
283e2841179SLoGin             if unlikely(action_inner.thread_fn().is_none()) {
284e2841179SLoGin                 warn_no_thread(irq, &mut action_inner);
285e2841179SLoGin             } else {
286e2841179SLoGin                 irq_manager().do_irq_wake_thread(desc, &mut action_inner);
287e2841179SLoGin             }
288e2841179SLoGin         };
289e2841179SLoGin     }
290e2841179SLoGin 
291e2841179SLoGin     return r.map(|_| ());
292e2841179SLoGin }
293e2841179SLoGin 
2940102d69fSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/chip.c?r=&mo=17578&fi=659
cond_unmask_eoi_irq( desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>, chip: &Arc<dyn IrqChip>, )2950102d69fSLoGin fn cond_unmask_eoi_irq(
2960102d69fSLoGin     desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>,
2970102d69fSLoGin     chip: &Arc<dyn IrqChip>,
2980102d69fSLoGin ) {
2990102d69fSLoGin     if !desc_inner_guard
3000102d69fSLoGin         .internal_state()
3010102d69fSLoGin         .contains(IrqDescState::IRQS_ONESHOT)
3020102d69fSLoGin     {
3030102d69fSLoGin         chip.irq_eoi(desc_inner_guard.irq_data());
3040102d69fSLoGin         return;
3050102d69fSLoGin     }
3060102d69fSLoGin 
3070102d69fSLoGin     /*
3080102d69fSLoGin      * We need to unmask in the following cases:
3090102d69fSLoGin      * - Oneshot irq which did not wake the thread (caused by a
3100102d69fSLoGin      *   spurious interrupt or a primary handler handling it
3110102d69fSLoGin      *   completely).
3120102d69fSLoGin      */
3130102d69fSLoGin 
3140102d69fSLoGin     if !desc_inner_guard.common_data().disabled()
3150102d69fSLoGin         && desc_inner_guard.common_data().masked()
3160102d69fSLoGin         && desc_inner_guard.threads_oneshot() == 0
3170102d69fSLoGin     {
318*2eab6dd7S曾俊         debug!(
3190102d69fSLoGin             "eoi unmask irq {}",
3200102d69fSLoGin             desc_inner_guard.irq_data().irq().data()
3210102d69fSLoGin         );
3220102d69fSLoGin         chip.irq_eoi(desc_inner_guard.irq_data());
3230102d69fSLoGin         unmask_irq(desc_inner_guard.irq_data());
3240102d69fSLoGin     } else if !chip.flags().contains(IrqChipFlags::IRQCHIP_EOI_THREADED) {
325*2eab6dd7S曾俊         debug!("eoi irq {}", desc_inner_guard.irq_data().irq().data());
3260102d69fSLoGin         chip.irq_eoi(desc_inner_guard.irq_data());
3270102d69fSLoGin     } else {
328*2eab6dd7S曾俊         warn!(
3290102d69fSLoGin             "irq {} eoi failed",
3300102d69fSLoGin             desc_inner_guard.irq_data().irq().data()
3310102d69fSLoGin         );
3320102d69fSLoGin     }
3330102d69fSLoGin }
3340102d69fSLoGin 
warn_no_thread(irq: IrqNumber, action_inner: &mut SpinLockGuard<'_, InnerIrqAction>)335e2841179SLoGin fn warn_no_thread(irq: IrqNumber, action_inner: &mut SpinLockGuard<'_, InnerIrqAction>) {
336e2841179SLoGin     // warn on once
337e2841179SLoGin     if action_inner
338e2841179SLoGin         .thread_flags_mut()
339e2841179SLoGin         .test_and_set_bit(ThreadedHandlerFlags::IRQTF_WARNED)
340e2841179SLoGin     {
341e2841179SLoGin         return;
342e2841179SLoGin     }
343e2841179SLoGin 
344*2eab6dd7S曾俊     warn!(
345e2841179SLoGin         "irq {}, device {} returned IRQ_WAKE_THREAD, but no threaded handler",
346e2841179SLoGin         irq.data(),
347e2841179SLoGin         action_inner.name()
348e2841179SLoGin     );
349e2841179SLoGin }
350338f6903SLoGin 
351338f6903SLoGin /// `handle_percpu_devid_irq` - 带有per-CPU设备id的perCPU本地中断处理程序
352338f6903SLoGin ///
353338f6903SLoGin ///
354338f6903SLoGin /// * `desc`: 此中断的中断描述结构
355338f6903SLoGin ///
356338f6903SLoGin /// 在没有锁定要求的SMP机器上的每个CPU中断。与linux的`handle_percpu_irq()`相同,但有以下额外内容:
357338f6903SLoGin ///
358338f6903SLoGin /// `action->percpu_dev_id`是一个指向per-cpu变量的指针,这些变量
359338f6903SLoGin /// 包含调用此处理程序的cpu的真实设备id
360338f6903SLoGin #[derive(Debug)]
361338f6903SLoGin pub struct PerCpuDevIdIrqHandler;
362338f6903SLoGin 
363338f6903SLoGin impl IrqFlowHandler for PerCpuDevIdIrqHandler {
handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame)364338f6903SLoGin     fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
365338f6903SLoGin         let desc_inner_guard = irq_desc.inner();
366338f6903SLoGin         let irq_data = desc_inner_guard.irq_data().clone();
367338f6903SLoGin         let chip = irq_data.chip_info_read().chip();
368338f6903SLoGin 
369338f6903SLoGin         chip.irq_ack(&irq_data);
370338f6903SLoGin 
371338f6903SLoGin         let irq = irq_data.irq();
372338f6903SLoGin 
373338f6903SLoGin         let action = desc_inner_guard.actions().first().cloned();
374338f6903SLoGin 
375338f6903SLoGin         drop(desc_inner_guard);
376338f6903SLoGin 
377338f6903SLoGin         if let Some(action) = action {
378338f6903SLoGin             let action_inner = action.inner();
379338f6903SLoGin             let per_cpu_devid = action_inner.per_cpu_dev_id().cloned();
380338f6903SLoGin 
381338f6903SLoGin             let handler = action_inner.handler().unwrap();
382338f6903SLoGin             drop(action_inner);
383338f6903SLoGin 
384338f6903SLoGin             let _r = handler.handle(
385338f6903SLoGin                 irq,
386338f6903SLoGin                 None,
387338f6903SLoGin                 per_cpu_devid.map(|d| d as Arc<dyn IrqHandlerData>),
388338f6903SLoGin             );
389338f6903SLoGin         } else {
390338f6903SLoGin             let cpu = smp_get_processor_id();
391338f6903SLoGin 
392338f6903SLoGin             let enabled = irq_desc
393338f6903SLoGin                 .inner()
394338f6903SLoGin                 .percpu_enabled()
395338f6903SLoGin                 .as_ref()
396338f6903SLoGin                 .unwrap()
397338f6903SLoGin                 .get(cpu)
398338f6903SLoGin                 .unwrap_or(false);
399338f6903SLoGin 
400338f6903SLoGin             if enabled {
401338f6903SLoGin                 irq_manager().irq_percpu_disable(irq_desc, &irq_data, &chip, cpu);
402338f6903SLoGin             }
403338f6903SLoGin             static ONCE: Once = Once::new();
404338f6903SLoGin 
405338f6903SLoGin             ONCE.call_once(|| {
406*2eab6dd7S曾俊                 error!(
407338f6903SLoGin                     "Spurious percpu irq {} on cpu {:?}, enabled: {}",
408338f6903SLoGin                     irq.data(),
409338f6903SLoGin                     cpu,
410338f6903SLoGin                     enabled
411338f6903SLoGin                 );
412338f6903SLoGin             });
413338f6903SLoGin         }
414338f6903SLoGin 
415338f6903SLoGin         chip.irq_eoi(&irq_data);
416338f6903SLoGin     }
417338f6903SLoGin }
418