Browse Source

Implement a TemporaryPage

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

+ 75
- 0
src/arch/x86_64/memory/paging/temporary_page.rs View File

@ -0,0 +1,75 @@
use arch::x86_64::memory::{Frame, FrameAllocator};
use super::{Page, Table, ActivePageTable};
use super::table::{Level1, Level4};
use super::{VirtualAddress};
pub struct TemporaryPage {
page: Page,
allocator: TinyAllocator,
}
impl TemporaryPage {
pub fn new<A>(page: Page, allocator: &mut A) -> TemporaryPage
where A: FrameAllocator {
TemporaryPage {
page: page,
allocator: TinyAllocator::new(allocator),
}
}
/// Maps the temporary page to the given frame, using the active table.
/// Returns the start address of the temporary page in VRAM.
pub fn map(&mut self, frame: Frame, active_table: &mut ActivePageTable) -> VirtualAddress {
use super::entry::WRITABLE;
assert!(active_table.page_to_frame(self.page).is_none(),
"Temporary page is already mapped!");
active_table.map_to(self.page, frame, WRITABLE, &mut self.allocator);
self.page.start_address()
}
/// Maps the temporary page to the given page table frame, using the active table.
/// Returns a &mut reference to the now-mapped table.
pub fn map_table_frame(&mut self, frame: Frame, active_table: &mut ActivePageTable)
-> &mut Table<Level1> {
unsafe { &mut *(self.map(frame, active_table) as *mut Table<Level1>) }
}
pub fn unmap(&mut self, active_table: &mut ActivePageTable) {
active_table.unmap(self.page, &mut self.allocator);
}
}
/// A tiny frame allocator which can only hold three frames,
/// used to temporarily create a P3, P2, and P1 table.
struct TinyAllocator([Option<Frame>; 3]);
impl TinyAllocator {
fn new<A>(allocator: &mut A) -> TinyAllocator
where A: FrameAllocator{
let mut f = || allocator.alloc_frame();
let frames = [f(), f(), f()];
TinyAllocator(frames)
}
}
impl FrameAllocator for TinyAllocator {
fn alloc_frame(&mut self) -> Option<Frame> {
for frame in &mut self.0 {
if frame.is_some() {
return frame.take();
}
}
None
}
fn dealloc_frame(&mut self, frame: Frame) {
for stored_frame in &mut self.0 {
if stored_frame.is_none() {
*stored_frame = Some(frame);
return;
}
}
panic!("TinyAllocator can only hold 3 frames!");
}
}

Loading…
Cancel
Save