xref: /DragonOS/kernel/src/arch/x86_64/driver/apic/lapic_vector.rs (revision bd70d2d1f490aabd570a5301b858bd5eb04149fa)
1e2841179SLoGin use core::intrinsics::unlikely;
2e2841179SLoGin 
3e2841179SLoGin use alloc::{string::ToString, sync::Arc};
4e2841179SLoGin use intertrait::CastFrom;
52eab6dd7S曾俊 use log::warn;
6e2841179SLoGin use system_error::SystemError;
7e2841179SLoGin 
8e2841179SLoGin use crate::{
9e2841179SLoGin     arch::{
10e2841179SLoGin         driver::apic::{
11e2841179SLoGin             apic_timer::{local_apic_timer_irq_desc_init, APIC_TIMER_IRQ_NUM},
12e2841179SLoGin             ioapic::ioapic_init,
13e2841179SLoGin         },
14e2841179SLoGin         interrupt::{
15e2841179SLoGin             entry::arch_setup_interrupt_gate,
16e2841179SLoGin             ipi::{arch_ipi_handler_init, send_ipi, IPI_NUM_FLUSH_TLB, IPI_NUM_KICK_CPU},
17e2841179SLoGin             msi::{X86MsiAddrHi, X86MsiAddrLoNormal, X86MsiDataNormal, X86_MSI_BASE_ADDRESS_LOW},
18e2841179SLoGin         },
19e2841179SLoGin     },
20e2841179SLoGin     driver::open_firmware::device_node::DeviceNode,
21e2841179SLoGin     exception::{
22e2841179SLoGin         ipi::{IpiKind, IpiTarget},
23e2841179SLoGin         irqchip::{IrqChip, IrqChipData, IrqChipFlags},
24e2841179SLoGin         irqdata::IrqData,
25e2841179SLoGin         irqdomain::{irq_domain_manager, IrqDomain, IrqDomainBusToken, IrqDomainOps},
26e2841179SLoGin         msi::MsiMsg,
27e2841179SLoGin         HardwareIrqNumber, IrqNumber,
28e2841179SLoGin     },
29e2841179SLoGin     libs::spinlock::{SpinLock, SpinLockGuard},
30e2841179SLoGin     smp::{core::smp_get_processor_id, cpu::ProcessorId},
31e2841179SLoGin };
32e2841179SLoGin 
33e2841179SLoGin use super::{hw_irq::HardwareIrqConfig, CurrentApic, LocalAPIC};
34e2841179SLoGin 
35e2841179SLoGin static mut LOCAL_APIC_CHIP: Option<Arc<LocalApicChip>> = None;
36e2841179SLoGin 
local_apic_chip() -> &'static Arc<LocalApicChip>37e2841179SLoGin pub fn local_apic_chip() -> &'static Arc<LocalApicChip> {
38e2841179SLoGin     unsafe { LOCAL_APIC_CHIP.as_ref().unwrap() }
39e2841179SLoGin }
40e2841179SLoGin 
41e2841179SLoGin #[derive(Debug)]
42e2841179SLoGin pub struct LocalApicChip {
43e2841179SLoGin     inner: SpinLock<InnerIrqChip>,
44e2841179SLoGin }
45e2841179SLoGin 
46e2841179SLoGin impl LocalApicChip {
new() -> Self47e2841179SLoGin     pub fn new() -> Self {
48e2841179SLoGin         Self {
49e2841179SLoGin             inner: SpinLock::new(InnerIrqChip {
50e2841179SLoGin                 flags: IrqChipFlags::empty(),
51e2841179SLoGin             }),
52e2841179SLoGin         }
53e2841179SLoGin     }
54e2841179SLoGin }
55e2841179SLoGin 
56e2841179SLoGin impl IrqChip for LocalApicChip {
name(&self) -> &'static str57e2841179SLoGin     fn name(&self) -> &'static str {
58e2841179SLoGin         "APIC"
59e2841179SLoGin     }
60e2841179SLoGin 
can_set_flow_type(&self) -> bool61e2841179SLoGin     fn can_set_flow_type(&self) -> bool {
62e2841179SLoGin         false
63e2841179SLoGin     }
64e2841179SLoGin 
irq_disable(&self, _irq: &Arc<IrqData>)65e2841179SLoGin     fn irq_disable(&self, _irq: &Arc<IrqData>) {}
66e2841179SLoGin 
irq_ack(&self, _irq: &Arc<IrqData>)67e2841179SLoGin     fn irq_ack(&self, _irq: &Arc<IrqData>) {
68e2841179SLoGin         CurrentApic.send_eoi();
69e2841179SLoGin     }
70e2841179SLoGin 
can_set_affinity(&self) -> bool71e2841179SLoGin     fn can_set_affinity(&self) -> bool {
72e2841179SLoGin         false
73e2841179SLoGin     }
74e2841179SLoGin 
can_mask_ack(&self) -> bool75e2841179SLoGin     fn can_mask_ack(&self) -> bool {
76e2841179SLoGin         false
77e2841179SLoGin     }
78e2841179SLoGin 
irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>79e2841179SLoGin     fn irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
80e2841179SLoGin         // 这里临时处理,后续需要修改
81e2841179SLoGin         return Ok(());
82e2841179SLoGin     }
83e2841179SLoGin 
irq_unmask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError>84e2841179SLoGin     fn irq_unmask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
85e2841179SLoGin         Ok(())
86e2841179SLoGin     }
87e2841179SLoGin 
irq_compose_msi_msg(&self, irq: &Arc<IrqData>, msg: &mut MsiMsg)88e2841179SLoGin     fn irq_compose_msi_msg(&self, irq: &Arc<IrqData>, msg: &mut MsiMsg) {
89e2841179SLoGin         let chip_data = irq.chip_info_read_irqsave().chip_data().unwrap();
90e2841179SLoGin         let apicd = chip_data.ref_any().downcast_ref::<ApicChipData>().unwrap();
91e2841179SLoGin         let cfg = &apicd.inner().hw_irq_cfg;
92e2841179SLoGin         irq_msi_compose_msg(cfg, msg, false);
93e2841179SLoGin     }
94e2841179SLoGin 
retrigger(&self, irq: &Arc<IrqData>) -> Result<(), SystemError>95e2841179SLoGin     fn retrigger(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
96e2841179SLoGin         let chip_data = irq
97e2841179SLoGin             .chip_info_read_irqsave()
98e2841179SLoGin             .chip_data()
99e2841179SLoGin             .ok_or(SystemError::EINVAL)?;
100e2841179SLoGin         let apicd = chip_data
101e2841179SLoGin             .ref_any()
102e2841179SLoGin             .downcast_ref::<ApicChipData>()
103e2841179SLoGin             .ok_or(SystemError::EINVAL)?;
104e2841179SLoGin         let inner = apicd.inner();
105e2841179SLoGin 
106e2841179SLoGin         send_ipi(
107e2841179SLoGin             IpiKind::SpecVector(inner.vector),
108e2841179SLoGin             IpiTarget::Specified(inner.cpu),
109e2841179SLoGin         );
110e2841179SLoGin 
111e2841179SLoGin         Ok(())
112e2841179SLoGin     }
113e2841179SLoGin 
flags(&self) -> IrqChipFlags114e2841179SLoGin     fn flags(&self) -> IrqChipFlags {
115e2841179SLoGin         self.inner.lock_irqsave().flags
116e2841179SLoGin     }
117e2841179SLoGin }
118e2841179SLoGin 
119e2841179SLoGin #[derive(Debug)]
120e2841179SLoGin struct InnerIrqChip {
121e2841179SLoGin     flags: IrqChipFlags,
122e2841179SLoGin }
123e2841179SLoGin 
124e2841179SLoGin #[derive(Debug)]
125e2841179SLoGin struct ApicChipData {
126e2841179SLoGin     inner: SpinLock<InnerApicChipData>,
127e2841179SLoGin }
128e2841179SLoGin 
129e2841179SLoGin impl ApicChipData {
130e2841179SLoGin     #[allow(dead_code)]
new( hw_irq_cfg: HardwareIrqConfig, irq: IrqNumber, vector: HardwareIrqNumber, cpu: ProcessorId, ) -> Self131e2841179SLoGin     pub fn new(
132e2841179SLoGin         hw_irq_cfg: HardwareIrqConfig,
133e2841179SLoGin         irq: IrqNumber,
134e2841179SLoGin         vector: HardwareIrqNumber,
135e2841179SLoGin         cpu: ProcessorId,
136e2841179SLoGin     ) -> Self {
137e2841179SLoGin         Self {
138e2841179SLoGin             inner: SpinLock::new(InnerApicChipData {
139e2841179SLoGin                 hw_irq_cfg,
140e2841179SLoGin                 irq,
141e2841179SLoGin                 vector,
142e2841179SLoGin                 prev_vector: None,
143e2841179SLoGin                 cpu,
144e2841179SLoGin                 prev_cpu: None,
145e2841179SLoGin                 status: ApicChipStatus::empty(),
146e2841179SLoGin             }),
147e2841179SLoGin         }
148e2841179SLoGin     }
149e2841179SLoGin 
inner(&self) -> SpinLockGuard<InnerApicChipData>150e2841179SLoGin     pub fn inner(&self) -> SpinLockGuard<InnerApicChipData> {
151e2841179SLoGin         self.inner.lock_irqsave()
152e2841179SLoGin     }
153e2841179SLoGin }
154e2841179SLoGin 
155e2841179SLoGin #[allow(dead_code)]
156e2841179SLoGin #[derive(Debug)]
157e2841179SLoGin struct InnerApicChipData {
158e2841179SLoGin     hw_irq_cfg: HardwareIrqConfig,
159e2841179SLoGin     irq: IrqNumber,
160e2841179SLoGin     vector: HardwareIrqNumber,
161e2841179SLoGin     prev_vector: Option<HardwareIrqNumber>,
162e2841179SLoGin     cpu: ProcessorId,
163e2841179SLoGin     prev_cpu: Option<ProcessorId>,
164e2841179SLoGin     status: ApicChipStatus,
165e2841179SLoGin }
166e2841179SLoGin 
167e2841179SLoGin impl IrqChipData for ApicChipData {
as_any_ref(&self) -> &dyn core::any::Any168e2841179SLoGin     fn as_any_ref(&self) -> &dyn core::any::Any {
169e2841179SLoGin         self
170e2841179SLoGin     }
171e2841179SLoGin }
172e2841179SLoGin 
173e2841179SLoGin bitflags! {
174e2841179SLoGin     pub struct ApicChipStatus: u32 {
175e2841179SLoGin         const MOVE_IN_PROGRESS = 1 << 0;
176e2841179SLoGin         const IS_MANAGED = 1 << 1;
177e2841179SLoGin         const CAN_RESERVE = 1 << 2;
178e2841179SLoGin         const HAS_RESERVED = 1 << 3;
179e2841179SLoGin     }
180e2841179SLoGin }
181e2841179SLoGin 
182*bd70d2d1SLoGin #[allow(dead_code)]
irq_msi_compose_msg(cfg: &HardwareIrqConfig, msg: &mut MsiMsg, dmar: bool)183e2841179SLoGin pub(super) fn irq_msi_compose_msg(cfg: &HardwareIrqConfig, msg: &mut MsiMsg, dmar: bool) {
184e2841179SLoGin     *msg = MsiMsg::new_zeroed();
185e2841179SLoGin 
186e2841179SLoGin     let arch_data = X86MsiDataNormal::new()
187e2841179SLoGin         .with_delivery_mode(x86::apic::DeliveryMode::Fixed as u8)
188e2841179SLoGin         .with_vector((cfg.vector.data() & 0xff) as u8);
189e2841179SLoGin     let mut address_lo = X86MsiAddrLoNormal::new()
190e2841179SLoGin         .with_base_address(X86_MSI_BASE_ADDRESS_LOW)
191e2841179SLoGin         .with_dest_mode_logical(false)
192e2841179SLoGin         .with_destid_0_7(cfg.apic_id.data() & 0xff);
193e2841179SLoGin 
194e2841179SLoGin     let mut address_hi = X86MsiAddrHi::new();
195e2841179SLoGin 
196e2841179SLoGin     /*
197e2841179SLoGin      * 只有IOMMU本身可以使用将目标APIC ID放入地址的高位的技术。
198e2841179SLoGin      * 任何其他尝试这样做的东西都只是在写内存,并且需要IR来
199e2841179SLoGin      * 寻址不能在正常的32位地址范围内0xFFExxxxx寻址的APIC。
200e2841179SLoGin      * 这通常是8位,但一些虚拟化程序允许在位5-11使用扩展的目的地ID字段,
201e2841179SLoGin      * 总共支持15位的APIC ID。
202e2841179SLoGin      */
203e2841179SLoGin     if dmar {
204e2841179SLoGin         address_hi.set_destid_8_31(cfg.apic_id.data() >> 8);
205e2841179SLoGin     } else if cfg.apic_id.data() < 0x8000 {
206e2841179SLoGin         // todo: 判断vmx是否支持 extended destination mode
207e2841179SLoGin         // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/apic.c?fi=__irq_msi_compose_msg#2580
208e2841179SLoGin         address_lo.set_virt_destid_8_14(cfg.apic_id.data() >> 8);
209b5b571e0SLoGin     } else if unlikely(cfg.apic_id.data() > 0xff) {
2102eab6dd7S曾俊         warn!(
211e2841179SLoGin             "irq_msi_compose_msg: Invalid APIC ID: {}",
212e2841179SLoGin             cfg.apic_id.data()
213e2841179SLoGin         );
214e2841179SLoGin     }
215b5b571e0SLoGin 
216e2841179SLoGin     msg.address_hi = address_hi.into();
217e2841179SLoGin     msg.address_lo = address_lo.into();
218e2841179SLoGin     msg.data = arch_data.into();
219e2841179SLoGin }
220e2841179SLoGin 
221e2841179SLoGin static mut X86_VECTOR_DOMAIN: Option<Arc<IrqDomain>> = None;
222e2841179SLoGin 
223e2841179SLoGin #[inline(always)]
224e2841179SLoGin #[allow(dead_code)]
x86_vector_domain() -> &'static Arc<IrqDomain>225e2841179SLoGin pub fn x86_vector_domain() -> &'static Arc<IrqDomain> {
226e2841179SLoGin     unsafe { X86_VECTOR_DOMAIN.as_ref().unwrap() }
227e2841179SLoGin }
228e2841179SLoGin 
229e2841179SLoGin #[inline(never)]
arch_early_irq_init() -> Result<(), SystemError>230e2841179SLoGin pub fn arch_early_irq_init() -> Result<(), SystemError> {
2310102d69fSLoGin     const IRQ_SIZE: u32 = 223;
232e2841179SLoGin     let vec_domain = irq_domain_manager()
233e2841179SLoGin         .create_and_add(
234e2841179SLoGin             "VECTOR".to_string(),
235e2841179SLoGin             &X86VectorDomainOps,
236e2841179SLoGin             IrqNumber::new(32),
237e2841179SLoGin             HardwareIrqNumber::new(32),
2380102d69fSLoGin             IRQ_SIZE,
239e2841179SLoGin         )
240e2841179SLoGin         .ok_or(SystemError::ENOMEM)?;
241e2841179SLoGin     irq_domain_manager().set_default_domain(vec_domain.clone());
2420102d69fSLoGin     irq_domain_manager().domain_associate_many(
2430102d69fSLoGin         &vec_domain,
2440102d69fSLoGin         IrqNumber::new(0),
2450102d69fSLoGin         HardwareIrqNumber::new(0),
2460102d69fSLoGin         IRQ_SIZE,
2470102d69fSLoGin     );
248e2841179SLoGin     unsafe { X86_VECTOR_DOMAIN = Some(vec_domain) };
249e2841179SLoGin 
250e2841179SLoGin     let apic_chip = Arc::new(LocalApicChip::new());
251e2841179SLoGin 
252e2841179SLoGin     unsafe { LOCAL_APIC_CHIP = Some(apic_chip) };
253e2841179SLoGin 
254e2841179SLoGin     // todo: add vector matrix
255e2841179SLoGin     // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c#803
2562eab6dd7S曾俊     warn!("arch_early_irq_init: todo: add vector matrix");
257e2841179SLoGin 
258e2841179SLoGin     local_apic_timer_irq_desc_init();
259e2841179SLoGin     arch_ipi_handler_init();
260e2841179SLoGin     CurrentApic.init_current_cpu();
261e2841179SLoGin     if smp_get_processor_id().data() == 0 {
262e2841179SLoGin         unsafe { arch_setup_interrupt_gate() };
263e2841179SLoGin         ioapic_init(&[APIC_TIMER_IRQ_NUM, IPI_NUM_KICK_CPU, IPI_NUM_FLUSH_TLB]);
264e2841179SLoGin     }
265e2841179SLoGin     return Ok(());
266e2841179SLoGin }
267e2841179SLoGin 
268e2841179SLoGin /// x86的中断域操作
269e2841179SLoGin ///
270e2841179SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c#693
271e2841179SLoGin #[derive(Debug)]
272e2841179SLoGin struct X86VectorDomainOps;
273e2841179SLoGin 
274e2841179SLoGin impl IrqDomainOps for X86VectorDomainOps {
match_node( &self, _irq_domain: &Arc<IrqDomain>, _device_node: &Arc<DeviceNode>, _bus_token: IrqDomainBusToken, ) -> bool275e2841179SLoGin     fn match_node(
276e2841179SLoGin         &self,
277e2841179SLoGin         _irq_domain: &Arc<IrqDomain>,
278e2841179SLoGin         _device_node: &Arc<DeviceNode>,
279e2841179SLoGin         _bus_token: IrqDomainBusToken,
280e2841179SLoGin     ) -> bool {
281e2841179SLoGin         todo!()
282e2841179SLoGin     }
283e2841179SLoGin 
map( &self, _irq_domain: &Arc<IrqDomain>, _hwirq: HardwareIrqNumber, _virq: IrqNumber, ) -> Result<(), SystemError>284e2841179SLoGin     fn map(
285e2841179SLoGin         &self,
286e2841179SLoGin         _irq_domain: &Arc<IrqDomain>,
287e2841179SLoGin         _hwirq: HardwareIrqNumber,
288e2841179SLoGin         _virq: IrqNumber,
289e2841179SLoGin     ) -> Result<(), SystemError> {
290e2841179SLoGin         Err(SystemError::ENOSYS)
291e2841179SLoGin     }
292e2841179SLoGin 
unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber)293e2841179SLoGin     fn unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber) {
294e2841179SLoGin         todo!()
295e2841179SLoGin     }
296e2841179SLoGin }
297