1e2841179SLoGin use core::intrinsics::unlikely; 2e2841179SLoGin 3e2841179SLoGin use alloc::{string::ToString, sync::Arc}; 4e2841179SLoGin use intertrait::CastFrom; 5e2841179SLoGin use system_error::SystemError; 6e2841179SLoGin 7e2841179SLoGin use crate::{ 8e2841179SLoGin arch::{ 9e2841179SLoGin driver::apic::{ 10e2841179SLoGin apic_timer::{local_apic_timer_irq_desc_init, APIC_TIMER_IRQ_NUM}, 11e2841179SLoGin ioapic::ioapic_init, 12e2841179SLoGin }, 13e2841179SLoGin interrupt::{ 14e2841179SLoGin entry::arch_setup_interrupt_gate, 15e2841179SLoGin ipi::{arch_ipi_handler_init, send_ipi, IPI_NUM_FLUSH_TLB, IPI_NUM_KICK_CPU}, 16e2841179SLoGin msi::{X86MsiAddrHi, X86MsiAddrLoNormal, X86MsiDataNormal, X86_MSI_BASE_ADDRESS_LOW}, 17e2841179SLoGin }, 18e2841179SLoGin }, 19e2841179SLoGin driver::open_firmware::device_node::DeviceNode, 20e2841179SLoGin exception::{ 21e2841179SLoGin ipi::{IpiKind, IpiTarget}, 22e2841179SLoGin irqchip::{IrqChip, IrqChipData, IrqChipFlags}, 23e2841179SLoGin irqdata::IrqData, 24e2841179SLoGin irqdomain::{irq_domain_manager, IrqDomain, IrqDomainBusToken, IrqDomainOps}, 25e2841179SLoGin msi::MsiMsg, 26e2841179SLoGin HardwareIrqNumber, IrqNumber, 27e2841179SLoGin }, 28e2841179SLoGin kwarn, 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 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 { 47e2841179SLoGin 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 { 57e2841179SLoGin fn name(&self) -> &'static str { 58e2841179SLoGin "APIC" 59e2841179SLoGin } 60e2841179SLoGin 61e2841179SLoGin fn can_set_flow_type(&self) -> bool { 62e2841179SLoGin false 63e2841179SLoGin } 64e2841179SLoGin 65e2841179SLoGin fn irq_disable(&self, _irq: &Arc<IrqData>) {} 66e2841179SLoGin 67e2841179SLoGin fn irq_ack(&self, _irq: &Arc<IrqData>) { 68e2841179SLoGin CurrentApic.send_eoi(); 69e2841179SLoGin } 70e2841179SLoGin 71e2841179SLoGin fn can_set_affinity(&self) -> bool { 72e2841179SLoGin false 73e2841179SLoGin } 74e2841179SLoGin 75e2841179SLoGin fn can_mask_ack(&self) -> bool { 76e2841179SLoGin false 77e2841179SLoGin } 78e2841179SLoGin 79e2841179SLoGin fn irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 80e2841179SLoGin // 这里临时处理,后续需要修改 81e2841179SLoGin return Ok(()); 82e2841179SLoGin } 83e2841179SLoGin 84e2841179SLoGin fn irq_unmask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> { 85e2841179SLoGin Ok(()) 86e2841179SLoGin } 87e2841179SLoGin 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 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 114e2841179SLoGin 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)] 131e2841179SLoGin 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 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 { 168e2841179SLoGin 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 182e2841179SLoGin pub(super) fn irq_msi_compose_msg(cfg: &HardwareIrqConfig, msg: &mut MsiMsg, dmar: bool) { 183e2841179SLoGin *msg = MsiMsg::new_zeroed(); 184e2841179SLoGin 185e2841179SLoGin let arch_data = X86MsiDataNormal::new() 186e2841179SLoGin .with_delivery_mode(x86::apic::DeliveryMode::Fixed as u8) 187e2841179SLoGin .with_vector((cfg.vector.data() & 0xff) as u8); 188e2841179SLoGin let mut address_lo = X86MsiAddrLoNormal::new() 189e2841179SLoGin .with_base_address(X86_MSI_BASE_ADDRESS_LOW) 190e2841179SLoGin .with_dest_mode_logical(false) 191e2841179SLoGin .with_destid_0_7(cfg.apic_id.data() & 0xff); 192e2841179SLoGin 193e2841179SLoGin let mut address_hi = X86MsiAddrHi::new(); 194e2841179SLoGin 195e2841179SLoGin /* 196e2841179SLoGin * 只有IOMMU本身可以使用将目标APIC ID放入地址的高位的技术。 197e2841179SLoGin * 任何其他尝试这样做的东西都只是在写内存,并且需要IR来 198e2841179SLoGin * 寻址不能在正常的32位地址范围内0xFFExxxxx寻址的APIC。 199e2841179SLoGin * 这通常是8位,但一些虚拟化程序允许在位5-11使用扩展的目的地ID字段, 200e2841179SLoGin * 总共支持15位的APIC ID。 201e2841179SLoGin */ 202e2841179SLoGin if dmar { 203e2841179SLoGin address_hi.set_destid_8_31(cfg.apic_id.data() >> 8); 204e2841179SLoGin } else if cfg.apic_id.data() < 0x8000 { 205e2841179SLoGin // todo: 判断vmx是否支持 extended destination mode 206e2841179SLoGin // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/apic.c?fi=__irq_msi_compose_msg#2580 207e2841179SLoGin address_lo.set_virt_destid_8_14(cfg.apic_id.data() >> 8); 208*b5b571e0SLoGin } else if unlikely(cfg.apic_id.data() > 0xff) { 209e2841179SLoGin kwarn!( 210e2841179SLoGin "irq_msi_compose_msg: Invalid APIC ID: {}", 211e2841179SLoGin cfg.apic_id.data() 212e2841179SLoGin ); 213e2841179SLoGin } 214*b5b571e0SLoGin 215e2841179SLoGin msg.address_hi = address_hi.into(); 216e2841179SLoGin msg.address_lo = address_lo.into(); 217e2841179SLoGin msg.data = arch_data.into(); 218e2841179SLoGin } 219e2841179SLoGin 220e2841179SLoGin static mut X86_VECTOR_DOMAIN: Option<Arc<IrqDomain>> = None; 221e2841179SLoGin 222e2841179SLoGin #[inline(always)] 223e2841179SLoGin #[allow(dead_code)] 224e2841179SLoGin pub fn x86_vector_domain() -> &'static Arc<IrqDomain> { 225e2841179SLoGin unsafe { X86_VECTOR_DOMAIN.as_ref().unwrap() } 226e2841179SLoGin } 227e2841179SLoGin 228e2841179SLoGin #[inline(never)] 229e2841179SLoGin pub fn arch_early_irq_init() -> Result<(), SystemError> { 230e2841179SLoGin let vec_domain = irq_domain_manager() 231e2841179SLoGin .create_and_add( 232e2841179SLoGin "VECTOR".to_string(), 233e2841179SLoGin &X86VectorDomainOps, 234e2841179SLoGin IrqNumber::new(32), 235e2841179SLoGin HardwareIrqNumber::new(32), 236e2841179SLoGin 223, 237e2841179SLoGin ) 238e2841179SLoGin .ok_or(SystemError::ENOMEM)?; 239e2841179SLoGin irq_domain_manager().set_default_domain(vec_domain.clone()); 240e2841179SLoGin unsafe { X86_VECTOR_DOMAIN = Some(vec_domain) }; 241e2841179SLoGin 242e2841179SLoGin let apic_chip = Arc::new(LocalApicChip::new()); 243e2841179SLoGin 244e2841179SLoGin unsafe { LOCAL_APIC_CHIP = Some(apic_chip) }; 245e2841179SLoGin 246e2841179SLoGin // todo: add vector matrix 247e2841179SLoGin // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c#803 248e2841179SLoGin kwarn!("arch_early_irq_init: todo: add vector matrix"); 249e2841179SLoGin 250e2841179SLoGin local_apic_timer_irq_desc_init(); 251e2841179SLoGin arch_ipi_handler_init(); 252e2841179SLoGin CurrentApic.init_current_cpu(); 253e2841179SLoGin if smp_get_processor_id().data() == 0 { 254e2841179SLoGin unsafe { arch_setup_interrupt_gate() }; 255e2841179SLoGin ioapic_init(&[APIC_TIMER_IRQ_NUM, IPI_NUM_KICK_CPU, IPI_NUM_FLUSH_TLB]); 256e2841179SLoGin } 257e2841179SLoGin return Ok(()); 258e2841179SLoGin } 259e2841179SLoGin 260e2841179SLoGin /// x86的中断域操作 261e2841179SLoGin /// 262e2841179SLoGin /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c#693 263e2841179SLoGin #[derive(Debug)] 264e2841179SLoGin struct X86VectorDomainOps; 265e2841179SLoGin 266e2841179SLoGin impl IrqDomainOps for X86VectorDomainOps { 267e2841179SLoGin fn match_node( 268e2841179SLoGin &self, 269e2841179SLoGin _irq_domain: &Arc<IrqDomain>, 270e2841179SLoGin _device_node: &Arc<DeviceNode>, 271e2841179SLoGin _bus_token: IrqDomainBusToken, 272e2841179SLoGin ) -> bool { 273e2841179SLoGin todo!() 274e2841179SLoGin } 275e2841179SLoGin 276e2841179SLoGin fn map( 277e2841179SLoGin &self, 278e2841179SLoGin _irq_domain: &Arc<IrqDomain>, 279e2841179SLoGin _hwirq: HardwareIrqNumber, 280e2841179SLoGin _virq: IrqNumber, 281e2841179SLoGin ) -> Result<(), SystemError> { 282e2841179SLoGin Err(SystemError::ENOSYS) 283e2841179SLoGin } 284e2841179SLoGin 285e2841179SLoGin fn unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber) { 286e2841179SLoGin todo!() 287e2841179SLoGin } 288e2841179SLoGin } 289