1e2841179SLoGin use alloc::sync::Arc; 291e9d4abSLoGin use system_error::SystemError; 370a4e555SLoGin use x86::apic::ApicId; 4aa0367d6SLoGin 570a4e555SLoGin use crate::{ 670a4e555SLoGin arch::{ 7e2841179SLoGin driver::apic::{lapic_vector::local_apic_chip, CurrentApic, LocalAPIC}, 870a4e555SLoGin smp::SMP_BOOT_DATA, 970a4e555SLoGin }, 10e2841179SLoGin exception::{ 11e2841179SLoGin ipi::{FlushTLBIpiHandler, IpiKind, IpiTarget, KickCpuIpiHandler}, 12e2841179SLoGin irqdata::{IrqData, IrqLineStatus}, 13e2841179SLoGin irqdesc::{irq_desc_manager, IrqDesc, IrqFlowHandler, IrqHandler}, 14e2841179SLoGin HardwareIrqNumber, IrqNumber, 15e2841179SLoGin }, 16e2841179SLoGin kerror, 17e2841179SLoGin smp::cpu::ProcessorId, 1870a4e555SLoGin }; 19aa0367d6SLoGin 20e2841179SLoGin use super::TrapFrame; 21e2841179SLoGin 22e2841179SLoGin pub const IPI_NUM_KICK_CPU: IrqNumber = IrqNumber::new(200); 23e2841179SLoGin pub const IPI_NUM_FLUSH_TLB: IrqNumber = IrqNumber::new(201); 24aa0367d6SLoGin /// IPI的种类(架构相关,指定了向量号) 25aa0367d6SLoGin #[derive(Debug, Copy, Clone, Eq, PartialEq)] 26e2841179SLoGin #[repr(u32)] 27aa0367d6SLoGin pub enum ArchIpiKind { 28e2841179SLoGin KickCpu = IPI_NUM_KICK_CPU.data(), 29e2841179SLoGin FlushTLB = IPI_NUM_FLUSH_TLB.data(), 30e2841179SLoGin SpecVector(HardwareIrqNumber), 31aa0367d6SLoGin } 32aa0367d6SLoGin 33aa0367d6SLoGin impl From<IpiKind> for ArchIpiKind { 34aa0367d6SLoGin fn from(kind: IpiKind) -> Self { 35aa0367d6SLoGin match kind { 36aa0367d6SLoGin IpiKind::KickCpu => ArchIpiKind::KickCpu, 37aa0367d6SLoGin IpiKind::FlushTLB => ArchIpiKind::FlushTLB, 38e2841179SLoGin IpiKind::SpecVector(vec) => ArchIpiKind::SpecVector(vec), 39e2841179SLoGin } 40e2841179SLoGin } 41e2841179SLoGin } 42e2841179SLoGin 43b5b571e0SLoGin impl From<ArchIpiKind> for u8 { 44b5b571e0SLoGin fn from(value: ArchIpiKind) -> Self { 45b5b571e0SLoGin match value { 46e2841179SLoGin ArchIpiKind::KickCpu => IPI_NUM_KICK_CPU.data() as u8, 47e2841179SLoGin ArchIpiKind::FlushTLB => IPI_NUM_FLUSH_TLB.data() as u8, 48e2841179SLoGin ArchIpiKind::SpecVector(vec) => (vec.data() & 0xFF) as u8, 49aa0367d6SLoGin } 50aa0367d6SLoGin } 51aa0367d6SLoGin } 52aa0367d6SLoGin 53aa0367d6SLoGin /// IPI投递目标 54aa0367d6SLoGin #[derive(Debug, Copy, Clone, Eq, PartialEq)] 55aa0367d6SLoGin pub enum ArchIpiTarget { 56aa0367d6SLoGin /// 当前CPU 57aa0367d6SLoGin Current, 58aa0367d6SLoGin /// 所有CPU 59aa0367d6SLoGin All, 60aa0367d6SLoGin /// 除了当前CPU以外的所有CPU 61aa0367d6SLoGin Other, 62aa0367d6SLoGin /// 指定的CPU 6370a4e555SLoGin Specified(x86::apic::ApicId), 64aa0367d6SLoGin } 65aa0367d6SLoGin 66aa0367d6SLoGin impl From<IpiTarget> for ArchIpiTarget { 67aa0367d6SLoGin fn from(target: IpiTarget) -> Self { 68aa0367d6SLoGin match target { 69aa0367d6SLoGin IpiTarget::Current => ArchIpiTarget::Current, 70aa0367d6SLoGin IpiTarget::All => ArchIpiTarget::All, 71aa0367d6SLoGin IpiTarget::Other => ArchIpiTarget::Other, 7270a4e555SLoGin IpiTarget::Specified(cpu_id) => { 73e2841179SLoGin ArchIpiTarget::Specified(Self::cpu_id_to_apic_id(cpu_id)) 7470a4e555SLoGin } 7570a4e555SLoGin } 7670a4e555SLoGin } 7770a4e555SLoGin } 7870a4e555SLoGin 79b5b571e0SLoGin impl From<ArchIpiTarget> for ApicId { 80b5b571e0SLoGin fn from(val: ArchIpiTarget) -> Self { 81b5b571e0SLoGin if let ArchIpiTarget::Specified(id) = val { 8270a4e555SLoGin return id; 83b5b571e0SLoGin } else if CurrentApic.x2apic_enabled() { 8470a4e555SLoGin return x86::apic::ApicId::X2Apic(0); 8570a4e555SLoGin } else { 8670a4e555SLoGin return x86::apic::ApicId::XApic(0); 8770a4e555SLoGin } 88aa0367d6SLoGin } 89aa0367d6SLoGin } 90aa0367d6SLoGin 91aa0367d6SLoGin impl ArchIpiTarget { 92f2022a8aSLoGin #[allow(dead_code)] 93aa0367d6SLoGin pub fn shorthand(&self) -> u8 { 94aa0367d6SLoGin match self { 95aa0367d6SLoGin ArchIpiTarget::Specified(_) => 0, 96aa0367d6SLoGin ArchIpiTarget::Current => 1, 97aa0367d6SLoGin ArchIpiTarget::All => 2, 98aa0367d6SLoGin ArchIpiTarget::Other => 3, 99aa0367d6SLoGin } 100aa0367d6SLoGin } 10170a4e555SLoGin 10270a4e555SLoGin #[inline(always)] 103e2841179SLoGin fn cpu_id_to_apic_id(cpu_id: ProcessorId) -> x86::apic::ApicId { 10470a4e555SLoGin if CurrentApic.x2apic_enabled() { 105b5b571e0SLoGin x86::apic::ApicId::X2Apic(cpu_id.data()) 10670a4e555SLoGin } else { 107e2841179SLoGin x86::apic::ApicId::XApic(cpu_id.data() as u8) 10870a4e555SLoGin } 10970a4e555SLoGin } 110aa0367d6SLoGin } 111aa0367d6SLoGin 112b5b571e0SLoGin impl From<ArchIpiTarget> for x86::apic::DestinationShorthand { 113b5b571e0SLoGin fn from(val: ArchIpiTarget) -> Self { 114b5b571e0SLoGin match val { 115aa0367d6SLoGin ArchIpiTarget::Specified(_) => x86::apic::DestinationShorthand::NoShorthand, 116aa0367d6SLoGin ArchIpiTarget::Current => x86::apic::DestinationShorthand::Myself, 117aa0367d6SLoGin ArchIpiTarget::All => x86::apic::DestinationShorthand::AllIncludingSelf, 118aa0367d6SLoGin ArchIpiTarget::Other => x86::apic::DestinationShorthand::AllExcludingSelf, 119aa0367d6SLoGin } 120aa0367d6SLoGin } 121aa0367d6SLoGin } 122aa0367d6SLoGin 123aa0367d6SLoGin #[inline(always)] 124aa0367d6SLoGin pub fn send_ipi(kind: IpiKind, target: IpiTarget) { 125aa0367d6SLoGin // kdebug!("send_ipi: {:?} {:?}", kind, target); 126aa0367d6SLoGin 127e2841179SLoGin let ipi_vec = ArchIpiKind::from(kind).into(); 128aa0367d6SLoGin let target = ArchIpiTarget::from(target); 129aa0367d6SLoGin let shorthand: x86::apic::DestinationShorthand = target.into(); 130aa0367d6SLoGin let destination: x86::apic::ApicId = target.into(); 13170a4e555SLoGin let icr = if CurrentApic.x2apic_enabled() { 132aa0367d6SLoGin // kdebug!("send_ipi: x2apic"); 13370a4e555SLoGin x86::apic::Icr::for_x2apic( 134aa0367d6SLoGin ipi_vec, 135aa0367d6SLoGin destination, 136aa0367d6SLoGin shorthand, 137aa0367d6SLoGin x86::apic::DeliveryMode::Fixed, 138aa0367d6SLoGin x86::apic::DestinationMode::Physical, 139aa0367d6SLoGin x86::apic::DeliveryStatus::Idle, 140aa0367d6SLoGin x86::apic::Level::Assert, 141aa0367d6SLoGin x86::apic::TriggerMode::Edge, 14270a4e555SLoGin ) 143aa0367d6SLoGin } else { 144aa0367d6SLoGin // kdebug!("send_ipi: xapic"); 14570a4e555SLoGin x86::apic::Icr::for_xapic( 146aa0367d6SLoGin ipi_vec, 147aa0367d6SLoGin destination, 148aa0367d6SLoGin shorthand, 149aa0367d6SLoGin x86::apic::DeliveryMode::Fixed, 150aa0367d6SLoGin x86::apic::DestinationMode::Physical, 151aa0367d6SLoGin x86::apic::DeliveryStatus::Idle, 152aa0367d6SLoGin x86::apic::Level::Assert, 153aa0367d6SLoGin x86::apic::TriggerMode::Edge, 15470a4e555SLoGin ) 15570a4e555SLoGin }; 156aa0367d6SLoGin 15770a4e555SLoGin CurrentApic.write_icr(icr); 158aa0367d6SLoGin } 15970a4e555SLoGin 16070a4e555SLoGin /// 发送smp初始化IPI 1618cb2e9b3SLoGin pub fn ipi_send_smp_init() { 16270a4e555SLoGin let target = ArchIpiTarget::Other; 16370a4e555SLoGin let icr = if CurrentApic.x2apic_enabled() { 16470a4e555SLoGin x86::apic::Icr::for_x2apic( 16570a4e555SLoGin 0, 16670a4e555SLoGin target.into(), 16770a4e555SLoGin x86::apic::DestinationShorthand::AllExcludingSelf, 16870a4e555SLoGin x86::apic::DeliveryMode::Init, 16970a4e555SLoGin x86::apic::DestinationMode::Physical, 17070a4e555SLoGin x86::apic::DeliveryStatus::Idle, 17170a4e555SLoGin x86::apic::Level::Deassert, 17270a4e555SLoGin x86::apic::TriggerMode::Edge, 17370a4e555SLoGin ) 17470a4e555SLoGin } else { 17570a4e555SLoGin x86::apic::Icr::for_xapic( 17670a4e555SLoGin 0, 17770a4e555SLoGin target.into(), 17870a4e555SLoGin x86::apic::DestinationShorthand::AllExcludingSelf, 17970a4e555SLoGin x86::apic::DeliveryMode::Init, 18070a4e555SLoGin x86::apic::DestinationMode::Physical, 18170a4e555SLoGin x86::apic::DeliveryStatus::Idle, 18270a4e555SLoGin x86::apic::Level::Deassert, 18370a4e555SLoGin x86::apic::TriggerMode::Edge, 18470a4e555SLoGin ) 18570a4e555SLoGin }; 18670a4e555SLoGin CurrentApic.write_icr(icr); 187aa0367d6SLoGin } 18870a4e555SLoGin 18970a4e555SLoGin /// 发送smp启动IPI 19070a4e555SLoGin /// 19170a4e555SLoGin /// ## 参数 19270a4e555SLoGin /// 19370a4e555SLoGin /// * `target_cpu` - 目标CPU 194e2841179SLoGin pub fn ipi_send_smp_startup(target_cpu: ProcessorId) -> Result<(), SystemError> { 195e2841179SLoGin if target_cpu.data() as usize >= SMP_BOOT_DATA.cpu_count() { 19670a4e555SLoGin return Err(SystemError::EINVAL); 19770a4e555SLoGin } 198e2841179SLoGin let target: ArchIpiTarget = IpiTarget::Specified(target_cpu).into(); 19970a4e555SLoGin 20070a4e555SLoGin let icr = if CurrentApic.x2apic_enabled() { 20170a4e555SLoGin x86::apic::Icr::for_x2apic( 20270a4e555SLoGin 0x20, 20370a4e555SLoGin target.into(), 20470a4e555SLoGin x86::apic::DestinationShorthand::NoShorthand, 20570a4e555SLoGin x86::apic::DeliveryMode::StartUp, 20670a4e555SLoGin x86::apic::DestinationMode::Physical, 20770a4e555SLoGin x86::apic::DeliveryStatus::Idle, 20870a4e555SLoGin x86::apic::Level::Deassert, 20970a4e555SLoGin x86::apic::TriggerMode::Edge, 21070a4e555SLoGin ) 21170a4e555SLoGin } else { 21270a4e555SLoGin x86::apic::Icr::for_xapic( 21370a4e555SLoGin 0x20, 21470a4e555SLoGin target.into(), 21570a4e555SLoGin x86::apic::DestinationShorthand::NoShorthand, 21670a4e555SLoGin x86::apic::DeliveryMode::StartUp, 21770a4e555SLoGin x86::apic::DestinationMode::Physical, 21870a4e555SLoGin x86::apic::DeliveryStatus::Idle, 21970a4e555SLoGin x86::apic::Level::Deassert, 22070a4e555SLoGin x86::apic::TriggerMode::Edge, 22170a4e555SLoGin ) 22270a4e555SLoGin }; 22370a4e555SLoGin 22470a4e555SLoGin CurrentApic.write_icr(icr); 22570a4e555SLoGin return Ok(()); 226aa0367d6SLoGin } 227e2841179SLoGin 228e2841179SLoGin /// 初始化IPI处理函数 229e2841179SLoGin pub fn arch_ipi_handler_init() { 230e2841179SLoGin do_init_irq_handler(IPI_NUM_KICK_CPU); 231e2841179SLoGin do_init_irq_handler(IPI_NUM_FLUSH_TLB); 232e2841179SLoGin } 233e2841179SLoGin 234e2841179SLoGin fn do_init_irq_handler(irq: IrqNumber) { 235e2841179SLoGin let desc = irq_desc_manager().lookup(irq).unwrap(); 236e2841179SLoGin let irq_data: Arc<IrqData> = desc.irq_data(); 237e2841179SLoGin let mut chip_info_guard = irq_data.chip_info_write_irqsave(); 238e2841179SLoGin chip_info_guard.set_chip(Some(local_apic_chip().clone())); 239e2841179SLoGin 240e2841179SLoGin desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty()); 241e2841179SLoGin drop(chip_info_guard); 242e2841179SLoGin desc.set_handler(&X86_64IpiIrqFlowHandler); 243e2841179SLoGin } 244e2841179SLoGin 245e2841179SLoGin #[derive(Debug)] 246e2841179SLoGin struct X86_64IpiIrqFlowHandler; 247e2841179SLoGin 248e2841179SLoGin impl IrqFlowHandler for X86_64IpiIrqFlowHandler { 249e2841179SLoGin fn handle(&self, irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) { 250e2841179SLoGin let irq = irq_desc.irq_data().irq(); 251e2841179SLoGin match irq { 252e2841179SLoGin IPI_NUM_KICK_CPU => { 253e2841179SLoGin KickCpuIpiHandler.handle(irq, None, None).ok(); 254e2841179SLoGin } 255e2841179SLoGin IPI_NUM_FLUSH_TLB => { 256e2841179SLoGin FlushTLBIpiHandler.handle(irq, None, None).ok(); 257*f0c87a89SGnoCiYeH CurrentApic.send_eoi(); 258e2841179SLoGin } 259e2841179SLoGin _ => { 260e2841179SLoGin kerror!("Unknown IPI: {}", irq.data()); 261e2841179SLoGin CurrentApic.send_eoi(); 262e2841179SLoGin } 263e2841179SLoGin } 264*f0c87a89SGnoCiYeH } 265*f0c87a89SGnoCiYeH } 266