xref: /DragonOS/kernel/src/exception/handle.rs (revision b5b571e02693d91eb6918d3b7561e088c3e7ee81)
1e2841179SLoGin use core::{intrinsics::unlikely, ops::BitAnd};
23bc96fa4SLoGin 
3e2841179SLoGin use alloc::sync::Arc;
4e2841179SLoGin use system_error::SystemError;
5e2841179SLoGin 
6e2841179SLoGin use crate::{
7e2841179SLoGin     arch::{interrupt::TrapFrame, CurrentIrqArch},
8e2841179SLoGin     exception::irqdesc::InnerIrqDesc,
9338f6903SLoGin     libs::{once::Once, spinlock::SpinLockGuard},
10e2841179SLoGin     process::{ProcessFlags, ProcessManager},
11338f6903SLoGin     smp::core::smp_get_processor_id,
12e2841179SLoGin };
133bc96fa4SLoGin 
143bc96fa4SLoGin use super::{
15e2841179SLoGin     irqdata::{IrqData, IrqHandlerData, IrqStatus},
16e2841179SLoGin     irqdesc::{
17e2841179SLoGin         InnerIrqAction, IrqDesc, IrqDescState, IrqFlowHandler, IrqReturn, ThreadedHandlerFlags,
18e2841179SLoGin     },
19e2841179SLoGin     manage::{irq_manager, IrqManager},
20e2841179SLoGin     InterruptArch, IrqNumber,
213bc96fa4SLoGin };
223bc96fa4SLoGin 
233bc96fa4SLoGin /// 获取用于处理错误的中断的处理程序
243bc96fa4SLoGin #[inline(always)]
253bc96fa4SLoGin pub fn bad_irq_handler() -> &'static dyn IrqFlowHandler {
263bc96fa4SLoGin     &HandleBadIrq
273bc96fa4SLoGin }
283bc96fa4SLoGin 
29e2841179SLoGin /// 获取用于处理快速EOI的中断的处理程序
30e2841179SLoGin #[inline(always)]
31e2841179SLoGin pub fn fast_eoi_irq_handler() -> &'static dyn IrqFlowHandler {
32e2841179SLoGin     &FastEOIIrqHandler
33e2841179SLoGin }
34e2841179SLoGin 
35e2841179SLoGin /// 获取用于处理边沿触发中断的处理程序
36e2841179SLoGin #[inline(always)]
37e2841179SLoGin pub fn edge_irq_handler() -> &'static dyn IrqFlowHandler {
38e2841179SLoGin     &EdgeIrqHandler
39e2841179SLoGin }
40e2841179SLoGin 
413bc96fa4SLoGin /// handle spurious and unhandled irqs
423bc96fa4SLoGin #[derive(Debug)]
433bc96fa4SLoGin struct HandleBadIrq;
443bc96fa4SLoGin 
453bc96fa4SLoGin impl IrqFlowHandler for HandleBadIrq {
463bc96fa4SLoGin     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/handle.c?fi=handle_bad_irq#33
47e2841179SLoGin     fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
483bc96fa4SLoGin         // todo: print_irq_desc
493bc96fa4SLoGin         // todo: 增加kstat计数
503bc96fa4SLoGin         CurrentIrqArch::ack_bad_irq(irq_desc.irq());
513bc96fa4SLoGin     }
523bc96fa4SLoGin }
53e2841179SLoGin 
54e2841179SLoGin #[derive(Debug)]
55e2841179SLoGin struct FastEOIIrqHandler;
56e2841179SLoGin 
57e2841179SLoGin impl IrqFlowHandler for FastEOIIrqHandler {
58e2841179SLoGin     fn handle(&self, _irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
59e2841179SLoGin         // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/chip.c?r=&mo=17578&fi=689#689
60e2841179SLoGin         todo!("FastEOIIrqHandler");
61e2841179SLoGin     }
62e2841179SLoGin }
63e2841179SLoGin 
64e2841179SLoGin #[derive(Debug)]
65e2841179SLoGin struct EdgeIrqHandler;
66e2841179SLoGin 
67e2841179SLoGin impl IrqFlowHandler for EdgeIrqHandler {
68e2841179SLoGin     // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/chip.c?fi=handle_edge_irq#775
69e2841179SLoGin     fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
70e2841179SLoGin         let mut desc_inner_guard: SpinLockGuard<'_, InnerIrqDesc> = irq_desc.inner();
71e2841179SLoGin         if !irq_may_run(&desc_inner_guard) {
72e2841179SLoGin             // kdebug!("!irq_may_run");
73e2841179SLoGin             desc_inner_guard
74e2841179SLoGin                 .internal_state_mut()
75e2841179SLoGin                 .insert(IrqDescState::IRQS_PENDING);
76e2841179SLoGin             mask_ack_irq(desc_inner_guard.irq_data());
77e2841179SLoGin             return;
78e2841179SLoGin         }
79e2841179SLoGin 
80e2841179SLoGin         if desc_inner_guard.common_data().disabled() {
81e2841179SLoGin             // kdebug!("desc_inner_guard.common_data().disabled()");
82e2841179SLoGin             desc_inner_guard
83e2841179SLoGin                 .internal_state_mut()
84e2841179SLoGin                 .insert(IrqDescState::IRQS_PENDING);
85e2841179SLoGin             mask_ack_irq(desc_inner_guard.irq_data());
86e2841179SLoGin             return;
87e2841179SLoGin         }
88e2841179SLoGin 
89e2841179SLoGin         let irq_data = desc_inner_guard.irq_data().clone();
90e2841179SLoGin 
91e2841179SLoGin         irq_data.chip_info_read_irqsave().chip().irq_ack(&irq_data);
92e2841179SLoGin 
93e2841179SLoGin         loop {
94e2841179SLoGin             if unlikely(desc_inner_guard.actions().is_empty()) {
95e2841179SLoGin                 kdebug!("no action for irq {}", irq_data.irq().data());
96e2841179SLoGin                 irq_manager().mask_irq(&irq_data);
97e2841179SLoGin                 return;
98e2841179SLoGin             }
99e2841179SLoGin 
100e2841179SLoGin             // 当我们在处理一个中断时,如果另一个中断到来,我们本可以屏蔽它.
101e2841179SLoGin             // 如果在此期间没有被禁用,请重新启用它。
102e2841179SLoGin             if desc_inner_guard
103e2841179SLoGin                 .internal_state()
104e2841179SLoGin                 .contains(IrqDescState::IRQS_PENDING)
105e2841179SLoGin             {
106e2841179SLoGin                 let status = desc_inner_guard.common_data().status();
107*b5b571e0SLoGin                 if !status.disabled() && status.masked() {
108e2841179SLoGin                     // kdebug!("re-enable irq");
109e2841179SLoGin                     irq_manager().unmask_irq(&desc_inner_guard);
110e2841179SLoGin                 }
111e2841179SLoGin             }
112e2841179SLoGin 
113e2841179SLoGin             // kdebug!("handle_irq_event");
114e2841179SLoGin 
115e2841179SLoGin             desc_inner_guard
116e2841179SLoGin                 .internal_state_mut()
117e2841179SLoGin                 .remove(IrqDescState::IRQS_PENDING);
118e2841179SLoGin             desc_inner_guard.common_data().set_inprogress();
119e2841179SLoGin 
120e2841179SLoGin             drop(desc_inner_guard);
121e2841179SLoGin 
122e2841179SLoGin             let _r = do_handle_irq_event(irq_desc);
123e2841179SLoGin 
124e2841179SLoGin             desc_inner_guard = irq_desc.inner();
125e2841179SLoGin             desc_inner_guard.common_data().clear_inprogress();
126e2841179SLoGin 
127*b5b571e0SLoGin             if !desc_inner_guard
128e2841179SLoGin                 .internal_state()
129e2841179SLoGin                 .contains(IrqDescState::IRQS_PENDING)
130*b5b571e0SLoGin                 || desc_inner_guard.common_data().disabled()
131e2841179SLoGin             {
132e2841179SLoGin                 break;
133e2841179SLoGin             }
134e2841179SLoGin         }
135e2841179SLoGin     }
136e2841179SLoGin }
137e2841179SLoGin 
138e2841179SLoGin /// 判断中断是否可以运行
139e2841179SLoGin fn irq_may_run(desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>) -> bool {
140e2841179SLoGin     let mask = IrqStatus::IRQD_IRQ_INPROGRESS | IrqStatus::IRQD_WAKEUP_ARMED;
141e2841179SLoGin     let status = desc_inner_guard.common_data().status();
142e2841179SLoGin 
143e2841179SLoGin     // 如果中断不在处理中并且没有被唤醒,则可以运行
144e2841179SLoGin     if status.bitand(mask).is_empty() {
145e2841179SLoGin         return true;
146e2841179SLoGin     }
147e2841179SLoGin 
148e2841179SLoGin     // todo: 检查其他处理器是否在轮询当前中断
149e2841179SLoGin     return false;
150e2841179SLoGin }
151e2841179SLoGin 
152338f6903SLoGin pub(super) fn mask_ack_irq(irq_data: &Arc<IrqData>) {
153e2841179SLoGin     let chip = irq_data.chip_info_read_irqsave().chip();
154e2841179SLoGin     if chip.can_mask_ack() {
155*b5b571e0SLoGin         chip.irq_mask_ack(irq_data);
156e2841179SLoGin         irq_data.common_data().set_masked();
157e2841179SLoGin     } else {
158e2841179SLoGin         irq_manager().mask_irq(irq_data);
159*b5b571e0SLoGin         chip.irq_ack(irq_data);
160e2841179SLoGin     }
161e2841179SLoGin }
162e2841179SLoGin 
163e2841179SLoGin impl IrqManager {
164e2841179SLoGin     pub(super) fn do_irq_wake_thread(
165e2841179SLoGin         &self,
166e2841179SLoGin         desc: &Arc<IrqDesc>,
167e2841179SLoGin         action_inner: &mut SpinLockGuard<'_, InnerIrqAction>,
168e2841179SLoGin     ) {
169e2841179SLoGin         let thread = action_inner.thread();
170e2841179SLoGin 
171e2841179SLoGin         if thread.is_none() {
172e2841179SLoGin             return;
173e2841179SLoGin         }
174e2841179SLoGin 
175e2841179SLoGin         let thread = thread.unwrap();
176e2841179SLoGin         if thread.flags().contains(ProcessFlags::EXITING) {
177e2841179SLoGin             return;
178e2841179SLoGin         }
179e2841179SLoGin 
180e2841179SLoGin         // 如果线程已经在运行,我们不需要唤醒它
181e2841179SLoGin         if action_inner
182e2841179SLoGin             .thread_flags_mut()
183e2841179SLoGin             .test_and_set_bit(ThreadedHandlerFlags::IRQTF_RUNTHREAD)
184e2841179SLoGin         {
185e2841179SLoGin             return;
186e2841179SLoGin         }
187e2841179SLoGin 
188e2841179SLoGin         desc.inc_threads_active();
189e2841179SLoGin 
190e2841179SLoGin         ProcessManager::wakeup(&thread).ok();
191e2841179SLoGin     }
192e2841179SLoGin }
193e2841179SLoGin 
194e2841179SLoGin /// 处理中断事件
195e2841179SLoGin ///
196e2841179SLoGin /// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/handle.c?fi=handle_irq_event#139
197e2841179SLoGin #[inline(never)]
198e2841179SLoGin fn do_handle_irq_event(desc: &Arc<IrqDesc>) -> Result<(), SystemError> {
199e2841179SLoGin     let desc_inner_guard = desc.inner();
200e2841179SLoGin     let irq_data = desc_inner_guard.irq_data().clone();
201e2841179SLoGin     let actions = desc_inner_guard.actions().clone();
202e2841179SLoGin     drop(desc_inner_guard);
203e2841179SLoGin 
204e2841179SLoGin     let irq = irq_data.irq();
205e2841179SLoGin     let mut r = Ok(IrqReturn::NotHandled);
206e2841179SLoGin 
207e2841179SLoGin     for action in actions {
208e2841179SLoGin         let mut action_inner: SpinLockGuard<'_, InnerIrqAction> = action.inner();
209e2841179SLoGin         // kdebug!("do_handle_irq_event: action: {:?}", action_inner.name());
210e2841179SLoGin         let dynamic_data = action_inner
211e2841179SLoGin             .dev_id()
212e2841179SLoGin             .clone()
213e2841179SLoGin             .map(|d| d as Arc<dyn IrqHandlerData>);
214e2841179SLoGin         r = action_inner
215e2841179SLoGin             .handler()
216e2841179SLoGin             .unwrap()
217e2841179SLoGin             .handle(irq, None, dynamic_data);
218e2841179SLoGin 
219e2841179SLoGin         if let Ok(IrqReturn::WakeThread) = r {
220e2841179SLoGin             if unlikely(action_inner.thread_fn().is_none()) {
221e2841179SLoGin                 warn_no_thread(irq, &mut action_inner);
222e2841179SLoGin             } else {
223e2841179SLoGin                 irq_manager().do_irq_wake_thread(desc, &mut action_inner);
224e2841179SLoGin             }
225e2841179SLoGin         };
226e2841179SLoGin     }
227e2841179SLoGin 
228e2841179SLoGin     return r.map(|_| ());
229e2841179SLoGin }
230e2841179SLoGin 
231e2841179SLoGin fn warn_no_thread(irq: IrqNumber, action_inner: &mut SpinLockGuard<'_, InnerIrqAction>) {
232e2841179SLoGin     // warn on once
233e2841179SLoGin     if action_inner
234e2841179SLoGin         .thread_flags_mut()
235e2841179SLoGin         .test_and_set_bit(ThreadedHandlerFlags::IRQTF_WARNED)
236e2841179SLoGin     {
237e2841179SLoGin         return;
238e2841179SLoGin     }
239e2841179SLoGin 
240e2841179SLoGin     kwarn!(
241e2841179SLoGin         "irq {}, device {} returned IRQ_WAKE_THREAD, but no threaded handler",
242e2841179SLoGin         irq.data(),
243e2841179SLoGin         action_inner.name()
244e2841179SLoGin     );
245e2841179SLoGin }
246338f6903SLoGin 
247338f6903SLoGin /// `handle_percpu_devid_irq` - 带有per-CPU设备id的perCPU本地中断处理程序
248338f6903SLoGin ///
249338f6903SLoGin ///
250338f6903SLoGin /// * `desc`: 此中断的中断描述结构
251338f6903SLoGin ///
252338f6903SLoGin /// 在没有锁定要求的SMP机器上的每个CPU中断。与linux的`handle_percpu_irq()`相同,但有以下额外内容:
253338f6903SLoGin ///
254338f6903SLoGin /// `action->percpu_dev_id`是一个指向per-cpu变量的指针,这些变量
255338f6903SLoGin /// 包含调用此处理程序的cpu的真实设备id
256338f6903SLoGin #[derive(Debug)]
257338f6903SLoGin pub struct PerCpuDevIdIrqHandler;
258338f6903SLoGin 
259338f6903SLoGin impl IrqFlowHandler for PerCpuDevIdIrqHandler {
260338f6903SLoGin     fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
261338f6903SLoGin         let desc_inner_guard = irq_desc.inner();
262338f6903SLoGin         let irq_data = desc_inner_guard.irq_data().clone();
263338f6903SLoGin         let chip = irq_data.chip_info_read().chip();
264338f6903SLoGin 
265338f6903SLoGin         chip.irq_ack(&irq_data);
266338f6903SLoGin 
267338f6903SLoGin         let irq = irq_data.irq();
268338f6903SLoGin 
269338f6903SLoGin         let action = desc_inner_guard.actions().first().cloned();
270338f6903SLoGin 
271338f6903SLoGin         drop(desc_inner_guard);
272338f6903SLoGin 
273338f6903SLoGin         if let Some(action) = action {
274338f6903SLoGin             let action_inner = action.inner();
275338f6903SLoGin             let per_cpu_devid = action_inner.per_cpu_dev_id().cloned();
276338f6903SLoGin 
277338f6903SLoGin             let handler = action_inner.handler().unwrap();
278338f6903SLoGin             drop(action_inner);
279338f6903SLoGin 
280338f6903SLoGin             let _r = handler.handle(
281338f6903SLoGin                 irq,
282338f6903SLoGin                 None,
283338f6903SLoGin                 per_cpu_devid.map(|d| d as Arc<dyn IrqHandlerData>),
284338f6903SLoGin             );
285338f6903SLoGin         } else {
286338f6903SLoGin             let cpu = smp_get_processor_id();
287338f6903SLoGin 
288338f6903SLoGin             let enabled = irq_desc
289338f6903SLoGin                 .inner()
290338f6903SLoGin                 .percpu_enabled()
291338f6903SLoGin                 .as_ref()
292338f6903SLoGin                 .unwrap()
293338f6903SLoGin                 .get(cpu)
294338f6903SLoGin                 .unwrap_or(false);
295338f6903SLoGin 
296338f6903SLoGin             if enabled {
297338f6903SLoGin                 irq_manager().irq_percpu_disable(irq_desc, &irq_data, &chip, cpu);
298338f6903SLoGin             }
299338f6903SLoGin             static ONCE: Once = Once::new();
300338f6903SLoGin 
301338f6903SLoGin             ONCE.call_once(|| {
302338f6903SLoGin                 kerror!(
303338f6903SLoGin                     "Spurious percpu irq {} on cpu {:?}, enabled: {}",
304338f6903SLoGin                     irq.data(),
305338f6903SLoGin                     cpu,
306338f6903SLoGin                     enabled
307338f6903SLoGin                 );
308338f6903SLoGin             });
309338f6903SLoGin         }
310338f6903SLoGin 
311338f6903SLoGin         chip.irq_eoi(&irq_data);
312338f6903SLoGin     }
313338f6903SLoGin }
314