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