Move PageSize to a mod and implement it for phys frames and virt pages
This commit is contained in:
		
							parent
							
								
									1eed756d04
								
							
						
					
					
						commit
						d278383184
					
				|  | @ -4,30 +4,6 @@ | |||
| 
 | ||||
| // Page 2068 actual page descriptor formats
 | ||||
| 
 | ||||
| /// A standard 16KiB page.
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum Size16KiB {} | ||||
| 
 | ||||
| impl PageSize for Size16KiB { | ||||
|     const SIZE: u64 = 16384; | ||||
|     const SIZE_AS_DEBUG_STR: &'static str = "16KiB"; | ||||
|     const SHIFT: usize = 14; | ||||
|     const MASK: u64 = 0x3fff; | ||||
| } | ||||
| 
 | ||||
| impl NotGiantPageSize for Size16KiB {} | ||||
| 
 | ||||
| /// A “giant” 1GiB page.
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum Size1GiB {} | ||||
| 
 | ||||
| impl PageSize for Size1GiB { | ||||
|     const SIZE: u64 = Size2MiB::SIZE * NUM_ENTRIES_4KIB; | ||||
|     const SIZE_AS_DEBUG_STR: &'static str = "1GiB"; | ||||
|     const SHIFT: usize = 59; // @todo
 | ||||
|     const MASK: u64 = 0xfffaaaaa; // @todo
 | ||||
| } | ||||
| 
 | ||||
| /// Errors from mapping layer
 | ||||
