use core::{ops::Deref, sync::atomic::Ordering}; use atomic::Atomic; use bytemuck::{Pod, Zeroable}; static KERNEL_VIRTUAL_BASE: Atomic = Atomic::new(PhysicalMemoryAddress(0)); pub fn init(kernel_virtual_base: PhysicalMemoryAddress) { KERNEL_VIRTUAL_BASE.store(kernel_virtual_base, Ordering::Relaxed); } #[derive(Clone, Copy, Pod, Zeroable)] #[repr(transparent)] pub struct VirtualMemoryAddress(pub usize); impl Deref for VirtualMemoryAddress { type Target = usize; fn deref(&self) -> &Self::Target { &self.0 } } impl From for VirtualMemoryAddress { fn from(value: usize) -> Self { Self(value) } } impl From for usize { fn from(value: VirtualMemoryAddress) -> Self { *value } } impl From for VirtualMemoryAddress { fn from(value: PhysicalMemoryAddress) -> Self { VirtualMemoryAddress(*value + *KERNEL_VIRTUAL_BASE.load(Ordering::Relaxed)) } } #[derive(Clone, Copy, Pod, Zeroable)] #[repr(transparent)] pub struct PhysicalMemoryAddress(pub usize); impl Deref for PhysicalMemoryAddress { type Target = usize; fn deref(&self) -> &Self::Target { &self.0 } } impl From for PhysicalMemoryAddress { fn from(value: usize) -> Self { PhysicalMemoryAddress(value) } } impl From for usize { fn from(value: PhysicalMemoryAddress) -> Self { *value } } impl From for PhysicalMemoryAddress { fn from(value: VirtualMemoryAddress) -> Self { PhysicalMemoryAddress(*value - *KERNEL_VIRTUAL_BASE.load(Ordering::Relaxed)) } } #[derive(Clone, Copy)] pub enum MemoryAddress { Virtual(VirtualMemoryAddress), Physical(PhysicalMemoryAddress), } impl From for MemoryAddress { fn from(value: VirtualMemoryAddress) -> Self { MemoryAddress::Virtual(value) } } impl From for MemoryAddress { fn from(value: PhysicalMemoryAddress) -> Self { MemoryAddress::Physical(value) } } impl From for usize { fn from(value: MemoryAddress) -> Self { match value { MemoryAddress::Virtual(v) => *v, MemoryAddress::Physical(p) => *p, } } } impl From for VirtualMemoryAddress { fn from(value: MemoryAddress) -> Self { match value { MemoryAddress::Virtual(v) => v, MemoryAddress::Physical(p) => p.into(), } } } impl From for PhysicalMemoryAddress { fn from(value: MemoryAddress) -> Self { match value { MemoryAddress::Virtual(v) => v.into(), MemoryAddress::Physical(p) => p, } } }