Browse Source

memory::paging::ActivePageTable: implement with(), switch()

master
3moon 8 years ago
parent
commit
c2a1b848cd
1 changed files with 37 additions and 0 deletions
  1. +37
    -0
      src/arch/x86_64/memory/paging/mod.rs

+ 37
- 0
src/arch/x86_64/memory/paging/mod.rs View File

@ -12,6 +12,8 @@ mod mapper;
use self::entry::*;
use self::table::{Table, Level4};
use self::temporary_page::TemporaryPage;
use self::mapper::Mapper;
/// Upper bound on entries per page table
const ENTRY_COUNT: usize = 512;
@ -40,18 +42,53 @@ impl ActivePageTable {
}
}
/// Executes a closure, with a different page table recursively mapped
pub fn with<F>(&mut self, table: &mut InactivePageTable, scratch_page: &mut TemporaryPage, f: F)
where F: FnOnce(&mut Mapper) {
use x86::shared::{tlb, control_regs};
{
// Backup the original P4 pointer
let backup = Frame::containing_address(
unsafe {control_regs::cr3()}
);
// Map a scratch page to the current p4 table
let p4_table = scratch_page.map_table_frame(backup.clone(), self);
// Overwrite main P4 recursive mapping
self.p4_mut()[511].set(table.p4_frame.clone(), PRESENT | WRITABLE);
unsafe {tlb::flush_all();} // flush *all* TLBs to prevent fuckiness
// Execute f in context of the new page table
f(self);
// Restore the original pointer to P4
p4_table[511].set(backup, PRESENT | WRITABLE);
unsafe {tlb::flush_all();} // prevent fuckiness
}
scratch_page.unmap(self);
}
/// Switches to a new [`InactivePageTable`], making it active.
///
/// Note: We don't need to flush the TLB here, as the CPU automatically flushes
/// the TLB when the P4 table is switched.
pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable {
use x86::shared::{control_regs};
let old_table = InactivePageTable {
p4_frame: Frame::containing_address(unsafe {control_regs::cr3()}),
};
unsafe {
control_regs::cr3_write(new_table.p4_frame.start_address());
}
old_table
}
}


Loading…
Cancel
Save