| @ -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!"); | |||
| } | |||
| } | |||