diff --git a/src/memory/paging/mod.rs b/src/memory/paging/mod.rs index 197917ee..cd9d3496 100644 --- a/src/memory/paging/mod.rs +++ b/src/memory/paging/mod.rs @@ -5,6 +5,7 @@ use self::table::{Table, Level4}; mod entry; mod table; +mod temporary_page; const ENTRY_COUNT: usize = 512; diff --git a/src/memory/paging/temporary_page.rs b/src/memory/paging/temporary_page.rs new file mode 100644 index 00000000..4b06bcae --- /dev/null +++ b/src/memory/paging/temporary_page.rs @@ -0,0 +1,79 @@ +use super::{Page, ActivePageTable, VirtualAddress}; +use super::table::{Table, Level1}; +use memory::{Frame, FrameAllocator}; + +pub struct TemporaryPage { + page: Page, + allocator: TinyAllocator, +} + +impl TemporaryPage { + pub fn new(page: Page, allocator: &mut A) -> TemporaryPage + where A: FrameAllocator + { + TemporaryPage { + page: page, + allocator: TinyAllocator::new(allocator), + } + } + + /// Maps the temporary page to the given frame in the active table. + /// Returns the start address of the temporary page. + pub fn map(&mut self, frame: Frame, active_table: &mut ActivePageTable) + -> VirtualAddress + { + use super::entry::WRITABLE; + + assert!(active_table.translate_page(self.page).is_none(), + "temporary page is already mapped"); + active_table.map_to(self.page, frame, WRITABLE, &mut self.allocator); + self.page.start_address() + } + + /// Unmaps the temporary page in the active table. + pub fn unmap(&mut self, active_table: &mut ActivePageTable) { + active_table.unmap(self.page, &mut self.allocator) + } + + /// Maps the temporary page to the given page table frame in the active + /// table. Returns a reference to the now mapped table. + pub fn map_table_frame(&mut self, + frame: Frame, + active_table: &mut ActivePageTable) + -> &mut Table { + unsafe { &mut *(self.map(frame, active_table) as *mut Table) } + } +} + +struct TinyAllocator([Option; 3]); + +impl TinyAllocator { + fn new(allocator: &mut A) -> TinyAllocator + where A: FrameAllocator + { + let mut f = || allocator.allocate_frame(); + let frames = [f(), f(), f()]; + TinyAllocator(frames) + } +} + +impl FrameAllocator for TinyAllocator { + fn allocate_frame(&mut self) -> Option { + for frame_option in &mut self.0 { + if frame_option.is_some() { + return frame_option.take(); + } + } + None + } + + fn deallocate_frame(&mut self, frame: Frame) { + for frame_option in &mut self.0 { + if frame_option.is_none() { + *frame_option = Some(frame); + return; + } + } + panic!("Tiny allocator can hold only 3 frames."); + } +}