Ensure that APIC ID is uses for all IPIs, enable multi_core feature

This commit is contained in:
Jeremy Soller
2025-08-03 20:53:58 -06:00
parent b4f566dab2
commit 5d06ad4e6a
10 changed files with 100 additions and 86 deletions
+8 -8
View File
@@ -15,12 +15,12 @@ static TRAMPOLINE_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/trampo
pub(super) fn init(madt: Madt) {
let local_apic = unsafe { the_local_apic() };
let me = local_apic.id() as u8;
let me = local_apic.id();
if local_apic.x2 {
println!(" X2APIC {}", me);
println!(" X2APIC {}", me.get());
} else {
println!(" XAPIC {}: {:>08X}", me, local_apic.address);
println!(" XAPIC {}: {:>08X}", me.get(), local_apic.address);
}
if cfg!(feature = "multi_core") {
@@ -53,7 +53,7 @@ pub(super) fn init(madt: Madt) {
println!(" {:x?}", madt_entry);
match madt_entry {
MadtEntry::LocalApic(ap_local_apic) => {
if ap_local_apic.id == me {
if u32::from(ap_local_apic.id) == me.get() {
println!(" This is my local APIC");
} else {
if ap_local_apic.flags & 1 == 1 {
@@ -98,9 +98,9 @@ pub(super) fn init(madt: Madt) {
{
let mut icr = 0x4500;
if local_apic.x2 {
icr |= (ap_local_apic.id as u64) << 32;
icr |= u64::from(ap_local_apic.id) << 32;
} else {
icr |= (ap_local_apic.id as u64) << 56;
icr |= u64::from(ap_local_apic.id) << 56;
}
print!(" IPI...");
local_apic.set_icr(icr);
@@ -113,9 +113,9 @@ pub(super) fn init(madt: Madt) {
let mut icr = 0x4600 | ap_segment as u64;
if local_apic.x2 {
icr |= (ap_local_apic.id as u64) << 32;
icr |= u64::from(ap_local_apic.id) << 32;
} else {
icr |= (ap_local_apic.id as u64) << 56;
icr |= u64::from(ap_local_apic.id) << 56;
}
print!(" SIPI...");
+2 -2
View File
@@ -21,8 +21,8 @@ pub fn ipi(_kind: IpiKind, _target: IpiTarget) {}
#[cfg(not(feature = "multi_core"))]
#[inline(always)]
pub fn ipi_single(_kind: IpiKind, _target: crate::cpu_set::LogicalCpuId) {}
pub fn ipi_single(_kind: IpiKind, _target: crate::percpu::PercpuBlock) {}
#[cfg(feature = "multi_core")]
#[inline(always)]
pub fn ipi_single(_kind: IpiKind, _target: crate::cpu_set::LogicalCpuId) {}
pub fn ipi_single(_kind: IpiKind, _target: crate::percpu::PercpuBlock) {}
+2 -2
View File
@@ -25,8 +25,8 @@ pub fn ipi(_kind: IpiKind, _target: IpiTarget) {}
#[cfg(not(feature = "multi_core"))]
#[inline(always)]
pub fn ipi_single(_kind: IpiKind, _target: crate::cpu_set::LogicalCpuId) {}
pub fn ipi_single(_kind: IpiKind, _target: crate::percpu::PercpuBlock) {}
#[cfg(feature = "multi_core")]
#[inline(always)]
pub fn ipi_single(_kind: IpiKind, _target: crate::cpu_set::LogicalCpuId) {}
pub fn ipi_single(_kind: IpiKind, _target: crate::percpu::PercpuBlock) {}
+5 -4
View File
@@ -12,7 +12,7 @@ use crate::{
paging::{entry::EntryFlags, Page, PageFlags, PhysicalAddress},
};
use super::pic;
use super::{local_apic::ApicId, pic};
use crate::arch::cpuid::cpuid;
#[cfg(target_arch = "x86_64")]
use {crate::memory::RmmA, rmm::Arch};
@@ -112,6 +112,7 @@ impl IoApic {
guard.write_ioredtbl(idx, reg);
}
}
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
pub enum ApicTriggerMode {
@@ -145,7 +146,7 @@ pub enum DeliveryMode {
#[derive(Clone, Copy, Debug)]
pub struct MapInfo {
pub dest: u8,
pub dest: ApicId,
pub mask: bool,
pub trigger_mode: ApicTriggerMode,
pub polarity: ApicPolarity,
@@ -161,7 +162,7 @@ impl MapInfo {
// TODO: Check for reserved fields.
(u64::from(self.dest) << 56)
(u64::from(self.dest.get()) << 56)
| (u64::from(self.mask) << 16)
| ((self.trigger_mode as u64) << 15)
| ((self.polarity as u64) << 13)
@@ -308,7 +309,7 @@ pub unsafe fn handle_src_override(src_override: &'static MadtIntSrcOverride) {
#[allow(dead_code)]
pub unsafe fn init(active_table: &mut KernelMapper) {
let bsp_apic_id = cpuid().get_feature_info().unwrap().initial_local_apic_id(); // TODO: remove unwraps
let bsp_apic_id = ApicId::new(u32::from(cpuid().get_feature_info().unwrap().initial_local_apic_id())); // TODO: remove unwraps
// search the madt for all IOAPICs.
#[cfg(feature = "acpi")]
+27 -14
View File
@@ -7,10 +7,24 @@ use x86::msr::*;
use crate::{
ipi::IpiKind,
paging::{PageFlags, PhysicalAddress},
percpu::PercpuBlock,
};
use crate::{arch::cpuid::cpuid, memory::KernelMapper};
#[derive(Clone, Copy, Debug)]
pub struct ApicId(u32);
impl ApicId {
pub fn new(inner: u32) -> Self {
Self(inner)
}
pub fn get(&self) -> u32 {
self.0
}
}
static LOCAL_APIC: SyncUnsafeCell<LocalApic> = SyncUnsafeCell::new(LocalApic {
address: 0,
x2: false,
@@ -79,6 +93,10 @@ impl LocalApic {
}
self.setup_error_int();
//self.setup_timer();
PercpuBlock::current()
.misc_arch_info
.apic_id_opt.set(Some(self.id()));
}
unsafe fn read(&self, reg: u32) -> u32 {
@@ -89,12 +107,12 @@ impl LocalApic {
write_volatile((self.address + reg as usize) as *mut u32, value);
}
pub fn id(&self) -> u32 {
if self.x2 {
pub fn id(&self) -> ApicId {
ApicId::new(if self.x2 {
unsafe { rdmsr(IA32_X2APIC_APICID) as u32 }
} else {
unsafe { self.read(0x20) }
}
})
}
pub fn version(&self) -> u32 {
@@ -133,18 +151,13 @@ impl LocalApic {
}
}
pub fn ipi(&mut self, apic_id: u32, kind: IpiKind) {
let mut icr = 0x40 | kind as u64;
if self.x2 {
icr |= u64::from(apic_id) << 32;
} else {
icr |= u64::from(apic_id) << 56;
}
self.set_icr(icr);
}
pub fn ipi_nmi(&mut self, apic_id: u32) {
pub fn ipi(&mut self, apic_id: ApicId, kind: IpiKind) {
let shift = if self.x2 { 32 } else { 56 };
self.set_icr((u64::from(apic_id) << shift) | (1 << 14) | (0b100 << 8));
self.set_icr((u64::from(apic_id.get()) << shift) | (1 << 6) | kind as u64);
}
pub fn ipi_nmi(&mut self, apic_id: ApicId) {
let shift = if self.x2 { 32 } else { 56 };
self.set_icr((u64::from(apic_id.get()) << shift) | (1 << 14) | (0b100 << 8));
}
pub unsafe fn eoi(&mut self) {
+2
View File
@@ -1,3 +1,4 @@
use core::cell::Cell;
use crate::memory::KernelMapper;
pub mod cpu;
@@ -75,6 +76,7 @@ pub unsafe fn init_ap() {
#[derive(Default)]
pub struct ArchPercpuMisc {
pub apic_id_opt: Cell<Option<local_apic::ApicId>>,
#[cfg(feature = "x86_kvm_pv")]
pub tsc_info: tsc::TscPercpu,
}
+6 -6
View File
@@ -37,19 +37,19 @@ pub fn ipi(kind: IpiKind, target: IpiTarget) {
let icr = (target as u64) << 18 | 1 << 14 | (kind as u64);
unsafe { the_local_apic().set_icr(icr) };
}
use crate::cpu_set::LogicalCpuId;
#[cfg(feature = "multi_core")]
#[inline(always)]
pub fn ipi_single(kind: IpiKind, target: LogicalCpuId) {
pub fn ipi_single(kind: IpiKind, target: &crate::percpu::PercpuBlock) {
use crate::device::local_apic::the_local_apic;
unsafe {
// TODO: Distinguish between logical and physical CPU IDs
the_local_apic().ipi(target.get(), kind);
if let Some(apic_id) = target.misc_arch_info.apic_id_opt.get() {
unsafe {
the_local_apic().ipi(apic_id, kind);
}
}
}
#[cfg(not(feature = "multi_core"))]
#[inline(always)]
pub fn ipi_single(_kind: IpiKind, _target: LogicalCpuId) {}
pub fn ipi_single(_kind: IpiKind, _target: &crate::percpu::PercpuBlock) {}
+1 -1
View File
@@ -106,7 +106,7 @@ pub fn shootdown_tlb_ipi(target: Option<LogicalCpuId>) {
}
}
crate::ipi::ipi_single(crate::ipi::IpiKind::Tlb, target);
crate::ipi::ipi_single(crate::ipi::IpiKind::Tlb, &percpublock);
} else {
for id in 0..crate::cpu_count() {
// TODO: Optimize: use global counter and percpu ack counters, send IPI using