diff --git a/arch/x86_64/src/lib.rs b/arch/x86_64/src/lib.rs index 6d07468..d9ff585 100644 --- a/arch/x86_64/src/lib.rs +++ b/arch/x86_64/src/lib.rs @@ -51,6 +51,9 @@ pub extern crate x86; /// Size of user stack 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 #[macro_export] @@ -126,7 +129,14 @@ macro_rules! interrupt_error { } // 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 rdx push rdi diff --git a/kernel/context/memory.rs b/kernel/context/memory.rs index 9cd57f2..ab9033b 100644 --- a/kernel/context/memory.rs +++ b/kernel/context/memory.rs @@ -101,6 +101,36 @@ impl Memory { 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) { let mut active_table = unsafe { ActivePageTable::new() }; diff --git a/kernel/elf.rs b/kernel/elf.rs index 819b1ec..7fb7f9a 100644 --- a/kernel/elf.rs +++ b/kernel/elf.rs @@ -55,8 +55,6 @@ impl<'a> Elf<'a> { /// Test function to run. Remove and replace with proper syscall pub fn run(self) -> SysResult { - let stack_addr = arch::USER_STACK_OFFSET; - let stack_size = arch::USER_STACK_SIZE; { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::NoProcess)?; @@ -105,8 +103,8 @@ impl<'a> Elf<'a> { // Map stack context.stack = Some(context::memory::Memory::new( - VirtualAddress::new(stack_addr), - stack_size, + VirtualAddress::new(arch::USER_STACK_OFFSET), + arch::USER_STACK_SIZE, entry::NO_EXECUTE | entry::WRITABLE | entry::USER_ACCESSIBLE, true, true @@ -114,7 +112,7 @@ impl<'a> Elf<'a> { } // 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); } } } diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index 3a511fb..9c3e5b4 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -47,8 +47,9 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { println!("Clone {:X}: {:X}", flags, stack_base); let arch; - let mut stack_option = None; + let mut kstack_option = None; let mut offset = 0; + let mut stack_option = None; // Copy from old process { @@ -63,6 +64,21 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { let func_ptr = new_stack.as_mut_ptr().offset(offset as isize); *(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); } } @@ -74,15 +90,19 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { let context_lock = contexts.new_context()?; let mut context = context_lock.write(); 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.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; pid = context.id; } - unsafe { context::switch(); } + //unsafe { context::switch(); } Ok(pid) }