use core::fmt;
use derive_more::{From, LowerHex, UpperHex};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
use super::SandboxSafe;
macro_rules! hex_fmt {
($ty:ident) => {
impl fmt::Display for $ty {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Debug for $ty {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}({:#x})", stringify!($ty), self.0)
}
}
};
}
#[derive(
Clone,
Copy,
Default,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
From,
LowerHex,
UpperHex,
FromBytes,
IntoBytes,
Immutable,
KnownLayout,
)]
#[repr(transparent)]
pub struct VirtAddr(pub u64);
unsafe impl SandboxSafe for VirtAddr {}
hex_fmt!(VirtAddr);
impl VirtAddr {
pub const fn is_canonical(self) -> bool {
let top = (self.0 >> 47) & 0x1ffff;
top == 0 || top == 0x1ffff
}
}
#[derive(
Clone,
Copy,
Default,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
From,
LowerHex,
UpperHex,
FromBytes,
IntoBytes,
Immutable,
KnownLayout,
)]
#[repr(transparent)]
pub struct PhysAddr(pub u64);
unsafe impl SandboxSafe for PhysAddr {}
hex_fmt!(PhysAddr);
impl From<usize> for VirtAddr {
fn from(v: usize) -> Self {
Self(v as u64)
}
}
impl From<usize> for PhysAddr {
fn from(v: usize) -> Self {
Self(v as u64)
}
}
impl From<VirtAddr> for u64 {
fn from(a: VirtAddr) -> u64 {
a.0
}
}
impl From<PhysAddr> for u64 {
fn from(a: PhysAddr) -> u64 {
a.0
}
}
#[macro_export]
macro_rules! newtype_ops {
($ty:ident) => {
impl $ty {
#[inline]
pub fn to_u64(self) -> u64 {
self.0 as u64
}
#[inline]
pub fn to_usize(self) -> usize {
self.0 as usize
}
#[inline]
pub fn is_zero(&self) -> bool {
self.0 == 0
}
#[inline]
pub fn align_down(self, align: u64) -> Self {
Self(self.0 & !(align - 1))
}
#[inline]
pub fn align_up(self, align: u64) -> Self {
Self((self.0 + align - 1) & !(align - 1))
}
#[inline]
pub fn page_offset(&self) -> usize {
(self.0 & 0xFFF) as usize
}
#[inline]
pub fn page_base(self) -> Self {
self.align_down(0x1000)
}
}
impl ::core::ops::BitAnd<u64> for $ty {
type Output = $ty;
#[inline]
fn bitand(self, rhs: u64) -> $ty {
$ty(self.0 & rhs)
}
}
impl ::core::ops::BitOr<u64> for $ty {
type Output = $ty;
#[inline]
fn bitor(self, rhs: u64) -> $ty {
$ty(self.0 | rhs)
}
}
impl ::core::ops::Not for $ty {
type Output = $ty;
#[inline]
fn not(self) -> $ty {
$ty(!self.0)
}
}
impl ::core::ops::Shl<u32> for $ty {
type Output = $ty;
#[inline]
fn shl(self, rhs: u32) -> $ty {
$ty(self.0 << rhs)
}
}
impl ::core::ops::Shr<u32> for $ty {
type Output = $ty;
#[inline]
fn shr(self, rhs: u32) -> $ty {
$ty(self.0 >> rhs)
}
}
};
}
newtype_ops!(VirtAddr);
newtype_ops!(PhysAddr);