xref: /DragonOS/kernel/src/exception/irqdata.rs (revision e28411791f090c421fe4b6fa5956fb1bd362a8d9)
1 use core::{any::Any, fmt::Debug};
2 
3 use alloc::sync::{Arc, Weak};
4 use intertrait::CastFromSync;
5 
6 use crate::libs::{
7     cpumask::CpuMask,
8     rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
9     spinlock::{SpinLock, SpinLockGuard},
10 };
11 
12 use super::{
13     irqchip::{IrqChip, IrqChipData},
14     irqdomain::IrqDomain,
15     msi::MsiDesc,
16     HardwareIrqNumber, IrqNumber,
17 };
18 
19 /// per irq chip data passed down to chip functions
20 ///
21 /// 该结构体用于表示每个Irq的私有数据,且与具体的中断芯片绑定
22 ///
23 /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#179
24 #[allow(dead_code)]
25 #[derive(Debug)]
26 pub struct IrqData {
27     /// 中断号, 用于表示软件逻辑视角的中断号,全局唯一
28     irq: IrqNumber,
29     inner: SpinLock<InnerIrqData>,
30 
31     chip_info: RwLock<InnerIrqChipInfo>,
32 }
33 
34 impl IrqData {
35     pub fn new(
36         irq: IrqNumber,
37         hwirq: HardwareIrqNumber,
38         common_data: Arc<IrqCommonData>,
39         chip: Arc<dyn IrqChip>,
40     ) -> Self {
41         return IrqData {
42             irq,
43             inner: SpinLock::new(InnerIrqData {
44                 hwirq,
45                 common_data,
46 
47                 domain: None,
48                 parent_data: None,
49             }),
50             chip_info: RwLock::new(InnerIrqChipInfo {
51                 chip: Some(chip),
52                 chip_data: None,
53             }),
54         };
55     }
56 
57     pub fn irqd_set(&self, status: IrqStatus) {
58         // clone是为了释放inner锁
59         let common_data = self.inner.lock_irqsave().common_data.clone();
60         common_data.insert_status(status);
61     }
62 
63     #[allow(dead_code)]
64     pub fn irqd_clear(&self, status: IrqStatus) {
65         // clone是为了释放inner锁
66         let common_data = self.inner.lock_irqsave().common_data.clone();
67         common_data.clear_status(status);
68     }
69 
70     pub fn irq(&self) -> IrqNumber {
71         self.irq
72     }
73 
74     pub fn hardware_irq(&self) -> HardwareIrqNumber {
75         self.inner.lock_irqsave().hwirq
76     }
77 
78     /// 是否为电平触发
79     pub fn is_level_type(&self) -> bool {
80         self.inner
81             .lock_irqsave()
82             .common_data
83             .inner
84             .lock_irqsave()
85             .state
86             .is_level_type()
87     }
88 
89     pub fn is_wakeup_set(&self) -> bool {
90         self.inner
91             .lock_irqsave()
92             .common_data
93             .inner
94             .lock_irqsave()
95             .state
96             .is_wakeup_set()
97     }
98 
99     pub fn common_data(&self) -> Arc<IrqCommonData> {
100         self.inner.lock_irqsave().common_data.clone()
101     }
102 
103     pub fn domain(&self) -> Option<Arc<IrqDomain>> {
104         self.inner.lock_irqsave().domain.clone()
105     }
106 
107     pub fn inner(&self) -> SpinLockGuard<InnerIrqData> {
108         self.inner.lock_irqsave()
109     }
110 
111     pub fn chip_info_read(&self) -> RwLockReadGuard<InnerIrqChipInfo> {
112         self.chip_info.read()
113     }
114 
115     pub fn chip_info_read_irqsave(&self) -> RwLockReadGuard<InnerIrqChipInfo> {
116         self.chip_info.read_irqsave()
117     }
118 
119     pub fn chip_info_write_irqsave(&self) -> RwLockWriteGuard<InnerIrqChipInfo> {
120         self.chip_info.write_irqsave()
121     }
122 
123     pub fn parent_data(&self) -> Option<Weak<IrqData>> {
124         self.inner.lock_irqsave().parent_data.clone()
125     }
126 }
127 
128 #[allow(dead_code)]
129 #[derive(Debug)]
130 pub struct InnerIrqData {
131     /// 硬件中断号, 用于表示在某个IrqDomain中的中断号
132     hwirq: HardwareIrqNumber,
133     /// 涉及的所有irqchip之间共享的数据
134     common_data: Arc<IrqCommonData>,
135 
136     /// 中断域
137     domain: Option<Arc<IrqDomain>>,
138     /// 中断的父中断(如果具有中断域继承的话)
139     parent_data: Option<Weak<IrqData>>,
140 }
141 
142 impl InnerIrqData {
143     pub fn set_hwirq(&mut self, hwirq: HardwareIrqNumber) {
144         self.hwirq = hwirq;
145     }
146 
147     #[allow(dead_code)]
148     pub fn domain(&self) -> Option<Arc<IrqDomain>> {
149         self.domain.clone()
150     }
151 
152     pub fn set_domain(&mut self, domain: Option<Arc<IrqDomain>>) {
153         self.domain = domain;
154     }
155 }
156 
157 #[derive(Debug)]
158 pub struct InnerIrqChipInfo {
159     /// 绑定到的中断芯片
160     chip: Option<Arc<dyn IrqChip>>,
161     /// 中断芯片的私有数据(与当前irq相关)
162     chip_data: Option<Arc<dyn IrqChipData>>,
163 }
164 
165 impl InnerIrqChipInfo {
166     pub fn set_chip(&mut self, chip: Option<Arc<dyn IrqChip>>) {
167         self.chip = chip;
168     }
169 
170     pub fn set_chip_data(&mut self, chip_data: Option<Arc<dyn IrqChipData>>) {
171         self.chip_data = chip_data;
172     }
173 
174     pub fn chip(&self) -> Arc<dyn IrqChip> {
175         self.chip.clone().unwrap()
176     }
177 
178     pub fn chip_data(&self) -> Option<Arc<dyn IrqChipData>> {
179         self.chip_data.clone()
180     }
181 }
182 
183 /// per irq data shared by all irqchips
184 ///
185 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#147
186 #[derive(Debug)]
187 pub struct IrqCommonData {
188     inner: SpinLock<InnerIrqCommonData>,
189 }
190 
191 impl IrqCommonData {
192     pub fn new() -> Self {
193         let inner = InnerIrqCommonData {
194             state: IrqStatus::empty(),
195             handler_data: None,
196             msi_desc: None,
197             affinity: CpuMask::new(),
198         };
199         return IrqCommonData {
200             inner: SpinLock::new(inner),
201         };
202     }
203 
204     pub fn insert_status(&self, status: IrqStatus) {
205         self.inner.lock_irqsave().irqd_insert(status);
206     }
207 
208     pub fn clear_status(&self, status: IrqStatus) {
209         self.inner.lock_irqsave().irqd_clear(status);
210     }
211 
212     pub fn clear_managed_shutdown(&self) {
213         self.inner
214             .lock_irqsave()
215             .state
216             .remove(IrqStatus::IRQD_MANAGED_SHUTDOWN);
217     }
218 
219     #[allow(dead_code)]
220     pub fn masked(&self) -> bool {
221         self.inner.lock_irqsave().state.masked()
222     }
223 
224     pub fn set_masked(&self) {
225         self.inner
226             .lock_irqsave()
227             .state
228             .insert(IrqStatus::IRQD_IRQ_MASKED);
229     }
230 
231     pub fn clear_masked(&self) {
232         self.clear_status(IrqStatus::IRQD_IRQ_MASKED);
233     }
234 
235     pub fn set_inprogress(&self) {
236         self.inner
237             .lock_irqsave()
238             .state
239             .insert(IrqStatus::IRQD_IRQ_INPROGRESS);
240     }
241 
242     pub fn clear_inprogress(&self) {
243         self.inner
244             .lock_irqsave()
245             .state
246             .remove(IrqStatus::IRQD_IRQ_INPROGRESS);
247     }
248 
249     pub fn disabled(&self) -> bool {
250         self.inner.lock_irqsave().state.disabled()
251     }
252 
253     #[allow(dead_code)]
254     pub fn set_disabled(&self) {
255         self.inner
256             .lock_irqsave()
257             .state
258             .insert(IrqStatus::IRQD_IRQ_DISABLED);
259     }
260 
261     pub fn clear_disabled(&self) {
262         self.clear_status(IrqStatus::IRQD_IRQ_DISABLED);
263     }
264 
265     pub fn status(&self) -> IrqStatus {
266         self.inner.lock_irqsave().state
267     }
268 
269     pub fn trigger_type(&self) -> IrqLineStatus {
270         self.inner.lock_irqsave().state.trigger_type()
271     }
272 
273     pub fn set_trigger_type(&self, trigger: IrqLineStatus) {
274         self.inner.lock_irqsave().state.set_trigger_type(trigger);
275     }
276 
277     pub fn set_started(&self) {
278         self.inner
279             .lock_irqsave()
280             .state
281             .insert(IrqStatus::IRQD_IRQ_STARTED);
282     }
283 
284     pub fn affinity(&self) -> CpuMask {
285         self.inner.lock_irqsave().affinity.clone()
286     }
287 
288     pub fn set_affinity(&self, affinity: CpuMask) {
289         self.inner.lock_irqsave().affinity = affinity;
290     }
291 }
292 
293 #[allow(dead_code)]
294 #[derive(Debug)]
295 struct InnerIrqCommonData {
296     /// status information for irq chip functions.
297     state: IrqStatus,
298     /// per-IRQ data for the irq_chip methods
299     handler_data: Option<Arc<dyn IrqHandlerData>>,
300     msi_desc: Option<Arc<MsiDesc>>,
301     affinity: CpuMask,
302 }
303 
304 impl InnerIrqCommonData {
305     pub fn irqd_insert(&mut self, status: IrqStatus) {
306         self.state.insert(status);
307     }
308 
309     pub fn irqd_clear(&mut self, status: IrqStatus) {
310         self.state.remove(status);
311     }
312 }
313 
314 /// 中断处理函数传入的数据
315 pub trait IrqHandlerData: Send + Sync + Any + Debug + CastFromSync {}
316 
317 bitflags! {
318     /// 中断线状态
319     /// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h?fi=IRQ_TYPE_PROBE#77
320     pub struct IrqLineStatus: u32 {
321         /// 默认,未指明类型
322         const IRQ_TYPE_NONE     = 0x00000000;
323         /// 上升沿触发
324         const IRQ_TYPE_EDGE_RISING  = 0x00000001;
325         /// 下降沿触发
326         const IRQ_TYPE_EDGE_FALLING = 0x00000002;
327         /// 上升沿和下降沿触发
328         const IRQ_TYPE_EDGE_BOTH    = Self::IRQ_TYPE_EDGE_RISING.bits | Self::IRQ_TYPE_EDGE_FALLING.bits;
329         /// 高电平触发
330         const IRQ_TYPE_LEVEL_HIGH   = 0x00000004;
331         /// 低电平触发
332         const IRQ_TYPE_LEVEL_LOW    = 0x00000008;
333         /// 过滤掉电平位的掩码
334         const IRQ_TYPE_LEVEL_MASK   = Self::IRQ_TYPE_LEVEL_LOW.bits | Self::IRQ_TYPE_LEVEL_HIGH.bits;
335         /// 上述位掩码的掩码
336         const IRQ_TYPE_SENSE_MASK   = 0x0000000f;
337         /// 某些PICs使用此类型要求 `IrqChip::irq_set_type()` 设置硬件到一个合理的默认值
338         /// (由irqdomain的map()回调使用,以便为新分配的描述符同步硬件状态和软件标志位)。
339         const IRQ_TYPE_DEFAULT      = Self::IRQ_TYPE_SENSE_MASK.bits;
340 
341         /// 特定于探测的过程中的特殊标志
342         const IRQ_TYPE_PROBE        = 0x00000010;
343 
344         /// 中断是电平类型。当上述触发位通过`IrqChip::irq_set_type()` 修改时,也会在代码中更新
345         const IRQ_LEVEL     = 1 << 8;
346         /// 标记一个PER_CPU的中断。将保护其免受亲和性设置的影响
347         const IRQ_PER_CPU       = 1 << 9;
348         /// 中断不能被自动探测
349         const IRQ_NOPROBE       = 1 << 10;
350         /// 中断不能通过request_irq()请求
351         const IRQ_NOREQUEST     = 1 << 11;
352         /// 中断在request/setup_irq()中不会自动启用
353         const IRQ_NOAUTOEN      = 1 << 12;
354         /// 中断不能被平衡(亲和性设置)
355         const IRQ_NO_BALANCING      = 1 << 13;
356         /// 中断可以从进程上下文中迁移
357         const IRQ_MOVE_PCNTXT       = 1 << 14;
358         /// 中断嵌套在另一个线程中
359         const IRQ_NESTED_THREAD = 1 << 15;
360         /// 中断不能被线程化
361         const IRQ_NOTHREAD      = 1 << 16;
362         /// Dev_id是一个per-CPU变量
363         const IRQ_PER_CPU_DEVID = 1 << 17;
364         /// 总是由另一个中断轮询。将其从错误的中断检测机制和核心侧轮询中排除
365         const IRQ_IS_POLLED     = 1 << 18;
366         /// 禁用延迟的中断禁用 (Disable lazy irq disable)
367         const IRQ_DISABLE_UNLAZY    = 1 << 19;
368         /// 在/proc/interrupts中不显示
369         const IRQ_HIDDEN        = 1 << 20;
370         /// 从note_interrupt()调试中排除
371         const IRQ_NO_DEBUG      = 1 << 21;
372     }
373 
374 
375 
376 }
377 
378 impl IrqLineStatus {
379     pub const fn trigger_bits(&self) -> u32 {
380         self.bits & Self::IRQ_TYPE_SENSE_MASK.bits
381     }
382 
383     pub fn trigger_type(&self) -> Self {
384         *self & Self::IRQ_TYPE_SENSE_MASK
385     }
386 
387     pub fn is_level_type(&self) -> bool {
388         self.contains(Self::IRQ_LEVEL)
389     }
390 
391     /// 是否为高电平触发
392     ///
393     /// ## 返回
394     ///
395     /// - 如果不是电平触发类型,则返回None
396     /// - 如果是电平触发类型,则返回Some(bool),当为true时表示高电平触发
397     pub fn is_level_high(&self) -> Option<bool> {
398         if !self.is_level_type() {
399             return None;
400         }
401         return Some(self.contains(Self::IRQ_TYPE_LEVEL_HIGH));
402     }
403 }
404 bitflags! {
405     /// 中断状态(存储在IrqCommonData)
406     ///
407     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#227
408     pub struct IrqStatus: u32 {
409         const IRQD_TRIGGER_NONE = IrqLineStatus::IRQ_TYPE_NONE.bits();
410         const IRQD_TRIGGER_RISING = IrqLineStatus::IRQ_TYPE_EDGE_RISING.bits();
411         const IRQD_TRIGGER_FALLING = IrqLineStatus::IRQ_TYPE_EDGE_FALLING.bits();
412         const IRQD_TRIGGER_HIGH = IrqLineStatus::IRQ_TYPE_LEVEL_HIGH.bits();
413         const IRQD_TRIGGER_LOW = IrqLineStatus::IRQ_TYPE_LEVEL_LOW.bits();
414 
415         /// 触发类型位的掩码
416         const IRQD_TRIGGER_MASK = 0xf;
417         /// 亲和性设置待处理
418         const IRQD_SETAFFINITY_PENDING = 1 << 8;
419         /// 中断已激活
420         const IRQD_ACTIVATED = 1 << 9;
421         /// 对此IRQ禁用平衡
422         const IRQD_NO_BALANCING = 1 << 10;
423         /// 中断是每个CPU特定的
424         const IRQD_PER_CPU = 1 << 11;
425         /// 中断亲和性已设置
426         const IRQD_AFFINITY_SET = 1 << 12;
427         /// 中断是电平触发
428         const IRQD_LEVEL = 1 << 13;
429         /// 中断配置为从挂起状态唤醒
430         const IRQD_WAKEUP_STATE = 1 << 14;
431         /// 中断可以在进程上下文中移动
432         const IRQD_MOVE_PCNTXT = 1 << 15;
433         /// 中断被禁用
434         const IRQD_IRQ_DISABLED = 1 << 16;
435         /// 中断被屏蔽
436         const IRQD_IRQ_MASKED = 1 << 17;
437         /// 中断正在处理中
438         const IRQD_IRQ_INPROGRESS = 1 << 18;
439         /// 唤醒模式已准备就绪
440         const IRQD_WAKEUP_ARMED = 1 << 19;
441         /// 中断被转发到一个虚拟CPU
442         const IRQD_FORWARDED_TO_VCPU = 1 << 20;
443         /// 亲和性由内核自动管理
444         const IRQD_AFFINITY_MANAGED = 1 << 21;
445         /// 中断已启动
446         const IRQD_IRQ_STARTED = 1 << 22;
447         /// 由于空亲和性掩码而关闭的中断。仅适用于亲和性管理的中断。
448         const IRQD_MANAGED_SHUTDOWN = 1 << 23;
449         /// IRQ只允许单个亲和性目标
450         const IRQD_SINGLE_TARGET = 1 << 24;
451         /// 默认的触发器已设置
452         const IRQD_DEFAULT_TRIGGER_SET = 1 << 25;
453         /// 可以使用保留模式
454         const IRQD_CAN_RESERVE = 1 << 26;
455         /// Non-maskable MSI quirk for affinity change required
456         const IRQD_MSI_NOMASK_QUIRK = 1 << 27;
457         /// 强制要求`handle_irq_()`只能在真实的中断上下文中调用
458         const IRQD_HANDLE_ENFORCE_IRQCTX = 1 << 28;
459         /// 激活时设置亲和性。在禁用时不要调用irq_chip::irq_set_affinity()。
460         const IRQD_AFFINITY_ON_ACTIVATE = 1 << 29;
461         /// 如果irqpm具有标志 IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND,则在挂起时中断被启用。
462         const IRQD_IRQ_ENABLED_ON_SUSPEND = 1 << 30;
463     }
464 }
465 
466 #[allow(dead_code)]
467 impl IrqStatus {
468     pub const fn is_set_affinity_pending(&self) -> bool {
469         self.contains(Self::IRQD_SETAFFINITY_PENDING)
470     }
471 
472     pub const fn is_per_cpu(&self) -> bool {
473         self.contains(Self::IRQD_PER_CPU)
474     }
475 
476     pub const fn can_balance(&self) -> bool {
477         !((self.bits & (Self::IRQD_PER_CPU.bits | Self::IRQD_NO_BALANCING.bits)) != 0)
478     }
479 
480     pub const fn affinity_was_set(&self) -> bool {
481         self.contains(Self::IRQD_AFFINITY_SET)
482     }
483 
484     pub fn masked(&self) -> bool {
485         self.contains(Self::IRQD_IRQ_MASKED)
486     }
487 
488     pub fn disabled(&self) -> bool {
489         self.contains(Self::IRQD_IRQ_DISABLED)
490     }
491 
492     pub fn mark_affinity_set(&mut self) {
493         self.insert(Self::IRQD_AFFINITY_SET);
494     }
495 
496     pub const fn trigger_type_was_set(&self) -> bool {
497         self.contains(Self::IRQD_DEFAULT_TRIGGER_SET)
498     }
499 
500     pub fn mark_trigger_type_set(&mut self) {
501         self.insert(Self::IRQD_DEFAULT_TRIGGER_SET);
502     }
503 
504     pub const fn trigger_type(&self) -> IrqLineStatus {
505         IrqLineStatus::from_bits_truncate(self.bits & Self::IRQD_TRIGGER_MASK.bits)
506     }
507 
508     /// Must only be called inside irq_chip.irq_set_type() functions or
509     /// from the DT/ACPI setup code.
510     pub const fn set_trigger_type(&mut self, trigger: IrqLineStatus) {
511         self.bits &= !Self::IRQD_TRIGGER_MASK.bits;
512         self.bits |= trigger.bits & Self::IRQD_TRIGGER_MASK.bits;
513 
514         self.bits |= Self::IRQD_DEFAULT_TRIGGER_SET.bits;
515     }
516 
517     pub const fn is_level_type(&self) -> bool {
518         self.contains(Self::IRQD_LEVEL)
519     }
520 
521     /// Must only be called of irqchip.irq_set_affinity() or low level
522     /// hierarchy domain allocation functions.
523     pub fn set_single_target(&mut self) {
524         self.insert(Self::IRQD_SINGLE_TARGET);
525     }
526 
527     pub const fn is_single_target(&self) -> bool {
528         self.contains(Self::IRQD_SINGLE_TARGET)
529     }
530 
531     pub fn set_handle_enforce_irqctx(&mut self) {
532         self.insert(Self::IRQD_HANDLE_ENFORCE_IRQCTX);
533     }
534 
535     pub const fn is_handle_enforce_irqctx(&self) -> bool {
536         self.contains(Self::IRQD_HANDLE_ENFORCE_IRQCTX)
537     }
538 
539     pub const fn is_enabled_on_suspend(&self) -> bool {
540         self.contains(Self::IRQD_IRQ_ENABLED_ON_SUSPEND)
541     }
542 
543     pub const fn is_wakeup_set(&self) -> bool {
544         self.contains(Self::IRQD_WAKEUP_STATE)
545     }
546 
547     pub const fn can_move_in_process_context(&self) -> bool {
548         self.contains(Self::IRQD_MOVE_PCNTXT)
549     }
550 
551     pub const fn is_irq_in_progress(&self) -> bool {
552         self.contains(Self::IRQD_IRQ_INPROGRESS)
553     }
554 
555     pub const fn is_wakeup_armed(&self) -> bool {
556         self.contains(Self::IRQD_WAKEUP_ARMED)
557     }
558 
559     pub const fn is_forwarded_to_vcpu(&self) -> bool {
560         self.contains(Self::IRQD_FORWARDED_TO_VCPU)
561     }
562 
563     pub fn set_forwarded_to_vcpu(&mut self) {
564         self.insert(Self::IRQD_FORWARDED_TO_VCPU);
565     }
566 
567     pub const fn affinity_managed(&self) -> bool {
568         self.contains(Self::IRQD_AFFINITY_MANAGED)
569     }
570 
571     pub const fn is_activated(&self) -> bool {
572         self.contains(Self::IRQD_ACTIVATED)
573     }
574 
575     pub fn set_activated(&mut self) {
576         self.insert(Self::IRQD_ACTIVATED);
577     }
578 
579     pub fn clear_activated(&mut self) {
580         self.remove(Self::IRQD_ACTIVATED);
581     }
582 
583     pub const fn is_started(&self) -> bool {
584         self.contains(Self::IRQD_IRQ_STARTED)
585     }
586 
587     pub const fn is_managed_and_shutdown(&self) -> bool {
588         self.contains(Self::IRQD_MANAGED_SHUTDOWN)
589     }
590 
591     pub fn set_can_reserve(&mut self) {
592         self.insert(Self::IRQD_CAN_RESERVE);
593     }
594 
595     pub const fn can_reserve(&self) -> bool {
596         self.contains(Self::IRQD_CAN_RESERVE)
597     }
598 
599     pub fn clear_can_reserve(&mut self) {
600         self.remove(Self::IRQD_CAN_RESERVE);
601     }
602 
603     pub fn set_msi_nomask_quirk(&mut self) {
604         self.insert(Self::IRQD_MSI_NOMASK_QUIRK);
605     }
606 
607     pub fn clear_msi_nomask_quirk(&mut self) {
608         self.remove(Self::IRQD_MSI_NOMASK_QUIRK);
609     }
610 
611     pub const fn is_msi_nomask_quirk(&self) -> bool {
612         self.contains(Self::IRQD_MSI_NOMASK_QUIRK)
613     }
614 
615     pub fn set_affinity_on_activate(&mut self) {
616         self.insert(Self::IRQD_AFFINITY_ON_ACTIVATE);
617     }
618 
619     pub const fn is_affinity_on_activate(&self) -> bool {
620         self.contains(Self::IRQD_AFFINITY_ON_ACTIVATE)
621     }
622 
623     pub const fn started(&self) -> bool {
624         self.contains(Self::IRQD_IRQ_STARTED)
625     }
626 }
627