hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
use core::sync::atomic::{AtomicU8, AtomicUsize, Ordering};

static VIRT_AVAILABLE: AtomicU8 = AtomicU8::new(0xFF);
static HYP_REG_BASE: AtomicUsize = AtomicUsize::new(0);

pub fn set_hyp_reg_base(base: usize) {
    HYP_REG_BASE.store(base, Ordering::Release);
}

pub fn is_el2_available() -> bool {
    let cached = VIRT_AVAILABLE.load(Ordering::Acquire);
    if cached != 0xFF {
        return cached != 0;
    }
    let el = crate::arch::aarch64::cpu::system_regs::read_current_el();
    let available = el >= 2;
    VIRT_AVAILABLE.store(available as u8, Ordering::Release);
    available
}

pub fn read_hcr_el2() -> u64 {
    let base = HYP_REG_BASE.load(Ordering::Acquire);
    if base != 0 {
        unsafe { core::ptr::read_volatile(base as *const u64) }
    } else {
        0
    }
}

pub fn read_vttbr_el2() -> u64 {
    let base = HYP_REG_BASE.load(Ordering::Acquire);
    if base != 0 {
        unsafe { core::ptr::read_volatile((base + 8) as *const u64) }
    } else {
        0
    }
}

pub fn vmid() -> u16 {
    let vttbr = read_vttbr_el2();
    ((vttbr >> 48) & 0xFFFF) as u16
}