mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
442 lines
9.2 KiB
Rust
442 lines
9.2 KiB
Rust
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<T>(&self) -> *mut T {
|
|
self.as_usize() as *mut T
|
|
}
|
|
fn as_const_ptr<T>(&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<NonZeroUsize>;
|
|
fn align_up<T>(&self, align: T) -> Self
|
|
where T: Into<usize>;
|
|
fn align_down<T>(&self, align: T) -> Self
|
|
where T: Into<usize>;
|
|
fn is_aligned<T>(&self, align: T) -> bool
|
|
where T: Into<usize> + 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> {
|
|
NonZeroUsize::new(self.0)
|
|
}
|
|
|
|
fn align_up<T>(&self, align: T) -> Self
|
|
where T: Into<usize> {
|
|
PhysAddr(align_up(self.0, align.into()))
|
|
}
|
|
|
|
fn align_down<T>(&self, align: T) -> Self
|
|
where T: Into<usize> {
|
|
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> {
|
|
NonZeroUsize::new(self.0)
|
|
}
|
|
|
|
fn align_up<T>(&self, align: T) -> Self
|
|
where T: Into<usize> {
|
|
VirtAddr(align_up(self.0, align.into()))
|
|
}
|
|
|
|
fn align_down<T>(&self, align: T) -> Self
|
|
where T: Into<usize> {
|
|
VirtAddr(align_down(self.0, align.into()))
|
|
}
|
|
}
|
|
|
|
impl Add<usize> for PhysAddr {
|
|
type Output = Self;
|
|
|
|
fn add(self, rhs: usize) -> Self::Output {
|
|
Self(self.0 + rhs)
|
|
}
|
|
}
|
|
|
|
impl Add<PhysAddr> for PhysAddr {
|
|
type Output = Self;
|
|
|
|
fn add(self, rhs: PhysAddr) -> Self::Output {
|
|
Self(self.0 + rhs.0)
|
|
}
|
|
}
|
|
|
|
impl AddAssign<usize> for PhysAddr {
|
|
fn add_assign(&mut self, rhs: usize) {
|
|
*self = PhysAddr::from(self.0 + rhs);
|
|
}
|
|
}
|
|
|
|
impl AddAssign<PhysAddr> for PhysAddr {
|
|
fn add_assign(&mut self, rhs: PhysAddr) {
|
|
*self = PhysAddr::from(self.0 + rhs.0);
|
|
}
|
|
}
|
|
|
|
impl Sub<usize> for PhysAddr {
|
|
type Output = Self;
|
|
|
|
fn sub(self, rhs: usize) -> Self::Output {
|
|
PhysAddr(self.0 - rhs)
|
|
}
|
|
}
|
|
|
|
impl Sub<PhysAddr> for PhysAddr {
|
|
type Output = Self;
|
|
|
|
fn sub(self, rhs: PhysAddr) -> Self::Output {
|
|
PhysAddr(self.0 - rhs.0)
|
|
}
|
|
}
|
|
|
|
impl SubAssign<usize> for PhysAddr {
|
|
fn sub_assign(&mut self, rhs: usize) {
|
|
*self = PhysAddr::from(self.0 - rhs);
|
|
}
|
|
}
|
|
|
|
impl SubAssign<PhysAddr> for PhysAddr {
|
|
fn sub_assign(&mut self, rhs: PhysAddr) {
|
|
*self = PhysAddr::from(self.0 - rhs.0);
|
|
}
|
|
}
|
|
|
|
impl Add<usize> for VirtAddr {
|
|
type Output = Self;
|
|
|
|
fn add(self, rhs: usize) -> Self::Output {
|
|
Self(self.0 + rhs)
|
|
}
|
|
}
|
|
|
|
impl Add<VirtAddr> for VirtAddr {
|
|
type Output = Self;
|
|
|
|
fn add(self, rhs: VirtAddr) -> Self::Output {
|
|
Self(self.0 + rhs.0)
|
|
}
|
|
}
|
|
|
|
impl AddAssign<usize> for VirtAddr {
|
|
fn add_assign(&mut self, rhs: usize) {
|
|
*self = VirtAddr::from(self.0 + rhs);
|
|
}
|
|
}
|
|
|
|
impl AddAssign<VirtAddr> for VirtAddr {
|
|
fn add_assign(&mut self, rhs: VirtAddr) {
|
|
*self = VirtAddr::from(self.0 + rhs.0);
|
|
}
|
|
}
|
|
|
|
impl Sub<usize> for VirtAddr {
|
|
type Output = VirtAddr;
|
|
|
|
fn sub(self, rhs: usize) -> Self::Output {
|
|
VirtAddr(self.0 - rhs)
|
|
}
|
|
}
|
|
|
|
impl Sub<VirtAddr> for VirtAddr {
|
|
type Output = Self;
|
|
|
|
fn sub(self, rhs: VirtAddr) -> Self::Output {
|
|
VirtAddr(self.0 - rhs.0)
|
|
}
|
|
}
|
|
|
|
impl SubAssign<usize> for VirtAddr {
|
|
fn sub_assign(&mut self, rhs: usize) {
|
|
*self = VirtAddr::from(self.0 - rhs);
|
|
}
|
|
}
|
|
|
|
impl SubAssign<VirtAddr> for VirtAddr {
|
|
fn sub_assign(&mut self, rhs: VirtAddr) {
|
|
*self = VirtAddr::from(self.0 - rhs.0);
|
|
}
|
|
}
|
|
|
|
impl From<usize> for PhysAddr {
|
|
fn from(addr: usize) -> Self {
|
|
PhysAddr(addr)
|
|
}
|
|
}
|
|
|
|
impl From<u32> for PhysAddr {
|
|
fn from(addr: u32) -> Self {
|
|
PhysAddr(addr as usize)
|
|
}
|
|
}
|
|
|
|
#[cfg(target_pointer_width = "64")]
|
|
impl From<u64> for PhysAddr {
|
|
fn from(addr: u64) -> Self {
|
|
PhysAddr(addr as usize)
|
|
}
|
|
}
|
|
|
|
impl From<NonZeroUsize> for PhysAddr {
|
|
fn from(addr: NonZeroUsize) -> Self {
|
|
PhysAddr(addr.get())
|
|
}
|
|
}
|
|
|
|
impl<T> From<*mut T> for PhysAddr {
|
|
fn from(addr: *mut T) -> Self {
|
|
PhysAddr(addr as usize)
|
|
}
|
|
}
|
|
|
|
impl<T> From<*const T> for PhysAddr {
|
|
fn from(addr: *const T) -> Self {
|
|
PhysAddr(addr as usize)
|
|
}
|
|
}
|
|
|
|
impl From<PhysAddr> for usize {
|
|
fn from(addr: PhysAddr) -> Self {
|
|
addr.0
|
|
}
|
|
}
|
|
|
|
impl From<PhysAddr> for NonZeroUsize {
|
|
fn from(addr: PhysAddr) -> Self {
|
|
NonZeroUsize::new(addr.0).unwrap()
|
|
}
|
|
}
|
|
|
|
impl<T> From<PhysAddr> for *mut T {
|
|
fn from(addr: PhysAddr) -> Self {
|
|
addr.0 as *mut T
|
|
}
|
|
}
|
|
|
|
impl From<usize> for VirtAddr {
|
|
fn from(addr: usize) -> Self {
|
|
VirtAddr(addr)
|
|
}
|
|
}
|
|
|
|
impl From<u32> for VirtAddr {
|
|
fn from(addr: u32) -> Self {
|
|
VirtAddr(addr as usize)
|
|
}
|
|
}
|
|
|
|
#[cfg(target_pointer_width = "64")]
|
|
impl From<u64> for VirtAddr {
|
|
fn from(addr: u64) -> Self {
|
|
VirtAddr(addr as usize)
|
|
}
|
|
}
|
|
|
|
impl From<NonZeroUsize> for VirtAddr {
|
|
fn from(addr: NonZeroUsize) -> Self {
|
|
VirtAddr(addr.get())
|
|
}
|
|
}
|
|
|
|
impl<T> From<*mut T> for VirtAddr {
|
|
fn from(addr: *mut T) -> Self {
|
|
VirtAddr(addr as usize)
|
|
}
|
|
}
|
|
|
|
impl<T> From<*const T> for VirtAddr {
|
|
fn from(addr: *const T) -> Self {
|
|
VirtAddr(addr as usize)
|
|
}
|
|
}
|
|
|
|
impl From<VirtAddr> for usize {
|
|
fn from(addr: VirtAddr) -> Self {
|
|
addr.0
|
|
}
|
|
}
|
|
|
|
impl From<VirtAddr> for NonZeroUsize {
|
|
fn from(addr: VirtAddr) -> Self {
|
|
NonZeroUsize::new(addr.0).unwrap()
|
|
}
|
|
}
|
|
|
|
impl<T> From<VirtAddr> 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<H: core::hash::Hasher>(&self, state: &mut H) {
|
|
self.0.hash(state);
|
|
}
|
|
}
|
|
|
|
impl Hash for VirtAddr {
|
|
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
|
self.0.hash(state);
|
|
}
|
|
}
|
|
|
|
impl Step for PhysAddr {
|
|
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
|
|
if end.0 >= start.0 {
|
|
Some(end.0 - start.0)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
fn forward_checked(start: Self, count: usize) -> Option<Self> {
|
|
start.as_usize().checked_add(count).map(PhysAddr)
|
|
}
|
|
|
|
fn backward_checked(start: Self, count: usize) -> Option<Self> {
|
|
start.as_usize().checked_sub(count).map(PhysAddr)
|
|
}
|
|
}
|
|
|
|
impl Step for VirtAddr {
|
|
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
|
|
if end.0 >= start.0 {
|
|
Some(end.0 - start.0)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
fn forward_checked(start: Self, count: usize) -> Option<Self> {
|
|
start.as_usize().checked_add(count).map(VirtAddr)
|
|
}
|
|
|
|
fn backward_checked(start: Self, count: usize) -> Option<Self> {
|
|
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)
|
|
}
|
|
}
|