diff --git a/src/arch/aarch64/paging/entry.rs b/src/arch/aarch64/paging/entry.rs index 31f38ed..d326780 100644 --- a/src/arch/aarch64/paging/entry.rs +++ b/src/arch/aarch64/paging/entry.rs @@ -3,7 +3,7 @@ use crate::memory::Frame; -use super::PhysicalAddress; +use super::{PageFlags, PhysicalAddress, RmmA, RmmArch}; /// A page table entry #[derive(Debug)] @@ -56,7 +56,7 @@ bitflags! { // These are translated to AArch64 specific Page and Table descriptors as and when needed. bitflags! { #[derive(Default)] - pub struct EntryFlags: u64 { + pub struct EntryFlags: usize { const PRESENT = 1 << 0; const HUGE_PAGE = 1 << 1; const GLOBAL = 1 << 2; @@ -102,8 +102,8 @@ impl Entry { } /// Get the current entry flags - pub fn flags(&self) -> EntryFlags { - EntryFlags::from_bits_truncate(self.0) + pub fn flags(&self) -> PageFlags { + unsafe { PageFlags::from_data((self.0 as usize & RmmA::ENTRY_FLAGS_MASK) & !(COUNTER_MASK as usize)) } } /// Get the associated frame, if available, for a level 4, 3, or 2 page @@ -138,17 +138,9 @@ impl Entry { self.0 = (frame.start_address().data() as u64) | flags.bits() | access_flag.bits() | (self.0 & COUNTER_MASK); } - pub fn set(&mut self, frame: Frame, flags: EntryFlags) { + pub fn set(&mut self, frame: Frame, flags: PageFlags) { debug_assert!(frame.start_address().data() & !ADDRESS_MASK == 0); - // ODDNESS Alert: We need to set the AF bit - despite this being a TableDescriptor!!! - // The Arm ARM says this bit (bit 10) is IGNORED in Table Descriptors so hopefully this is OK - let mut translated_flags = TableDescriptorFlags::AF | TableDescriptorFlags::TABLE; - - if flags.contains(EntryFlags::PRESENT) { - translated_flags.insert(TableDescriptorFlags::VALID); - } - - self.0 = (frame.start_address().data() as u64) | translated_flags.bits() | (self.0 & COUNTER_MASK); + self.0 = (frame.start_address().data() as u64) | (flags.data() as u64) | (self.0 & COUNTER_MASK); } /// Get bit 51 in entry, used as 1 of 9 bits (in 9 entries) used as a counter for the page table diff --git a/src/arch/aarch64/paging/mapper.rs b/src/arch/aarch64/paging/mapper.rs index 44a872a..27e9ed0 100644 --- a/src/arch/aarch64/paging/mapper.rs +++ b/src/arch/aarch64/paging/mapper.rs @@ -3,95 +3,25 @@ use core::ptr::Unique; use crate::memory::{allocate_frames, deallocate_frames, Frame}; -use super::{ActivePageTable, Page, PAGE_SIZE, PhysicalAddress, VirtualAddress, VirtualAddressType}; +use super::{ActivePageTable, Page, PAGE_SIZE, PageFlags, PhysicalAddress, TableKind, VirtualAddress}; use super::entry::{EntryFlags, PageDescriptorFlags}; use super::table::{self, Table, Level4}; +use super::RmmA; -/// In order to enforce correct paging operations in the kernel, these types -/// are returned on any mapping operation to get the code involved to specify -/// how it intends to flush changes to a page table -#[must_use = "The page table must be flushed, or the changes unsafely ignored"] -pub struct MapperFlush(Page); - -impl MapperFlush { - /// Create a new page flush promise - pub fn new(page: Page) -> MapperFlush { - MapperFlush(page) - } - - /// Flush this page in the active table - pub fn flush(self, table: &mut ActivePageTable) { - table.flush(self.0); - mem::forget(self); - } - - /// Ignore the flush. This is unsafe, and a reason should be provided for use - pub unsafe fn ignore(self) { - mem::forget(self); - } -} - -/// A flush cannot be dropped, it must be consumed -impl Drop for MapperFlush { - fn drop(&mut self) { - panic!("Mapper flush was not utilized"); - } -} - -/// To allow for combining multiple flushes into one, we have a way of flushing -/// the active table, which can consume `MapperFlush` structs -#[must_use = "The page table must be flushed, or the changes unsafely ignored"] -pub struct MapperFlushAll(bool); - -impl MapperFlushAll { - /// Create a new promise to flush all mappings - pub fn new() -> MapperFlushAll { - MapperFlushAll(false) - } - - /// Consume a single page flush - pub fn consume(&mut self, flush: MapperFlush) { - self.0 = true; - mem::forget(flush); - } - - /// Flush the active page table - pub fn flush(self, table: &mut ActivePageTable) { - if self.0 { - table.flush_all(); - } - mem::forget(self); - } - - /// Ignore the flush. This is unsafe, and a reason should be provided for use - pub unsafe fn ignore(self) { - mem::forget(self); - } -} - -/// A flush cannot be dropped, it must be consumed -impl Drop for MapperFlushAll { - fn drop(&mut self) { - panic!("Mapper flush all was not utilized"); - } -} +pub use rmm::{PageFlush, PageFlushAll}; +#[derive(Debug)] pub struct Mapper { p4: Unique>, - pub mapper_type: MapperType -} - -pub enum MapperType { - User, - Kernel + pub table_kind: TableKind } impl Mapper { /// Create a new page table - pub unsafe fn new(mapper_type: MapperType) -> Mapper { - match mapper_type { - MapperType::User => Mapper { p4: Unique::new_unchecked(table::U4), mapper_type }, - MapperType::Kernel => Mapper { p4: Unique::new_unchecked(table::P4), mapper_type } + pub unsafe fn new(table_kind: TableKind) -> Mapper { + match table_kind { + TableKind::User => Mapper { p4: Unique::new_unchecked(table::U4), table_kind }, + TableKind::Kernel => Mapper { p4: Unique::new_unchecked(table::P4), table_kind } } } @@ -104,105 +34,44 @@ impl Mapper { } /// Map a page to a frame - pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags) -> MapperFlush { + pub fn map_to(&mut self, page: Page, frame: Frame, flags: PageFlags) -> PageFlush { let p3 = self.p4_mut().next_table_create(page.p4_index()); let p2 = p3.next_table_create(page.p3_index()); let p1 = p2.next_table_create(page.p2_index()); - let mut translated_flags: PageDescriptorFlags = PageDescriptorFlags::VALID | PageDescriptorFlags::PAGE | PageDescriptorFlags::AF; - - if flags.contains(EntryFlags::NO_EXECUTE) { - match page.start_address().kind() { - TableKind::User => { - translated_flags.insert(PageDescriptorFlags::UXN); - }, - TableKind::Kernel => { - translated_flags.insert(PageDescriptorFlags::PXN); - }, - } - } - - if flags.contains(EntryFlags::WRITABLE) { - if flags.contains(EntryFlags::USER_ACCESSIBLE) { - translated_flags.remove(PageDescriptorFlags::AP_2); - translated_flags.insert(PageDescriptorFlags::AP_1); - } else { - translated_flags.remove(PageDescriptorFlags::AP_2); - translated_flags.remove(PageDescriptorFlags::AP_1); - } - } else { - if flags.contains(EntryFlags::USER_ACCESSIBLE) { - translated_flags.insert(PageDescriptorFlags::AP_2); - translated_flags.insert(PageDescriptorFlags::AP_1); - } else { - translated_flags.insert(PageDescriptorFlags::AP_2); - translated_flags.remove(PageDescriptorFlags::AP_1); - } - } assert!(p1[page.p1_index()].is_unused(), "{:X}: Set to {:X}: {:?}, requesting {:X}: {:?}", page.start_address().data(), - p1[page.p1_index()].address().data(), p1[page.p1_index()].page_descriptor_entry_flags(), - frame.start_address().data(), translated_flags); + p1[page.p1_index()].address().data(), p1[page.p1_index()].flags(), + frame.start_address().data(), flags); p1.increment_entry_count(); - p1[page.p1_index()].page_descriptor_entry_set(frame, translated_flags); - MapperFlush::new(page) + p1[page.p1_index()].set(frame, flags); + PageFlush::new(page.start_address()) } /// Map a page to the next free frame - pub fn map(&mut self, page: Page, flags: EntryFlags) -> MapperFlush { + pub fn map(&mut self, page: Page, flags: PageFlags) -> PageFlush { let frame = allocate_frames(1).expect("out of frames"); self.map_to(page, frame, flags) } /// Update flags for a page - pub fn remap(&mut self, page: Page, flags: EntryFlags) -> MapperFlush { + pub fn remap(&mut self, page: Page, flags: PageFlags) -> PageFlush { let p3 = self.p4_mut().next_table_mut(page.p4_index()).expect("failed to remap: no p3"); let p2 = p3.next_table_mut(page.p3_index()).expect("failed to remap: no p2"); let p1 = p2.next_table_mut(page.p2_index()).expect("failed to remap: no p1"); let frame = p1[page.p1_index()].pointed_frame_at_l1().expect("failed to remap: not mapped"); - let mut translated_flags: PageDescriptorFlags = PageDescriptorFlags::VALID | PageDescriptorFlags::PAGE | PageDescriptorFlags::AF; - - if flags.contains(EntryFlags::NO_EXECUTE) { - match page.start_address().get_type() { - VirtualAddressType::User => { - translated_flags.insert(PageDescriptorFlags::UXN); - }, - VirtualAddressType::Kernel => { - translated_flags.insert(PageDescriptorFlags::PXN); - }, - } - } - - if flags.contains(EntryFlags::WRITABLE) { - if flags.contains(EntryFlags::USER_ACCESSIBLE) { - translated_flags.remove(PageDescriptorFlags::AP_2); - translated_flags.insert(PageDescriptorFlags::AP_1); - } else { - translated_flags.remove(PageDescriptorFlags::AP_2); - translated_flags.remove(PageDescriptorFlags::AP_1); - } - } else { - if flags.contains(EntryFlags::USER_ACCESSIBLE) { - translated_flags.insert(PageDescriptorFlags::AP_2); - translated_flags.insert(PageDescriptorFlags::AP_1); - } else { - translated_flags.insert(PageDescriptorFlags::AP_2); - translated_flags.remove(PageDescriptorFlags::AP_1); - } - } - - p1[page.p1_index()].page_descriptor_entry_set(frame, translated_flags); - MapperFlush::new(page) + p1[page.p1_index()].set(frame, flags); + PageFlush::new(page.start_address()) } /// Identity map a frame - pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags) -> MapperFlush { + pub fn identity_map(&mut self, frame: Frame, flags: PageFlags) -> PageFlush { let page = Page::containing_address(VirtualAddress::new(frame.start_address().data())); self.map_to(page, frame, flags) } - fn unmap_inner(&mut self, page: &Page, keep_parents: bool) -> Frame { + fn unmap_inner(&mut self, page: Page, keep_parents: bool) -> Frame { let frame; let p4 = self.p4_mut(); @@ -270,16 +139,16 @@ impl Mapper { } /// Unmap a page - pub fn unmap(&mut self, page: Page) -> MapperFlush { - let frame = self.unmap_inner(&page, false); + pub fn unmap(&mut self, page: Page) -> PageFlush { + let frame = self.unmap_inner(page, false); deallocate_frames(frame, 1); - MapperFlush::new(page) + PageFlush::new(page.start_address()) } /// Unmap a page, return frame without free - pub fn unmap_return(&mut self, page: Page, keep_parents: bool) -> (MapperFlush, Frame) { - let frame = self.unmap_inner(&page, keep_parents); - (MapperFlush::new(page), frame) + pub fn unmap_return(&mut self, page: Page, keep_parents: bool) -> (PageFlush, Frame) { + let frame = self.unmap_inner(page, keep_parents); + (PageFlush::new(page.start_address()), frame) } pub fn translate_page(&self, page: Page) -> Option { @@ -289,52 +158,11 @@ impl Mapper { .and_then(|p1| p1[page.p1_index()].pointed_frame()) } - pub fn translate_page_flags(&self, page: Page) -> Option { - let mut translated_flags: EntryFlags = Default::default(); - - if let Some(flags) = self.p4().next_table(page.p4_index()) + pub fn translate_page_flags(&self, page: Page) -> Option> { + self.p4().next_table(page.p4_index()) .and_then(|p3| p3.next_table(page.p3_index())) .and_then(|p2| p2.next_table(page.p2_index())) - .and_then(|p1| Some(p1[page.p1_index()].page_descriptor_entry_flags())) { - - if flags.contains(PageDescriptorFlags::VALID) { - translated_flags.insert(EntryFlags::PRESENT); - } - - if flags.contains(PageDescriptorFlags::AF) { - translated_flags.insert(EntryFlags::AF); - } - translated_flags.insert(EntryFlags::AF); - - if flags.contains(PageDescriptorFlags::UXN) || flags.contains(PageDescriptorFlags::PXN) { - translated_flags.insert(EntryFlags::NO_EXECUTE); - } - - if !flags.contains(PageDescriptorFlags::AP_2) && !flags.contains(PageDescriptorFlags::AP_1) { - translated_flags.insert(EntryFlags::WRITABLE); - translated_flags.remove(EntryFlags::USER_ACCESSIBLE); - } - - if !flags.contains(PageDescriptorFlags::AP_2) && flags.contains(PageDescriptorFlags::AP_1) { - translated_flags.insert(EntryFlags::WRITABLE); - translated_flags.insert(EntryFlags::USER_ACCESSIBLE); - } - - if flags.contains(PageDescriptorFlags::AP_2) && !flags.contains(PageDescriptorFlags::AP_1) { - translated_flags.remove(EntryFlags::WRITABLE); - translated_flags.remove(EntryFlags::USER_ACCESSIBLE); - } - - if flags.contains(PageDescriptorFlags::AP_2) && flags.contains(PageDescriptorFlags::AP_1) { - translated_flags.remove(EntryFlags::WRITABLE); - translated_flags.insert(EntryFlags::USER_ACCESSIBLE); - } - - Some(translated_flags) - } - else { - None - } + .and_then(|p1| Some(p1[page.p1_index()].flags())) } /// Translate a virtual address to a physical one