| #[derive(Debug, Snafu)] | ||||
| pub enum TranslationError { | ||||
|  |  | |||
|  | @ -93,50 +93,6 @@ fn into_mmu_attributes( | |||
|     desc | ||||
| } | ||||
| 
 | ||||
| /// Trait for abstracting over the possible page sizes, 4KiB, 16KiB, 2MiB, 1GiB.
 | ||||
| pub trait PageSize: Copy + Eq + PartialOrd + Ord { | ||||
|     /// The page size in bytes.
 | ||||
|     const SIZE: u64; | ||||
| 
 | ||||
|     /// A string representation of the page size for debug output.
 | ||||
|     const SIZE_AS_DEBUG_STR: &'static str; | ||||
| 
 | ||||
|     /// The page shift in bits.
 | ||||
|     const SHIFT: usize; | ||||
| 
 | ||||
|     /// The page mask in bits.
 | ||||
|     const MASK: u64; | ||||
| } | ||||
| 
 | ||||
| /// This trait is implemented for 4KiB, 16KiB, and 2MiB pages, but not for 1GiB pages.
 | ||||
| pub trait NotGiantPageSize: PageSize {} // @todo doesn't have to be pub??
 | ||||
| 
 | ||||
| /// A standard 4KiB page.
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum Size4KiB {} | ||||
| 
 | ||||
| impl PageSize for Size4KiB { | ||||
|     const SIZE: u64 = 4096; | ||||
|     const SIZE_AS_DEBUG_STR: &'static str = "4KiB"; | ||||
|     const SHIFT: usize = 12; | ||||
|     const MASK: u64 = 0xfff; | ||||
| } | ||||
| 
 | ||||
| impl NotGiantPageSize for Size4KiB {} | ||||
| 
 | ||||
| /// A “huge” 2MiB page.
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum Size2MiB {} | ||||
| 
 | ||||
| impl PageSize for Size2MiB { | ||||
|     const SIZE: u64 = Size4KiB::SIZE * NUM_ENTRIES_4KIB; | ||||
|     const SIZE_AS_DEBUG_STR: &'static str = "2MiB"; | ||||
|     const SHIFT: usize = 21; | ||||
|     const MASK: u64 = 0x1fffff; | ||||
| } | ||||
| 
 | ||||
| impl NotGiantPageSize for Size2MiB {} | ||||
| 
 | ||||
| /// Type-safe enum wrapper covering Table<L>'s 64-bit entries.
 | ||||
| #[derive(Clone)] | ||||
| // #[repr(transparent)]
 | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ use { | |||
| mod addr; | ||||
| // pub mod mmu;
 | ||||
| mod features; | ||||
| mod page_size; | ||||
| mod phys_frame; | ||||
| mod virt_page; | ||||
| 
 | ||||
|  | @ -26,6 +27,7 @@ pub use mmu2::*; | |||
| 
 | ||||
| pub use addr::PhysAddr; | ||||
| pub use addr::VirtAddr; | ||||
| pub use page_size::PageSize; | ||||
| pub use phys_frame::PhysFrame; | ||||
| 
 | ||||
| use mmu_experimental::PhysFrame; | ||||
|  |  | |||
|  | @ -0,0 +1,68 @@ | |||
| /// Trait for abstracting over the possible page sizes, 4KiB, 16KiB, 2MiB, 1GiB.
 | ||||
| pub trait PageSize: Copy + PartialEq + Eq + PartialOrd + Ord { | ||||
|     /// The page size in bytes.
 | ||||
|     const SIZE: usize; | ||||
| 
 | ||||
|     /// A string representation of the page size for debug output.
 | ||||
|     const SIZE_AS_DEBUG_STR: &'static str; | ||||
| 
 | ||||
|     /// The page shift in bits.
 | ||||
|     const SHIFT: usize; | ||||
| 
 | ||||
|     /// The page mask in bits.
 | ||||
|     const MASK: u64; | ||||
| } | ||||
| 
 | ||||
| /// This trait is implemented for 4KiB, 16KiB, and 2MiB pages, but not for 1GiB pages.
 | ||||
| pub trait NotGiantPageSize: PageSize {} // @todo doesn't have to be pub??
 | ||||
| 
 | ||||
| /// A standard 4KiB page.
 | ||||
| #[derive(Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum Size4KiB {} | ||||
| 
 | ||||
| impl PageSize for Size4KiB { | ||||
|     const SIZE: usize = 4 * 1024; | ||||
|     const SIZE_AS_DEBUG_STR: &'static str = "4KiB"; | ||||
|     const SHIFT: usize = 12; | ||||
|     const MASK: u64 = 0xfff; | ||||
| } | ||||
| 
 | ||||
| impl NotGiantPageSize for Size4KiB {} | ||||
| 
 | ||||
| /// A standard 16KiB page.
 | ||||
| /// Currently unused.
 | ||||
| #[derive(Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum Size16KiB {} | ||||
| 
 | ||||
| impl PageSize for Size16KiB { | ||||
|     const SIZE: usize = 16 * 1024; | ||||
|     const SIZE_AS_DEBUG_STR: &'static str = "16KiB"; | ||||
|     const SHIFT: usize = 14; | ||||
|     const MASK: u64 = 0x3fff; | ||||
| } | ||||
| 
 | ||||
| impl NotGiantPageSize for Size16KiB {} | ||||
| 
 | ||||
| /// A “huge” 2MiB page.
 | ||||
| #[derive(Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum Size2MiB {} | ||||
| 
 | ||||
| impl PageSize for Size2MiB { | ||||
|     const SIZE: usize = 2 * 1024 * 1024; | ||||
|     const SIZE_AS_DEBUG_STR: &'static str = "2MiB"; | ||||
|     const SHIFT: usize = 21; | ||||
|     const MASK: u64 = 0x1f_ffff; | ||||
| } | ||||
| 
 | ||||
| impl NotGiantPageSize for Size2MiB {} | ||||
| 
 | ||||
| /// A “giant” 1GiB page.
 | ||||
| #[derive(Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum Size1GiB {} | ||||
| 
 | ||||
| impl PageSize for Size1GiB { | ||||
|     const SIZE: usize = 1024 * 1024 * 1024; | ||||
|     const SIZE_AS_DEBUG_STR: &'static str = "1GiB"; | ||||
|     const SHIFT: usize = 30; | ||||
|     const MASK: u64 = 0x3fff_ffff; | ||||
| } | ||||
|  | @ -1,6 +1,18 @@ | |||
| // Verbatim from https://github.com/rust-osdev/x86_64/blob/aa9ae54657beb87c2a491f2ab2140b2332afa6ba/src/structures/paging/frame.rs
 | ||||
| // Abstractions for default-sized and huge physical memory frames.
 | ||||
| 
 | ||||
| use { | ||||
|     crate::memory::{ | ||||
|         page_size::{PageSize, Size4KiB}, | ||||
|         PhysAddr, | ||||
|     }, | ||||
|     core::{ | ||||
|         fmt, | ||||
|         marker::PhantomData, | ||||
|         ops::{Add, AddAssign, Sub, SubAssign}, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| /// A physical memory frame.
 | ||||
| /// Frame is an addressable unit of the physical address space.
 | ||||
| #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
|  | @ -47,7 +59,7 @@ impl<S: PageSize> PhysFrame<S> { | |||
|     } | ||||
| 
 | ||||
|     /// Returns the size the frame (4KB, 2MB or 1GB).
 | ||||
|     pub fn size(&self) -> u64 { | ||||
|     pub fn size(&self) -> usize { | ||||
|         S::SIZE | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,6 +3,18 @@ | |||
| 
 | ||||
| // x86_64 page level numbering: P4 -> P3 -> P2 -> P1
 | ||||
| // armv8a page level numbering: L0 -> L1 -> L2 -> L3
 | ||||
| use { | ||||
|     crate::memory::{ | ||||
|         page_size::{NotGiantPageSize, PageSize, Size1GiB, Size2MiB, Size4KiB}, | ||||
|         VirtAddr, | ||||
|     }, | ||||
|     core::{ | ||||
|         fmt, | ||||
|         marker::PhantomData, | ||||
|         ops::{Add, AddAssign, Sub, SubAssign}, | ||||
|     }, | ||||
|     ux::u9, | ||||
| }; | ||||
| 
 | ||||
| /// A virtual memory page.
 | ||||
| #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
|  | @ -14,7 +26,7 @@ pub struct Page<S: PageSize = Size4KiB> { | |||
| 
 | ||||
| impl<S: PageSize> Page<S> { | ||||
|     /// The page size in bytes.
 | ||||
|     pub const SIZE: u64 = S::SIZE; | ||||
|     pub const SIZE: usize = S::SIZE; | ||||
| 
 | ||||
|     /// Returns the page that starts at the given virtual address.
 | ||||
|     ///
 | ||||
|  | @ -40,7 +52,7 @@ impl<S: PageSize> Page<S> { | |||
|     } | ||||
| 
 | ||||
|     /// Returns the size the page (4KB, 2MB or 1GB).
 | ||||
|     pub const fn size(&self) -> u64 { | ||||
|     pub const fn size(&self) -> usize { | ||||
|         S::SIZE | ||||
|     } | ||||
| 
 | ||||
|  | @ -174,6 +186,10 @@ impl<S: PageSize> PageRange<S> { | |||
|     pub fn is_empty(&self) -> bool { | ||||
|         self.start >= self.end | ||||
|     } | ||||
| 
 | ||||
|     pub fn num_pages(&self) -> usize { | ||||
|         (self.end - self.start) as usize / S::SIZE | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<S: PageSize> Iterator for PageRange<S> { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue