|  |  |  | @ -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>; | 
			
		
	
	
		
			
				
					|  |  |  | 
 |