xref: /DragonOS/kernel/src/exception/irqchip.rs (revision e28411791f090c421fe4b6fa5956fb1bd362a8d9)
1ce5850adSLoGin use core::{any::Any, fmt::Debug};
2ce5850adSLoGin 
3ce5850adSLoGin use alloc::{
4ce5850adSLoGin     sync::{Arc, Weak},
5ce5850adSLoGin     vec::Vec,
6ce5850adSLoGin };
7ce5850adSLoGin use system_error::SystemError;
8ce5850adSLoGin 
9*e2841179SLoGin use crate::{
10*e2841179SLoGin     libs::{cpumask::CpuMask, spinlock::SpinLock},
11*e2841179SLoGin     mm::VirtAddr,
12*e2841179SLoGin };
13ce5850adSLoGin 
14ce5850adSLoGin use super::{
15ce5850adSLoGin     irqdata::{IrqData, IrqLineStatus},
16ce5850adSLoGin     irqdomain::IrqDomain,
17*e2841179SLoGin     manage::IrqManager,
18ce5850adSLoGin     msi::MsiMsg,
19ce5850adSLoGin };
20ce5850adSLoGin 
21ce5850adSLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#506
22ce5850adSLoGin pub trait IrqChip: Sync + Send + Any + Debug {
23ce5850adSLoGin     fn name(&self) -> &'static str;
24ce5850adSLoGin     /// start up the interrupt (defaults to ->enable if ENOSYS)
25ce5850adSLoGin     fn irq_startup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
26ce5850adSLoGin         Err(SystemError::ENOSYS)
27ce5850adSLoGin     }
28ce5850adSLoGin 
29ce5850adSLoGin     /// shut down the interrupt (defaults to ->disable if ENOSYS)
30ce5850adSLoGin     fn irq_shutdown(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
31ce5850adSLoGin         Err(SystemError::ENOSYS)
32ce5850adSLoGin     }
33ce5850adSLoGin 
34ce5850adSLoGin     /// enable the interrupt
35ce5850adSLoGin     ///
36ce5850adSLoGin     /// (defaults to ->unmask if ENOSYS)
37ce5850adSLoGin     fn irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
38ce5850adSLoGin         Err(SystemError::ENOSYS)
39ce5850adSLoGin     }
40ce5850adSLoGin 
41ce5850adSLoGin     /// disable the interrupt
42ce5850adSLoGin     fn irq_disable(&self, irq: &Arc<IrqData>);
43ce5850adSLoGin 
44ce5850adSLoGin     /// start of a new interrupt
45ce5850adSLoGin     fn irq_ack(&self, irq: &Arc<IrqData>);
46ce5850adSLoGin 
47ce5850adSLoGin     /// mask an interrupt source
48*e2841179SLoGin     ///
49*e2841179SLoGin     /// 用于屏蔽中断
50*e2841179SLoGin     ///
51*e2841179SLoGin     /// 如果返回ENOSYS,则表明irq_mask()不支持.
52*e2841179SLoGin     ///
53*e2841179SLoGin     /// 如果返回错误,那么中断的屏蔽状态将不会改变。
54*e2841179SLoGin     fn irq_mask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
55*e2841179SLoGin         Err(SystemError::ENOSYS)
56*e2841179SLoGin     }
57*e2841179SLoGin 
58*e2841179SLoGin     /// 指示当前芯片是否实现了`irq_mask_ack`函数
59*e2841179SLoGin     fn can_mask_ack(&self) -> bool;
60*e2841179SLoGin 
61ce5850adSLoGin     /// ack and mask an interrupt source
623bc96fa4SLoGin     fn irq_mask_ack(&self, _irq: &Arc<IrqData>) {}
63*e2841179SLoGin 
64ce5850adSLoGin     /// unmask an interrupt source
65*e2841179SLoGin     ///
66*e2841179SLoGin     /// 用于取消屏蔽中断
67*e2841179SLoGin     ///
68*e2841179SLoGin     /// 如果返回ENOSYS,则表明irq_unmask()不支持.
69*e2841179SLoGin     fn irq_unmask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
70*e2841179SLoGin         Err(SystemError::ENOSYS)
71*e2841179SLoGin     }
72ce5850adSLoGin     /// end of interrupt
733bc96fa4SLoGin     fn irq_eoi(&self, _irq: &Arc<IrqData>) {}
74ce5850adSLoGin 
75*e2841179SLoGin     /// 指示当前芯片是否可以设置中断亲和性。
76*e2841179SLoGin     fn can_set_affinity(&self) -> bool;
77*e2841179SLoGin 
78*e2841179SLoGin     /// 在SMP机器上设置CPU亲和性。
79*e2841179SLoGin     ///
80*e2841179SLoGin     /// 如果force参数为真,它告诉驱动程序无条件地应用亲和性设置。
81*e2841179SLoGin     /// 不需要对提供的亲和性掩码进行完整性检查。这用于CPU热插拔,其中目标CPU尚未在cpu_online_mask中设置。
82*e2841179SLoGin     fn irq_set_affinity(
83*e2841179SLoGin         &self,
84*e2841179SLoGin         _irq: &Arc<IrqData>,
85*e2841179SLoGin         _cpu: &CpuMask,
86*e2841179SLoGin         _force: bool,
87*e2841179SLoGin     ) -> Result<IrqChipSetMaskResult, SystemError> {
88*e2841179SLoGin         Err(SystemError::ENOSYS)
89*e2841179SLoGin     }
90ce5850adSLoGin 
91ce5850adSLoGin     /// retrigger an IRQ to the CPU
92*e2841179SLoGin     fn retrigger(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
93*e2841179SLoGin         Err(SystemError::ENOSYS)
94*e2841179SLoGin     }
95*e2841179SLoGin 
96*e2841179SLoGin     /// 指示当前芯片是否可以设置中断流类型。
97*e2841179SLoGin     ///
98*e2841179SLoGin     /// 如果返回true,则可以调用irq_set_type()。
99*e2841179SLoGin     fn can_set_flow_type(&self) -> bool;
100ce5850adSLoGin 
101ce5850adSLoGin     /// set the flow type of an interrupt
102ce5850adSLoGin     ///
103ce5850adSLoGin     /// flow_type: the flow type to set
104ce5850adSLoGin     ///
105ce5850adSLoGin     fn irq_set_type(
106ce5850adSLoGin         &self,
107ce5850adSLoGin         _irq: &Arc<IrqData>,
108ce5850adSLoGin         _flow_type: IrqLineStatus,
109*e2841179SLoGin     ) -> Result<IrqChipSetMaskResult, SystemError> {
110ce5850adSLoGin         Err(SystemError::ENOSYS)
111ce5850adSLoGin     }
112ce5850adSLoGin 
113ce5850adSLoGin     /// enable/disable power management wake-on of an interrupt
114ce5850adSLoGin     fn irq_set_wake(&self, _irq: &Arc<IrqData>, _on: bool) -> Result<(), SystemError> {
115ce5850adSLoGin         Err(SystemError::ENOSYS)
116ce5850adSLoGin     }
117ce5850adSLoGin 
118ce5850adSLoGin     /// function to lock access to slow bus (i2c) chips
119ce5850adSLoGin     fn irq_bus_lock(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
120ce5850adSLoGin         Ok(())
121ce5850adSLoGin     }
122ce5850adSLoGin 
123ce5850adSLoGin     /// function to sync and unlock slow bus (i2c) chips
124ce5850adSLoGin     fn irq_bus_sync_unlock(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
125ce5850adSLoGin         Ok(())
126ce5850adSLoGin     }
127ce5850adSLoGin 
128ce5850adSLoGin     /// function called from core code on suspend once per
129ce5850adSLoGin     /// chip, when one or more interrupts are installed
1303bc96fa4SLoGin     fn irq_suspend(&self, _irq: &Arc<IrqData>) {}
131ce5850adSLoGin 
132ce5850adSLoGin     /// function called from core code on resume once per chip,
133ce5850adSLoGin     /// when one ore more interrupts are installed
1343bc96fa4SLoGin     fn irq_resume(&self, _irq: &Arc<IrqData>) {}
135ce5850adSLoGin 
136ce5850adSLoGin     /// function called from core code on shutdown once per chip
1373bc96fa4SLoGin     fn irq_pm_shutdown(&self, _irq: &Arc<IrqData>) {}
138ce5850adSLoGin 
139ce5850adSLoGin     /// Optional function to set irq_data.mask for special cases
140ce5850adSLoGin     fn irq_calc_mask(&self, _irq: &Arc<IrqData>) {}
141ce5850adSLoGin 
142ce5850adSLoGin     // todo: print chip
143ce5850adSLoGin 
144ce5850adSLoGin     /// optional to request resources before calling
145ce5850adSLoGin     /// any other callback related to this irq
146ce5850adSLoGin     fn irq_request_resources(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
147ce5850adSLoGin         Ok(())
148ce5850adSLoGin     }
149ce5850adSLoGin 
150ce5850adSLoGin     /// optional to release resources acquired with
151ce5850adSLoGin     /// irq_request_resources
152ce5850adSLoGin     fn irq_release_resources(&self, _irq: &Arc<IrqData>) {}
153ce5850adSLoGin 
154ce5850adSLoGin     /// optional to compose message content for MSI
155*e2841179SLoGin     ///
156*e2841179SLoGin     /// 组装MSI消息并返回到msg中
157ce5850adSLoGin     fn irq_compose_msi_msg(&self, _irq: &Arc<IrqData>, _msg: &mut MsiMsg) {}
158ce5850adSLoGin 
159ce5850adSLoGin     /// optional to write message content for MSI
160ce5850adSLoGin     fn irq_write_msi_msg(&self, _irq: &Arc<IrqData>, _msg: &MsiMsg) {}
161ce5850adSLoGin 
162ce5850adSLoGin     /// return the internal state of an interrupt
163ce5850adSLoGin     fn irqchip_state(
164ce5850adSLoGin         &self,
165ce5850adSLoGin         _irq: &Arc<IrqData>,
166ce5850adSLoGin         _which: IrqChipState,
167ce5850adSLoGin     ) -> Result<bool, SystemError> {
168ce5850adSLoGin         Err(SystemError::ENOSYS)
169ce5850adSLoGin     }
170ce5850adSLoGin 
171ce5850adSLoGin     /// set the internal state of an interrupt
172ce5850adSLoGin     fn set_irqchip_state(
173ce5850adSLoGin         &self,
174ce5850adSLoGin         _irq: &Arc<IrqData>,
175ce5850adSLoGin         _which: IrqChipState,
176ce5850adSLoGin         _state: bool,
177ce5850adSLoGin     ) -> Result<(), SystemError> {
178ce5850adSLoGin         Err(SystemError::ENOSYS)
179ce5850adSLoGin     }
180ce5850adSLoGin 
181ce5850adSLoGin     // todo: set vcpu affinity
182ce5850adSLoGin 
183ce5850adSLoGin     /// send a single IPI to destination cpus
1843bc96fa4SLoGin     fn send_single_ipi(&self, _irq: &Arc<IrqData>, _cpu: u32) {}
185ce5850adSLoGin 
186ce5850adSLoGin     // todo: send ipi with cpu mask
187ce5850adSLoGin 
188ce5850adSLoGin     /// function called from core code before enabling an NMI
189ce5850adSLoGin     fn irq_nmi_setup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
190ce5850adSLoGin         Err(SystemError::ENOSYS)
191ce5850adSLoGin     }
192ce5850adSLoGin 
193ce5850adSLoGin     /// function called from core code after disabling an NMI
1943bc96fa4SLoGin     fn irq_nmi_teardown(&self, _irq: &Arc<IrqData>) {}
1953bc96fa4SLoGin 
1963bc96fa4SLoGin     fn flags(&self) -> IrqChipFlags;
197ce5850adSLoGin }
198ce5850adSLoGin 
199ce5850adSLoGin #[allow(dead_code)]
200ce5850adSLoGin #[derive(Debug, Clone, Copy)]
201ce5850adSLoGin pub enum IrqChipState {
202ce5850adSLoGin     /// Is the interrupt pending?
203ce5850adSLoGin     Pending,
204ce5850adSLoGin     /// Is the interrupt in progress?
205ce5850adSLoGin     Active,
206ce5850adSLoGin     /// Is the interrupt masked?
207ce5850adSLoGin     Masked,
208ce5850adSLoGin     /// Is Irq line high?
209ce5850adSLoGin     LineLevel,
210ce5850adSLoGin }
211ce5850adSLoGin 
212*e2841179SLoGin /// 中断芯片的数据(per-irq的)
213*e2841179SLoGin pub trait IrqChipData: Sync + Send + Any + Debug {
214*e2841179SLoGin     fn as_any_ref(&self) -> &dyn Any;
215*e2841179SLoGin }
216ce5850adSLoGin 
217ce5850adSLoGin bitflags! {
218ce5850adSLoGin     /// 定义 IrqGcFlags 位标志
219ce5850adSLoGin     pub struct IrqGcFlags: u32 {
220ce5850adSLoGin         /// 通过读取mask reg来初始化mask_cache
221ce5850adSLoGin         const IRQ_GC_INIT_MASK_CACHE = 1 << 0;
222ce5850adSLoGin         /// 对于需要在父irq上调用irq_set_wake()的irq芯片, 将irqs的锁类设置为嵌套。Usually GPIO implementations
223ce5850adSLoGin         const IRQ_GC_INIT_NESTED_LOCK = 1 << 1;
224ce5850adSLoGin         /// Mask cache是芯片类型私有的
225ce5850adSLoGin         const IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2;
226ce5850adSLoGin         /// 不计算irqData->mask
227ce5850adSLoGin         const IRQ_GC_NO_MASK = 1 << 3;
228ce5850adSLoGin         /// 使用大端字节序的寄存器访问(默认:小端LE)
229ce5850adSLoGin         const IRQ_GC_BE_IO = 1 << 4;
230ce5850adSLoGin     }
231ce5850adSLoGin }
232ce5850adSLoGin 
233ce5850adSLoGin #[allow(dead_code)]
234ce5850adSLoGin #[derive(Debug)]
235ce5850adSLoGin pub struct IrqChipGeneric {
236ce5850adSLoGin     inner: SpinLock<InnerIrqChipGeneric>,
237ce5850adSLoGin }
238ce5850adSLoGin 
239ce5850adSLoGin #[allow(dead_code)]
240ce5850adSLoGin #[derive(Debug)]
241ce5850adSLoGin struct InnerIrqChipGeneric {
242ce5850adSLoGin     /// Register base address
243ce5850adSLoGin     reg_base: VirtAddr,
244ce5850adSLoGin     ops: &'static dyn IrqChipGenericOps,
245ce5850adSLoGin     /// Interrupt base num for this chip
246ce5850adSLoGin     irq_base: u32,
247ce5850adSLoGin     /// Number of interrupts handled by this chip
248ce5850adSLoGin     irq_cnt: u32,
249ce5850adSLoGin     /// Cached mask register shared between all chip types
250ce5850adSLoGin     mask_cache: u32,
251ce5850adSLoGin     /// Cached type register
252ce5850adSLoGin     type_cache: u32,
253ce5850adSLoGin     /// Cached polarity register
254ce5850adSLoGin     polarity_cache: u32,
255ce5850adSLoGin     /// Interrupt can wakeup from suspend
256ce5850adSLoGin     wake_enabled: bool,
257ce5850adSLoGin     /// Interrupt is marked as an wakeup from suspend source
258ce5850adSLoGin     wake_active: bool,
259ce5850adSLoGin     /// Number of available irq_chip_type instances (usually 1)
260ce5850adSLoGin     num_chip_type: u32,
261ce5850adSLoGin     private_data: Option<Arc<dyn IrqChipGenericPrivateData>>,
262ce5850adSLoGin     installed: u64,
263ce5850adSLoGin     unused: u64,
264ce5850adSLoGin     domain: Weak<IrqDomain>,
265ce5850adSLoGin     chip_types: Vec<IrqChipType>,
266ce5850adSLoGin }
267ce5850adSLoGin 
2683bc96fa4SLoGin pub trait IrqChipGenericOps: Debug + Send + Sync {
269ce5850adSLoGin     /// Alternate I/O accessor (defaults to readl if NULL)
270ce5850adSLoGin     unsafe fn reg_readl(&self, addr: VirtAddr) -> u32;
271ce5850adSLoGin 
272ce5850adSLoGin     /// Alternate I/O accessor (defaults to writel if NULL)
273ce5850adSLoGin     unsafe fn reg_writel(&self, addr: VirtAddr, val: u32);
274ce5850adSLoGin 
275ce5850adSLoGin     /// Function called from core code on suspend once per
276ce5850adSLoGin     /// chip; can be useful instead of irq_chip::suspend to
277ce5850adSLoGin     /// handle chip details even when no interrupts are in use
278ce5850adSLoGin     fn suspend(&self, gc: &Arc<IrqChipGeneric>);
279ce5850adSLoGin     /// Function called from core code on resume once per chip;
280ce5850adSLoGin     /// can be useful instead of irq_chip::resume to handle chip
281ce5850adSLoGin     /// details even when no interrupts are in use
282ce5850adSLoGin     fn resume(&self, gc: &Arc<IrqChipGeneric>);
283ce5850adSLoGin }
284ce5850adSLoGin 
285ce5850adSLoGin pub trait IrqChipGenericPrivateData: Sync + Send + Any + Debug {}
286ce5850adSLoGin 
287ce5850adSLoGin #[derive(Debug)]
288ce5850adSLoGin pub struct IrqChipType {
289ce5850adSLoGin     // todo https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#1024
290ce5850adSLoGin }
2913bc96fa4SLoGin 
292*e2841179SLoGin #[allow(dead_code)]
293*e2841179SLoGin #[derive(Debug)]
294*e2841179SLoGin pub enum IrqChipSetMaskResult {
295*e2841179SLoGin     /// core updates mask ok.
296*e2841179SLoGin     SetMaskOk,
297*e2841179SLoGin     /// core updates mask ok. No change.
298*e2841179SLoGin     SetMaskOkNoChange,
299*e2841179SLoGin     /// core updates mask ok. Done.(same as SetMaskOk)
300*e2841179SLoGin     ///
301*e2841179SLoGin     /// 支持堆叠irq芯片的特殊代码, 表示跳过所有子irq芯片。
302*e2841179SLoGin     SetMaskOkDone,
303*e2841179SLoGin }
304*e2841179SLoGin 
3053bc96fa4SLoGin bitflags! {
3063bc96fa4SLoGin     /// IrqChip specific flags
3073bc96fa4SLoGin     pub struct IrqChipFlags: u32 {
308*e2841179SLoGin         /// 在调用chip.irq_set_type()之前屏蔽中断
3093bc96fa4SLoGin         const IRQCHIP_SET_TYPE_MASKED = 1 << 0;
3103bc96fa4SLoGin         /// 只有在irq被处理时才发出irq_eoi()
3113bc96fa4SLoGin         const IRQCHIP_EOI_IF_HANDLED = 1 << 1;
3123bc96fa4SLoGin         /// 在挂起路径中屏蔽非唤醒irq
3133bc96fa4SLoGin         const IRQCHIP_MASK_ON_SUSPEND = 1 << 2;
3143bc96fa4SLoGin         /// 只有在irq启用时才调用irq_on/off_line回调
3153bc96fa4SLoGin         const IRQCHIP_ONOFFLINE_ENABLED = 1 << 3;
3163bc96fa4SLoGin         /// 跳过chip.irq_set_wake(),对于这个irq芯片
3173bc96fa4SLoGin         const IRQCHIP_SKIP_SET_WAKE = 1 << 4;
3183bc96fa4SLoGin         /// 单次触发不需要屏蔽/取消屏蔽
3193bc96fa4SLoGin         const IRQCHIP_ONESHOT_SAFE = 1 << 5;
3203bc96fa4SLoGin         /// 芯片在线程模式下需要在取消屏蔽时eoi()
3213bc96fa4SLoGin         const IRQCHIP_EOI_THREADED = 1 << 6;
3223bc96fa4SLoGin         /// 芯片可以为Level MSIs提供两个门铃
3233bc96fa4SLoGin         const IRQCHIP_SUPPORTS_LEVEL_MSI = 1 << 7;
3243bc96fa4SLoGin         /// 芯片可以传递NMIs,仅适用于根irqchips
3253bc96fa4SLoGin         const IRQCHIP_SUPPORTS_NMI = 1 << 8;
3263bc96fa4SLoGin         /// 在挂起路径中,如果它们处于禁用状态,则调用__enable_irq()/__disable_irq()以唤醒irq
3273bc96fa4SLoGin         const IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND = 1 << 9;
3283bc96fa4SLoGin         /// 在启动前更新默认亲和性
3293bc96fa4SLoGin         const IRQCHIP_AFFINITY_PRE_STARTUP = 1 << 10;
3303bc96fa4SLoGin         /// 不要在这个芯片中改变任何东西
3313bc96fa4SLoGin         const IRQCHIP_IMMUTABLE = 1 << 11;
3323bc96fa4SLoGin     }
3333bc96fa4SLoGin }
334*e2841179SLoGin 
335*e2841179SLoGin impl IrqManager {
336*e2841179SLoGin     /// Acknowledge the parent interrupt
337*e2841179SLoGin     #[allow(dead_code)]
338*e2841179SLoGin     pub fn irq_chip_ack_parent(&self, irq_data: &Arc<IrqData>) {
339*e2841179SLoGin         let parent_data = irq_data.parent_data().map(|p| p.upgrade()).flatten();
340*e2841179SLoGin 
341*e2841179SLoGin         if let Some(parent_data) = parent_data {
342*e2841179SLoGin             let parent_chip = parent_data.chip_info_read_irqsave().chip();
343*e2841179SLoGin             parent_chip.irq_ack(&parent_data);
344*e2841179SLoGin         }
345*e2841179SLoGin     }
346*e2841179SLoGin 
347*e2841179SLoGin     /// 在硬件中重新触发中断
348*e2841179SLoGin     ///
349*e2841179SLoGin     /// 遍历中断域的层次结构,并检查是否存在一个硬件重新触发函数。如果存在则调用它
350*e2841179SLoGin     pub fn irq_chip_retrigger_hierarchy(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
351*e2841179SLoGin         let mut data: Option<Arc<IrqData>> = Some(irq_data.clone());
352*e2841179SLoGin         loop {
353*e2841179SLoGin             if let Some(d) = data {
354*e2841179SLoGin                 if let Err(e) = d.chip_info_read_irqsave().chip().retrigger(&d) {
355*e2841179SLoGin                     if e == SystemError::ENOSYS {
356*e2841179SLoGin                         data = d.parent_data().map(|p| p.upgrade()).flatten();
357*e2841179SLoGin                     } else {
358*e2841179SLoGin                         return Err(e);
359*e2841179SLoGin                     }
360*e2841179SLoGin                 } else {
361*e2841179SLoGin                     return Ok(());
362*e2841179SLoGin                 }
363*e2841179SLoGin             } else {
364*e2841179SLoGin                 break;
365*e2841179SLoGin             }
366*e2841179SLoGin         }
367*e2841179SLoGin 
368*e2841179SLoGin         return Ok(());
369*e2841179SLoGin     }
370*e2841179SLoGin }
371