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
 | // 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
 | /// Errors from mapping layer
 | ||||||
| #[derive(Debug, Snafu)] | #[derive(Debug, Snafu)] | ||||||
| pub enum TranslationError { | pub enum TranslationError { | ||||||
|  |  | ||||||
|  | @ -93,50 +93,6 @@ fn into_mmu_attributes( | ||||||
|     desc |     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.
 | /// Type-safe enum wrapper covering Table<L>'s 64-bit entries.
 | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| // #[repr(transparent)]
 | // #[repr(transparent)]
 | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ use { | ||||||
| mod addr; | mod addr; | ||||||
| // pub mod mmu;
 | // pub mod mmu;
 | ||||||
| mod features; | mod features; | ||||||
|  | mod page_size; | ||||||
| mod phys_frame; | mod phys_frame; | ||||||
| mod virt_page; | mod virt_page; | ||||||
| 
 | 
 | ||||||
|  | @ -26,6 +27,7 @@ pub use mmu2::*; | ||||||
| 
 | 
 | ||||||
| pub use addr::PhysAddr; | pub use addr::PhysAddr; | ||||||
| pub use addr::VirtAddr; | pub use addr::VirtAddr; | ||||||
|  | pub use page_size::PageSize; | ||||||
| pub use phys_frame::PhysFrame; | pub use phys_frame::PhysFrame; | ||||||
| 
 | 
 | ||||||
| use mmu_experimental::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
 | // 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.
 | // 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.
 | /// A physical memory frame.
 | ||||||
| /// Frame is an addressable unit of the physical address space.
 | /// Frame is an addressable unit of the physical address space.
 | ||||||
| #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | #[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).
 |     /// Returns the size the frame (4KB, 2MB or 1GB).
 | ||||||
|     pub fn size(&self) -> u64 { |     pub fn size(&self) -> usize { | ||||||
|         S::SIZE |         S::SIZE | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,18 @@ | ||||||
| 
 | 
 | ||||||
| // x86_64 page level numbering: P4 -> P3 -> P2 -> P1
 | // x86_64 page level numbering: P4 -> P3 -> P2 -> P1
 | ||||||
| // armv8a page level numbering: L0 -> L1 -> L2 -> L3
 | // 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.
 | /// A virtual memory page.
 | ||||||
| #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||||
|  | @ -14,7 +26,7 @@ pub struct Page<S: PageSize = Size4KiB> { | ||||||
| 
 | 
 | ||||||
| impl<S: PageSize> Page<S> { | impl<S: PageSize> Page<S> { | ||||||
|     /// The page size in bytes.
 |     /// 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.
 |     /// 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).
 |     /// Returns the size the page (4KB, 2MB or 1GB).
 | ||||||
|     pub const fn size(&self) -> u64 { |     pub const fn size(&self) -> usize { | ||||||
|         S::SIZE |         S::SIZE | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -174,6 +186,10 @@ impl<S: PageSize> PageRange<S> { | ||||||
|     pub fn is_empty(&self) -> bool { |     pub fn is_empty(&self) -> bool { | ||||||
|         self.start >= self.end |         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> { | impl<S: PageSize> Iterator for PageRange<S> { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue