54 lines
1.5 KiB
Rust
54 lines
1.5 KiB
Rust
use core::sync::atomic::{AtomicU64, Ordering};
|
|
|
|
static HHDM_OFFSET: AtomicU64 = AtomicU64::new(0);
|
|
|
|
/// Store the Higher-Half Direct Map offset obtained from the bootloader.
|
|
/// Must be called once during early boot, before any address translation.
|
|
pub fn init_hhdm(offset: u64) {
|
|
HHDM_OFFSET.store(offset, Ordering::Release);
|
|
}
|
|
|
|
/// Return the HHDM offset (kernel virtual base for physical memory).
|
|
#[inline]
|
|
pub fn get_hhdm() -> u64 {
|
|
HHDM_OFFSET.load(Ordering::Relaxed)
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
#[repr(transparent)]
|
|
pub struct PhysAddr(pub u64);
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
#[repr(transparent)]
|
|
pub struct VirtAddr(pub u64);
|
|
|
|
impl PhysAddr {
|
|
/// Convert physical address to virtual via HHDM offset
|
|
pub fn to_virt(self) -> VirtAddr {
|
|
VirtAddr(self.0 + get_hhdm())
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn is_aligned(self) -> bool { self.0 % 4096 == 0 }
|
|
|
|
#[allow(dead_code)]
|
|
pub fn align_down(self) -> Self { Self(self.0 & !0xFFF) }
|
|
|
|
#[allow(dead_code)]
|
|
pub fn align_up(self) -> Self { Self((self.0 + 4095) & !0xFFF) }
|
|
}
|
|
|
|
impl VirtAddr {
|
|
#[allow(dead_code)]
|
|
pub fn to_phys(self) -> Option<PhysAddr> {
|
|
let hhdm = get_hhdm();
|
|
if self.0 < hhdm { return None; }
|
|
Some(PhysAddr(self.0 - hhdm))
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn as_ptr<T>(self) -> *const T { self.0 as *const T }
|
|
|
|
pub fn as_mut_ptr<T>(self) -> *mut T { self.0 as *mut T }
|
|
}
|