Update page table.

master
Yuhao Zhou 6 years ago
parent cc5bb8a81f
commit 77ba66a0a3

@ -9,7 +9,7 @@ use mips::paging::{
use mips::tlb::*; use mips::tlb::*;
use rcore_memory::paging::*; use rcore_memory::paging::*;
pub struct ActivePageTable(TwoLevelPageTable<'static>, PageEntry); pub struct ActivePageTable(usize, PageEntry);
/// PageTableEntry: the contents of this entry. /// PageTableEntry: the contents of this entry.
/// Page: this entry is the pte of page `Page`. /// Page: this entry is the pte of page `Page`.
@ -21,9 +21,8 @@ impl PageTable for ActivePageTable {
let flags = EF::VALID | EF::WRITABLE | EF::CACHEABLE; let flags = EF::VALID | EF::WRITABLE | EF::CACHEABLE;
let page = Page::of_addr(VirtAddr::new(addr)); let page = Page::of_addr(VirtAddr::new(addr));
let frame = Frame::of_addr(PhysAddr::new(target)); let frame = Frame::of_addr(PhysAddr::new(target));
// map the page to the frame using FrameAllocatorForRiscv
// we may need frame allocator to alloc frame for new page table(first/second) // we may need frame allocator to alloc frame for new page table(first/second)
self.0 self.get_table()
.map_to(page, frame, flags, &mut FrameAllocatorForRiscv) .map_to(page, frame, flags, &mut FrameAllocatorForRiscv)
.unwrap() .unwrap()
.flush(); .flush();
@ -32,13 +31,13 @@ impl PageTable for ActivePageTable {
fn unmap(&mut self, addr: usize) { fn unmap(&mut self, addr: usize) {
let page = Page::of_addr(VirtAddr::new(addr)); let page = Page::of_addr(VirtAddr::new(addr));
let (_, flush) = self.0.unmap(page).unwrap(); let (_, flush) = self.get_table().unmap(page).unwrap();
flush.flush(); flush.flush();
} }
fn get_entry(&mut self, vaddr: usize) -> Option<&mut Entry> { fn get_entry(&mut self, vaddr: usize) -> Option<&mut Entry> {
let page = Page::of_addr(VirtAddr::new(vaddr)); let page = Page::of_addr(VirtAddr::new(vaddr));
if let Ok(e) = self.0.ref_entry(page.clone()) { if let Ok(e) = self.get_table().ref_entry(page.clone()) {
let e = unsafe { &mut *(e as *mut PageTableEntry) }; let e = unsafe { &mut *(e as *mut PageTableEntry) };
self.1 = PageEntry(e, page); self.1 = PageEntry(e, page);
Some(&mut self.1 as &mut Entry) Some(&mut self.1 as &mut Entry)
@ -70,15 +69,31 @@ pub fn root_page_table_buffer() -> &'static mut MIPSPageTable {
impl PageTableExt for ActivePageTable {} impl PageTableExt for ActivePageTable {}
static mut __page_table_with_mode: bool = false;
/// The virtual address of root page table /// The virtual address of root page table
impl ActivePageTable { impl ActivePageTable {
pub unsafe fn new() -> Self { pub unsafe fn new() -> Self {
ActivePageTable( ActivePageTable(
TwoLevelPageTable::new(root_page_table_buffer()), get_root_page_table_ptr(),
::core::mem::uninitialized(), ::core::mem::uninitialized(),
) )
} }
unsafe fn get_raw_table(&mut self) -> *mut MIPSPageTable {
if __page_table_with_mode {
get_root_page_table_ptr() as *mut MIPSPageTable
} else {
self.0 as *mut MIPSPageTable
}
}
fn get_table(&mut self) -> TwoLevelPageTable<'static> {
unsafe {
TwoLevelPageTable::new(&mut *self.get_raw_table())
}
}
} }
/// implementation for the Entry trait in /crate/memory/src/paging/mod.rs /// implementation for the Entry trait in /crate/memory/src/paging/mod.rs
@ -189,26 +204,54 @@ impl InactivePageTable for InactivePageTable0 {
} }
fn edit<T>(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T { fn edit<T>(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T {
let pt: *mut MIPSPageTable = unsafe { self.token() as *mut MIPSPageTable };
unsafe { unsafe {
clear_all_tlb(); clear_all_tlb();
} }
debug!("edit table {:x?} -> {:x?}", Self::active_token(), self.token());
let mut active = unsafe { let mut active = unsafe {
ActivePageTable( ActivePageTable(
TwoLevelPageTable::new(&mut *pt), self.token(),
::core::mem::uninitialized(), ::core::mem::uninitialized(),
) )
}; };
let ret = f(&mut active); let ret = f(&mut active);
debug!("finish table");
unsafe { unsafe {
clear_all_tlb(); clear_all_tlb();
} }
ret ret
} }
unsafe fn with<T>(&self, f: impl FnOnce() -> T) -> T {
let old_token = Self::active_token();
let new_token = self.token();
let old_mode = unsafe { __page_table_with_mode };
unsafe {
__page_table_with_mode = true;
}
debug!("switch table {:x?} -> {:x?}", old_token, new_token);
if old_token != new_token {
Self::set_token(new_token);
Self::flush_tlb();
}
let ret = f();
debug!("switch table {:x?} -> {:x?}", new_token, old_token);
if old_token != new_token {
Self::set_token(old_token);
Self::flush_tlb();
}
unsafe {
__page_table_with_mode = old_mode;
}
ret
}
} }
impl Drop for InactivePageTable0 { impl Drop for InactivePageTable0 {

Loading…
Cancel
Save