From b40daef15cf8983278d12613f3f449f43b3e1415 Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Sun, 17 May 2026 14:57:18 +0300 Subject: [PATCH] chore: remove kernel patch artifacts --- .../source/src/acpi/madt/arch/x86.rs.before | 591 ------------------ .../source/src/acpi/madt/arch/x86.rs.orig | 160 ----- .../source/src/acpi/madt/arch/x86.rs.rej | 41 -- .../x86_shared/device/local_apic.rs.before | 312 --------- .../arch/x86_shared/device/local_apic.rs.rej | 14 - 5 files changed, 1118 deletions(-) delete mode 100644 recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.before delete mode 100644 recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.orig delete mode 100644 recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.rej delete mode 100644 recipes/core/kernel/source/src/arch/x86_shared/device/local_apic.rs.before delete mode 100644 recipes/core/kernel/source/src/arch/x86_shared/device/local_apic.rs.rej diff --git a/recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.before b/recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.before deleted file mode 100644 index a4d5a98b23..0000000000 --- a/recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.before +++ /dev/null @@ -1,591 +0,0 @@ -use core::{ - hint, - sync::atomic::{AtomicU8, Ordering}, -}; - -use x86::time::rdtsc; - -use crate::{ - arch::{ - device::local_apic::the_local_apic, - start::{kstart_ap, KernelArgsAp}, - }, - cpu_set::LogicalCpuId, - memory::{ - allocate_p2frame, map_device_memory, Frame, KernelMapper, Page, PageFlags, - PhysicalAddress, RmmA, RmmArch, VirtualAddress, PAGE_SIZE, - }, - startup::AP_READY, -}; - -use super::{Madt, MadtEntry}; - -use alloc::collections::BTreeSet; -use alloc::vec::Vec; - -/// Maximum number of APIC→CPU mappings we track for NUMA topology. -const MAX_APIC_MAPPINGS: usize = 256; - -struct ApicMapping { - apic_id: u32, - cpu_id: LogicalCpuId, -} - -const UNINIT_MAPPING: ApicMapping = ApicMapping { apic_id: u32::MAX, cpu_id: LogicalCpuId::new(0) }; - -static mut APIC_MAPPINGS: [ApicMapping; MAX_APIC_MAPPINGS] = [UNINIT_MAPPING; MAX_APIC_MAPPINGS]; -static mut APIC_MAPPING_COUNT: usize = 0; - -unsafe fn record_apic_mapping(apic_id: u32, cpu_id: LogicalCpuId) { - let count = APIC_MAPPING_COUNT; - if count < MAX_APIC_MAPPINGS { - APIC_MAPPINGS[count] = ApicMapping { apic_id, cpu_id }; - APIC_MAPPING_COUNT = count + 1; - } -} - -const AP_SPIN_LIMIT: u32 = 1_000_000; -const TRAMPOLINE: usize = 0x8000; -static TRAMPOLINE_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/trampoline")); - -/// Estimate TSC frequency in MHz from CPUID. -/// -/// Tries CPUID leaf 0x16 (Processor Frequency Information) first, -/// then CPUID leaf 0x15 (TSC/Core Crystal Clock Ratio). -/// Returns None if frequency cannot be determined. -fn tsc_freq_mhz_cpuid() -> Option { - let max_leaf = unsafe { core::arch::x86_64::__cpuid(0).eax as u32 }; - - // CPUID leaf 0x16: EAX = Core Base Frequency in MHz (Intel) - if max_leaf >= 0x16 { - let mhz = unsafe { core::arch::x86_64::__cpuid(0x16) }.eax as u64; - if mhz > 0 { - return Some(mhz); - } - } - - // CPUID leaf 0x15: EAX = denominator, EBX = numerator, ECX = crystal Hz - if max_leaf >= 0x15 { - let res = unsafe { core::arch::x86_64::__cpuid(0x15) }; - let denom = res.eax as u64; - let numer = res.ebx as u64; - let crystal_hz = res.ecx as u64; - if denom > 0 && numer > 0 && crystal_hz > 0 { - // TSC freq = crystal_hz * numer / denom - let tsc_hz = crystal_hz * numer / denom; - return Some(tsc_hz / 1_000_000); // Hz → MHz - } - } - - None -} - -/// Early-boot microsecond delay using the Time Stamp Counter. -/// -/// Uses CPUID-based TSC frequency estimation when available. -/// Falls back to a conservative spin loop calibrated for the -/// minimum expected CPU speed (1 GHz). -/// -/// # Safety -/// Must only be called after the BSP TSC is running (always true -/// after CPU reset on x86). -fn early_udelay(us: u64) { - if let Some(mhz) = tsc_freq_mhz_cpuid() { - // TSC-based delay: precise on invariant TSC (all modern x86). - // MHz = cycles per µs. - let target = unsafe { rdtsc() } + us * mhz; - while unsafe { rdtsc() } < target { - hint::spin_loop(); - } - } else { - // Fallback: conservative spin loop. - // spin_loop() (PAUSE) is ~40 cycles on modern Intel, ~1 on AMD. - // At 1 GHz minimum: 1000 cycles/µs ÷ 40 cycles/iter = 25 iters/µs. - // Use 50 iters/µs for safety margin on slower/variable CPUs. - let iters = us.saturating_mul(50); - for _ in 0..iters { - hint::spin_loop(); - } - } -} - -fn current_x2apic_processor_uid(madt: &Madt, apic_id: u32) -> Option { - madt.iter().find_map(|entry| match entry { - MadtEntry::LocalX2Apic(x2apic) if x2apic.x2apic_id == apic_id => Some(x2apic.processor_uid), - _ => None, - }) -} - -fn apply_lapic_address_override( - local_apic: &mut crate::arch::device::local_apic::LocalApic, - address: u64, -) { - if local_apic.x2 || address == 0 { - return; - } - - let Ok(physaddr) = usize::try_from(address) else { - warn!( - "Ignoring LAPIC address override {:#x}: does not fit host usize", - address - ); - return; - }; - - let mapped = unsafe { map_device_memory(PhysicalAddress::new(physaddr), 4096) }.data(); - local_apic.address = mapped; - debug!("Applied LAPIC address override: {:#x}", address); -} - -pub(super) fn init(madt: Madt) { - let local_apic = unsafe { the_local_apic() }; - let me = local_apic.id(); - - if local_apic.x2 { - debug!(" X2APIC {}", me.get()); - } else { - debug!(" XAPIC {}: {:>08X}", me.get(), local_apic.address); - } - - if cfg!(not(feature = "multi_core")) { - unsafe { - record_apic_mapping(me.get(), LogicalCpuId::new(0)); - } - crate::numa::init_default(); - return; - } - - // Map trampoline - let trampoline_frame = Frame::containing(PhysicalAddress::new(TRAMPOLINE)); - let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); - let (result, page_table_physaddr) = unsafe { - //TODO: do not have writable and executable! - let mut mapper = KernelMapper::lock_rw(); - - let result = match mapper.map_phys( - trampoline_page.start_address(), - trampoline_frame.base(), - PageFlags::new().execute(true).write(true), - ) { - Some(result) => result, - None => { - println!("KERNEL AP: failed to map trampoline page, AP bring-up disabled"); - return; - } - }; - - (result, mapper.table().phys().data()) - }; - result.flush(); - - // Write trampoline, make sure TRAMPOLINE page is free for use - for (i, val) in TRAMPOLINE_DATA.iter().enumerate() { - unsafe { - (*((TRAMPOLINE as *mut u8).add(i) as *const AtomicU8)).store(*val, Ordering::SeqCst); - } - } - - unsafe { - let preliminary_cpu_count = madt - .iter() - .filter(|entry| match entry { - MadtEntry::LocalApic(local) => u32::from(local.id) == me.get() || local.flags & 1 == 1, - MadtEntry::LocalX2Apic(local) => local.x2apic_id == me.get() || local.flags & 1 == 1, - _ => false, - }) - .count(); - crate::profiling::allocate(preliminary_cpu_count as u32); - } - - // Firmware bug detection: check for duplicate APIC IDs in MADT. - // Some firmware (especially on early BIOS/UEFI) may list the same - // processor multiple times. Keep first occurrence, warn on duplicates. - let mut seen_apic_ids: BTreeSet = BTreeSet::new(); - { - let _ = seen_apic_ids.insert(me.get()); // BSP - for entry in madt.iter() { - match entry { - MadtEntry::LocalApic(local) if local.flags & 1 == 1 => { - let id = u32::from(local.id); - if !seen_apic_ids.insert(id) { - warn!("MADT: duplicate APIC ID {} in LocalApic entry, firmware bug", id); - } - } - MadtEntry::LocalX2Apic(local) if local.flags & 1 == 1 => { - let id = local.x2apic_id; - if !seen_apic_ids.insert(id) { - warn!("MADT: duplicate x2APIC ID {} in LocalX2Apic entry, firmware bug", id); - } - } - _ => {} - } - } - } - - for madt_entry in madt.iter() { - debug!(" {:x?}", madt_entry); - if let MadtEntry::LocalApic(ap_local_apic) = madt_entry { - if u32::from(ap_local_apic.id) == me.get() { - debug!(" This is my local APIC"); - } else if ap_local_apic.flags & 1 == 1 { - // Allocate a stack - let alloc = match allocate_p2frame(4) { - Some(frame) => frame, - None => { - println!("KERNEL AP: CPU {} no memory for stack, skipping", ap_local_apic.id); - continue; - } - }; - let stack_start = RmmA::phys_to_virt(alloc.base()).data(); - let stack_end = stack_start + (PAGE_SIZE << 4); - - // Atomically allocate a CPU ID — fetch_add is SeqCst so that - // all later stores (PercpuBlock, NUMA node) are ordered after. - let cpu_id = LogicalCpuId::new(crate::CPU_COUNT.fetch_add(1, Ordering::SeqCst)); - if cpu_id.get() >= crate::cpu_set::MAX_CPU_COUNT { - println!( - "KERNEL AP: CPU {} exceeds logical CPU limit, skipping", - ap_local_apic.id - ); - continue; - } - - let pcr_ptr = crate::arch::gdt::allocate_and_init_pcr(cpu_id, stack_end); - - let idt_ptr = crate::arch::idt::allocate_and_init_idt(cpu_id); - - let args = KernelArgsAp { - stack_end: stack_end as *mut u8, - cpu_id, - pcr_ptr, - idt_ptr, - }; - - let ap_ready = (TRAMPOLINE + 8) as *mut u64; - let ap_args_ptr = unsafe { ap_ready.add(1) }; - let ap_page_table = unsafe { ap_ready.add(2) }; - let ap_code = unsafe { ap_ready.add(3) }; - - // Set the ap_ready to 0, volatile - unsafe { - ap_ready.write(0); - ap_args_ptr.write(&args as *const _ as u64); - ap_page_table.write(page_table_physaddr as u64); - #[expect(clippy::fn_to_numeric_cast)] - ap_code.write(kstart_ap as u64); - - // Ensure all trampoline writes are visible to the AP before - // it starts executing. asm!("") is only a compiler barrier; - // fence(SeqCst) is a full hardware memory barrier. - core::sync::atomic::fence(Ordering::SeqCst); - }; - AP_READY.store(false, Ordering::SeqCst); - - // Clear APIC Error Status Register before starting AP. - // Intel SDM §8.4.4: ESR should be cleared before sending SIPI. - unsafe { local_apic.esr(); } - - // Send INIT IPI (Assert) - { - // ICR: Delivery Mode=INIT(101), Level=Assert, Trigger=Edge - let mut icr = 0x4500u64; - if local_apic.x2 { - icr |= u64::from(ap_local_apic.id) << 32; - } else { - icr |= u64::from(ap_local_apic.id) << 56; - } - local_apic.set_icr(icr); - } - - // Intel SDM Vol 3A §8.4.4: wait 10ms after INIT deassert - // before sending first SIPI. Modern CPUs may need less, - // but 10ms is the safe specification-compliant value. - early_udelay(10_000); - - // Send START IPI #1 - { - let ap_segment = (TRAMPOLINE >> 12) & 0xFF; - // ICR: Delivery Mode=StartUp(110), Vector=ap_segment - // Note: bit 14 (Level) must be 0 for SIPI per Intel SDM. - let mut icr = 0x0600 | ap_segment as u64; - if local_apic.x2 { - icr |= u64::from(ap_local_apic.id) << 32; - } else { - icr |= u64::from(ap_local_apic.id) << 56; - } - local_apic.set_icr(icr); - } - - // Intel SDM: wait 200µs between SIPIs - early_udelay(200); - - // Send START IPI #2 (recommended for compatibility) - { - let ap_segment = (TRAMPOLINE >> 12) & 0xFF; - let mut icr = 0x0600 | ap_segment as u64; - if local_apic.x2 { - icr |= u64::from(ap_local_apic.id) << 32; - } else { - icr |= u64::from(ap_local_apic.id) << 56; - } - local_apic.set_icr(icr); - } - - // Wait briefly for SIPI to be accepted - early_udelay(200); - - // Check ESR for delivery errors after SIPI sequence. - // Bit 5 = Send Accept Error, Bit 6 = Send Illegal Vector. - let esr_val = unsafe { local_apic.esr() }; - if esr_val != 0 { - println!( - "KERNEL AP: CPU {} SIPI delivery error (ESR={:#x}), continuing", - ap_local_apic.id, esr_val - ); - } - - // Wait for trampoline ready with timeout - let mut trampoline_ready = false; - for _ in 0..AP_SPIN_LIMIT { - if unsafe { (*ap_ready.cast::()).load(Ordering::SeqCst) } != 0 { - trampoline_ready = true; - break; - } - hint::spin_loop(); - } - if !trampoline_ready { - println!("KERNEL AP: CPU {} trampoline timeout, skipping", ap_local_apic.id); - continue; - } - - let mut kernel_ready = false; - for _ in 0..AP_SPIN_LIMIT { - if AP_READY.load(Ordering::SeqCst) { - kernel_ready = true; - break; - } - hint::spin_loop(); - } - if !kernel_ready { - println!("KERNEL AP: CPU {} AP_READY timeout, skipping", ap_local_apic.id); - continue; - } - - // Record APIC→CPU mapping for NUMA topology. - unsafe { - record_apic_mapping(u32::from(ap_local_apic.id), cpu_id); - } - // Set NUMA node from SRAT data. - if let Some(percpu) = crate::percpu::get_for_cpu(cpu_id) { - if let Some(node) = crate::acpi::srat::numa_node_for_apic(u32::from(ap_local_apic.id)) { - percpu.numa_node.set(node); - } - } - - RmmA::invalidate_all(); - } else { - debug!("KERNEL AP: LAPIC CPU {} disabled in MADT, skipping", u32::from(ap_local_apic.id)); - } - } else if let MadtEntry::LocalX2Apic(ap_x2apic) = madt_entry { - let apic_id = ap_x2apic.x2apic_id; - let flags = ap_x2apic.flags; - - if apic_id == me.get() { - debug!(" This is my local x2APIC"); - } else if flags & 1 == 1 { - let alloc = match allocate_p2frame(4) { - Some(frame) => frame, - None => { - println!("KERNEL AP: CPU {} no memory for stack, skipping", apic_id); - continue; - } - }; - let stack_start = RmmA::phys_to_virt(alloc.base()).data(); - let stack_end = stack_start + (PAGE_SIZE << 4); - - // Atomically allocate a CPU ID — fetch_add is SeqCst so that - // all later stores (PercpuBlock, NUMA node) are ordered after. - let cpu_id = LogicalCpuId::new(crate::CPU_COUNT.fetch_add(1, Ordering::SeqCst)); - if cpu_id.get() >= crate::cpu_set::MAX_CPU_COUNT { - println!( - "KERNEL AP: CPU {} exceeds logical CPU limit, skipping", - apic_id - ); - continue; - } - - let pcr_ptr = crate::arch::gdt::allocate_and_init_pcr(cpu_id, stack_end); - let idt_ptr = crate::arch::idt::allocate_and_init_idt(cpu_id); - - let args = KernelArgsAp { - stack_end: stack_end as *mut u8, - cpu_id, - pcr_ptr, - idt_ptr, - }; - - let ap_ready = (TRAMPOLINE + 8) as *mut u64; - let ap_args_ptr = unsafe { ap_ready.add(1) }; - let ap_page_table = unsafe { ap_ready.add(2) }; - let ap_code = unsafe { ap_ready.add(3) }; - - unsafe { - ap_ready.write(0); - ap_args_ptr.write(&args as *const _ as u64); - ap_page_table.write(page_table_physaddr as u64); - #[expect(clippy::fn_to_numeric_cast)] - ap_code.write(kstart_ap as u64); - // Ensure all trampoline writes are visible to the AP. - core::sync::atomic::fence(Ordering::SeqCst); - } - AP_READY.store(false, Ordering::SeqCst); - - // Clear APIC Error Status Register before starting AP. - unsafe { local_apic.esr(); } - - // Send INIT IPI (Assert) - { - let mut icr = 0x4500u64; - if local_apic.x2 { - icr |= u64::from(apic_id) << 32; - } else { - icr |= u64::from(apic_id as u8) << 56; - } - local_apic.set_icr(icr); - } - - // Intel SDM Vol 3A §8.4.4: wait 10ms after INIT - early_udelay(10_000); - - // Send START IPI #1 - { - let ap_segment = (TRAMPOLINE >> 12) & 0xFF; - let mut icr = 0x0600u64 | ap_segment as u64; - if local_apic.x2 { - icr |= u64::from(apic_id) << 32; - } else { - icr |= u64::from(apic_id as u8) << 56; - } - local_apic.set_icr(icr); - } - - // Intel SDM: wait 200µs between SIPIs - early_udelay(200); - - // Send START IPI #2 (recommended for compatibility) - { - let ap_segment = (TRAMPOLINE >> 12) & 0xFF; - let mut icr = 0x0600u64 | ap_segment as u64; - if local_apic.x2 { - icr |= u64::from(apic_id) << 32; - } else { - icr |= u64::from(apic_id as u8) << 56; - } - local_apic.set_icr(icr); - } - - // Wait briefly for SIPI acceptance - early_udelay(200); - - // Check ESR for delivery errors. - let esr_val = unsafe { local_apic.esr() }; - if esr_val != 0 { - println!( - "KERNEL AP: CPU {} SIPI delivery error (ESR={:#x}), continuing", - apic_id, esr_val - ); - } - - let mut trampoline_ready = false; - for _ in 0..AP_SPIN_LIMIT { - if unsafe { (*ap_ready.cast::()).load(Ordering::SeqCst) } != 0 { - trampoline_ready = true; - break; - } - hint::spin_loop(); - } - if !trampoline_ready { - println!("KERNEL AP: CPU {} trampoline timeout, skipping", apic_id); - continue; - } - - let mut kernel_ready = false; - for _ in 0..AP_SPIN_LIMIT { - if AP_READY.load(Ordering::SeqCst) { - kernel_ready = true; - break; - } - hint::spin_loop(); - } - if !kernel_ready { - println!("KERNEL AP: CPU {} AP_READY timeout, skipping", apic_id); - continue; - } - - // Record APIC→CPU mapping for NUMA topology. - unsafe { - record_apic_mapping(apic_id, cpu_id); - } - // Set NUMA node from SRAT data. - if let Some(percpu) = crate::percpu::get_for_cpu(cpu_id) { - if let Some(node) = crate::acpi::srat::numa_node_for_apic(apic_id) { - percpu.numa_node.set(node); - } - } - - RmmA::invalidate_all(); - } else { - debug!("KERNEL AP: x2APIC CPU {} disabled in MADT (flags={:#x}), skipping", apic_id, flags); - } - } else if let MadtEntry::LocalApicNmi(nmi) = madt_entry { - let target_apic = nmi.processor; - if target_apic == 0xFF || target_apic == local_apic.id().get() as u8 { - unsafe { local_apic.set_lvt_nmi(nmi.nmi_pin, nmi.flags) }; - } - } else if let MadtEntry::LocalX2ApicNmi(nmi) = madt_entry { - let current_uid = current_x2apic_processor_uid(&madt, me.get()); - if nmi.processor_uid == u32::MAX || current_uid == Some(nmi.processor_uid) { - unsafe { local_apic.set_lvt_nmi(nmi.nmi_pin, nmi.flags) }; - } - } else if let MadtEntry::LapicAddressOverride(override_entry) = madt_entry { - apply_lapic_address_override(local_apic, override_entry.local_apic_address); - } - } - - // Initialize NUMA topology from APIC→CPU mappings and SRAT. - { - let mappings = unsafe { &APIC_MAPPINGS[..APIC_MAPPING_COUNT] }; - let mappings_ref: Vec<(u32, LogicalCpuId)> = mappings - .iter() - .map(|m| (m.apic_id, m.cpu_id)) - .collect(); - crate::numa::init_from_srat(&mappings_ref); - } - // Set BSP's NUMA node from SRAT. - if let Some(node) = crate::acpi::srat::numa_node_for_apic(me.get()) { - crate::percpu::PercpuBlock::current().numa_node.set(node); - } - - // Log final CPU count vs maximum - let cpu_count = crate::CPU_COUNT.load(Ordering::SeqCst); - info!( - "SMP: {} CPUs online (max {})", - cpu_count, crate::cpu_set::MAX_CPU_COUNT - ); - if cpu_count > crate::cpu_set::MAX_CPU_COUNT * 80 / 100 { - warn!( - "SMP: CPU count approaching MAX_CPU_COUNT limit ({}/{})", - cpu_count, crate::cpu_set::MAX_CPU_COUNT - ); - } - - // Unmap trampoline - if let Some((_frame, _, flush)) = unsafe { - KernelMapper::lock_rw() - .unmap_phys(trampoline_page.start_address()) - } { - flush.flush(); - } else { - println!("KERNEL AP: failed to unmap trampoline page (non-fatal)"); - } -} diff --git a/recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.orig b/recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.orig deleted file mode 100644 index 4dc2388398..0000000000 --- a/recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.orig +++ /dev/null @@ -1,160 +0,0 @@ -use core::{ - hint, - sync::atomic::{AtomicU8, Ordering}, -}; - -use crate::{ - arch::{ - device::local_apic::the_local_apic, - start::{kstart_ap, KernelArgsAp}, - }, - cpu_set::LogicalCpuId, - memory::{ - allocate_p2frame, Frame, KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch, - VirtualAddress, PAGE_SIZE, - }, - startup::AP_READY, -}; - -use super::{Madt, MadtEntry}; - -const TRAMPOLINE: usize = 0x8000; -static TRAMPOLINE_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/trampoline")); - -pub(super) fn init(madt: Madt) { - let local_apic = unsafe { the_local_apic() }; - let me = local_apic.id(); - - if local_apic.x2 { - debug!(" X2APIC {}", me.get()); - } else { - debug!(" XAPIC {}: {:>08X}", me.get(), local_apic.address); - } - - if cfg!(not(feature = "multi_core")) { - return; - } - - // Map trampoline - let trampoline_frame = Frame::containing(PhysicalAddress::new(TRAMPOLINE)); - let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE)); - let (result, page_table_physaddr) = unsafe { - //TODO: do not have writable and executable! - let mut mapper = KernelMapper::lock_rw(); - - let result = mapper - .map_phys( - trampoline_page.start_address(), - trampoline_frame.base(), - PageFlags::new().execute(true).write(true), - ) - .expect("failed to map trampoline"); - - (result, mapper.table().phys().data()) - }; - result.flush(); - - // Write trampoline, make sure TRAMPOLINE page is free for use - for (i, val) in TRAMPOLINE_DATA.iter().enumerate() { - unsafe { - (*((TRAMPOLINE as *mut u8).add(i) as *const AtomicU8)).store(*val, Ordering::SeqCst); - } - } - - unsafe { - let preliminary_cpu_count = madt.iter().filter(|e| matches!(e, MadtEntry::LocalApic(entry) if u32::from(entry.id) == me.get() || entry.flags & 1 == 1)).count(); - crate::profiling::allocate(preliminary_cpu_count as u32); - } - - for madt_entry in madt.iter() { - debug!(" {:x?}", madt_entry); - if let MadtEntry::LocalApic(ap_local_apic) = madt_entry { - if u32::from(ap_local_apic.id) == me.get() { - debug!(" This is my local APIC"); - } else if ap_local_apic.flags & 1 == 1 { - let cpu_id = LogicalCpuId::next(); - - // Allocate a stack - let stack_start = RmmA::phys_to_virt( - allocate_p2frame(4) - .expect("no more frames in acpi stack_start") - .base(), - ) - .data(); - let stack_end = stack_start + (PAGE_SIZE << 4); - - let pcr_ptr = crate::arch::gdt::allocate_and_init_pcr(cpu_id, stack_end); - - let idt_ptr = crate::arch::idt::allocate_and_init_idt(cpu_id); - - let args = KernelArgsAp { - stack_end: stack_end as *mut u8, - cpu_id, - pcr_ptr, - idt_ptr, - }; - - let ap_ready = (TRAMPOLINE + 8) as *mut u64; - let ap_args_ptr = unsafe { ap_ready.add(1) }; - let ap_page_table = unsafe { ap_ready.add(2) }; - let ap_code = unsafe { ap_ready.add(3) }; - - // Set the ap_ready to 0, volatile - unsafe { - ap_ready.write(0); - ap_args_ptr.write(&args as *const _ as u64); - ap_page_table.write(page_table_physaddr as u64); - #[expect(clippy::fn_to_numeric_cast)] - ap_code.write(kstart_ap as u64); - - // TODO: Is this necessary (this fence)? - core::arch::asm!(""); - }; - AP_READY.store(false, Ordering::SeqCst); - - // Send INIT IPI - { - let mut icr = 0x4500; - if local_apic.x2 { - icr |= u64::from(ap_local_apic.id) << 32; - } else { - icr |= u64::from(ap_local_apic.id) << 56; - } - local_apic.set_icr(icr); - } - - // Send START IPI - { - let ap_segment = (TRAMPOLINE >> 12) & 0xFF; - let mut icr = 0x4600 | ap_segment as u64; - - if local_apic.x2 { - icr |= u64::from(ap_local_apic.id) << 32; - } else { - icr |= u64::from(ap_local_apic.id) << 56; - } - - local_apic.set_icr(icr); - } - - // Wait for trampoline ready - while unsafe { (*ap_ready.cast::()).load(Ordering::SeqCst) } == 0 { - hint::spin_loop(); - } - while !AP_READY.load(Ordering::SeqCst) { - hint::spin_loop(); - } - - RmmA::invalidate_all(); - } - } - } - - // Unmap trampoline - let (_frame, _, flush) = unsafe { - KernelMapper::lock_rw() - .unmap_phys(trampoline_page.start_address()) - .expect("failed to unmap trampoline page") - }; - flush.flush(); -} diff --git a/recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.rej b/recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.rej deleted file mode 100644 index d53ad0dcb6..0000000000 --- a/recipes/core/kernel/source/src/acpi/madt/arch/x86.rs.rej +++ /dev/null @@ -1,41 +0,0 @@ ---- src/acpi/madt/arch/x86.rs -+++ src/acpi/madt/arch/x86.rs -@@ -446,11 +446,7 @@ - // Send INIT IPI (Assert) - { - let mut icr = 0x4500u64; -- if local_apic.x2 { -- icr |= u64::from(apic_id) << 32; -- } else { -- icr |= u64::from(apic_id as u8) << 56; -- } -+ icr |= u64::from(apic_id) << 32; - local_apic.set_icr(icr); - } - -@@ -460,11 +456,7 @@ - { - let ap_segment = (TRAMPOLINE >> 12) & 0xFF; - let mut icr = 0x0600u64 | ap_segment as u64; -- if local_apic.x2 { -- icr |= u64::from(apic_id) << 32; -- } else { -- icr |= u64::from(apic_id as u8) << 56; -- } -+ icr |= u64::from(apic_id) << 32; - local_apic.set_icr(icr); - } - -@@ -476,11 +468,7 @@ - { - let ap_segment = (TRAMPOLINE >> 12) & 0xFF; - let mut icr = 0x0600u64 | ap_segment as u64; -- if local_apic.x2 { -- icr |= u64::from(apic_id) << 32; -- } else { -- icr |= u64::from(apic_id as u8) << 56; -- } -+ icr |= u64::from(apic_id) << 32; - local_apic.set_icr(icr); - } - diff --git a/recipes/core/kernel/source/src/arch/x86_shared/device/local_apic.rs.before b/recipes/core/kernel/source/src/arch/x86_shared/device/local_apic.rs.before deleted file mode 100644 index 87c5a31ff3..0000000000 --- a/recipes/core/kernel/source/src/arch/x86_shared/device/local_apic.rs.before +++ /dev/null @@ -1,312 +0,0 @@ -use core::{ - cell::SyncUnsafeCell, - ptr::{read_volatile, write_volatile}, -}; -use x86::msr::*; - -use crate::{ - arch::{cpuid::cpuid, ipi::IpiKind}, - memory::{map_device_memory, PhysicalAddress}, - percpu::PercpuBlock, -}; - -#[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 = SyncUnsafeCell::new(LocalApic { - address: 0, - x2: false, -}); -pub unsafe fn the_local_apic() -> &'static mut LocalApic { - unsafe { &mut *LOCAL_APIC.get() } -} - -pub unsafe fn init() { - unsafe { - the_local_apic().init(); - } -} - -pub unsafe fn init_ap() { - unsafe { - the_local_apic().init_ap(); - } -} - -/// Local APIC -pub struct LocalApic { - pub address: usize, - pub x2: bool, -} - -impl LocalApic { - unsafe fn init(&mut self) { - unsafe { - let physaddr = PhysicalAddress::new(rdmsr(IA32_APIC_BASE) as usize & 0xFFFF_0000); - - self.x2 = cpuid() - .get_feature_info() - .is_some_and(|feature_info| feature_info.has_x2apic()); - - if !self.x2 { - info!("Detected xAPIC at {:#x}", physaddr.data()); - self.address = map_device_memory(physaddr, 4096).data(); - } else { - info!("Detected x2APIC"); - } - - self.init_ap(); - } - } - - unsafe fn init_ap(&mut self) { - unsafe { - if self.x2 { - wrmsr(IA32_APIC_BASE, rdmsr(IA32_APIC_BASE) | (1 << 10)); - wrmsr(IA32_X2APIC_SIVR, 0x100); - } else { - self.write(0xF0, 0x100); - } - 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 { - debug_assert!(!self.x2); - unsafe { read_volatile((self.address + reg as usize) as *const u32) } - } - - unsafe fn write(&mut self, reg: u32, value: u32) { - debug_assert!(!self.x2); - unsafe { - write_volatile((self.address + reg as usize) as *mut u32, value); - } - } - - pub fn id(&self) -> ApicId { - ApicId::new(if self.x2 { - unsafe { rdmsr(IA32_X2APIC_APICID) as u32 } - } else { - unsafe { self.read(0x20) >> 24 } - }) - } - - pub fn version(&self) -> u32 { - if self.x2 { - unsafe { rdmsr(IA32_X2APIC_VERSION) as u32 } - } else { - unsafe { self.read(0x30) } - } - } - - pub fn icr(&self) -> u64 { - if self.x2 { - unsafe { rdmsr(IA32_X2APIC_ICR) } - } else { - unsafe { ((self.read(0x310) as u64) << 32) | self.read(0x300) as u64 } - } - } - - pub fn set_icr(&mut self, value: u64) { - if self.x2 { - unsafe { - const PENDING: u32 = 1 << 12; - while (rdmsr(IA32_X2APIC_ICR) as u32) & PENDING == PENDING { - core::hint::spin_loop(); - } - wrmsr(IA32_X2APIC_ICR, value); - while (rdmsr(IA32_X2APIC_ICR) as u32) & PENDING == PENDING { - core::hint::spin_loop(); - } - } - } else { - unsafe { - const PENDING: u32 = 1 << 12; - while self.read(0x300) & PENDING == PENDING { - core::hint::spin_loop(); - } - self.write(0x310, (value >> 32) as u32); - self.write(0x300, value as u32); - while self.read(0x300) & PENDING == PENDING { - core::hint::spin_loop(); - } - } - } - } - - 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.get()) << shift) | 0x40 | 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) { - unsafe { - if self.x2 { - wrmsr(IA32_X2APIC_EOI, 0); - } else { - self.write(0xB0, 0); - } - } - } - /// Reads the Error Status Register. - pub unsafe fn esr(&mut self) -> u32 { - unsafe { - if self.x2 { - // update the ESR to the current state of the local apic. - wrmsr(IA32_X2APIC_ESR, 0); - // read the updated value - rdmsr(IA32_X2APIC_ESR) as u32 - } else { - self.write(0x280, 0); - self.read(0x280) - } - } - } - pub unsafe fn lvt_timer(&mut self) -> u32 { - unsafe { - if self.x2 { - rdmsr(IA32_X2APIC_LVT_TIMER) as u32 - } else { - self.read(0x320) - } - } - } - pub unsafe fn set_lvt_timer(&mut self, value: u32) { - unsafe { - if self.x2 { - wrmsr(IA32_X2APIC_LVT_TIMER, u64::from(value)); - } else { - self.write(0x320, value); - } - } - } - pub unsafe fn init_count(&mut self) -> u32 { - unsafe { - if self.x2 { - rdmsr(IA32_X2APIC_INIT_COUNT) as u32 - } else { - self.read(0x380) - } - } - } - pub unsafe fn set_init_count(&mut self, initial_count: u32) { - unsafe { - if self.x2 { - wrmsr(IA32_X2APIC_INIT_COUNT, u64::from(initial_count)); - } else { - self.write(0x380, initial_count); - } - } - } - pub unsafe fn cur_count(&mut self) -> u32 { - unsafe { - if self.x2 { - rdmsr(IA32_X2APIC_CUR_COUNT) as u32 - } else { - self.read(0x390) - } - } - } - pub unsafe fn div_conf(&mut self) -> u32 { - unsafe { - if self.x2 { - rdmsr(IA32_X2APIC_DIV_CONF) as u32 - } else { - self.read(0x3E0) - } - } - } - pub unsafe fn set_div_conf(&mut self, div_conf: u32) { - unsafe { - if self.x2 { - wrmsr(IA32_X2APIC_DIV_CONF, u64::from(div_conf)); - } else { - self.write(0x3E0, div_conf); - } - } - } - pub unsafe fn lvt_error(&mut self) -> u32 { - unsafe { - if self.x2 { - rdmsr(IA32_X2APIC_LVT_ERROR) as u32 - } else { - self.read(0x370) - } - } - } - pub unsafe fn set_lvt_error(&mut self, lvt_error: u32) { - unsafe { - if self.x2 { - wrmsr(IA32_X2APIC_LVT_ERROR, u64::from(lvt_error)); - } else { - self.write(0x370, lvt_error); - } - } - } - - pub unsafe fn set_lvt_nmi(&mut self, pin: u8, flags: u16) { - let polarity = match flags & 0b11 { - 0b11 => 1 << 13, - _ => 0, - }; - let trigger_mode = match (flags >> 2) & 0b11 { - 0b11 => 1 << 15, - _ => 0, - }; - let lvt_value = (0b100 << 8) | polarity | trigger_mode; - - unsafe { - match pin { - 0 => { - if self.x2 { - wrmsr(IA32_X2APIC_LVT_LINT0, u64::from(lvt_value)); - } else { - self.write(0x350, lvt_value); - } - } - 1 => { - if self.x2 { - wrmsr(IA32_X2APIC_LVT_LINT1, u64::from(lvt_value)); - } else { - self.write(0x360, lvt_value); - } - } - _ => {} - } - } - } - - unsafe fn setup_error_int(&mut self) { - unsafe { - let vector = 49u32; - self.set_lvt_error(vector); - } - } -} - -#[repr(u8)] -pub enum LvtTimerMode { - OneShot = 0b00, - Periodic = 0b01, - TscDeadline = 0b10, -} diff --git a/recipes/core/kernel/source/src/arch/x86_shared/device/local_apic.rs.rej b/recipes/core/kernel/source/src/arch/x86_shared/device/local_apic.rs.rej deleted file mode 100644 index ebc5ff76fd..0000000000 --- a/recipes/core/kernel/source/src/arch/x86_shared/device/local_apic.rs.rej +++ /dev/null @@ -1,14 +0,0 @@ ---- src/arch/x86_shared/device/local_apic.rs -+++ src/arch/x86_shared/device/local_apic.rs -@@ -61,9 +61,9 @@ - - if !self.x2 { -- info!("Detected xAPIC at {:#x}", physaddr.data()); -+ debug!("Detected xAPIC at {:#x}", physaddr.data()); - self.address = map_device_memory(physaddr, 4096).data(); - } else { -- info!("Detected x2APIC"); -+ debug!("Detected x2APIC"); - } - -