54 lines
1.4 KiB
Rust
54 lines
1.4 KiB
Rust
// 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);
|
|
}
|