WIP: Copy usermode stack

This commit is contained in:
Jeremy Soller 2016-09-13 21:27:27 -06:00
parent 3f9012b931
commit 6e16298e71
4 changed files with 67 additions and 9 deletions

View file

@ -51,6 +51,9 @@ pub extern crate x86;
/// Size of user stack /// Size of user stack
pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB
/// Offset to user temporary stack (used when cloning)
pub const USER_TMP_STACK_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE;
/// Print to console /// Print to console
#[macro_export] #[macro_export]
@ -126,7 +129,14 @@ macro_rules! interrupt_error {
} }
// Push scratch registers // Push scratch registers
asm!("push rax asm!("pop rax
pop rbx
pop rcx
pop rdx
pop rsi
pop rdi
hlt
push rax
push rcx push rcx
push rdx push rdx
push rdi push rdi

View file

@ -101,6 +101,36 @@ impl Memory {
self.flags = new_flags; self.flags = new_flags;
} }
pub fn replace(&mut self, new_start: VirtualAddress, 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);
if flush {
//active_table.flush(page);
flush_all = true;
}
}
if flush_all {
active_table.flush_all();
}
}
pub fn resize(&mut self, new_size: usize, flush: bool, clear: bool) { pub fn resize(&mut self, new_size: usize, flush: bool, clear: bool) {
let mut active_table = unsafe { ActivePageTable::new() }; let mut active_table = unsafe { ActivePageTable::new() };

View file

@ -55,8 +55,6 @@ impl<'a> Elf<'a> {
/// Test function to run. Remove and replace with proper syscall /// Test function to run. Remove and replace with proper syscall
pub fn run(self) -> SysResult<!> { pub fn run(self) -> SysResult<!> {
let stack_addr = arch::USER_STACK_OFFSET;
let stack_size = arch::USER_STACK_SIZE;
{ {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::NoProcess)?; let context_lock = contexts.current().ok_or(Error::NoProcess)?;
@ -105,8 +103,8 @@ impl<'a> Elf<'a> {
// Map stack // Map stack
context.stack = Some(context::memory::Memory::new( context.stack = Some(context::memory::Memory::new(
VirtualAddress::new(stack_addr), VirtualAddress::new(arch::USER_STACK_OFFSET),
stack_size, arch::USER_STACK_SIZE,
entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE,
true, true,
true true
@ -114,7 +112,7 @@ impl<'a> Elf<'a> {
} }
// Go to usermode // Go to usermode
unsafe { usermode(self.entry(), stack_addr + stack_size - 256); } unsafe { usermode(self.entry(), arch::USER_STACK_OFFSET + arch::USER_STACK_SIZE - 256); }
} }
} }

View file

@ -47,8 +47,9 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
println!("Clone {:X}: {:X}", flags, stack_base); println!("Clone {:X}: {:X}", flags, stack_base);
let arch; let arch;
let mut stack_option = None; let mut kstack_option = None;
let mut offset = 0; let mut offset = 0;
let mut stack_option = None;
// Copy from old process // Copy from old process
{ {
@ -63,6 +64,21 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
let func_ptr = new_stack.as_mut_ptr().offset(offset as isize); let func_ptr = new_stack.as_mut_ptr().offset(offset as isize);
*(func_ptr as *mut usize) = arch::interrupt::syscall::clone_ret as usize; *(func_ptr as *mut usize) = arch::interrupt::syscall::clone_ret as usize;
} }
kstack_option = Some(new_stack);
}
if let Some(ref stack) = context.stack {
let mut new_stack = context::memory::Memory::new(
VirtualAddress::new(arch::USER_TMP_STACK_OFFSET),
stack.size(),
entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE,
true,
true //TODO: Don't clear stack?
);
unsafe {
arch::externs::memcpy(new_stack.start_address().get() as *mut u8,
stack.start_address().get() as *const u8,
stack.size());
}
stack_option = Some(new_stack); stack_option = Some(new_stack);
} }
} }
@ -74,15 +90,19 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
let context_lock = contexts.new_context()?; let context_lock = contexts.new_context()?;
let mut context = context_lock.write(); let mut context = context_lock.write();
context.arch = arch; context.arch = arch;
if let Some(stack) = stack_option.take() { if let Some(stack) = kstack_option.take() {
context.arch.set_stack(stack.as_ptr() as usize + offset); context.arch.set_stack(stack.as_ptr() as usize + offset);
context.kstack = Some(stack); context.kstack = Some(stack);
} }
if let Some(mut stack) = stack_option.take() {
//stack.replace(VirtualAddress::new(arch::USER_STACK_OFFSET), true);
context.stack = Some(stack);
}
context.blocked = false; context.blocked = false;
pid = context.id; pid = context.id;
} }
unsafe { context::switch(); } //unsafe { context::switch(); }
Ok(pid) Ok(pid)
} }