|
|
|
@ -1,34 +1,41 @@
|
|
|
|
|
use crate::config::{PAGE_SIZE, PAGE_SIZE_BITS};
|
|
|
|
|
use crate::mm::page_table::PageTableEntry;
|
|
|
|
|
|
|
|
|
|
const PA_WIDTH_SV39: usize = 56; // 真实物理地址 的字节宽度 44(物理页宽) + 12(4kb的宽度)
|
|
|
|
|
const VA_WIDTH_SV39: usize = 39; // 虚拟地址的宽度 9 + 9 + 9 + 12
|
|
|
|
|
const PPN_WIDTH_SV39: usize = PA_WIDTH_SV39 - PAGE_SIZE_BITS; // 物理页 的宽度, 也就是 物理地址宽度-每页宽度=物理页宽度
|
|
|
|
|
const VPN_WIDTH_SV39: usize = VA_WIDTH_SV39 - PAGE_SIZE_BITS; // 虚拟页的宽度 27
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 物理地址
|
|
|
|
|
// 物理地址 56bit 44 12
|
|
|
|
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
|
|
|
pub struct PhysAddr(pub usize);
|
|
|
|
|
|
|
|
|
|
// 虚拟地址
|
|
|
|
|
// 虚拟地址 39bit 9 9 9 12
|
|
|
|
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
|
|
|
pub struct VirtAddr(pub usize);
|
|
|
|
|
|
|
|
|
|
// 物理页
|
|
|
|
|
// 物理页 44bit
|
|
|
|
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
|
|
|
pub struct PhysPageNum(pub usize);
|
|
|
|
|
|
|
|
|
|
// 虚拟页
|
|
|
|
|
// 虚拟页 29bit 布局为 9 9 9
|
|
|
|
|
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
|
|
|
|
pub struct VirtPageNum(pub usize);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 把usize 转为真实地址(只保留 PA_WIDTH_SV39 位字节)
|
|
|
|
|
impl From<usize> for PhysAddr {
|
|
|
|
|
fn from(v: usize) -> Self { Self(v & ( (1 << PA_WIDTH_SV39) - 1 )) }
|
|
|
|
|
fn from(v: usize) -> Self {
|
|
|
|
|
Self(v & ( (1 << PA_WIDTH_SV39) - 1 ))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 把usize类型的物理页号 转为物理页结构体 (只保留物理页的宽度)
|
|
|
|
|
impl From<usize> for PhysPageNum {
|
|
|
|
|
fn from(v: usize) -> Self { Self(v & ( (1 << PPN_WIDTH_SV39) - 1 )) }
|
|
|
|
|
fn from(v: usize) -> Self {
|
|
|
|
|
Self(v & ( (1 << PPN_WIDTH_SV39) - 1 ))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 把物理地址转为 usize, 直接返回即可
|
|
|
|
@ -74,12 +81,12 @@ impl PhysAddr {
|
|
|
|
|
|
|
|
|
|
impl PhysPageNum {
|
|
|
|
|
// // 从当前物理页保存的数据中得到所有的 PTE
|
|
|
|
|
// pub fn get_pte_array(&self) -> &'static mut [PageTableEntry] {
|
|
|
|
|
// // 物理页号 转为物理地址
|
|
|
|
|
// let pa: PhysAddr = (*self).into();
|
|
|
|
|
// // 从物理页地址读出一页 512个8字节(4k)的数据
|
|
|
|
|
// unsafe { core::slice::from_raw_parts_mut(pa.0 as *mut PageTableEntry, 512) }
|
|
|
|
|
// }
|
|
|
|
|
pub fn get_pte_array(&self) -> &'static mut [PageTableEntry] {
|
|
|
|
|
// 物理页号 转为物理地址
|
|
|
|
|
let pa: PhysAddr = (*self).into();
|
|
|
|
|
// 从物理页地址读出一页 512个8字节(4k)的数据
|
|
|
|
|
unsafe { core::slice::from_raw_parts_mut(pa.0 as *mut PageTableEntry, 512) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从当前物理页得到 引用类型的 byte array
|
|
|
|
|
pub fn get_bytes_array(&self) -> &'static mut [u8] {
|
|
|
|
@ -93,3 +100,44 @@ impl PhysPageNum {
|
|
|
|
|
unsafe { (pa.0 as *mut T).as_mut().unwrap() }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 把usize 转为 虚拟地址, 只保留39位
|
|
|
|
|
impl From<usize> for VirtAddr {
|
|
|
|
|
fn from(value: usize) -> Self {
|
|
|
|
|
Self(value & ((1 << PPN_WIDTH_SV39) - 1 ))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 把虚拟地址, 转为usize
|
|
|
|
|
impl From<VirtAddr> for usize {
|
|
|
|
|
fn from(v: VirtAddr) -> Self {
|
|
|
|
|
if v.0 >= (1 << (VA_WIDTH_SV39 - 1)) {
|
|
|
|
|
// 将高位全部设置为1, 虚拟地址就是这样的, 64~39 位, 随着38位变化
|
|
|
|
|
v.0 | (!((1 << VA_WIDTH_SV39) - 1))
|
|
|
|
|
} else {
|
|
|
|
|
v.0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 把usize类型的页号 转为 虚拟页号结构体, 只保留27位即可
|
|
|
|
|
impl From<usize> for VirtPageNum {
|
|
|
|
|
fn from(v: usize) -> Self {
|
|
|
|
|
Self(v & ((1 << VPN_WIDTH_SV39) - 1))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl VirtPageNum{
|
|
|
|
|
// 从虚拟页号中 抽离 9 9 9 的布局
|
|
|
|
|
pub fn indexes(&self) -> [usize; 3] {
|
|
|
|
|
let mut vpn = self.0;
|
|
|
|
|
let mut idx = [0usize; 3];
|
|
|
|
|
for i in (0..3).rev() {
|
|
|
|
|
idx[i] = vpn & 511;
|
|
|
|
|
vpn >>= 9;
|
|
|
|
|
}
|
|
|
|
|
idx
|
|
|
|
|
}
|
|
|
|
|
}
|