From 86073670586d161f3d749b6a3d66a9ab0ac0d6f3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Wed, 14 Sep 2016 22:21:52 -0600 Subject: [PATCH] WIP: Create new page table for clone --- context/memory.rs | 37 ++++++++++++++++++------------------- syscall/process.rs | 31 ++++++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/context/memory.rs b/context/memory.rs index ab9033bc..e0eaa5fc 100644 --- a/context/memory.rs +++ b/context/memory.rs @@ -1,6 +1,7 @@ use arch::externs::memset; -use arch::paging::{ActivePageTable, Page, PageIter, VirtualAddress}; +use arch::paging::{ActivePageTable, InactivePageTable, Page, PageIter, VirtualAddress}; use arch::paging::entry::EntryFlags; +use arch::paging::temporary_page::TemporaryPage; #[derive(Debug)] pub struct Memory { @@ -36,7 +37,7 @@ impl Memory { Page::range_inclusive(start_page, end_page) } - pub fn map(&mut self, flush: bool, clear: bool) { + fn map(&mut self, flush: bool, clear: bool) { let mut active_table = unsafe { ActivePageTable::new() }; let mut flush_all = false; @@ -61,7 +62,7 @@ impl Memory { } } - pub fn unmap(&mut self, flush: bool) { + fn unmap(&mut self, flush: bool) { let mut active_table = unsafe { ActivePageTable::new() }; let mut flush_all = false; @@ -80,13 +81,20 @@ impl Memory { } } - pub fn remap(&mut self, new_flags: EntryFlags, flush: bool) { + /// A complicated operation to move a piece of memory to a new page table + /// It also allows for changing the address at the same time + pub fn move_to(&mut self, new_start: VirtualAddress, new_table: &mut InactivePageTable, temporary_page: &mut TemporaryPage, flush: bool) { let mut active_table = unsafe { ActivePageTable::new() }; let mut flush_all = false; for page in self.pages() { - active_table.remap(page, new_flags); + let frame = active_table.unmap_return(page); + + active_table.with(new_table, temporary_page, |mapper| { + let new_page = Page::containing_address(VirtualAddress::new(page.start_address().get() - self.start.get() + new_start.get())); + mapper.map_to(new_page, frame, self.flags); + }); if flush { //active_table.flush(page); @@ -98,27 +106,16 @@ impl Memory { active_table.flush_all(); } - self.flags = new_flags; + self.start = new_start; } - pub fn replace(&mut self, new_start: VirtualAddress, flush: bool) { + pub fn remap(&mut self, new_flags: EntryFlags, flush: bool) { let mut active_table = unsafe { ActivePageTable::new() }; let mut flush_all = false; for page in self.pages() { - active_table.unmap(page); - - if flush { - //active_table.flush(page); - flush_all = true; - } - } - - self.start = new_start; - - for page in self.pages() { - active_table.map(page, self.flags); + active_table.remap(page, new_flags); if flush { //active_table.flush(page); @@ -129,6 +126,8 @@ impl Memory { if flush_all { active_table.flush_all(); } + + self.flags = new_flags; } pub fn resize(&mut self, new_size: usize, flush: bool, clear: bool) { diff --git a/syscall/process.rs b/syscall/process.rs index c7ff1ee4..d760d5c5 100644 --- a/syscall/process.rs +++ b/syscall/process.rs @@ -4,7 +4,9 @@ use core::mem; use core::str; use arch; -use arch::paging::{VirtualAddress, entry}; +use arch::memory::allocate_frame; +use arch::paging::{ActivePageTable, InactivePageTable, Page, VirtualAddress, entry}; +use arch::paging::temporary_page::TemporaryPage; use context; use elf; use syscall::{self, Error, Result}; @@ -67,7 +69,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> { kstack_option = Some(new_stack); } if let Some(ref stack) = context.stack { - let mut new_stack = context::memory::Memory::new( + let new_stack = context::memory::Memory::new( VirtualAddress::new(arch::USER_TMP_STACK_OFFSET), stack.size(), entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, @@ -79,7 +81,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> { stack.start_address().get() as *const u8, stack.size()); } - new_stack.unmap(true); stack_option = Some(new_stack); } } @@ -91,19 +92,39 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> { let context_lock = contexts.new_context()?; let mut context = context_lock.write(); context.arch = arch; + + let mut active_table = unsafe { ActivePageTable::new() }; + + let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(0x8_0000_0000))); + + let mut new_table = { + let frame = allocate_frame().expect("no more frames in syscall::clone new_table"); + InactivePageTable::new(frame, &mut active_table, &mut temporary_page) + }; + + // Copy kernel mapping + let kernel_frame = active_table.p4()[510].pointed_frame().expect("kernel table not mapped"); + active_table.with(&mut new_table, &mut temporary_page, |mapper| { + mapper.p4_mut()[510].set(kernel_frame, entry::PRESENT | entry::WRITABLE); + }); + if let Some(stack) = kstack_option.take() { context.arch.set_stack(stack.as_ptr() as usize + offset); context.kstack = Some(stack); } + if let Some(mut stack) = stack_option.take() { - //stack.replace(VirtualAddress::new(arch::USER_STACK_OFFSET), true); + stack.move_to(VirtualAddress::new(arch::USER_STACK_OFFSET), &mut new_table, &mut temporary_page, true); context.stack = Some(stack); } + + context.arch.set_page_table(unsafe { new_table.address() }); + context.blocked = false; pid = context.id; } - //unsafe { context::switch(); } + unsafe { context::switch(); } Ok(pid) } -- GitLab