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 { let hhdm = get_hhdm(); if self.0 < hhdm { return None; } Some(PhysAddr(self.0 - hhdm)) } #[allow(dead_code)] pub fn as_ptr(self) -> *const T { self.0 as *const T } pub fn as_mut_ptr(self) -> *mut T { self.0 as *mut T } }