From 7ce86b3a806a23db21d0377472c0b6f5b765ae1b Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Thu, 31 Dec 2015 01:53:57 +0100 Subject: [PATCH] Add temporary_page submodule --- src/memory/paging/mod.rs | 1 + src/memory/paging/table.rs | 2 +- src/memory/paging/temporary_page.rs | 86 +++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/memory/paging/temporary_page.rs diff --git a/src/memory/paging/mod.rs b/src/memory/paging/mod.rs index df2e2099..52e92008 100644 --- a/src/memory/paging/mod.rs +++ b/src/memory/paging/mod.rs @@ -14,6 +14,7 @@ use core::ptr::Unique; mod entry; mod table; +mod temporary_page; const ENTRY_COUNT: usize = 512; diff --git a/src/memory/paging/table.rs b/src/memory/paging/table.rs index e06c3db0..6b3c4bb2 100644 --- a/src/memory/paging/table.rs +++ b/src/memory/paging/table.rs @@ -89,7 +89,7 @@ pub trait TableLevel {} pub enum Level4 {} enum Level3 {} enum Level2 {} -enum Level1 {} +pub enum Level1 {} impl TableLevel for Level4 {} impl TableLevel for Level3 {} diff --git a/src/memory/paging/temporary_page.rs b/src/memory/paging/temporary_page.rs new file mode 100644 index 00000000..dac447f1 --- /dev/null +++ b/src/memory/paging/temporary_page.rs @@ -0,0 +1,86 @@ +// Copyright 2015 Philipp Oppermann. See the README.md +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +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() + } + + /// 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) } + } + + /// 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) + } +} + +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."); + } +}