xref: /DragonOS/kernel/src/exception/irqchip.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
1 use core::{any::Any, fmt::Debug, intrinsics::unlikely};
2 
3 use alloc::{
4     string::{String, ToString},
5     sync::{Arc, Weak},
6     vec::Vec,
7 };
8 use log::warn;
9 use system_error::SystemError;
10 
11 use crate::{
12     exception::{
13         dummychip::no_irq_chip,
14         handle::{bad_irq_handler, mask_ack_irq},
15         irqdata::IrqStatus,
16         irqdesc::irq_desc_manager,
17         manage::irq_manager,
18     },
19     libs::{
20         cpumask::CpuMask,
21         once::Once,
22         spinlock::{SpinLock, SpinLockGuard},
23     },
24     mm::VirtAddr,
25     smp::cpu::ProcessorId,
26 };
27 
28 use super::{
29     irqdata::{IrqData, IrqHandlerData, IrqLineStatus},
30     irqdesc::{InnerIrqDesc, IrqAction, IrqDesc, IrqFlowHandler, IrqHandler, IrqReturn},
31     irqdomain::IrqDomain,
32     manage::IrqManager,
33     msi::MsiMsg,
34     IrqNumber,
35 };
36 
37 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#506
38 pub trait IrqChip: Sync + Send + Any + Debug {
39     fn name(&self) -> &'static str;
40     /// start up the interrupt (defaults to ->enable if ENOSYS)
41     fn irq_startup(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
42         Err(SystemError::ENOSYS)
43     }
44 
45     /// shut down the interrupt (defaults to ->disable if ENOSYS)
46     fn irq_shutdown(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
47         Err(SystemError::ENOSYS)
48     }
49 
50     /// enable the interrupt
51     ///
52     /// (defaults to ->unmask if ENOSYS)
53     fn irq_enable(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
54         Err(SystemError::ENOSYS)
55     }
56 
57     /// disable the interrupt
58     fn irq_disable(&self, irq_data: &Arc<IrqData>);
59 
60     /// start of a new interrupt
61     fn irq_ack(&self, irq_data: &Arc<IrqData>);
62 
63     /// mask an interrupt source
64     ///
65     /// 用于屏蔽中断
66     ///
67     /// 如果返回ENOSYS,则表明irq_mask()不支持. 那么中断机制代码将调用irq_disable()。
68     ///
69     /// 如果返回错误,那么中断的屏蔽状态将不会改变。
70     fn irq_mask(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
71         Err(SystemError::ENOSYS)
72     }
73 
74     /// 指示当前芯片是否实现了`irq_mask_ack`函数
75     fn can_mask_ack(&self) -> bool;
76 
77     /// ack and mask an interrupt source
78     fn irq_mask_ack(&self, _irq_data: &Arc<IrqData>) {}
79 
80     /// unmask an interrupt source
81     ///
82     /// 用于取消屏蔽中断
83     ///
84     /// 如果返回ENOSYS,则表明irq_unmask()不支持.
85     fn irq_unmask(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
86         Err(SystemError::ENOSYS)
87     }
88     /// end of interrupt
89     fn irq_eoi(&self, _irq_data: &Arc<IrqData>) {}
90 
91     /// 指示当前芯片是否可以设置中断亲和性。
92     fn can_set_affinity(&self) -> bool;
93 
94     /// 在SMP机器上设置CPU亲和性。
95     ///
96     /// 如果force参数为真,它告诉驱动程序无条件地应用亲和性设置。
97     /// 不需要对提供的亲和性掩码进行完整性检查。这用于CPU热插拔,其中目标CPU尚未在cpu_online_mask中设置。
98     fn irq_set_affinity(
99         &self,
100         _irq_data: &Arc<IrqData>,
101         _cpu: &CpuMask,
102         _force: bool,
103     ) -> Result<IrqChipSetMaskResult, SystemError> {
104         Err(SystemError::ENOSYS)
105     }
106 
107     /// retrigger an IRQ to the CPU
108     fn retrigger(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
109         Err(SystemError::ENOSYS)
110     }
111 
112     /// 指示当前芯片是否可以设置中断流类型。
113     ///
114     /// 如果返回true,则可以调用irq_set_type()。
115     fn can_set_flow_type(&self) -> bool;
116 
117     /// set the flow type of an interrupt
118     ///
119     /// flow_type: the flow type to set
120     ///
121     fn irq_set_type(
122         &self,
123         _irq_data: &Arc<IrqData>,
124         _flow_type: IrqLineStatus,
125     ) -> Result<IrqChipSetMaskResult, SystemError> {
126         Err(SystemError::ENOSYS)
127     }
128 
129     /// enable/disable power management wake-on of an interrupt
130     fn irq_set_wake(&self, _irq_data: &Arc<IrqData>, _on: bool) -> Result<(), SystemError> {
131         Err(SystemError::ENOSYS)
132     }
133 
134     /// function to lock access to slow bus (i2c) chips
135     fn irq_bus_lock(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
136         Ok(())
137     }
138 
139     /// function to sync and unlock slow bus (i2c) chips
140     fn irq_bus_sync_unlock(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
141         Ok(())
142     }
143 
144     /// function called from core code on suspend once per
145     /// chip, when one or more interrupts are installed
146     fn irq_suspend(&self, _irq_data: &Arc<IrqData>) {}
147 
148     /// function called from core code on resume once per chip,
149     /// when one ore more interrupts are installed
150     fn irq_resume(&self, _irq_data: &Arc<IrqData>) {}
151 
152     /// function called from core code on shutdown once per chip
153     fn irq_pm_shutdown(&self, _irq_data: &Arc<IrqData>) {}
154 
155     /// Optional function to set irq_data.mask for special cases
156     fn irq_calc_mask(&self, _irq_data: &Arc<IrqData>) {}
157 
158     // todo: print chip
159 
160     /// optional to request resources before calling
161     /// any other callback related to this irq
162     fn irq_request_resources(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
163         Ok(())
164     }
165 
166     /// optional to release resources acquired with
167     /// irq_request_resources
168     fn irq_release_resources(&self, _irq_data: &Arc<IrqData>) {}
169 
170     /// optional to compose message content for MSI
171     ///
172     /// 组装MSI消息并返回到msg中
173     fn irq_compose_msi_msg(&self, _irq_data: &Arc<IrqData>, _msg: &mut MsiMsg) {}
174 
175     /// optional to write message content for MSI
176     fn irq_write_msi_msg(&self, _irq_data: &Arc<IrqData>, _msg: &MsiMsg) {}
177 
178     /// return the internal state of an interrupt
179     fn irqchip_state(
180         &self,
181         _irq_data: &Arc<IrqData>,
182         _which: IrqChipState,
183     ) -> Result<bool, SystemError> {
184         Err(SystemError::ENOSYS)
185     }
186 
187     /// set the internal state of an interrupt
188     fn set_irqchip_state(
189         &self,
190         _irq_data: &Arc<IrqData>,
191         _which: IrqChipState,
192         _state: bool,
193     ) -> Result<(), SystemError> {
194         Err(SystemError::ENOSYS)
195     }
196 
197     // todo: set vcpu affinity
198 
199     /// send a single IPI to destination cpus
200     fn send_single_ipi(&self, _irq_data: &Arc<IrqData>, _cpu: u32) {}
201 
202     // todo: send ipi with cpu mask
203 
204     /// function called from core code before enabling an NMI
205     fn irq_nmi_setup(&self, _irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
206         Err(SystemError::ENOSYS)
207     }
208 
209     /// function called from core code after disabling an NMI
210     fn irq_nmi_teardown(&self, _irq_data: &Arc<IrqData>) {}
211 
212     fn flags(&self) -> IrqChipFlags;
213 }
214 
215 #[allow(dead_code)]
216 #[derive(Debug, Clone, Copy)]
217 pub enum IrqChipState {
218     /// Is the interrupt pending?
219     Pending,
220     /// Is the interrupt in progress?
221     Active,
222     /// Is the interrupt masked?
223     Masked,
224     /// Is Irq line high?
225     LineLevel,
226 }
227 
228 /// 中断芯片的数据(per-irq的)
229 pub trait IrqChipData: Sync + Send + Any + Debug {
230     fn as_any_ref(&self) -> &dyn Any;
231 }
232 
233 bitflags! {
234     /// 定义 IrqGcFlags 位标志
235     pub struct IrqGcFlags: u32 {
236         /// 通过读取mask reg来初始化mask_cache
237         const IRQ_GC_INIT_MASK_CACHE = 1 << 0;
238         /// 对于需要在父irq上调用irq_set_wake()的irq芯片, 将irqs的锁类设置为嵌套。Usually GPIO implementations
239         const IRQ_GC_INIT_NESTED_LOCK = 1 << 1;
240         /// Mask cache是芯片类型私有的
241         const IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2;
242         /// 不计算irqData->mask
243         const IRQ_GC_NO_MASK = 1 << 3;
244         /// 使用大端字节序的寄存器访问(默认:小端LE)
245         const IRQ_GC_BE_IO = 1 << 4;
246     }
247 }
248 
249 #[allow(dead_code)]
250 #[derive(Debug)]
251 pub struct IrqChipGeneric {
252     inner: SpinLock<InnerIrqChipGeneric>,
253 }
254 
255 #[allow(dead_code)]
256 #[derive(Debug)]
257 struct InnerIrqChipGeneric {
258     /// Register base address
259     reg_base: VirtAddr,
260     ops: &'static dyn IrqChipGenericOps,
261     /// Interrupt base num for this chip
262     irq_base: u32,
263     /// Number of interrupts handled by this chip
264     irq_cnt: u32,
265     /// Cached mask register shared between all chip types
266     mask_cache: u32,
267     /// Cached type register
268     type_cache: u32,
269     /// Cached polarity register
270     polarity_cache: u32,
271     /// Interrupt can wakeup from suspend
272     wake_enabled: bool,
273     /// Interrupt is marked as an wakeup from suspend source
274     wake_active: bool,
275     /// Number of available irq_chip_type instances (usually 1)
276     num_chip_type: u32,
277     private_data: Option<Arc<dyn IrqChipGenericPrivateData>>,
278     installed: u64,
279     unused: u64,
280     domain: Weak<IrqDomain>,
281     chip_types: Vec<IrqChipType>,
282 }
283 
284 pub trait IrqChipGenericOps: Debug + Send + Sync {
285     /// Alternate I/O accessor (defaults to readl if NULL)
286     unsafe fn reg_readl(&self, addr: VirtAddr) -> u32;
287 
288     /// Alternate I/O accessor (defaults to writel if NULL)
289     unsafe fn reg_writel(&self, addr: VirtAddr, val: u32);
290 
291     /// Function called from core code on suspend once per
292     /// chip; can be useful instead of irq_chip::suspend to
293     /// handle chip details even when no interrupts are in use
294     fn suspend(&self, gc: &Arc<IrqChipGeneric>);
295     /// Function called from core code on resume once per chip;
296     /// can be useful instead of irq_chip::resume to handle chip
297     /// details even when no interrupts are in use
298     fn resume(&self, gc: &Arc<IrqChipGeneric>);
299 }
300 
301 pub trait IrqChipGenericPrivateData: Sync + Send + Any + Debug {}
302 
303 #[derive(Debug)]
304 pub struct IrqChipType {
305     // todo https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#1024
306 }
307 
308 #[allow(dead_code)]
309 #[derive(Debug)]
310 pub enum IrqChipSetMaskResult {
311     /// core updates mask ok.
312     Success,
313     /// core updates mask ok. No change.
314     NoChange,
315     /// core updates mask ok. Done.(same as SetMaskOk)
316     ///
317     /// 支持堆叠irq芯片的特殊代码, 表示跳过所有子irq芯片。
318     Done,
319 }
320 
321 bitflags! {
322     /// IrqChip specific flags
323     pub struct IrqChipFlags: u32 {
324         /// 在调用chip.irq_set_type()之前屏蔽中断
325         const IRQCHIP_SET_TYPE_MASKED = 1 << 0;
326         /// 只有在irq被处理时才发出irq_eoi()
327         const IRQCHIP_EOI_IF_HANDLED = 1 << 1;
328         /// 在挂起路径中屏蔽非唤醒irq
329         const IRQCHIP_MASK_ON_SUSPEND = 1 << 2;
330         /// 只有在irq启用时才调用irq_on/off_line回调
331         const IRQCHIP_ONOFFLINE_ENABLED = 1 << 3;
332         /// 跳过chip.irq_set_wake(),对于这个irq芯片
333         const IRQCHIP_SKIP_SET_WAKE = 1 << 4;
334         /// 单次触发不需要屏蔽/取消屏蔽
335         const IRQCHIP_ONESHOT_SAFE = 1 << 5;
336         /// 芯片在线程模式下需要在取消屏蔽时eoi()
337         const IRQCHIP_EOI_THREADED = 1 << 6;
338         /// 芯片可以为Level MSIs提供两个门铃
339         const IRQCHIP_SUPPORTS_LEVEL_MSI = 1 << 7;
340         /// 芯片可以传递NMIs,仅适用于根irqchips
341         const IRQCHIP_SUPPORTS_NMI = 1 << 8;
342         /// 在挂起路径中,如果它们处于禁用状态,则调用__enable_irq()/__disable_irq()以唤醒irq
343         const IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = 1 << 9;
344         /// 在启动前更新默认亲和性
345         const IRQCHIP_AFFINITY_PRE_STARTUP = 1 << 10;
346         /// 不要在这个芯片中改变任何东西
347         const IRQCHIP_IMMUTABLE = 1 << 11;
348     }
349 }
350 
351 impl IrqManager {
352     /// Acknowledge the parent interrupt
353     #[allow(dead_code)]
354     pub fn irq_chip_ack_parent(&self, irq_data: &Arc<IrqData>) {
355         let parent_data = irq_data.parent_data().and_then(|p| p.upgrade());
356 
357         if let Some(parent_data) = parent_data {
358             let parent_chip = parent_data.chip_info_read_irqsave().chip();
359             parent_chip.irq_ack(&parent_data);
360         }
361     }
362 
363     /// 在硬件中重新触发中断
364     ///
365     /// 遍历中断域的层次结构,并检查是否存在一个硬件重新触发函数。如果存在则调用它
366     pub fn irq_chip_retrigger_hierarchy(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
367         let mut data: Option<Arc<IrqData>> = Some(irq_data.clone());
368         while let Some(d) = data {
369             if let Err(e) = d.chip_info_read_irqsave().chip().retrigger(&d) {
370                 if e == SystemError::ENOSYS {
371                     data = d.parent_data().and_then(|p| p.upgrade());
372                 } else {
373                     return Err(e);
374                 }
375             } else {
376                 return Ok(());
377             }
378         }
379 
380         return Ok(());
381     }
382 
383     pub(super) fn __irq_set_handler(
384         &self,
385         irq: IrqNumber,
386         handler: &'static dyn IrqFlowHandler,
387         is_chained: bool,
388         name: Option<String>,
389     ) {
390         let r = irq_desc_manager().lookup_and_lock_bus(irq, false, false);
391         if r.is_none() {
392             return;
393         }
394 
395         let irq_desc = r.unwrap();
396 
397         let mut desc_inner = irq_desc.inner();
398         self.__irq_do_set_handler(&irq_desc, &mut desc_inner, Some(handler), is_chained, name);
399 
400         drop(desc_inner);
401         irq_desc.chip_bus_sync_unlock();
402     }
403 
404     fn __irq_do_set_handler(
405         &self,
406         desc: &Arc<IrqDesc>,
407         desc_inner: &mut SpinLockGuard<'_, InnerIrqDesc>,
408         mut handler: Option<&'static dyn IrqFlowHandler>,
409         is_chained: bool,
410         name: Option<String>,
411     ) {
412         if handler.is_none() {
413             handler = Some(bad_irq_handler());
414         } else {
415             let mut irq_data = Some(desc_inner.irq_data().clone());
416 
417             /*
418              * 在具有中断域继承的domain中,我们可能会遇到这样的情况,
419              * 最外层的芯片还没有设置好,但是内部的芯片已经存在了。
420              * 我们选择安装处理程序,而不是退出,
421              * 但显然我们此时无法启用/启动中断。
422              */
423             while irq_data.is_some() {
424                 let dt = irq_data.as_ref().unwrap().clone();
425 
426                 let chip_info = dt.chip_info_read_irqsave();
427 
428                 if !Arc::ptr_eq(&chip_info.chip(), &no_irq_chip()) {
429                     break;
430                 }
431 
432                 /*
433                  * 如果最外层的芯片没有设置好,并且预期立即开始中断,
434                  * 则放弃。
435                  */
436                 if unlikely(is_chained) {
437                     warn!(
438                         "Chained handler for irq {} is not supported",
439                         dt.irq().data()
440                     );
441                     return;
442                 }
443 
444                 //  try the parent
445                 let parent_data = dt.parent_data().and_then(|p| p.upgrade());
446 
447                 irq_data = parent_data;
448             }
449 
450             if unlikely(
451                 irq_data.is_none()
452                     || Arc::ptr_eq(
453                         &irq_data.as_ref().unwrap().chip_info_read_irqsave().chip(),
454                         &no_irq_chip(),
455                     ),
456             ) {
457                 warn!("No irq chip for irq {}", desc_inner.irq_data().irq().data());
458                 return;
459             }
460         }
461         let handler = handler.unwrap();
462         if handler.type_id() == bad_irq_handler().type_id()
463             && Arc::ptr_eq(
464                 &desc_inner.irq_data().chip_info_read_irqsave().chip(),
465                 &no_irq_chip(),
466             )
467         {
468             let irq_data = desc_inner.irq_data();
469             mask_ack_irq(irq_data);
470 
471             irq_data.irqd_set(IrqStatus::IRQD_IRQ_DISABLED);
472 
473             if is_chained {
474                 desc_inner.clear_actions();
475             }
476             desc_inner.set_depth(1);
477         }
478         let chip = desc_inner.irq_data().chip_info_read_irqsave().chip();
479         desc.set_handler_no_lock_inner(handler, desc_inner.irq_data(), &chip);
480         desc_inner.set_name(name);
481 
482         if handler.type_id() != bad_irq_handler().type_id() && is_chained {
483             let trigger_type = desc_inner.common_data().trigger_type();
484 
485             /*
486              * 我们即将立即启动这个中断,
487              * 因此需要设置触发配置。
488              * 但是 .irq_set_type 回调可能已经覆盖了
489              * irqflowhandler,忽略了我们正在处理的
490              * 是一个链式中断。立即重置它,因为我们
491              * 确实知道更好的处理方式。
492              */
493 
494             if trigger_type != IrqLineStatus::IRQ_TYPE_NONE {
495                 irq_manager()
496                     .do_set_irq_trigger(desc.clone(), desc_inner, trigger_type)
497                     .ok();
498                 desc.set_handler(handler);
499             }
500 
501             desc_inner.set_noprobe();
502             desc_inner.set_norequest();
503             desc_inner.set_nothread();
504 
505             desc_inner.clear_actions();
506             desc_inner.add_action(chained_action());
507 
508             irq_manager()
509                 .irq_activate_and_startup(desc, desc_inner, IrqManager::IRQ_RESEND)
510                 .ok();
511         }
512 
513         return;
514     }
515 
516     pub fn irq_set_handler_data(
517         &self,
518         irq: IrqNumber,
519         data: Option<Arc<dyn IrqHandlerData>>,
520     ) -> Result<(), SystemError> {
521         let desc = irq_desc_manager().lookup(irq).ok_or(SystemError::EINVAL)?;
522         desc.inner().common_data().inner().set_handler_data(data);
523 
524         return Ok(());
525     }
526 
527     pub fn irq_percpu_disable(
528         &self,
529         desc: &Arc<IrqDesc>,
530         irq_data: &Arc<IrqData>,
531         irq_chip: &Arc<dyn IrqChip>,
532         cpu: ProcessorId,
533     ) {
534         if let Err(e) = irq_chip.irq_mask(irq_data) {
535             if e == SystemError::ENOSYS {
536                 irq_chip.irq_disable(irq_data);
537             }
538         }
539 
540         desc.inner()
541             .percpu_enabled_mut()
542             .as_mut()
543             .unwrap()
544             .set(cpu, false);
545     }
546 }
547 
548 lazy_static! {
549     pub(super) static ref CHAINED_ACTION: Arc<IrqAction> = IrqAction::new(
550         IrqNumber::new(0),
551         "".to_string(),
552         Some(&ChainedActionHandler),
553         None,
554     );
555 }
556 
557 #[allow(dead_code)]
558 pub(super) fn chained_action() -> Arc<IrqAction> {
559     CHAINED_ACTION.clone()
560 }
561 
562 /// Chained handlers 永远不应该在它们的IRQ上调用irqaction。如果发生这种情况,
563 /// 这个默认irqaction将发出警告。
564 #[derive(Debug)]
565 struct ChainedActionHandler;
566 
567 impl IrqHandler for ChainedActionHandler {
568     fn handle(
569         &self,
570         irq: IrqNumber,
571         _static_data: Option<&dyn IrqHandlerData>,
572         _dynamic_data: Option<Arc<dyn IrqHandlerData>>,
573     ) -> Result<IrqReturn, SystemError> {
574         static ONCE: Once = Once::new();
575         ONCE.call_once(|| {
576             warn!("Chained irq {} should not call an action.", irq.data());
577         });
578 
579         Ok(IrqReturn::NotHandled)
580     }
581 }
582