|
|
|
@ -1,22 +1,23 @@
|
|
|
|
|
//! Implementation of physical and virtual address and page number.
|
|
|
|
|
use super::PageTableEntry;
|
|
|
|
|
use crate::config::{PAGE_SIZE, PAGE_SIZE_BITS};
|
|
|
|
|
use core::fmt::{self, Debug, Formatter};
|
|
|
|
|
|
|
|
|
|
/// physical address
|
|
|
|
|
const PA_WIDTH_SV39: usize = 56;
|
|
|
|
|
const VA_WIDTH_SV39: usize = 39;
|
|
|
|
|
const PPN_WIDTH_SV39: usize = PA_WIDTH_SV39 - PAGE_SIZE_BITS;
|
|
|
|
|
const VPN_WIDTH_SV39: usize = VA_WIDTH_SV39 - PAGE_SIZE_BITS;
|
|
|
|
|
|
|
|
|
|
/// Definitions
|
|
|
|
|
/// physical address
|
|
|
|
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
|
|
|
pub struct PhysAddr(pub usize);
|
|
|
|
|
|
|
|
|
|
/// virtual address
|
|
|
|
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
|
|
|
pub struct VirtAddr(pub usize);
|
|
|
|
|
|
|
|
|
|
/// physical page number
|
|
|
|
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
|
|
|
pub struct PhysPageNum(pub usize);
|
|
|
|
|
|
|
|
|
|
/// virtual page number
|
|
|
|
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
|
|
|
pub struct VirtPageNum(pub usize);
|
|
|
|
|
|
|
|
|
@ -87,17 +88,21 @@ impl From<VirtPageNum> for usize {
|
|
|
|
|
v.0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
impl VirtAddr {
|
|
|
|
|
///`VirtAddr`->`VirtPageNum`
|
|
|
|
|
pub fn floor(&self) -> VirtPageNum {
|
|
|
|
|
VirtPageNum(self.0 / PAGE_SIZE)
|
|
|
|
|
}
|
|
|
|
|
///`VirtAddr`->`VirtPageNum`
|
|
|
|
|
pub fn ceil(&self) -> VirtPageNum {
|
|
|
|
|
VirtPageNum((self.0 - 1 + PAGE_SIZE) / PAGE_SIZE)
|
|
|
|
|
}
|
|
|
|
|
///Get page offset
|
|
|
|
|
pub fn page_offset(&self) -> usize {
|
|
|
|
|
self.0 & (PAGE_SIZE - 1)
|
|
|
|
|
}
|
|
|
|
|
///Check page aligned
|
|
|
|
|
pub fn aligned(&self) -> bool {
|
|
|
|
|
self.page_offset() == 0
|
|
|
|
|
}
|
|
|
|
@ -114,15 +119,19 @@ impl From<VirtPageNum> for VirtAddr {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl PhysAddr {
|
|
|
|
|
///`PhysAddr`->`PhysPageNum`
|
|
|
|
|
pub fn floor(&self) -> PhysPageNum {
|
|
|
|
|
PhysPageNum(self.0 / PAGE_SIZE)
|
|
|
|
|
}
|
|
|
|
|
///`PhysAddr`->`PhysPageNum`
|
|
|
|
|
pub fn ceil(&self) -> PhysPageNum {
|
|
|
|
|
PhysPageNum((self.0 - 1 + PAGE_SIZE) / PAGE_SIZE)
|
|
|
|
|
}
|
|
|
|
|
///Get page offset
|
|
|
|
|
pub fn page_offset(&self) -> usize {
|
|
|
|
|
self.0 & (PAGE_SIZE - 1)
|
|
|
|
|
}
|
|
|
|
|
///Check page aligned
|
|
|
|
|
pub fn aligned(&self) -> bool {
|
|
|
|
|
self.page_offset() == 0
|
|
|
|
|
}
|
|
|
|
@ -140,6 +149,7 @@ impl From<PhysPageNum> for PhysAddr {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl VirtPageNum {
|
|
|
|
|
///Return VPN 3 level index
|
|
|
|
|
pub fn indexes(&self) -> [usize; 3] {
|
|
|
|
|
let mut vpn = self.0;
|
|
|
|
|
let mut idx = [0usize; 3];
|
|
|
|
@ -152,19 +162,23 @@ impl VirtPageNum {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PhysAddr {
|
|
|
|
|
///Get mutable reference to `PhysAddr` value
|
|
|
|
|
pub fn get_mut<T>(&self) -> &'static mut T {
|
|
|
|
|
unsafe { (self.0 as *mut T).as_mut().unwrap() }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl PhysPageNum {
|
|
|
|
|
///Get `PageTableEntry` on `PhysPageNum`
|
|
|
|
|
pub fn get_pte_array(&self) -> &'static mut [PageTableEntry] {
|
|
|
|
|
let pa: PhysAddr = (*self).into();
|
|
|
|
|
unsafe { core::slice::from_raw_parts_mut(pa.0 as *mut PageTableEntry, 512) }
|
|
|
|
|
}
|
|
|
|
|
///
|
|
|
|
|
pub fn get_bytes_array(&self) -> &'static mut [u8] {
|
|
|
|
|
let pa: PhysAddr = (*self).into();
|
|
|
|
|
unsafe { core::slice::from_raw_parts_mut(pa.0 as *mut u8, 4096) }
|
|
|
|
|
}
|
|
|
|
|
///
|
|
|
|
|
pub fn get_mut<T>(&self) -> &'static mut T {
|
|
|
|
|
let pa: PhysAddr = (*self).into();
|
|
|
|
|
pa.get_mut()
|
|
|
|
@ -181,6 +195,7 @@ impl StepByOne for VirtPageNum {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
|
/// a simple range structure for type T
|
|
|
|
|
pub struct SimpleRange<T>
|
|
|
|
|
where
|
|
|
|
|
T: StepByOne + Copy + PartialEq + PartialOrd + Debug,
|
|
|
|
@ -213,6 +228,7 @@ where
|
|
|
|
|
SimpleRangeIterator::new(self.l, self.r)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// iterator for the simple range structure
|
|
|
|
|
pub struct SimpleRangeIterator<T>
|
|
|
|
|
where
|
|
|
|
|
T: StepByOne + Copy + PartialEq + PartialOrd + Debug,
|
|
|
|
@ -243,4 +259,5 @@ where
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// a simple range structure for virtual page number
|
|
|
|
|
pub type VPNRange = SimpleRange<VirtPageNum>;
|
|
|
|
|