diff --git a/src/arch/aarch64/init/pre_kstart/helpers/vectors.S b/src/arch/aarch64/init/pre_kstart/helpers/vectors.S
index 2241348397ad149e2b5cea03057881b1727075be..dec303bc98eb33131a6cd6a5639cefeae9b611a7 100644
--- a/src/arch/aarch64/init/pre_kstart/helpers/vectors.S
+++ b/src/arch/aarch64/init/pre_kstart/helpers/vectors.S
@@ -7,95 +7,117 @@
     .align 11
 exception_vector_base:
 
+    // Synchronous
     .align 7
 __vec_00:
     mov     x18, #0xb0b0
-    b       do_exception_synchronous
+    b       synchronous_exception_at_el1_with_sp0
     b       __vec_00
 
+    // IRQ
     .align 7
 __vec_01:
     mov     x18, #0xb0b1
     b       do_exception_irq
     b       __vec_01
 
+    // FIQ
     .align 7
 __vec_02:
     mov     x18, #0xb0b2
     b       do_exception_unhandled
     b       __vec_02
 
+    // SError
     .align 7
 __vec_03:
     mov     x18, #0xb0b3
     b       do_exception_unhandled
     b       __vec_03
 
+    // Synchronous
     .align 7
 __vec_04:
     mov     x18, #0xb0b4
-    b       do_exception_synchronous
+    b       synchronous_exception_at_el1_with_spx
     b       __vec_04
 
+    // IRQ
     .align 7
 __vec_05:
     mov     x18, #0xb0b5
     b       do_exception_irq
     b       __vec_05
 
+    // FIQ
     .align 7
 __vec_06:
     mov     x18, #0xb0b6
     b       do_exception_unhandled
     b       __vec_06
 
+    // SError
     .align 7
 __vec_07:
     mov     x18, #0xb0b7
     b       do_exception_unhandled
     b       __vec_07
 
+    // Synchronous
     .align 7
 __vec_08:
     mov     x18, #0xb0b8
-    b       do_exception_synchronous
+    b       synchronous_exception_at_el0
     b       __vec_08
 
+    // IRQ
     .align 7
 __vec_09:
     mov     x18, #0xb0b9
     b       do_exception_irq
     b       __vec_09
 
+    // FIQ
     .align 7
 __vec_10:
     mov     x18, #0xb0ba
     b       do_exception_unhandled
     b       __vec_10
 
+    // SError
     .align 7
 __vec_11:
     mov     x18, #0xb0bb
     b       do_exception_unhandled
     b       __vec_11
 
+    // Synchronous
     .align 7
 __vec_12:
     mov     x18, #0xb0bc
     b       do_exception_unhandled
     b       __vec_12
 
+    // IRQ
     .align 7
 __vec_13:
     mov     x18, #0xb0bd
     b       do_exception_unhandled
     b       __vec_13
 
+    // FIQ
     .align 7
 __vec_14:
     mov     x18, #0xb0be
     b       do_exception_unhandled
     b       __vec_14
 
+    // SError
+    .align 7
+__vec_15:
+    mov     x18, #0xb0bf
+    b       do_exception_unhandled
+    b       __vec_15
+    
     .align 7
 exception_vector_end:
