From 932026fed817de51bfaec73c940e65f4a6a3477a Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Tue, 13 Sep 2016 21:27:27 -0600
Subject: [PATCH] WIP: Copy usermode stack

---
 context/memory.rs  | 30 ++++++++++++++++++++++++++++++
 elf.rs             |  8 +++-----
 syscall/process.rs | 26 +++++++++++++++++++++++---
 3 files changed, 56 insertions(+), 8 deletions(-)

diff --git a/context/memory.rs b/context/memory.rs
index 9cd57f2a..ab9033bc 100644
--- a/context/memory.rs
+++ b/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/elf.rs b/elf.rs
index 819b1ece..7fb7f9a8 100644
--- a/elf.rs
+++ b/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/syscall/process.rs b/syscall/process.rs
index 3a511fb1..9c3e5b4f 100644
--- a/syscall/process.rs
+++ b/syscall/process.rs
@@ -47,8 +47,9 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
     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<usize> {
                 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<usize> {
         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)
 }
-- 
GitLab