xref: /DragonOS/kernel/src/arch/x86_64/driver/apic/ioapic.rs (revision 52bcb59e9286def2b66d766f6bf6f46745795ec8)
1 use core::ptr::NonNull;
2 
3 use acpi::madt::Madt;
4 use alloc::sync::Arc;
5 use bit_field::BitField;
6 use bitflags::bitflags;
7 use system_error::SystemError;
8 
9 use crate::{
10     driver::acpi::acpi_manager,
11     exception::{
12         handle::{edge_irq_handler, fast_eoi_irq_handler},
13         irqchip::{IrqChip, IrqChipData, IrqChipFlags, IrqChipSetMaskResult, IrqChipState},
14         irqdata::{IrqData, IrqLineStatus},
15         irqdesc::{irq_desc_manager, IrqDesc, IrqFlowHandler},
16         manage::irq_manager,
17         IrqNumber,
18     },
19     kdebug, kinfo,
20     libs::{
21         cpumask::CpuMask,
22         once::Once,
23         spinlock::{SpinLock, SpinLockGuard},
24         volatile::{volwrite, Volatile},
25     },
26     mm::{
27         mmio_buddy::{mmio_pool, MMIOSpaceGuard},
28         PhysAddr,
29     },
30 };
31 
32 use super::{CurrentApic, LocalAPIC};
33 
34 static mut __IOAPIC: Option<SpinLock<IoApic>> = None;
35 static mut IOAPIC_IR_CHIP: Option<Arc<IoApicChip>> = None;
36 
37 #[allow(non_snake_case)]
38 fn IOAPIC() -> &'static SpinLock<IoApic> {
39     unsafe { __IOAPIC.as_ref().unwrap() }
40 }
41 
42 #[inline(always)]
43 pub(super) fn ioapic_ir_chip() -> Arc<dyn IrqChip> {
44     unsafe { IOAPIC_IR_CHIP.as_ref().unwrap().clone() }
45 }
46 
47 #[allow(dead_code)]
48 pub struct IoApic {
49     reg: *mut u32,
50     data: *mut u32,
51     virt_eoi: *mut u32,
52     phys_base: PhysAddr,
53     mmio_guard: MMIOSpaceGuard,
54 }
55 
56 impl IoApic {
57     /// IO APIC的中断向量号从32开始
58     pub const VECTOR_BASE: u8 = 32;
59 
60     /// Create a new IOAPIC.
61     ///
62     /// # Safety
63     ///
64     /// You must provide a valid address.
65     pub unsafe fn new() -> Self {
66         static INIT_STATE: Once = Once::new();
67         assert!(!INIT_STATE.is_completed());
68 
69         let mut result: Option<IoApic> = None;
70         INIT_STATE.call_once(|| {
71             kinfo!("Initializing ioapic...");
72 
73             // get ioapic base from acpi
74 
75             let madt = acpi_manager()
76                 .tables()
77                 .unwrap()
78                 .find_table::<Madt>()
79                 .expect("IoApic::new(): failed to find MADT");
80 
81             let io_apic_paddr = madt
82                 .entries()
83                 .find(|x| {
84                     if let acpi::madt::MadtEntry::IoApic(_x) = x {
85                         return true;
86                     }
87                     return false;
88                 })
89                 .map(|x| {
90                     if let acpi::madt::MadtEntry::IoApic(x) = x {
91                         Some(x.io_apic_address)
92                     } else {
93                         None
94                     }
95                 })
96                 .flatten()
97                 .unwrap();
98 
99             let phys_base = PhysAddr::new(io_apic_paddr as usize);
100 
101             let mmio_guard = mmio_pool()
102                 .create_mmio(0x1000)
103                 .expect("IoApic::new(): failed to create mmio");
104             assert!(
105                 mmio_guard.map_phys(phys_base, 0x1000).is_ok(),
106                 "IoApic::new(): failed to map phys"
107             );
108             kdebug!("Ioapic map ok");
109             let reg = mmio_guard.vaddr();
110 
111             result = Some(IoApic {
112                 reg: reg.data() as *mut u32,
113                 data: (reg + 0x10).data() as *mut u32,
114                 virt_eoi: (reg + 0x40).data() as *mut u32,
115                 phys_base,
116                 mmio_guard,
117             });
118             kdebug!("IOAPIC: to mask all RTE");
119             // 屏蔽所有的RTE
120             let res_mut = result.as_mut().unwrap();
121             for i in 0..res_mut.supported_interrupts() {
122                 res_mut.write_rte(i, 0x20 + i, RedirectionEntry::DISABLED, 0);
123             }
124             kdebug!("Ioapic init done");
125         });
126 
127         assert!(
128             result.is_some(),
129             "Failed to init ioapic, maybe this is a double initialization bug?"
130         );
131         return result.unwrap();
132     }
133 
134     /// Disable all interrupts.
135     #[allow(dead_code)]
136     pub fn disable_all(&mut self) {
137         // Mark all interrupts edge-triggered, active high, disabled,
138         // and not routed to any CPUs.
139         for i in 0..self.supported_interrupts() {
140             self.disable(i);
141         }
142     }
143 
144     unsafe fn read(&mut self, reg: u8) -> u32 {
145         assert!(!(0x3..REG_TABLE).contains(&reg));
146         self.reg.write_volatile(reg as u32);
147         self.data.read_volatile()
148     }
149 
150     /// 直接写入REG_TABLE内的寄存器
151     ///
152     /// ## 参数
153     ///
154     /// * `reg` - 寄存器下标
155     /// * `data` - 寄存器数据
156     unsafe fn write(&mut self, reg: u8, data: u32) {
157         // 0x1 & 0x2 are read-only regs
158         assert!(!(0x1..REG_TABLE).contains(&reg));
159         self.reg.write_volatile(reg as u32);
160         self.data.write_volatile(data);
161     }
162 
163     fn write_rte(&mut self, rte_index: u8, vector: u8, flags: RedirectionEntry, dest: u8) {
164         unsafe {
165             self.write(REG_TABLE + 2 * rte_index, vector as u32 | flags.bits());
166             self.write(REG_TABLE + 2 * rte_index + 1, (dest as u32) << 24);
167         }
168     }
169 
170     /// 标记中断边沿触发、高电平有效、
171     /// 启用并路由到给定的 cpunum,即是是该 cpu 的 APIC ID(不是cpuid)
172     pub fn enable(&mut self, rte_index: u8) {
173         let mut val = unsafe { self.read(REG_TABLE + 2 * rte_index) };
174         val &= !RedirectionEntry::DISABLED.bits();
175         unsafe { self.write(REG_TABLE + 2 * rte_index, val) };
176     }
177 
178     pub fn disable(&mut self, rte_index: u8) {
179         let reg = REG_TABLE + 2 * rte_index;
180         let mut val = unsafe { self.read(reg) };
181         val |= RedirectionEntry::DISABLED.bits();
182         unsafe { self.write(reg, val) };
183     }
184 
185     /// 安装中断
186     ///
187     /// ## 参数
188     ///
189     /// * `rte_index` - RTE下标
190     /// * `vector` - 中断向量号
191     /// * `dest` - 目标CPU的APIC ID
192     /// * `level_triggered` - 是否为电平触发
193     /// * `active_high` - 是否为高电平有效
194     /// * `dest_logic` - 是否为逻辑模式
195     /// * `mask` - 是否屏蔽
196     pub fn install(
197         &mut self,
198         rte_index: u8,
199         vector: u8,
200         dest: u8,
201         level_triggered: bool,
202         active_high: bool,
203         dest_logic: bool,
204         mut mask: bool,
205     ) -> Result<(), SystemError> {
206         // 重定向表从 REG_TABLE 开始,使用两个寄存器来配置每个中断。
207         // 一对中的第一个(低位)寄存器包含配置位。32bit
208         // 第二个(高)寄存器包含一个位掩码,告诉哪些 CPU 可以服务该中断。
209         //  level_triggered:如果为真,表示中断触发方式为电平触发(level-triggered),则将RedirectionEntry::LEVEL标志位设置在flags中。
210         //  active_high:如果为假,表示中断的极性为低电平有效(active-low),则将RedirectionEntry::ACTIVELOW标志位设置在flags中。
211         //  dest_logic:如果为真,表示中断目标为逻辑模式(logical mode),则将RedirectionEntry::LOGICAL标志位设置在flags中。
212         //  !(0x20..=0xef).contains(&vector):判断中断向量号(vector)是否在范围0x20到0xef之外,如果是,则表示中断无效,将mask标志位设置为真。
213         //  mask:如果为真,表示中断被屏蔽(masked),将RedirectionEntry::DISABLED标志位设置在flags中。
214         let mut flags = RedirectionEntry::NONE;
215         if level_triggered {
216             flags |= RedirectionEntry::LEVEL;
217         }
218         if !active_high {
219             flags |= RedirectionEntry::ACTIVELOW;
220         }
221         if dest_logic {
222             flags |= RedirectionEntry::LOGICAL;
223         }
224         if !(0x20..=0xef).contains(&vector) {
225             mask = true;
226         }
227         if mask {
228             flags |= RedirectionEntry::DISABLED;
229         }
230         self.write_rte(rte_index, vector, flags, dest);
231         return Ok(());
232     }
233 
234     /// Get the vector number for the given IRQ.
235     #[allow(dead_code)]
236     pub fn irq_vector(&mut self, irq: u8) -> u8 {
237         unsafe { self.read(REG_TABLE + 2 * irq).get_bits(0..8) as u8 }
238     }
239 
240     /// Set the vector number for the given IRQ.
241     #[allow(dead_code)]
242     pub fn set_irq_vector(&mut self, irq: u8, vector: u8) {
243         let mut old = unsafe { self.read(REG_TABLE + 2 * irq) };
244         let old_vector = old.get_bits(0..8);
245         if !(0x20..=0xfe).contains(&old_vector) {
246             old |= RedirectionEntry::DISABLED.bits();
247         }
248         unsafe {
249             self.write(REG_TABLE + 2 * irq, *old.set_bits(0..8, vector as u32));
250         }
251     }
252 
253     #[allow(dead_code)]
254     pub fn id(&mut self) -> u8 {
255         unsafe { self.read(REG_ID).get_bits(24..28) as u8 }
256     }
257 
258     /// IO APIC Version
259     #[allow(dead_code)]
260     pub fn version(&mut self) -> u8 {
261         unsafe { self.read(REG_VER).get_bits(0..8) as u8 }
262     }
263 
264     /// Number of supported interrupts by this IO APIC.
265     ///
266     /// Max Redirection Entry = "how many IRQs can this I/O APIC handle - 1"
267     /// The -1 is silly so we add one back to it.
268     pub fn supported_interrupts(&mut self) -> u8 {
269         unsafe { (self.read(REG_VER).get_bits(16..24) + 1) as u8 }
270     }
271 
272     pub fn pending(&mut self, irq: u8) -> bool {
273         let rte_index = Self::vector_rte_index(irq);
274         let data = unsafe { self.read(REG_TABLE + 2 * rte_index) };
275         data & (1 << 12) != 0
276     }
277 
278     fn vector_rte_index(irq_num: u8) -> u8 {
279         assert!(irq_num >= Self::VECTOR_BASE);
280         irq_num - Self::VECTOR_BASE
281     }
282 
283     /// 电平响应
284     #[allow(dead_code)]
285     fn level_ack(&mut self, irq_num: u8) {
286         #[repr(C)]
287         struct LevelAck {
288             virt_eoi: Volatile<u32>,
289         }
290 
291         let p = NonNull::new(self.virt_eoi as *mut LevelAck).unwrap();
292 
293         unsafe {
294             volwrite!(p, virt_eoi, irq_num as u32);
295         }
296     }
297 }
298 
299 /// Register index: ID
300 const REG_ID: u8 = 0x00;
301 /// 获取IO APIC Version
302 const REG_VER: u8 = 0x01;
303 /// Redirection table base
304 const REG_TABLE: u8 = 0x10;
305 
306 bitflags! {
307     /// The redirection table starts at REG_TABLE and uses
308     /// two registers to configure each interrupt.
309     /// The first (low) register in a pair contains configuration bits.
310     /// The second (high) register contains a bitmask telling which
311     /// CPUs can serve that interrupt.
312     struct RedirectionEntry: u32 {
313         /// Interrupt disabled
314         const DISABLED  = 0x00010000;
315         /// Level-triggered (vs edge-)
316         const LEVEL     = 0x00008000;
317         /// Active low (vs high)
318         const ACTIVELOW = 0x00002000;
319         /// Destination is CPU id (vs APIC ID)
320         const LOGICAL   = 0x00000800;
321         /// None
322         const NONE		= 0x00000000;
323     }
324 }
325 
326 #[derive(Debug)]
327 struct IoApicChipData {
328     inner: SpinLock<InnerIoApicChipData>,
329 }
330 
331 impl IrqChipData for IoApicChipData {
332     fn as_any_ref(&self) -> &dyn core::any::Any {
333         self
334     }
335 }
336 
337 impl IoApicChipData {
338     const DEFAULT: Self = Self::new(0, 0, 0, false, false, false, true);
339 
340     const fn new(
341         rte_index: u8,
342         vector: u8,
343         dest: u8,
344         level_triggered: bool,
345         active_high: bool,
346         dest_logic: bool,
347         mask: bool,
348     ) -> Self {
349         IoApicChipData {
350             inner: SpinLock::new(InnerIoApicChipData {
351                 rte_index,
352                 vector,
353                 dest,
354                 level_triggered,
355                 active_high,
356                 dest_logic,
357                 mask,
358             }),
359         }
360     }
361 
362     fn inner(&self) -> SpinLockGuard<InnerIoApicChipData> {
363         self.inner.lock_irqsave()
364     }
365 }
366 
367 #[derive(Debug)]
368 struct InnerIoApicChipData {
369     rte_index: u8,
370     vector: u8,
371     dest: u8,
372     level_triggered: bool,
373     active_high: bool,
374     dest_logic: bool,
375     mask: bool,
376 }
377 
378 impl InnerIoApicChipData {
379     /// 把中断数据同步到芯片
380     fn sync_to_chip(&self) -> Result<(), SystemError> {
381         ioapic_install(
382             self.vector,
383             self.dest,
384             self.level_triggered,
385             self.active_high,
386             self.dest_logic,
387             self.mask,
388         )
389     }
390 }
391 
392 #[inline(never)]
393 pub fn ioapic_init(ignore: &'static [IrqNumber]) {
394     kinfo!("Initializing ioapic...");
395     let ioapic = unsafe { IoApic::new() };
396     unsafe {
397         __IOAPIC = Some(SpinLock::new(ioapic));
398     }
399     unsafe {
400         IOAPIC_IR_CHIP = Some(Arc::new(IoApicChip));
401     }
402 
403     // 绑定irqchip
404     for i in 32..256 {
405         let irq = IrqNumber::new(i);
406 
407         if ignore.contains(&irq) {
408             continue;
409         }
410 
411         let desc = irq_desc_manager().lookup(irq).unwrap();
412         let irq_data = desc.irq_data();
413         let mut chip_info_guard = irq_data.chip_info_write_irqsave();
414         chip_info_guard.set_chip(Some(ioapic_ir_chip()));
415         let chip_data = IoApicChipData::DEFAULT;
416         chip_data.inner().rte_index = IoApic::vector_rte_index(i as u8);
417         chip_data.inner().vector = i as u8;
418         chip_info_guard.set_chip_data(Some(Arc::new(chip_data)));
419         drop(chip_info_guard);
420         let level = irq_data.is_level_type();
421 
422         register_handler(&desc, level);
423     }
424 
425     kinfo!("IO Apic initialized.");
426 }
427 
428 fn register_handler(desc: &Arc<IrqDesc>, level_triggered: bool) {
429     let fasteoi: bool;
430     if level_triggered {
431         desc.modify_status(IrqLineStatus::empty(), IrqLineStatus::IRQ_LEVEL);
432         fasteoi = true;
433     } else {
434         desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty());
435         fasteoi = false;
436     }
437 
438     let handler: &dyn IrqFlowHandler = if fasteoi {
439         fast_eoi_irq_handler()
440     } else {
441         edge_irq_handler()
442     };
443     desc.set_handler(handler);
444 }
445 
446 /// 安装中断
447 ///
448 /// ## 参数
449 ///
450 /// * `vector` - 中断向量号
451 /// * `dest` - 目标CPU的APIC ID
452 /// * `level_triggered` - 是否为电平触发
453 /// * `active_high` - 是否为高电平有效
454 /// * `dest_logic` - 是否为逻辑模式
455 /// * `mask` - 是否屏蔽
456 fn ioapic_install(
457     vector: u8,
458     dest: u8,
459     level_triggered: bool,
460     active_high: bool,
461     dest_logic: bool,
462     mask: bool,
463 ) -> Result<(), SystemError> {
464     let rte_index = IoApic::vector_rte_index(vector);
465     return IOAPIC().lock_irqsave().install(
466         rte_index,
467         vector,
468         dest,
469         level_triggered,
470         active_high,
471         dest_logic,
472         mask,
473     );
474 }
475 
476 /// IoApic中断芯片
477 ///
478 /// https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/io_apic.c#1994
479 #[derive(Debug)]
480 struct IoApicChip;
481 
482 impl IrqChip for IoApicChip {
483     fn name(&self) -> &'static str {
484         "IR-IO-APIC"
485     }
486 
487     fn irq_startup(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
488         self.irq_unmask(irq)
489     }
490 
491     fn irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
492         let binding = irq
493             .chip_info_read_irqsave()
494             .chip_data()
495             .ok_or(SystemError::EINVAL)?;
496         let chip_data = binding
497             .as_any_ref()
498             .downcast_ref::<IoApicChipData>()
499             .ok_or(SystemError::EINVAL)?;
500 
501         let mut chip_data_inner = chip_data.inner();
502         chip_data_inner.mask = true;
503         chip_data_inner.sync_to_chip().ok();
504 
505         drop(chip_data_inner);
506 
507         return Ok(());
508     }
509 
510     fn can_set_affinity(&self) -> bool {
511         true
512     }
513 
514     fn can_set_flow_type(&self) -> bool {
515         true
516     }
517 
518     fn irq_set_type(
519         &self,
520         irq: &Arc<IrqData>,
521         flow_type: IrqLineStatus,
522     ) -> Result<IrqChipSetMaskResult, SystemError> {
523         let binding = irq
524             .chip_info_read_irqsave()
525             .chip_data()
526             .ok_or(SystemError::EINVAL)?;
527         let chip_data = binding
528             .as_any_ref()
529             .downcast_ref::<IoApicChipData>()
530             .ok_or(SystemError::EINVAL)?;
531         let mut chip_data_inner = chip_data.inner();
532 
533         let level_triggered = flow_type.is_level_type();
534         let active_high = flow_type.is_level_high().unwrap_or(false);
535         chip_data_inner.active_high = active_high;
536         chip_data_inner.level_triggered = level_triggered;
537         chip_data_inner.sync_to_chip()?;
538 
539         return Ok(IrqChipSetMaskResult::SetMaskOk);
540     }
541 
542     fn irq_set_affinity(
543         &self,
544         irq: &Arc<IrqData>,
545         cpu: &CpuMask,
546         _force: bool,
547     ) -> Result<IrqChipSetMaskResult, SystemError> {
548         // 使用mask的第1个可用CPU
549         let dest = (cpu.first().ok_or(SystemError::EINVAL)?.data() & 0xff) as u8;
550 
551         let binding = irq
552             .chip_info_read_irqsave()
553             .chip_data()
554             .ok_or(SystemError::EINVAL)?;
555         let chip_data = binding
556             .as_any_ref()
557             .downcast_ref::<IoApicChipData>()
558             .ok_or(SystemError::EINVAL)?;
559 
560         let mut chip_data_inner = chip_data.inner();
561         let origin_dest = chip_data_inner.dest;
562         if origin_dest == dest {
563             return Ok(IrqChipSetMaskResult::SetMaskOk);
564         }
565 
566         chip_data_inner.dest = dest;
567 
568         chip_data_inner.sync_to_chip()?;
569 
570         return Ok(IrqChipSetMaskResult::SetMaskOk);
571     }
572 
573     fn irq_unmask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
574         IOAPIC()
575             .lock_irqsave()
576             .enable(IoApic::vector_rte_index(irq.irq().data() as u8));
577         Ok(())
578     }
579 
580     fn can_mask_ack(&self) -> bool {
581         true
582     }
583 
584     fn irq_mask_ack(&self, irq: &Arc<IrqData>) {
585         self.irq_mask(irq).ok();
586         self.irq_eoi(irq);
587     }
588 
589     fn irq_eoi(&self, irq: &Arc<IrqData>) {
590         if irq.is_level_type() {
591             IOAPIC().lock_irqsave().level_ack(irq.irq().data() as u8);
592         } else {
593             CurrentApic.send_eoi();
594         }
595     }
596 
597     fn retrigger(&self, irq_data: &Arc<IrqData>) -> Result<(), SystemError> {
598         irq_manager().irq_chip_retrigger_hierarchy(irq_data)
599     }
600 
601     fn irqchip_state(&self, irq: &Arc<IrqData>, which: IrqChipState) -> Result<bool, SystemError> {
602         let binding = irq
603             .chip_info_read_irqsave()
604             .chip_data()
605             .ok_or(SystemError::EINVAL)?;
606         let chip_data = binding
607             .as_any_ref()
608             .downcast_ref::<IoApicChipData>()
609             .ok_or(SystemError::EINVAL)?;
610 
611         match which {
612             IrqChipState::Pending => {
613                 return Ok(IOAPIC().lock_irqsave().pending(irq.irq().data() as u8));
614             }
615             IrqChipState::Active => {
616                 let chip_data_inner = chip_data.inner();
617                 return Ok(!chip_data_inner.mask);
618             }
619             IrqChipState::Masked => {
620                 let chip_data_inner = chip_data.inner();
621                 return Ok(chip_data_inner.mask);
622             }
623             IrqChipState::LineLevel => {
624                 let chip_data_inner = chip_data.inner();
625                 return Ok(chip_data_inner.active_high);
626             }
627             #[allow(unreachable_patterns)]
628             _ => {
629                 return Err(SystemError::EINVAL);
630             }
631         }
632     }
633 
634     fn irq_disable(&self, irq: &Arc<IrqData>) {
635         let binding = irq
636             .chip_info_read_irqsave()
637             .chip_data()
638             .ok_or(SystemError::EINVAL)
639             .unwrap();
640         let chip_data = binding
641             .as_any_ref()
642             .downcast_ref::<IoApicChipData>()
643             .ok_or(SystemError::EINVAL)
644             .unwrap();
645         let mut chip_data_inner = chip_data.inner();
646         chip_data_inner.mask = true;
647         chip_data_inner.sync_to_chip().ok();
648     }
649 
650     fn irq_ack(&self, irq_data: &Arc<IrqData>) {
651         // irq_manager().irq_chip_ack_parent(irq_data);
652         self.irq_eoi(irq_data);
653     }
654 
655     fn flags(&self) -> IrqChipFlags {
656         IrqChipFlags::IRQCHIP_SKIP_SET_WAKE | IrqChipFlags::IRQCHIP_AFFINITY_PRE_STARTUP
657     }
658 }
659