diff --git a/src/arch/aarch64/interrupt/exception.rs b/src/arch/aarch64/interrupt/exception.rs
new file mode 100644
index 0000000000000000000000000000000000000000..01d0ef396070c67aa486e6b2ccff05b965459a60
--- /dev/null
+++ b/src/arch/aarch64/interrupt/exception.rs
@@ -0,0 +1,47 @@
+use crate::{
+    interrupt::stack_trace,
+    syscall,
+    syscall::flag::*,
+
+    with_exception_stack,
+    exception_stack,
+};
+
+exception_stack!(synchronous_exception_at_el1_with_sp0, |stack| {
+    println!("Synchronous exception at EL1 with SP0");
+    stack.dump();
+    stack_trace();
+    loop {}
+});
+
+exception_stack!(synchronous_exception_at_el1_with_spx, |stack| {
+    println!("Synchronous exception at EL1 with SPx");
+    stack.dump();
+    stack_trace();
+    loop {}
+});
+
+exception_stack!(synchronous_exception_at_el0, |stack| {
+    with_exception_stack!(|stack| {
+        let fp;
+        asm!("mov {}, fp", out(reg) fp);
+
+        let exception_code = (stack.iret.esr_el1 & (0x3f << 26)) >> 26;
+        if exception_code != 0b010101 {
+            println!("FATAL: Not an SVC induced synchronous exception");
+            stack.dump();
+            stack_trace();
+            loop {}
+        }
+
+        let scratch = &stack.scratch;
+        syscall::syscall(scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, fp, stack)
+    });
+});
+
+exception_stack!(unhandled_exception, |stack| {
+    println!("Unhandled exception");
+    stack.dump();
+    stack_trace();
+    loop {}
+});
diff --git a/src/arch/aarch64/interrupt/handler.rs b/src/arch/aarch64/interrupt/handler.rs
index 279c89a36b646a33c58fb33fc44a5676efa2f994..9be3973a5ebcbad009d6b98c1f38bd5cac3563cd 100644
--- a/src/arch/aarch64/interrupt/handler.rs
+++ b/src/arch/aarch64/interrupt/handler.rs
@@ -1,25 +1,28 @@
+use crate::syscall::IntRegisters;
+
 #[derive(Default)]
 #[repr(packed)]
 pub struct ScratchRegisters {
-    pub x18: usize,
-    pub x17: usize,
-    pub x16: usize,
-    pub x15: usize,
-    pub x14: usize,
-    pub x13: usize,
-    pub x12: usize,
-    pub x11: usize,
-    pub x10: usize,
-    pub x9: usize,
-    pub x8: usize,
-    pub x7: usize,
-    pub x6: usize,
-    pub x5: usize,
-    pub x4: usize,
-    pub x3: usize,
-    pub x2: usize,
-    pub x1: usize,
     pub x0: usize,
+    pub x1: usize,
+    pub x2: usize,
+    pub x3: usize,
+    pub x4: usize,
+    pub x5: usize,
+    pub x6: usize,
+    pub x7: usize,
+    pub x8: usize,
+    pub x9: usize,
+    pub x10: usize,
+    pub x11: usize,
+    pub x12: usize,
+    pub x13: usize,
+    pub x14: usize,
+    pub x15: usize,
+    pub x16: usize,
+    pub x17: usize,
+    pub x18: usize,
+    pub padding: usize,
 }
 
 impl ScratchRegisters {
@@ -50,18 +53,18 @@ impl ScratchRegisters {
 #[repr(packed)]
 pub struct PreservedRegisters {
     //TODO: is X30 a preserved register?
-    pub x30: usize,
-    pub x29: usize,
-    pub x28: usize,
-    pub x27: usize,
-    pub x26: usize,
-    pub x25: usize,
-    pub x24: usize,
-    pub x23: usize,
-    pub x22: usize,
-    pub x21: usize,
-    pub x20: usize,
     pub x19: usize,
+    pub x20: usize,
+    pub x21: usize,
+    pub x22: usize,
+    pub x23: usize,
+    pub x24: usize,
+    pub x25: usize,
+    pub x26: usize,
+    pub x27: usize,
+    pub x28: usize,
+    pub x29: usize,
+    pub x30: usize,
 }
 
 impl PreservedRegisters {
@@ -83,34 +86,245 @@ impl PreservedRegisters {
 
 #[derive(Default)]
 #[repr(packed)]
-pub struct InterruptStack {
-    pub elr_el1: usize,
-    //TODO: should this push be removed?
-    pub unknown: usize,
-    pub tpidr_el0: usize,
-    pub tpidrro_el0: usize,
-    pub spsr_el1: usize,
+pub struct IretRegisters {
+                            // occurred
+                            // The exception vector disambiguates at which EL the interrupt
+    pub sp_el0: usize,      // Shouldn't be used if interrupt occurred at EL1
     pub esr_el1: usize,
-    pub sp_el0: usize,
-    pub preserved: PreservedRegisters,
+    pub spsr_el1: usize,
+    pub tpidrro_el0: usize,
+    pub tpidr_el0: usize,
+    pub elr_el1: usize,
+}
+
+impl IretRegisters {
+    pub fn dump(&self) {
+        println!("ELR_EL1: {:>016X}", { self.elr_el1 });
+        println!("TPIDR_EL0: {:>016X}", { self.tpidr_el0 });
+        println!("TPIDRRO_EL0: {:>016X}", { self.tpidrro_el0 });
+        println!("SPSR_EL1: {:>016X}", { self.spsr_el1 });
+        println!("ESR_EL1: {:>016X}", { self.esr_el1 });
+        println!("SP_EL0: {:>016X}", { self.sp_el0 });
+    }
+}
+
+#[derive(Default)]
+#[repr(packed)]
+pub struct InterruptStack {
+    pub iret: IretRegisters,
     pub scratch: ScratchRegisters,
-    //TODO: eret registers
+    pub preserved: PreservedRegisters,
 }
 
 impl InterruptStack {
     pub fn dump(&self) {
+        self.iret.dump();
         self.scratch.dump();
         self.preserved.dump();
-        println!("SP_EL0:      {:>016X}", { self.sp_el0 });
-        println!("ESR_EL1:     {:>016X}", { self.esr_el1 });
-        println!("SPSR_EL1:    {:>016X}", { self.spsr_el1 });
-        println!("TPIDRRO_EL0: {:>016X}", { self.tpidrro_el0 });
-        println!("TPIDR_EL0:   {:>016X}", { self.tpidr_el0 });
-        println!("UNKNOWN:     {:>016X}", { self.unknown });
-        println!("ELR_EL1:     {:>016X}", { self.elr_el1 });
+    }
+
+    /// Saves all registers to a struct used by the proc:
+    /// scheme to read/write registers.
+    pub fn save(&self, all: &mut IntRegisters) {
+        all.elr_el1 = self.iret.elr_el1;
+        all.tpidr_el0 = self.iret.tpidr_el0;
+        all.tpidrro_el0 = self.iret.tpidrro_el0;
+        all.spsr_el1 = self.iret.spsr_el1;
+        all.esr_el1 = self.iret.esr_el1;
+        all.sp_el0 = self.iret.sp_el0;
+        all.padding = 0;
+        all.x30 = self.preserved.x30;
+        all.x29 = self.preserved.x29;
+        all.x28 = self.preserved.x28;
+        all.x27 = self.preserved.x27;
+        all.x26 = self.preserved.x26;
+        all.x25 = self.preserved.x25;
+        all.x24 = self.preserved.x24;
+        all.x23 = self.preserved.x23;
+        all.x22 = self.preserved.x22;
+        all.x21 = self.preserved.x21;
+        all.x20 = self.preserved.x20;
+        all.x19 = self.preserved.x19;
+        all.x18 = self.scratch.x18;
+        all.x17 = self.scratch.x17;
+        all.x16 = self.scratch.x16;
+        all.x15 = self.scratch.x15;
+        all.x14 = self.scratch.x14;
+        all.x13 = self.scratch.x13;
+        all.x12 = self.scratch.x12;
+        all.x11 = self.scratch.x11;
+        all.x10 = self.scratch.x10;
+        all.x9 = self.scratch.x9;
+        all.x8 = self.scratch.x8;
+        all.x7 = self.scratch.x7;
+        all.x6 = self.scratch.x6;
+        all.x5 = self.scratch.x5;
+        all.x4 = self.scratch.x4;
+        all.x3 = self.scratch.x3;
+        all.x2 = self.scratch.x2;
+        all.x1 = self.scratch.x1;
+        all.x0 = self.scratch.x0;
     }
 
     //TODO
     pub fn is_singlestep(&self) -> bool { false }
     pub fn set_singlestep(&mut self, singlestep: bool) {}
 }
+
+#[macro_export]
+macro_rules! aarch64_asm {
+    ($($strings:expr,)+) => {
+        global_asm!(concat!(
+            $($strings),+,
+        ));
+    };
+}
+
+#[macro_export]
+macro_rules! function {
+    ($name:ident => { $($body:expr,)+ }) => {
+        aarch64_asm!(
+            ".global ", stringify!($name), "\n",
+            ".type ", stringify!($name), ", @function\n",
+            ".section .text.", stringify!($name), ", \"ax\", @progbits\n",
+            stringify!($name), ":\n",
+            $($body),+,
+            ".size ", stringify!($name), ", . - ", stringify!($name), "\n",
+            ".text\n",
+        );
+        extern "C" {
+            pub fn $name();
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! push_scratch {
+    () => { "
+        // Push scratch registers
+        stp     x18, x18, [sp, #-16]!
+        stp     x16, x17, [sp, #-16]!
+        stp     x14, x15, [sp, #-16]!
+        stp     x12, x13, [sp, #-16]!
+        stp     x10, x11, [sp, #-16]!
+        stp     x8, x9, [sp, #-16]!
+        stp     x6, x7, [sp, #-16]!
+        stp     x4, x5, [sp, #-16]!
+        stp     x2, x3, [sp, #-16]!
+        stp     x0, x1, [sp, #-16]!
+    " };
+}
+
+#[macro_export]
+macro_rules! pop_scratch {
+    () => { "
+        // Pop scratch registers
+        ldp     x0, x1, [sp], #16
+        ldp     x2, x3, [sp], #16
+        ldp     x4, x5, [sp], #16
+        ldp     x6, x7, [sp], #16
+        ldp     x8, x9, [sp], #16
+        ldp     x10, x11, [sp], #16
+        ldp     x12, x13, [sp], #16
+        ldp     x14, x15, [sp], #16
+        ldp     x16, x17, [sp], #16
+        ldp     x18, x18, [sp], #16
+    " };
+}
+
+#[macro_export]
+macro_rules! push_preserved {
+    () => { "
+        // Push preserved registers
+        stp     x29, x30, [sp, #-16]!
+        stp     x27, x28, [sp, #-16]!
+        stp     x25, x26, [sp, #-16]!
+        stp     x23, x24, [sp, #-16]!
+        stp     x21, x22, [sp, #-16]!
+        stp     x19, x20, [sp, #-16]!
+    " };
+}
+
+#[macro_export]
+macro_rules! pop_preserved {
+    () => { "
+        // Pop preserved registers
+        ldp     x19, x20, [sp], #16
+        ldp     x21, x22, [sp], #16
+        ldp     x23, x24, [sp], #16
+        ldp     x25, x26, [sp], #16
+        ldp     x27, x28, [sp], #16
+        ldp     x29, x30, [sp], #16
+    " };
+}
+
+#[macro_export]
+macro_rules! push_special {
+    () => { "
+        mrs     x14, tpidr_el0
+        mrs     x15, elr_el1
+        stp     x14, x15, [sp, #-16]!
+
+        mrs     x14, spsr_el1
+        mrs     x15, tpidrro_el0
+        stp     x14, x15, [sp, #-16]!
+
+        mrs     x14, sp_el0
+        mrs     x15, esr_el1
+        stp     x14, x15, [sp, #-16]!
+    " };
+}
+
+#[macro_export]
+macro_rules! pop_special {
+    () => { "
+        ldp     x14, x15, [sp], 16
+        msr     esr_el1, x15
+        msr     sp_el0, x14
+
+        ldp     x14, x15, [sp], 16
+        msr     tpidrro_el0, x15
+        msr     spsr_el1, x14
+        
+        ldp     x14, x15, [sp], 16
+        msr     elr_el1, x15
+        msr     tpidr_el0, x14
+    " };
+}
+
+#[macro_export]
+macro_rules! exception_stack {
+    ($name:ident, |$stack:ident| $code:block) => {
+        paste::item! {
+            #[no_mangle]
+            unsafe extern "C" fn [<__exception_ $name>](stack: *mut $crate::arch::aarch64::interrupt::InterruptStack) {
+                // This inner function is needed because macros are buggy:
+                // https://github.com/dtolnay/paste/issues/7
+                #[inline(always)]
+                unsafe fn inner($stack: &mut $crate::arch::aarch64::interrupt::InterruptStack) {
+                    $code
+                }
+                inner(&mut *stack);
+            }
+
+            function!($name => {
+                // Backup all userspace registers to stack
+                push_preserved!(),
+                push_scratch!(),
+                push_special!(),
+
+                // Call inner function with pointer to stack
+                "mov x29, sp\n",
+                "mov x0, sp\n",
+                "bl __exception_", stringify!($name), "\n",
+
+                // Restore all userspace registers
+                pop_special!(),
+                pop_scratch!(),
+                pop_preserved!(),
+
+                "eret\n",
+            });
+        }
+    };
+}
diff --git a/src/arch/aarch64/interrupt/mod.rs b/src/arch/aarch64/interrupt/mod.rs
index 9811df2f7c5e1a828f72afd91a07ff9848359eb1..4639332f0bcfa84f272305aaa3718862cd2d6edb 100644
--- a/src/arch/aarch64/interrupt/mod.rs
+++ b/src/arch/aarch64/interrupt/mod.rs
@@ -1,10 +1,12 @@
 //! Interrupt instructions
 
+#[macro_use]
 pub mod handler;
+
+pub mod exception;
 pub mod irq;
 pub mod syscall;
 pub mod trace;
-pub mod unhandled_exceptions;
 
 pub use self::handler::InterruptStack;
 pub use self::trace::stack_trace;
diff --git a/src/arch/aarch64/interrupt/syscall.rs b/src/arch/aarch64/interrupt/syscall.rs
index 42b64ffa0c1ca2209185dbe699d2ccc34da69732..afd14167d6c593ecd5c29e615f17aea29568b547 100644
--- a/src/arch/aarch64/interrupt/syscall.rs
+++ b/src/arch/aarch64/interrupt/syscall.rs
@@ -1,6 +1,14 @@
-use crate::interrupt::InterruptStack;
-use crate::syscall;
+use crate::{
+    arch::{interrupt::InterruptStack},
+    context,
+    syscall,
+    syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_PRE_SYSCALL, PTRACE_STOP_POST_SYSCALL},
+};
 
+#[no_mangle]
+pub unsafe extern fn do_exception_unhandled() {}
+
+/*
 #[naked]
 #[no_mangle]
 pub unsafe extern fn do_exception_unhandled() {
@@ -69,7 +77,12 @@ pub unsafe extern fn do_exception_unhandled() {
 
     let a = inner(&mut *(sp as *mut InterruptStack));
 }
+*/
 
+#[no_mangle]
+pub unsafe extern fn do_exception_synchronous() {}
+
+/*
 #[naked]
 #[no_mangle]
 pub unsafe extern fn do_exception_synchronous() {
@@ -219,6 +232,7 @@ pub unsafe extern fn do_exception_synchronous() {
 
     llvm_asm!("eret" :::: "volatile");
 }
+*/
 
 #[allow(dead_code)]
 #[repr(packed)]
@@ -263,8 +277,55 @@ pub struct SyscallStack {
     pub x0: usize,
 }
 
-#[naked]
-pub unsafe extern fn clone_ret() {
-    llvm_asm!("ldp x29, x30, [sp], #0x60");
-    llvm_asm!("mov x0, 0");
+#[macro_export]
+macro_rules! with_exception_stack {
+    (|$stack:ident| $code:block) => {{
+            let $stack = &mut *$stack;
+            (*$stack).scratch.x0 = $code;
+    }}
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn __inner_syscall_instruction(stack: *mut InterruptStack) {
+    with_exception_stack!(|stack| {
+        // Set a restore point for clone
+        let fp;
+        asm!("mov {}, fp", out(reg) fp);
+
+        let scratch = &stack.scratch;
+        syscall::syscall(scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, fp, stack)
+    });
 }
+
+function!(syscall_instruction => {
+    "
+        nop
+    ",
+
+    // Push context registers
+    push_preserved!(),
+    push_scratch!(),
+    push_special!(),
+
+    // TODO: Map PTI
+
+    // Call inner function
+    "mov x0, sp\n",
+    "bl __inner_syscall_instruction\n",
+
+    // TODO: Unmap PTI
+
+    // Pop context registers
+    pop_special!(),
+    pop_scratch!(),
+    pop_preserved!(),
+
+    // Return
+    "eret\n",
+});
+
+function!(clone_ret => {
+    "ldp x29, x30, [sp], #16\n",
+    "mov sp, x29\n",
+    "ret\n",
+});
diff --git a/src/arch/aarch64/interrupt/unhandled_exceptions.rs b/src/arch/aarch64/interrupt/unhandled_exceptions.rs
deleted file mode 100644
index 6897d89a357a688b99ca6d2ae7679672d5440506..0000000000000000000000000000000000000000
--- a/src/arch/aarch64/interrupt/unhandled_exceptions.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-use crate::{
-    context,
-    cpu_id,
-    interrupt::{self, InterruptStack, stack_trace},
-};
-
-bitflags! {
-    pub struct ExceptionClasses: u32 {
-        const   SVC_INSN_IN_AARCH64_STATE = 0b10101 << 26;
-        const   DATA_ABORT_FROM_LOWER_EL  = 0b100100 << 26;
-        const   BKPT_INSN_IN_AARCH64_STATE = 0b111100 << 26;
-    }
-}
-
-#[inline(never)]
-pub unsafe extern fn report_exception(stack: &InterruptStack) {
-    println!("Unhandled exception");
-
-    stack.dump();
-    stack_trace();
-
-    println!("CPU {}, PID {:?}", cpu_id(), context::context_id());
-    //WARNING: name cannot be grabed, it may deadlock
-
-    println!("HALT");
-    loop {
-        interrupt::halt();
-    }
-}
-
-#[naked]
-#[no_mangle]
-pub unsafe extern fn do_report_exception() {
-    llvm_asm!("str	    x0, [sp, #-8]!
-          str	    x1, [sp, #-8]!
-          str	    x2, [sp, #-8]!
-          str	    x3, [sp, #-8]!
-          str	    x4, [sp, #-8]!
-          str	    x5, [sp, #-8]!
-          str	    x6, [sp, #-8]!
-          str	    x7, [sp, #-8]!
-          str	    x8, [sp, #-8]!
-          str	    x9, [sp, #-8]!
-          str	    x10, [sp, #-8]!
-          str	    x11, [sp, #-8]!
-          str	    x12, [sp, #-8]!
-          str	    x13, [sp, #-8]!
-          str	    x14, [sp, #-8]!
-          str	    x15, [sp, #-8]!
-          str	    x16, [sp, #-8]!
-          str	    x17, [sp, #-8]!
-          str	    x18, [sp, #-8]!
-          str	    x19, [sp, #-8]!
-          str	    x20, [sp, #-8]!
-          str	    x21, [sp, #-8]!
-          str	    x22, [sp, #-8]!
-          str	    x23, [sp, #-8]!
-          str	    x24, [sp, #-8]!
-          str	    x25, [sp, #-8]!
-          str	    x26, [sp, #-8]!
-          str	    x27, [sp, #-8]!
-          str	    x28, [sp, #-8]!
-          str	    x29, [sp, #-8]!
-          str	    x30, [sp, #-8]!
-
-          mrs       x18, sp_el0
-          str       x18, [sp, #-8]!
-
-          mrs       x18, esr_el1
-          str       x18, [sp, #-8]!
-
-          mrs       x18, spsr_el1
-          str       x18, [sp, #-8]!
-
-          mrs       x18, tpidrro_el0
-          str       x18, [sp, #-8]!
-
-          mrs       x18, tpidr_el0
-          str       x18, [sp, #-8]!
-
-          str       x18, [sp, #-8]!
-
-          mrs       x18, elr_el1
-          str       x18, [sp, #-8]!"
-    : : : : "volatile");
-
-    let sp: usize;
-    llvm_asm!("" : "={sp}"(sp) : : : "volatile");
-    report_exception(&*(sp as *const InterruptStack));
-
-    llvm_asm!("ldr	    x18, [sp], #8
-          msr	    elr_el1, x18
-
-          ldr	    x18, [sp], #8
-
-          ldr	    x18, [sp], #8
-          msr	    tpidr_el0, x18
-
-          ldr	    x18, [sp], #8
-          msr	    tpidrro_el0, x18
-
-          ldr	    x18, [sp], #8
-          msr	    spsr_el1, x18
-
-          ldr	    x18, [sp], #8
-          msr	    esr_el1, x18
-
-          ldr	    x18, [sp], #8
-          msr       sp_el0, x18
-
-          ldr	    x30, [sp], #8
-          ldr	    x29, [sp], #8
-          ldr	    x28, [sp], #8
-          ldr	    x27, [sp], #8
-          ldr	    x26, [sp], #8
-          ldr	    x25, [sp], #8
-          ldr	    x24, [sp], #8
-          ldr	    x23, [sp], #8
-          ldr	    x22, [sp], #8
-          ldr	    x21, [sp], #8
-          ldr	    x20, [sp], #8
-          ldr	    x19, [sp], #8
-          ldr	    x18, [sp], #8
-          ldr	    x17, [sp], #8
-          ldr	    x16, [sp], #8
-          ldr	    x15, [sp], #8
-          ldr	    x14, [sp], #8
-          ldr	    x13, [sp], #8
-          ldr	    x12, [sp], #8
-          ldr	    x11, [sp], #8
-          ldr	    x10, [sp], #8
-          ldr	    x9, [sp], #8
-          ldr	    x8, [sp], #8
-          ldr	    x7, [sp], #8
-          ldr	    x6, [sp], #8
-          ldr	    x5, [sp], #8
-          ldr	    x4, [sp], #8
-          ldr	    x3, [sp], #8
-          ldr	    x2, [sp], #8
-          ldr	    x1, [sp], #8
-          ldr	    x0, [sp], #8"
-    : : : : "volatile");
-
-    llvm_asm!("eret" :::: "volatile");
-}
diff --git a/src/context/arch/aarch64.rs b/src/context/arch/aarch64.rs
index 863766506a6ec5f1fc9b2d565599e6b1c9b37e74..3af07fd3a2c398e52b00b8260719f839c623635a 100644
--- a/src/context/arch/aarch64.rs
+++ b/src/context/arch/aarch64.rs
@@ -150,6 +150,42 @@ impl Context {
         value
     }
 
+    pub fn dump(&self) {
+        println!("elr_el1: 0x{:016x}", self.elr_el1);
+        println!("sp_el0: 0x{:016x}", self.sp_el0);
+        println!("ttbr0_el1: 0x{:016x}", self.ttbr0_el1);
+        println!("ttbr1_el1: 0x{:016x}", self.ttbr1_el1);
+        println!("tpidr_el0: 0x{:016x}", self.tpidr_el0);
+        println!("tpidrro_el0: 0x{:016x}", self.tpidrro_el0);
+        println!("rflags: 0x{:016x}", self.rflags);
+        println!("esr_el1: 0x{:016x}", self.esr_el1);
+        println!("padding: 0x{:016x}", self.padding);
+        println!("sp: 0x{:016x}", self.sp);
+        println!("lr: 0x{:016x}", self.lr);
+        println!("fp: 0x{:016x}", self.fp);
+        println!("x28: 0x{:016x}", self.x28);
+        println!("x27: 0x{:016x}", self.x27);
+        println!("x26: 0x{:016x}", self.x26);
+        println!("x25: 0x{:016x}", self.x25);
+        println!("x24: 0x{:016x}", self.x24);
+        println!("x23: 0x{:016x}", self.x23);
+        println!("x22: 0x{:016x}", self.x22);
+        println!("x21: 0x{:016x}", self.x21);
+        println!("x20: 0x{:016x}", self.x20);
+        println!("x19: 0x{:016x}", self.x19);
+        println!("x18: 0x{:016x}", self.x18);
+        println!("x17: 0x{:016x}", self.x17);
+        println!("x16: 0x{:016x}", self.x16);
+        println!("x15: 0x{:016x}", self.x15);
+        println!("x14: 0x{:016x}", self.x14);
+        println!("x13: 0x{:016x}", self.x13);
+        println!("x12: 0x{:016x}", self.x12);
+        println!("x11: 0x{:016x}", self.x11);
+        println!("x10: 0x{:016x}", self.x10);
+        println!("x9: 0x{:016x}", self.x9);
+        println!("x8: 0x{:016x}", self.x8);
+    }
+
     #[cold]
     #[inline(never)]
     #[naked]
diff --git a/src/syscall/process.rs b/src/syscall/process.rs
index 05b66e266757429f01cca2c7e01e7bef5c258216..5e7dd27c080dc9e6b67a52e19ac4489ac3f06e4d 100644
--- a/src/syscall/process.rs
+++ b/src/syscall/process.rs
@@ -510,14 +510,25 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
             {
                 if let Some(stack) = &mut context.kstack {
                     unsafe {
-                        let interrupt_stack_offset_from_stack_base = *(stack_base as *const u64) - stack_base as u64;
-                        let mut interrupt_stack = &mut *(stack.as_mut_ptr().add(offset + interrupt_stack_offset_from_stack_base as usize) as *mut crate::arch::interrupt::InterruptStack);
-                        interrupt_stack.tpidr_el0 = tcb_addr;
+                        // stack_base contains a pointer to InterruptStack. Get its offset from
+                        // stack_base itself
+                        let istack_offset = *(stack_base as *const u64) - stack_base as u64;
+
+                        // Get the top of the new process' stack
+                        let new_sp = stack.as_mut_ptr().add(offset);
+
+                        // Update the pointer to the InterruptStack to reflect the new process'
+                        // stack. (Without this the pointer would be InterruptStack on the parent
+                        // process' stack.
+                        *(new_sp as *mut u64) = new_sp as u64 + istack_offset;
+
+                        // Update tpidr_el0 in the new process' InterruptStack
+                        let mut interrupt_stack = &mut *(stack.as_mut_ptr().add(offset + istack_offset as usize) as *mut crate::arch::interrupt::InterruptStack);
+                        interrupt_stack.iret.tpidr_el0 = tcb_addr;
                     }
                 }
             }
-
-
+            
             // Setup user TLS
             if let Some(mut tls) = tls_opt {
                 // Copy TLS mapping