diff --git a/context/mod.rs b/context/mod.rs
index a31d7b4aa1df553c0414c2f68f6b49ab1a33b3a0..4b657da583328afc85af8dd24aababa558306f05 100644
--- a/context/mod.rs
+++ b/context/mod.rs
@@ -141,11 +141,25 @@ pub unsafe fn switch() {
 
     let mut to_ptr = 0 as *mut Context;
 
-    for (_pid, context_lock) in contexts().map.iter() {
-        let mut context = context_lock.write();
-        if ! context.running && ! context.blocked && ! context.exited {
-            to_ptr = context.deref_mut() as *mut Context;
-            break;
+    for (pid, context_lock) in contexts().map.iter() {
+        if *pid > (*from_ptr).id {
+            let mut context = context_lock.write();
+            if ! context.running && ! context.blocked && ! context.exited {
+                to_ptr = context.deref_mut() as *mut Context;
+                break;
+            }
+        }
+    }
+
+    if to_ptr as usize == 0 {
+        for (pid, context_lock) in contexts().map.iter() {
+            if *pid < (*from_ptr).id {
+                let mut context = context_lock.write();
+                if ! context.running && ! context.blocked && ! context.exited {
+                    to_ptr = context.deref_mut() as *mut Context;
+                    break;
+                }
+            }
         }
     }
 
@@ -159,6 +173,9 @@ pub unsafe fn switch() {
 
     (&mut *from_ptr).running = false;
     (&mut *to_ptr).running = true;
+    if let Some(ref stack) = (*to_ptr).kstack {
+        arch::gdt::TSS.rsp[0] = (stack.as_ptr() as usize + stack.len() - 256) as u64;
+    }
     CONTEXT_ID.store((&mut *to_ptr).id, Ordering::SeqCst);
 
     (&mut *from_ptr).arch.switch_to(&mut (&mut *to_ptr).arch);
diff --git a/syscall/mod.rs b/syscall/mod.rs
index 3fdb7a579f0f9cc9fd6f72a0005ba0bf12a39490..bd53ad479f3dbe283d2145922bf6cbd3555f5771 100644
--- a/syscall/mod.rs
+++ b/syscall/mod.rs
@@ -105,32 +105,33 @@ pub fn convert_slice_mut<T>(ptr: *mut T, len: usize) -> Result<&'static mut [T]>
     Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
 }
 
-pub fn handle(a: usize, b: usize, c: usize, d: usize, e: usize, _f: usize) -> Result<usize> {
-    match Call::from(a) {
-        Ok(call) => match call {
-            Call::Exit => exit(b),
-            Call::Read => read(b, convert_slice_mut(c as *mut u8, d)?),
-            Call::Write => write(b, convert_slice(c as *const u8, d)?),
-            Call::Open => open(convert_slice(b as *const u8, c)?, d),
-            Call::Close => close(b),
-            Call::Exec => exec(convert_slice(b as *const u8, c)?, convert_slice(d as *const [usize; 2], e)?),
-            Call::GetPid => getpid(),
-            Call::Dup => dup(b),
-            Call::Brk => brk(b),
-            Call::Iopl => iopl(b),
-            Call::Clone => clone(b),
-            Call::SchedYield => sched_yield()
-        },
-        Err(err) => {
-            println!("Unknown syscall {}", a);
-            Err(err)
+#[no_mangle]
+pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> usize {
+    #[inline(always)]
+    fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, _f: usize, stack: usize) -> Result<usize> {
+        match Call::from(a) {
+            Ok(call) => match call {
+                Call::Exit => exit(b),
+                Call::Read => read(b, convert_slice_mut(c as *mut u8, d)?),
+                Call::Write => write(b, convert_slice(c as *const u8, d)?),
+                Call::Open => open(convert_slice(b as *const u8, c)?, d),
+                Call::Close => close(b),
+                Call::Exec => exec(convert_slice(b as *const u8, c)?, convert_slice(d as *const [usize; 2], e)?),
+                Call::GetPid => getpid(),
+                Call::Dup => dup(b),
+                Call::Brk => brk(b),
+                Call::Iopl => iopl(b),
+                Call::Clone => clone(b, stack),
+                Call::SchedYield => sched_yield()
+            },
+            Err(err) => {
+                println!("Unknown syscall {}", a);
+                Err(err)
+            }
         }
     }
-}
 
-#[no_mangle]
-pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> usize {
-    match handle(a, b, c, d, e, f) {
+    match inner(a, b, c, d, e, f, stack) {
         Ok(value) => value,
         Err(value) => (-(value as isize)) as usize
     }
diff --git a/syscall/process.rs b/syscall/process.rs
index ad1d107ca0f6b11eb927a7395ffd0ed148a3ea68..c4f846ba057e9b6d4ab80304fa0b69624078c835 100644
--- a/syscall/process.rs
+++ b/syscall/process.rs
@@ -1,5 +1,6 @@
 ///! Process syscalls
 
+use core::mem;
 use core::str;
 
 use arch;
@@ -42,9 +43,52 @@ pub fn brk(address: usize) -> Result<usize> {
     }
 }
 
-pub fn clone(flags: usize) -> Result<usize> {
-    println!("Clone {:X}", flags);
-    Ok(0)
+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 offset = 0;
+
+    // Copy from old process
+    {
+        let contexts = context::contexts();
+        let context_lock = contexts.current().ok_or(Error::NoProcess)?;
+        let context = context_lock.read();
+        arch = context.arch.clone();
+        if let Some(ref stack) = context.kstack {
+            offset = stack_base - stack.as_ptr() as usize - mem::size_of::<usize>(); // Add clone ret
+            let mut new_stack = stack.clone();
+            unsafe {
+                let func_ptr = new_stack.as_mut_ptr().offset(offset as isize);
+                *(func_ptr as *mut usize) = arch::interrupt::syscall::clone_ret as usize;
+            }
+            stack_option = Some(new_stack);
+        }
+    }
+
+    // Set up new process
+    let pid;
+    {
+        let mut contexts = context::contexts_mut();
+        let context_lock = contexts.new_context()?;
+        let mut context = context_lock.write();
+        context.arch = arch;
+        if let Some(stack) = stack_option.take() {
+            context.arch.set_stack(stack.as_ptr() as usize + offset);
+            context.kstack = Some(stack);
+        }
+        context.blocked = false;
+        pid = context.id;
+    }
+
+    println!("Clone {}", pid);
+
+    unsafe { asm!("xchg bx, bx" : : : : "intel", "volatile"); }
+
+    unsafe { context::switch(); }
+
+    Ok(pid)
 }
 
 pub fn exit(status: usize) -> ! {