use core::arch::asm;
use core::mem::size_of;
use core::sync::atomic::{AtomicU32, Ordering};
use raw_cpuid::{CpuId, CpuIdReader};
use super::int::apic::LAPIC_IDS;
use super::int::lapic::LAPIC;
use crate::MAX_CPUS;
static ONLINE_MASK: AtomicU32 = AtomicU32::new(0);
const _: () = assert!(MAX_CPUS <= size_of::<AtomicU32>() * 8);
pub fn halt() {
unsafe { asm!("hlt", options(nomem, nostack)) };
}
pub fn init(core: usize) {
ONLINE_MASK.fetch_or(1 << core, Ordering::AcqRel);
}
pub fn id() -> usize {
if let Some(ids) = LAPIC_IDS.get() {
let id = LAPIC.id();
ids.iter().position(|v| *v == id).unwrap_or(0)
} else {
0
}
}
pub fn online() -> u32 {
ONLINE_MASK.load(Ordering::Acquire)
}
pub fn iter() -> impl Iterator<Item = usize> {
let mask = ONLINE_MASK.load(Ordering::Acquire);
(0..MAX_CPUS).filter(move |i| mask & (1 << i) != 0)
}
pub fn cpuid() -> CpuId<impl CpuIdReader> {
#[derive(Clone, Copy)]
struct CpuIdNative;
impl CpuIdReader for CpuIdNative {
fn cpuid2(&self, eax: u32, ecx: u32) -> raw_cpuid::CpuIdResult {
let core::arch::x86::CpuidResult { eax, ebx, ecx, edx } =
unsafe { core::arch::x86::__cpuid_count(eax, ecx) };
raw_cpuid::CpuIdResult { eax, ebx, ecx, edx }
}
}
CpuId::with_cpuid_reader(CpuIdNative)
}