Move frame allocation to two global functions, locking happens inside them
This commit is contained in:
parent
ebf9766ef5
commit
78432b3875
11 changed files with 97 additions and 140 deletions
|
@ -1,6 +1,6 @@
|
|||
use core::ptr::Unique;
|
||||
|
||||
use memory::{Frame, FrameAllocator};
|
||||
use memory::{allocate_frame, deallocate_frame, Frame};
|
||||
|
||||
use super::{Page, PAGE_SIZE, PhysicalAddress, VirtualAddress};
|
||||
use super::entry::{self, EntryFlags};
|
||||
|
@ -27,37 +27,29 @@ impl Mapper {
|
|||
}
|
||||
|
||||
/// Map a page to a frame
|
||||
pub fn map_to<A>(&mut self, page: Page, frame: Frame, flags: EntryFlags, allocator: &mut A)
|
||||
where A: FrameAllocator
|
||||
{
|
||||
let mut p3 = self.p4_mut().next_table_create(page.p4_index(), allocator);
|
||||
let mut p2 = p3.next_table_create(page.p3_index(), allocator);
|
||||
let mut p1 = p2.next_table_create(page.p2_index(), allocator);
|
||||
pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags) {
|
||||
let mut p3 = self.p4_mut().next_table_create(page.p4_index());
|
||||
let mut p2 = p3.next_table_create(page.p3_index());
|
||||
let mut p1 = p2.next_table_create(page.p2_index());
|
||||
|
||||
assert!(p1[page.p1_index()].is_unused());
|
||||
p1[page.p1_index()].set(frame, flags | entry::PRESENT);
|
||||
}
|
||||
|
||||
/// Map a page to the next free frame
|
||||
pub fn map<A>(&mut self, page: Page, flags: EntryFlags, allocator: &mut A)
|
||||
where A: FrameAllocator
|
||||
{
|
||||
let frame = allocator.allocate_frame().expect("out of memory");
|
||||
self.map_to(page, frame, flags, allocator)
|
||||
pub fn map(&mut self, page: Page, flags: EntryFlags) {
|
||||
let frame = allocate_frame().expect("out of memory");
|
||||
self.map_to(page, frame, flags)
|
||||
}
|
||||
|
||||
/// Identity map a frame
|
||||
pub fn identity_map<A>(&mut self, frame: Frame, flags: EntryFlags, allocator: &mut A)
|
||||
where A: FrameAllocator
|
||||
{
|
||||
pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags) {
|
||||
let page = Page::containing_address(VirtualAddress::new(frame.start_address().get()));
|
||||
self.map_to(page, frame, flags, allocator)
|
||||
self.map_to(page, frame, flags)
|
||||
}
|
||||
|
||||
/// Unmap a page
|
||||
pub fn unmap<A>(&mut self, page: Page, allocator: &mut A)
|
||||
where A: FrameAllocator
|
||||
{
|
||||
pub fn unmap(&mut self, page: Page) {
|
||||
assert!(self.translate(page.start_address()).is_some());
|
||||
|
||||
let p1 = self.p4_mut()
|
||||
|
@ -68,7 +60,7 @@ impl Mapper {
|
|||
let frame = p1[page.p1_index()].pointed_frame().unwrap();
|
||||
p1[page.p1_index()].set_unused();
|
||||
// TODO free p(1,2,3) table if empty
|
||||
allocator.deallocate_frame(frame);
|
||||
deallocate_frame(frame);
|
||||
}
|
||||
|
||||
pub fn translate_page(&self, page: Page) -> Option<Frame> {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
use memory::{Frame, FrameAllocator};
|
||||
use memory::{allocate_frame, Frame};
|
||||
|
||||
use self::entry::{EntryFlags, PRESENT, WRITABLE, NO_EXECUTE};
|
||||
use self::mapper::Mapper;
|
||||
|
@ -21,7 +21,7 @@ pub const ENTRY_COUNT: usize = 512;
|
|||
pub const PAGE_SIZE: usize = 4096;
|
||||
|
||||
/// Initialize paging
|
||||
pub unsafe fn init<A>(stack_start: usize, stack_end: usize, allocator: &mut A) -> ActivePageTable where A: FrameAllocator {
|
||||
pub unsafe fn init(stack_start: usize, stack_end: usize) -> ActivePageTable {
|
||||
extern {
|
||||
/// The starting byte of the text (code) data segment.
|
||||
static mut __text_start: u8;
|
||||
|
@ -43,10 +43,10 @@ pub unsafe fn init<A>(stack_start: usize, stack_end: usize, allocator: &mut A) -
|
|||
|
||||
let mut active_table = ActivePageTable::new();
|
||||
|
||||
let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(0x80000000)), allocator);
|
||||
let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(0x80000000)));
|
||||
|
||||
let mut new_table = {
|
||||
let frame = allocator.allocate_frame().expect("no more frames");
|
||||
let frame = allocate_frame().expect("no more frames");
|
||||
InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
|
||||
};
|
||||
|
||||
|
@ -55,7 +55,7 @@ pub unsafe fn init<A>(stack_start: usize, stack_end: usize, allocator: &mut A) -
|
|||
let start_frame = Frame::containing_address(PhysicalAddress::new(start));
|
||||
let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1));
|
||||
for frame in Frame::range_inclusive(start_frame, end_frame) {
|
||||
mapper.identity_map(frame, flags, allocator);
|
||||
mapper.identity_map(frame, flags);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
use core::marker::PhantomData;
|
||||
use core::ops::{Index, IndexMut};
|
||||
|
||||
use memory::FrameAllocator;
|
||||
use memory::{allocate_frame, deallocate_frame};
|
||||
|
||||
use super::entry::*;
|
||||
use super::ENTRY_COUNT;
|
||||
|
@ -61,13 +61,11 @@ impl<L> Table<L> where L: HierarchicalLevel {
|
|||
self.next_table_address(index).map(|address| unsafe { &mut *(address as *mut _) })
|
||||
}
|
||||
|
||||
pub fn next_table_create<A>(&mut self, index: usize, allocator: &mut A) -> &mut Table<L::NextLevel>
|
||||
where A: FrameAllocator
|
||||
{
|
||||
pub fn next_table_create(&mut self, index: usize) -> &mut Table<L::NextLevel> {
|
||||
if self.next_table(index).is_none() {
|
||||
assert!(!self.entries[index].flags().contains(HUGE_PAGE),
|
||||
"mapping code does not support huge pages");
|
||||
let frame = allocator.allocate_frame().expect("no frames available");
|
||||
let frame = allocate_frame().expect("no frames available");
|
||||
self.entries[index].set(frame, PRESENT | WRITABLE);
|
||||
self.next_table_mut(index).unwrap().zero();
|
||||
}
|
||||
|
|
|
@ -9,24 +9,20 @@ use super::table::{Table, Level1};
|
|||
|
||||
pub struct TemporaryPage {
|
||||
page: Page,
|
||||
allocator: TinyAllocator,
|
||||
}
|
||||
|
||||
impl TemporaryPage {
|
||||
pub fn new<A>(page: Page, allocator: &mut A) -> TemporaryPage where A: FrameAllocator {
|
||||
pub fn new(page: Page) -> TemporaryPage {
|
||||
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, flags: EntryFlags, active_table: &mut ActivePageTable) -> VirtualAddress {
|
||||
println!("map {:?}", frame);
|
||||
assert!(active_table.translate_page(self.page).is_none(),
|
||||
"temporary page is already mapped");
|
||||
active_table.map_to(self.page, frame, flags, &mut self.allocator);
|
||||
assert!(active_table.translate_page(self.page).is_none(), "temporary page is already mapped");
|
||||
active_table.map_to(self.page, frame, flags);
|
||||
self.page.start_address()
|
||||
}
|
||||
|
||||
|
@ -38,44 +34,6 @@ impl TemporaryPage {
|
|||
|
||||
/// Unmaps the temporary page in the active table.
|
||||
pub fn unmap(&mut self, active_table: &mut ActivePageTable) {
|
||||
println!("unmap {:?}", self.page);
|
||||
active_table.unmap(self.page, &mut self.allocator)
|
||||
}
|
||||
}
|
||||
|
||||
struct TinyAllocator([Option<Frame>; 3]);
|
||||
|
||||
impl TinyAllocator {
|
||||
fn new<A>(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<Frame> {
|
||||
for frame_option in &mut self.0 {
|
||||
if frame_option.is_some() {
|
||||
println!("Allocate {:?}", frame_option);
|
||||
return frame_option.take();
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn deallocate_frame(&mut self, frame: Frame) {
|
||||
for frame_option in &mut self.0 {
|
||||
if frame_option.is_none() {
|
||||
println!("Deallocate {:?}", frame);
|
||||
*frame_option = Some(frame);
|
||||
return;
|
||||
}
|
||||
}
|
||||
println!("Cannot dealloc {:?}", frame);
|
||||
for frame_option in &self.0 {
|
||||
println!("Already dealloc {:?}", frame_option)
|
||||
}
|
||||
//panic!("Tiny allocator can hold only 3 frames. {:?}", frame);
|
||||
active_table.unmap(self.page)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue