diff --git a/src/lib.rs b/src/lib.rs index 3df8733..cccc1ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,5 +16,8 @@ pub mod lang; // entrypoint pub mod entry; +// page table +pub mod mm; + // logging pub mod logging; diff --git a/src/mm/addr.rs b/src/mm/addr.rs new file mode 100644 index 0000000..a892af3 --- /dev/null +++ b/src/mm/addr.rs @@ -0,0 +1,223 @@ +use core::fmt::{Debug, Formatter, LowerHex, Result, UpperHex}; +use core::hash::Hash; +use core::ops::{Add, AddAssign, Sub, SubAssign}; + +#[inline(always)] +fn align_up(addr: usize, align: usize) -> usize { + (addr + align - 1) & !(align - 1) +} + +#[inline(always)] +fn align_down(addr: usize, align: usize) -> usize { + addr & !(align - 1) +} + +pub struct PhysAddr(pub usize); + +pub struct VirtAddr(pub usize); + +pub trait AddressOps { + fn as_u32(&self) -> u32; + fn as_u64(&self) -> u64; + fn as_usize(&self) -> usize; + fn align_up(&self, align: T) -> Self + where + T: Into; + fn align_down(&self, align: T) -> Self + where + T: Into; + fn is_aligned(&self, align: T) -> bool + where + T: Into + Copy, + { + if align.into().is_power_of_two() { + self.as_usize() & (align.into() - 1) == 0 + } else { + false + } + } +} + +impl AddressOps for PhysAddr { + fn as_u32(&self) -> u32 { + self.0 as u32 + } + + fn as_u64(&self) -> u64 { + self.0 as u64 + } + + fn as_usize(&self) -> usize { + self.0 + } + + fn align_up(&self, align: T) -> Self + where + T: Into, + { + PhysAddr(align_up(self.0, align.into())) + } + + fn align_down(&self, align: T) -> Self + where + T: Into, + { + PhysAddr(align_down(self.0, align.into())) + } +} + +impl AddressOps for VirtAddr { + fn as_u32(&self) -> u32 { + self.0 as u32 + } + + fn as_u64(&self) -> u64 { + self.0 as u64 + } + + fn as_usize(&self) -> usize { + self.0 + } + + fn align_up(&self, align: T) -> Self + where + T: Into, + { + VirtAddr(align_up(self.0, align.into())) + } + + fn align_down(&self, align: T) -> Self + where + T: Into, + { + VirtAddr(align_down(self.0, align.into())) + } +} + +impl Add for PhysAddr { + type Output = Self; + + fn add(self, rhs: usize) -> Self::Output { + Self(self.0 + rhs) + } +} + +impl AddAssign for PhysAddr { + fn add_assign(&mut self, rhs: usize) { + *self = PhysAddr::from(self.0 + rhs); + } +} + +impl Sub for PhysAddr { + type Output = PhysAddr; + + fn sub(self, rhs: usize) -> Self::Output { + PhysAddr(self.0 - rhs) + } +} + +impl SubAssign for PhysAddr { + fn sub_assign(&mut self, rhs: usize) { + *self = PhysAddr::from(self.0 - rhs); + } +} + +impl Add for VirtAddr { + type Output = Self; + + fn add(self, rhs: usize) -> Self::Output { + Self(self.0 + rhs) + } +} + +impl AddAssign for VirtAddr { + fn add_assign(&mut self, rhs: usize) { + *self = VirtAddr::from(self.0 + rhs); + } +} + +impl Sub for VirtAddr { + type Output = VirtAddr; + + fn sub(self, rhs: usize) -> Self::Output { + VirtAddr(self.0 - rhs) + } +} + +impl SubAssign for VirtAddr { + fn sub_assign(&mut self, rhs: usize) { + *self = VirtAddr::from(self.0 - rhs); + } +} + +impl From for PhysAddr { + fn from(addr: usize) -> Self { + PhysAddr(addr) + } +} + +impl From for usize { + fn from(addr: PhysAddr) -> Self { + addr.0 + } +} + +impl From for VirtAddr { + fn from(addr: usize) -> Self { + VirtAddr(addr) + } +} + +impl From for usize { + fn from(addr: VirtAddr) -> Self { + addr.0 + } +} + +impl Debug for PhysAddr { + fn fmt(&self, f: &mut Formatter) -> Result { + write!(f, "PhysAddr({:#x})", self.0) + } +} + +impl LowerHex for PhysAddr { + fn fmt(&self, f: &mut Formatter) -> Result { + write!(f, "{:#x}", self.0) + } +} + +impl UpperHex for PhysAddr { + fn fmt(&self, f: &mut Formatter) -> Result { + write!(f, "{:#X}", self.0) + } +} + +impl Debug for VirtAddr { + fn fmt(&self, f: &mut Formatter) -> Result { + write!(f, "VirtAddr({:#x})", self.0) + } +} + +impl LowerHex for VirtAddr { + fn fmt(&self, f: &mut Formatter) -> Result { + write!(f, "{:#x}", self.0) + } +} + +impl UpperHex for VirtAddr { + fn fmt(&self, f: &mut Formatter) -> Result { + write!(f, "{:#X}", self.0) + } +} + +impl Hash for PhysAddr { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +impl Hash for VirtAddr { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} diff --git a/src/mm/mod.rs b/src/mm/mod.rs new file mode 100644 index 0000000..9f3b826 --- /dev/null +++ b/src/mm/mod.rs @@ -0,0 +1 @@ +pub mod addr;