1 use core::{intrinsics::unlikely, ops::BitAnd};
2
3 use alloc::sync::Arc;
4 use system_error::SystemError;
5
6 use crate::{
7 arch::{interrupt::TrapFrame, CurrentIrqArch},
8 exception::irqdesc::InnerIrqDesc,
9 libs::{once::Once, spinlock::SpinLockGuard},
10 process::{ProcessFlags, ProcessManager},
11 smp::core::smp_get_processor_id,
12 };
13
14 use super::{
15 irqdata::{IrqData, IrqHandlerData, IrqStatus},
16 irqdesc::{
17 InnerIrqAction, IrqDesc, IrqDescState, IrqFlowHandler, IrqReturn, ThreadedHandlerFlags,
18 },
19 manage::{irq_manager, IrqManager},
20 InterruptArch, IrqNumber,
21 };
22
23 /// 获取用于处理错误的中断的处理程序
24 #[inline(always)]
bad_irq_handler() -> &'static dyn IrqFlowHandler25 pub fn bad_irq_handler() -> &'static dyn IrqFlowHandler {
26 &HandleBadIrq
27 }
28
29 /// 获取用于处理快速EOI的中断的处理程序
30 #[inline(always)]
fast_eoi_irq_handler() -> &'static dyn IrqFlowHandler31 pub fn fast_eoi_irq_handler() -> &'static dyn IrqFlowHandler {
32 &FastEOIIrqHandler
33 }
34
35 /// 获取用于处理边沿触发中断的处理程序
36 #[inline(always)]
edge_irq_handler() -> &'static dyn IrqFlowHandler37 pub fn edge_irq_handler() -> &'static dyn IrqFlowHandler {
38 &EdgeIrqHandler
39 }
40
41 /// handle spurious and unhandled irqs
42 #[derive(Debug)]
43 struct HandleBadIrq;
44
45 impl IrqFlowHandler for HandleBadIrq {
46 /// 参考: 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)47 fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
48 // todo: print_irq_desc
49 // todo: 增加kstat计数
50 CurrentIrqArch::ack_bad_irq(irq_desc.irq());
51 }
52 }
53
54 #[derive(Debug)]
55 struct FastEOIIrqHandler;
56
57 impl IrqFlowHandler for FastEOIIrqHandler {
handle(&self, _irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame)58 fn handle(&self, _irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
59 // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/chip.c?r=&mo=17578&fi=689#689
60 todo!("FastEOIIrqHandler");
61 }
62 }
63
64 #[derive(Debug)]
65 struct EdgeIrqHandler;
66
67 impl IrqFlowHandler for EdgeIrqHandler {
68 // 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)69 fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
70 let mut desc_inner_guard: SpinLockGuard<'_, InnerIrqDesc> = irq_desc.inner();
71 if !irq_may_run(&desc_inner_guard) {
72 // kdebug!("!irq_may_run");
73 desc_inner_guard
74 .internal_state_mut()
75 .insert(IrqDescState::IRQS_PENDING);
76 mask_ack_irq(desc_inner_guard.irq_data());
77 return;
78 }
79
80 if desc_inner_guard.common_data().disabled() {
81 // kdebug!("desc_inner_guard.common_data().disabled()");
82 desc_inner_guard
83 .internal_state_mut()
84 .insert(IrqDescState::IRQS_PENDING);
85 mask_ack_irq(desc_inner_guard.irq_data());
86 return;
87 }
88
89 let irq_data = desc_inner_guard.irq_data().clone();
90
91 irq_data.chip_info_read_irqsave().chip().irq_ack(&irq_data);
92
93 loop {
94 if unlikely(desc_inner_guard.actions().is_empty()) {
95 kdebug!("no action for irq {}", irq_data.irq().data());
96 irq_manager().mask_irq(&irq_data);
97 return;
98 }
99
100 // 当我们在处理一个中断时,如果另一个中断到来,我们本可以屏蔽它.
101 // 如果在此期间没有被禁用,请重新启用它。
102 if desc_inner_guard
103 .internal_state()
104 .contains(IrqDescState::IRQS_PENDING)
105 {
106 let status = desc_inner_guard.common_data().status();
107 if status.disabled() == false && status.masked() {
108 // kdebug!("re-enable irq");
109 irq_manager().unmask_irq(&desc_inner_guard);
110 }
111 }
112
113 // kdebug!("handle_irq_event");
114
115 desc_inner_guard
116 .internal_state_mut()
117 .remove(IrqDescState::IRQS_PENDING);
118 desc_inner_guard.common_data().set_inprogress();
119
120 drop(desc_inner_guard);
121
122 let _r = do_handle_irq_event(irq_desc);
123
124 desc_inner_guard = irq_desc.inner();
125 desc_inner_guard.common_data().clear_inprogress();
126
127 if !(desc_inner_guard
128 .internal_state()
129 .contains(IrqDescState::IRQS_PENDING)
130 && desc_inner_guard.common_data().disabled() == false)
131 {
132 break;
133 }
134 }
135 }
136 }
137
138 /// 判断中断是否可以运行
irq_may_run(desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>) -> bool139 fn irq_may_run(desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>) -> bool {
140 let mask = IrqStatus::IRQD_IRQ_INPROGRESS | IrqStatus::IRQD_WAKEUP_ARMED;
141 let status = desc_inner_guard.common_data().status();
142
143 // 如果中断不在处理中并且没有被唤醒,则可以运行
144 if status.bitand(mask).is_empty() {
145 return true;
146 }
147
148 // todo: 检查其他处理器是否在轮询当前中断
149 return false;
150 }
151
mask_ack_irq(irq_data: &Arc<IrqData>)152 pub(super) fn mask_ack_irq(irq_data: &Arc<IrqData>) {
153 let chip = irq_data.chip_info_read_irqsave().chip();
154 if chip.can_mask_ack() {
155 chip.irq_mask_ack(&irq_data);
156 irq_data.common_data().set_masked();
157 } else {
158 irq_manager().mask_irq(irq_data);
159 chip.irq_ack(&irq_data);
160 }
161 }
162
163 impl IrqManager {
do_irq_wake_thread( &self, desc: &Arc<IrqDesc>, action_inner: &mut SpinLockGuard<'_, InnerIrqAction>, )164 pub(super) fn do_irq_wake_thread(
165 &self,
166 desc: &Arc<IrqDesc>,
167 action_inner: &mut SpinLockGuard<'_, InnerIrqAction>,
168 ) {
169 let thread = action_inner.thread();
170
171 if thread.is_none() {
172 return;
173 }
174
175 let thread = thread.unwrap();
176 if thread.flags().contains(ProcessFlags::EXITING) {
177 return;
178 }
179
180 // 如果线程已经在运行,我们不需要唤醒它
181 if action_inner
182 .thread_flags_mut()
183 .test_and_set_bit(ThreadedHandlerFlags::IRQTF_RUNTHREAD)
184 {
185 return;
186 }
187
188 desc.inc_threads_active();
189
190 ProcessManager::wakeup(&thread).ok();
191 }
192 }
193
194 /// 处理中断事件
195 ///
196 /// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/handle.c?fi=handle_irq_event#139
197 #[inline(never)]
do_handle_irq_event(desc: &Arc<IrqDesc>) -> Result<(), SystemError>198 fn do_handle_irq_event(desc: &Arc<IrqDesc>) -> Result<(), SystemError> {
199 let desc_inner_guard = desc.inner();
200 let irq_data = desc_inner_guard.irq_data().clone();
201 let actions = desc_inner_guard.actions().clone();
202 drop(desc_inner_guard);
203
204 let irq = irq_data.irq();
205 let mut r = Ok(IrqReturn::NotHandled);
206
207 for action in actions {
208 let mut action_inner: SpinLockGuard<'_, InnerIrqAction> = action.inner();
209 // kdebug!("do_handle_irq_event: action: {:?}", action_inner.name());
210 let dynamic_data = action_inner
211 .dev_id()
212 .clone()
213 .map(|d| d as Arc<dyn IrqHandlerData>);
214 r = action_inner
215 .handler()
216 .unwrap()
217 .handle(irq, None, dynamic_data);
218
219 if let Ok(IrqReturn::WakeThread) = r {
220 if unlikely(action_inner.thread_fn().is_none()) {
221 warn_no_thread(irq, &mut action_inner);
222 } else {
223 irq_manager().do_irq_wake_thread(desc, &mut action_inner);
224 }
225 };
226 }
227
228 return r.map(|_| ());
229 }
230
warn_no_thread(irq: IrqNumber, action_inner: &mut SpinLockGuard<'_, InnerIrqAction>)231 fn warn_no_thread(irq: IrqNumber, action_inner: &mut SpinLockGuard<'_, InnerIrqAction>) {
232 // warn on once
233 if action_inner
234 .thread_flags_mut()
235 .test_and_set_bit(ThreadedHandlerFlags::IRQTF_WARNED)
236 {
237 return;
238 }
239
240 kwarn!(
241 "irq {}, device {} returned IRQ_WAKE_THREAD, but no threaded handler",
242 irq.data(),
243 action_inner.name()
244 );
245 }
246
247 /// `handle_percpu_devid_irq` - 带有per-CPU设备id的perCPU本地中断处理程序
248 ///
249 ///
250 /// * `desc`: 此中断的中断描述结构
251 ///
252 /// 在没有锁定要求的SMP机器上的每个CPU中断。与linux的`handle_percpu_irq()`相同,但有以下额外内容:
253 ///
254 /// `action->percpu_dev_id`是一个指向per-cpu变量的指针,这些变量
255 /// 包含调用此处理程序的cpu的真实设备id
256 #[derive(Debug)]
257 pub struct PerCpuDevIdIrqHandler;
258
259 impl IrqFlowHandler for PerCpuDevIdIrqHandler {
handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame)260 fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
261 let desc_inner_guard = irq_desc.inner();
262 let irq_data = desc_inner_guard.irq_data().clone();
263 let chip = irq_data.chip_info_read().chip();
264
265 chip.irq_ack(&irq_data);
266
267 let irq = irq_data.irq();
268
269 let action = desc_inner_guard.actions().first().cloned();
270
271 drop(desc_inner_guard);
272
273 if let Some(action) = action {
274 let action_inner = action.inner();
275 let per_cpu_devid = action_inner.per_cpu_dev_id().cloned();
276
277 let handler = action_inner.handler().unwrap();
278 drop(action_inner);
279
280 let _r = handler.handle(
281 irq,
282 None,
283 per_cpu_devid.map(|d| d as Arc<dyn IrqHandlerData>),
284 );
285 } else {
286 let cpu = smp_get_processor_id();
287
288 let enabled = irq_desc
289 .inner()
290 .percpu_enabled()
291 .as_ref()
292 .unwrap()
293 .get(cpu)
294 .unwrap_or(false);
295
296 if enabled {
297 irq_manager().irq_percpu_disable(irq_desc, &irq_data, &chip, cpu);
298 }
299 static ONCE: Once = Once::new();
300
301 ONCE.call_once(|| {
302 kerror!(
303 "Spurious percpu irq {} on cpu {:?}, enabled: {}",
304 irq.data(),
305 cpu,
306 enabled
307 );
308 });
309 }
310
311 chip.irq_eoi(&irq_data);
312 }
313 }
314