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)] 25 pub fn bad_irq_handler() -> &'static dyn IrqFlowHandler { 26 &HandleBadIrq 27 } 28 29 /// 获取用于处理快速EOI的中断的处理程序 30 #[inline(always)] 31 pub fn fast_eoi_irq_handler() -> &'static dyn IrqFlowHandler { 32 &FastEOIIrqHandler 33 } 34 35 /// 获取用于处理边沿触发中断的处理程序 36 #[inline(always)] 37 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 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 { 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 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() && 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() 131 { 132 break; 133 } 134 } 135 } 136 } 137 138 /// 判断中断是否可以运行 139 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 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 { 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)] 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 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 { 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