use core::fmt::*; use core::hash::*; use core::iter::*; use core::num::*; use core::ops::*; #[inline(always)] pub fn align_up(addr: usize, align: usize) -> usize { (addr + align - 1) & !(align - 1) } #[inline(always)] pub fn align_down(addr: usize, align: usize) -> usize { addr & !(align - 1) } #[inline(always)] pub fn is_aligned(addr: usize, align: usize) -> bool { if align.is_power_of_two() { addr & (align - 1) == 0 } else { false } } #[derive(Copy, Clone, Default, Eq, Ord, PartialOrd, PartialEq)] pub struct PhysAddr(pub usize); #[derive(Copy, Clone, Default, Eq, Ord, PartialOrd, PartialEq)] pub struct VirtAddr(pub usize); pub trait AddressOps: Copy + Clone + Default + Eq + Ord + PartialOrd + PartialEq { fn as_mut_ptr(&self) -> *mut T { self.as_usize() as *mut T } fn as_const_ptr(&self) -> *const T { self.as_usize() as *const T } fn as_u32(&self) -> u32; fn as_u64(&self) -> u64; fn as_usize(&self) -> usize; fn as_non_zero_usize(&self) -> Option; 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 { is_aligned(self.as_usize(), align.into()) } } 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 as_non_zero_usize(&self) -> Option { NonZeroUsize::new(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 as_non_zero_usize(&self) -> Option { NonZeroUsize::new(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 Add for PhysAddr { type Output = Self; fn add(self, rhs: PhysAddr) -> Self::Output { Self(self.0 + rhs.0) } } impl AddAssign for PhysAddr { fn add_assign(&mut self, rhs: usize) { *self = PhysAddr::from(self.0 + rhs); } } impl AddAssign for PhysAddr { fn add_assign(&mut self, rhs: PhysAddr) { *self = PhysAddr::from(self.0 + rhs.0); } } impl Sub for PhysAddr { type Output = Self; fn sub(self, rhs: usize) -> Self::Output { PhysAddr(self.0 - rhs) } } impl Sub for PhysAddr { type Output = Self; fn sub(self, rhs: PhysAddr) -> Self::Output { PhysAddr(self.0 - rhs.0) } } impl SubAssign for PhysAddr { fn sub_assign(&mut self, rhs: usize) { *self = PhysAddr::from(self.0 - rhs); } } impl SubAssign for PhysAddr { fn sub_assign(&mut self, rhs: PhysAddr) { *self = PhysAddr::from(self.0 - rhs.0); } } impl Add for VirtAddr { type Output = Self; fn add(self, rhs: usize) -> Self::Output { Self(self.0 + rhs) } } impl Add for VirtAddr { type Output = Self; fn add(self, rhs: VirtAddr) -> Self::Output { Self(self.0 + rhs.0) } } impl AddAssign for VirtAddr { fn add_assign(&mut self, rhs: usize) { *self = VirtAddr::from(self.0 + rhs); } } impl AddAssign for VirtAddr { fn add_assign(&mut self, rhs: VirtAddr) { *self = VirtAddr::from(self.0 + rhs.0); } } impl Sub for VirtAddr { type Output = VirtAddr; fn sub(self, rhs: usize) -> Self::Output { VirtAddr(self.0 - rhs) } } impl Sub for VirtAddr { type Output = Self; fn sub(self, rhs: VirtAddr) -> Self::Output { VirtAddr(self.0 - rhs.0) } } impl SubAssign for VirtAddr { fn sub_assign(&mut self, rhs: usize) { *self = VirtAddr::from(self.0 - rhs); } } impl SubAssign for VirtAddr { fn sub_assign(&mut self, rhs: VirtAddr) { *self = VirtAddr::from(self.0 - rhs.0); } } impl From for PhysAddr { fn from(addr: usize) -> Self { PhysAddr(addr) } } impl From for PhysAddr { fn from(addr: u32) -> Self { PhysAddr(addr as usize) } } #[cfg(target_pointer_width = "64")] impl From for PhysAddr { fn from(addr: u64) -> Self { PhysAddr(addr as usize) } } impl From for PhysAddr { fn from(addr: NonZeroUsize) -> Self { PhysAddr(addr.get()) } } impl From<*mut T> for PhysAddr { fn from(addr: *mut T) -> Self { PhysAddr(addr as usize) } } impl From<*const T> for PhysAddr { fn from(addr: *const T) -> Self { PhysAddr(addr as usize) } } impl From for usize { fn from(addr: PhysAddr) -> Self { addr.0 } } impl From for NonZeroUsize { fn from(addr: PhysAddr) -> Self { NonZeroUsize::new(addr.0).unwrap() } } impl From for *mut T { fn from(addr: PhysAddr) -> Self { addr.0 as *mut T } } impl From for VirtAddr { fn from(addr: usize) -> Self { VirtAddr(addr) } } impl From for VirtAddr { fn from(addr: u32) -> Self { VirtAddr(addr as usize) } } #[cfg(target_pointer_width = "64")] impl From for VirtAddr { fn from(addr: u64) -> Self { VirtAddr(addr as usize) } } impl From for VirtAddr { fn from(addr: NonZeroUsize) -> Self { VirtAddr(addr.get()) } } impl From<*mut T> for VirtAddr { fn from(addr: *mut T) -> Self { VirtAddr(addr as usize) } } impl From<*const T> for VirtAddr { fn from(addr: *const T) -> Self { VirtAddr(addr as usize) } } impl From for usize { fn from(addr: VirtAddr) -> Self { addr.0 } } impl From for NonZeroUsize { fn from(addr: VirtAddr) -> Self { NonZeroUsize::new(addr.0).unwrap() } } impl From for *mut T { fn from(addr: VirtAddr) -> Self { addr.0 as *mut T } } impl Debug for PhysAddr { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, "PhysAddr({:#x})", self.0) } } impl Display for PhysAddr { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, "{:#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 Display for VirtAddr { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, "{:#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); } } impl Step for PhysAddr { fn steps_between(start: &Self, end: &Self) -> Option { if end.0 >= start.0 { Some(end.0 - start.0) } else { None } } fn forward_checked(start: Self, count: usize) -> Option { start.as_usize().checked_add(count).map(PhysAddr) } fn backward_checked(start: Self, count: usize) -> Option { start.as_usize().checked_sub(count).map(PhysAddr) } } impl Step for VirtAddr { fn steps_between(start: &Self, end: &Self) -> Option { if end.0 >= start.0 { Some(end.0 - start.0) } else { None } } fn forward_checked(start: Self, count: usize) -> Option { start.as_usize().checked_add(count).map(VirtAddr) } fn backward_checked(start: Self, count: usize) -> Option { start.as_usize().checked_sub(count).map(VirtAddr) } } impl PhysAddr { /// # Safety /// Only provided for the sake of completeness. Use `{mmap, kernel}_phys_to_virt` instead. pub unsafe fn to_virt_addr(&self) -> VirtAddr { VirtAddr(self.0) } } impl VirtAddr { /// # Safety /// Only provided for the sake of completeness. Use `{mmap, kernel}_virt_to_phys` instead. pub unsafe fn to_phys_addr(&self) -> PhysAddr { PhysAddr(self.0) } }