fix rv32 entry editing

master
WangRunji 6 years ago
parent ff806d4465
commit 704af94211

@ -36,9 +36,9 @@ pub fn setup_page_table(frame: Frame) {
info!("setup init page table end"); 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 { impl PageTable for ActivePageTable {
/* /*
@ -84,17 +84,27 @@ impl PageTable for ActivePageTable {
* a mutable PageEntry reference of 'addr' * a mutable PageEntry reference of 'addr'
*/ */
fn get_entry(&mut self, addr: usize) -> Option<&mut Entry> { 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; return None;
} }
let page = Page::of_addr(VirtAddr::new(addr)); let entry = edit_entry_of(&page, |entry| *entry);
// ??? self.1 = PageEntry(entry, page);
let _ = self.0.translate_page(page); Some(&mut self.1)
let entry_addr = ((addr >> 10) & ((1 << 22) - 4)) | (RECURSIVE_INDEX << 22);
unsafe { Some(&mut *(entry_addr as *mut PageEntry)) }
} }
} }
fn edit_entry_of<T>(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 {} impl PageTableExt for ActivePageTable {}
// define the ROOT_PAGE_TABLE, and the virtual address of it? // define the ROOT_PAGE_TABLE, and the virtual address of it?
@ -103,23 +113,26 @@ const ROOT_PAGE_TABLE: *mut RvPageTable =
impl ActivePageTable { impl ActivePageTable {
pub unsafe fn new() -> Self { 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 /// implementation for the Entry trait in /crate/memory/src/paging/mod.rs
impl Entry for PageEntry { impl Entry for PageEntry {
fn update(&mut self) { fn update(&mut self) {
let addr = VirtAddr::new((self as *const _ as usize) << 10); edit_entry_of(&self.1, |entry| *entry = self.0);
sfence_vma(0, addr); sfence_vma(0, self.1.start_address());
} }
fn accessed(&self) -> bool { self.0.flags().contains(EF::ACCESSED) } fn accessed(&self) -> bool { self.0.flags().contains(EF::ACCESSED) }
fn dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) } fn dirty(&self) -> bool { self.0.flags().contains(EF::DIRTY) }
fn writable(&self) -> bool { self.0.flags().contains(EF::WRITABLE) } fn writable(&self) -> bool { self.0.flags().contains(EF::WRITABLE) }
fn present(&self) -> bool { self.0.flags().contains(EF::VALID | EF::READABLE) } 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_accessed(&mut self) { self.0.flags_mut().remove(EF::ACCESSED); }
fn clear_dirty(&mut self) { self.as_flags().remove(EF::DIRTY); } fn clear_dirty(&mut self) { self.0.flags_mut().remove(EF::DIRTY); }
fn set_writable(&mut self, value: bool) { self.as_flags().set(EF::WRITABLE, value); } fn set_writable(&mut self, value: bool) { self.0.flags_mut().set(EF::WRITABLE, value); }
fn set_present(&mut self, value: bool) { self.as_flags().set(EF::VALID | EF::READABLE, 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 target(&self) -> usize { self.0.addr().as_u32() as usize }
fn set_target(&mut self, target: usize) { fn set_target(&mut self, target: usize) {
let flags = self.0.flags(); 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 writable_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED1) }
fn readonly_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED2) } fn readonly_shared(&self) -> bool { self.0.flags().contains(EF::RESERVED2) }
fn set_shared(&mut self, writable: bool) { 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::RESERVED1, writable);
flags.set(EF::RESERVED2, !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 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 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 execute(&self) -> bool { self.0.flags().contains(EF::EXECUTABLE) }
fn set_execute(&mut self, value: bool) { self.as_flags().set(EF::EXECUTABLE, value); } fn set_execute(&mut self, value: bool) { self.0.flags_mut().set(EF::EXECUTABLE, value); }
fn mmio(&self) -> bool { unimplemented!() } fn mmio(&self) -> bool { false }
fn set_mmio(&mut self, value: bool) { unimplemented!() } fn set_mmio(&mut self, value: bool) { }
}
impl PageEntry {
fn as_flags(&mut self) -> &mut EF {
unsafe { &mut *(self as *mut _ as *mut EF) }
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -174,15 +181,12 @@ impl InactivePageTable for InactivePageTable0 {
let e1 = table[KERNEL_P2_INDEX]; let e1 = table[KERNEL_P2_INDEX];
let e2 = table[KERNEL_P2_INDEX + 1]; let e2 = table[KERNEL_P2_INDEX + 1];
let e3 = table[KERNEL_P2_INDEX + 2]; let e3 = table[KERNEL_P2_INDEX + 2];
assert!(!e1.is_unused());
assert!(!e2.is_unused());
assert!(!e3.is_unused());
self.edit(|_| { self.edit(|_| {
table[0x40] = e0; table[0x40] = e0;
table[KERNEL_P2_INDEX].set(e1.frame(), EF::VALID | EF::GLOBAL); table[KERNEL_P2_INDEX] = e1;
table[KERNEL_P2_INDEX + 1].set(e2.frame(), EF::VALID | EF::GLOBAL); table[KERNEL_P2_INDEX + 1] = e2;
table[KERNEL_P2_INDEX + 2].set(e3.frame(), EF::VALID | EF::GLOBAL); table[KERNEL_P2_INDEX + 2] = e3;
}); });
} }

Loading…
Cancel
Save