// src/cpu/lapic.rs use core::sync::atomic::{AtomicU64, Ordering}; use crate::mem::address::get_hhdm; pub const LAPIC_DEFAULT_BASE: u64 = 0xFEE00_000; const LAPIC_EOI: u64 = 0x0B0; const LAPIC_ICR_LOW: u64 = 0x300; static LAPIC_VIRT_BASE: AtomicU64 = AtomicU64::new(0); pub fn init() { LAPIC_VIRT_BASE.store(LAPIC_DEFAULT_BASE + get_hhdm(), Ordering::SeqCst); } #[inline(always)] pub fn current_core_id() -> u32 { let mut ebx: u32; unsafe { core::arch::asm!( "mov {tmp:r}, rbx", "mov eax, 1", "cpuid", "mov {out:e}, ebx", "mov rbx, {tmp:r}", tmp = out(reg) _, out = out(reg) ebx, out("eax") _, out("ecx") _, out("edx") _, options(nostack, preserves_flags) ); } ebx >> 24 } #[inline(always)] fn write_lapic_reg(offset: u64, value: u32) { let base = LAPIC_VIRT_BASE.load(Ordering::Relaxed); if base == 0 { return; } unsafe { core::ptr::write_volatile((base + offset) as *mut u32, value) } } #[inline(always)] pub fn send_eoi() { write_lapic_reg(LAPIC_EOI, 0); } pub fn broadcast_ipi_exclude_self(vector: u8) { // Destination Shorthand = 10b (All excluding self) // Level = 1 (Assert) // Delivery Mode = 000b let icr_low = (2 << 18) | (1 << 14) | (vector as u32); write_lapic_reg(LAPIC_ICR_LOW, icr_low); }