1 use crate::exception::ipi::{IpiKind, IpiTarget}; 2 3 extern "C" { 4 pub fn apic_write_icr(value: u64); 5 pub fn apic_x2apic_enabled() -> bool; 6 } 7 8 /// IPI的种类(架构相关,指定了向量号) 9 #[derive(Debug, Copy, Clone, Eq, PartialEq)] 10 #[repr(u8)] 11 pub enum ArchIpiKind { 12 KickCpu = 200, 13 FlushTLB = 201, 14 } 15 16 impl From<IpiKind> for ArchIpiKind { 17 fn from(kind: IpiKind) -> Self { 18 match kind { 19 IpiKind::KickCpu => ArchIpiKind::KickCpu, 20 IpiKind::FlushTLB => ArchIpiKind::FlushTLB, 21 } 22 } 23 } 24 25 /// IPI投递目标 26 #[derive(Debug, Copy, Clone, Eq, PartialEq)] 27 pub enum ArchIpiTarget { 28 /// 当前CPU 29 Current, 30 /// 所有CPU 31 All, 32 /// 除了当前CPU以外的所有CPU 33 Other, 34 /// 指定的CPU 35 Specified(usize), 36 } 37 38 impl From<IpiTarget> for ArchIpiTarget { 39 fn from(target: IpiTarget) -> Self { 40 match target { 41 IpiTarget::Current => ArchIpiTarget::Current, 42 IpiTarget::All => ArchIpiTarget::All, 43 IpiTarget::Other => ArchIpiTarget::Other, 44 IpiTarget::Specified(cpu_id) => ArchIpiTarget::Specified(cpu_id), 45 } 46 } 47 } 48 49 impl ArchIpiTarget { 50 pub fn shorthand(&self) -> u8 { 51 match self { 52 ArchIpiTarget::Specified(_) => 0, 53 ArchIpiTarget::Current => 1, 54 ArchIpiTarget::All => 2, 55 ArchIpiTarget::Other => 3, 56 } 57 } 58 } 59 60 impl Into<x86::apic::DestinationShorthand> for ArchIpiTarget { 61 fn into(self) -> x86::apic::DestinationShorthand { 62 match self { 63 ArchIpiTarget::Specified(_) => x86::apic::DestinationShorthand::NoShorthand, 64 ArchIpiTarget::Current => x86::apic::DestinationShorthand::Myself, 65 ArchIpiTarget::All => x86::apic::DestinationShorthand::AllIncludingSelf, 66 ArchIpiTarget::Other => x86::apic::DestinationShorthand::AllExcludingSelf, 67 } 68 } 69 } 70 71 impl Into<x86::apic::ApicId> for ArchIpiTarget { 72 fn into(self) -> x86::apic::ApicId { 73 let id = match self { 74 ArchIpiTarget::Specified(cpu_id) => cpu_id, 75 _ => 0, 76 }; 77 78 if unsafe { apic_x2apic_enabled() } { 79 return x86::apic::ApicId::X2Apic(id as u32); 80 } else { 81 return x86::apic::ApicId::XApic(id as u8); 82 } 83 } 84 } 85 86 #[inline(always)] 87 pub fn send_ipi(kind: IpiKind, target: IpiTarget) { 88 // kdebug!("send_ipi: {:?} {:?}", kind, target); 89 90 let ipi_vec = ArchIpiKind::from(kind) as u8; 91 let target = ArchIpiTarget::from(target); 92 let shorthand: x86::apic::DestinationShorthand = target.into(); 93 let destination: x86::apic::ApicId = target.into(); 94 if unsafe { apic_x2apic_enabled() } { 95 // kdebug!("send_ipi: x2apic"); 96 let icr = x86::apic::Icr::for_x2apic( 97 ipi_vec, 98 destination, 99 shorthand, 100 x86::apic::DeliveryMode::Fixed, 101 x86::apic::DestinationMode::Physical, 102 x86::apic::DeliveryStatus::Idle, 103 x86::apic::Level::Assert, 104 x86::apic::TriggerMode::Edge, 105 ); 106 107 unsafe { 108 apic_write_icr(((icr.upper() as u64) << 32) | icr.lower() as u64); 109 } 110 } else { 111 // kdebug!("send_ipi: xapic"); 112 let icr = x86::apic::Icr::for_xapic( 113 ipi_vec, 114 destination, 115 shorthand, 116 x86::apic::DeliveryMode::Fixed, 117 x86::apic::DestinationMode::Physical, 118 x86::apic::DeliveryStatus::Idle, 119 x86::apic::Level::Assert, 120 x86::apic::TriggerMode::Edge, 121 ); 122 123 unsafe { 124 apic_write_icr(((icr.upper() as u64) << 32) | icr.lower() as u64); 125 } 126 } 127 } 128