diff --git a/kernel/src/arch/riscv32/paging.rs b/kernel/src/arch/riscv32/paging.rs index 795c384..0d86c29 100644 --- a/kernel/src/arch/riscv32/paging.rs +++ b/kernel/src/arch/riscv32/paging.rs @@ -36,9 +36,9 @@ pub fn setup_page_table(frame: Frame) { info!("setup init page table end"); } -pub struct ActivePageTable(RecursivePageTable<'static>); +pub struct ActivePageTable(RecursivePageTable<'static>, PageEntry); -pub struct PageEntry(PageTableEntry); +pub struct PageEntry(PageTableEntry, Page); impl PageTable for ActivePageTable { /* @@ -84,17 +84,27 @@ impl PageTable for ActivePageTable { * a mutable PageEntry reference of 'addr' */ fn get_entry(&mut self, addr: usize) -> Option<&mut Entry> { - if unsafe { !(*ROOT_PAGE_TABLE)[addr >> 22].flags().contains(EF::VALID) } { + let p2 = unsafe { ROOT_PAGE_TABLE.as_mut().unwrap() }; + let page = Page::of_addr(VirtAddr::new(addr)); + if !p2[page.p2_index()].flags().contains(EF::VALID) { return None; } - let page = Page::of_addr(VirtAddr::new(addr)); - // ??? - let _ = self.0.translate_page(page); - let entry_addr = ((addr >> 10) & ((1 << 22) - 4)) | (RECURSIVE_INDEX << 22); - unsafe { Some(&mut *(entry_addr as *mut PageEntry)) } + let entry = edit_entry_of(&page, |entry| *entry); + self.1 = PageEntry(entry, page); + Some(&mut self.1) } } +fn edit_entry_of(page: &Page, f: impl FnOnce(&mut PageTableEntry) -> T) -> T { + let p2_flags = unsafe { (*ROOT_PAGE_TABLE)[page.p2_index()].flags_mut() }; + p2_flags.insert(EF::READABLE | EF::WRITABLE); + let entry_addr = (RECURSIVE_INDEX << 22) | (page.p2_index() << 12) | (page.p1_index() << 2); + let entry = unsafe { &mut *(entry_addr as *mut PageTableEntry) }; + let ret = f(entry); + p2_flags.remove(EF::READABLE | EF::WRITABLE); + ret +} + impl PageTableExt for ActivePageTable {} // define the ROOT_PAGE_TABLE, and the virtual address of it? @@ -103,23 +113,26 @@ const ROOT_PAGE_TABLE: *mut RvPageTable = impl ActivePageTable { pub unsafe fn new() -> Self { - ActivePageTable(RecursivePageTable::new(&mut *ROOT_PAGE_TABLE).unwrap()) + ActivePageTable( + RecursivePageTable::new(&mut *ROOT_PAGE_TABLE).unwrap(), + ::core::mem::zeroed() + ) } } /// implementation for the Entry trait in /crate/memory/src/paging/mod.rs impl Entry for PageEntry { fn update(&mut self) { - let addr = VirtAddr::new((self as *const _ as usize) << 10); - sfence_vma(0, addr); + edit_entry_of(&self.1, |entry| *entry = self.0); + sfence_vma(0, self.1.start_address()); } fn accessed(&self) -> bool { self.0.flags().contains(EF::ACCESSED) } fn dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) } fn writable(&self) -> bool { self.0.flags().contains(EF::WRITABLE) } fn present(&self) -> bool { self.0.flags().contains(EF::VALID | EF::READABLE) } - fn clear_accessed(&mut self) { self.as_flags().remove(EF::ACCESSED); } - fn clear_dirty(&mut self) { self.as_flags().remove(EF::DIRTY); } - fn set_writable(&mut self, value: bool) { self.as_flags().set(EF::WRITABLE, value); } - fn set_present(&mut self, value: bool) { self.as_flags().set(EF::VALID | EF::READABLE, value); } + fn clear_accessed(&mut self) { self.0.flags_mut().remove(EF::ACCESSED); } + fn clear_dirty(&mut self) { self.0.flags_mut().remove(EF::DIRTY); } + fn set_writable(&mut self, value: bool) { self.0.flags_mut().set(EF::WRITABLE, value); } + fn set_present(&mut self, value: bool) { self.0.flags_mut().set(EF::VALID | EF::READABLE, value); } fn target(&self) -> usize { self.0.addr().as_u32() as usize } fn set_target(&mut self, target: usize) { let flags = self.0.flags(); @@ -129,25 +142,19 @@ impl Entry for PageEntry { fn writable_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED1) } fn readonly_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED2) } fn set_shared(&mut self, writable: bool) { - let flags = self.as_flags(); + let flags = self.0.flags_mut(); flags.set(EF::RESERVED1, writable); flags.set(EF::RESERVED2, !writable); } - fn clear_shared(&mut self) { self.as_flags().remove(EF::RESERVED1 | EF::RESERVED2); } + fn clear_shared(&mut self) { self.0.flags_mut().remove(EF::RESERVED1 | EF::RESERVED2); } fn swapped(&self) -> bool { self.0.flags().contains(EF::RESERVED1) } - fn set_swapped(&mut self, value: bool) { self.as_flags().set(EF::RESERVED1, value); } + fn set_swapped(&mut self, value: bool) { self.0.flags_mut().set(EF::RESERVED1, value); } fn user(&self) -> bool { self.0.flags().contains(EF::USER) } - fn set_user(&mut self, value: bool) { self.as_flags().set(EF::USER, value); } + fn set_user(&mut self, value: bool) { self.0.flags_mut().set(EF::USER, value); } fn execute(&self) -> bool { self.0.flags().contains(EF::EXECUTABLE) } - fn set_execute(&mut self, value: bool) { self.as_flags().set(EF::EXECUTABLE, value); } - fn mmio(&self) -> bool { unimplemented!() } - fn set_mmio(&mut self, value: bool) { unimplemented!() } -} - -impl PageEntry { - fn as_flags(&mut self) -> &mut EF { - unsafe { &mut *(self as *mut _ as *mut EF) } - } + fn set_execute(&mut self, value: bool) { self.0.flags_mut().set(EF::EXECUTABLE, value); } + fn mmio(&self) -> bool { false } + fn set_mmio(&mut self, value: bool) { } } #[derive(Debug)] @@ -174,15 +181,12 @@ impl InactivePageTable for InactivePageTable0 { let e1 = table[KERNEL_P2_INDEX]; let e2 = table[KERNEL_P2_INDEX + 1]; let e3 = table[KERNEL_P2_INDEX + 2]; - assert!(!e1.is_unused()); - assert!(!e2.is_unused()); - assert!(!e3.is_unused()); self.edit(|_| { table[0x40] = e0; - table[KERNEL_P2_INDEX].set(e1.frame(), EF::VALID | EF::GLOBAL); - table[KERNEL_P2_INDEX + 1].set(e2.frame(), EF::VALID | EF::GLOBAL); - table[KERNEL_P2_INDEX + 2].set(e3.frame(), EF::VALID | EF::GLOBAL); + table[KERNEL_P2_INDEX] = e1; + table[KERNEL_P2_INDEX + 1] = e2; + table[KERNEL_P2_INDEX + 2] = e3; }); }