diff --git a/src/arch/x86_64/interrupt/exception.rs b/src/arch/x86_64/interrupt/exception.rs
index 9fbd3780f8cdc2f0bc9d3553cb13079fe6c356f2..c98e579433a63195c83e16d152fbfb4744d7beb5 100644
--- a/src/arch/x86_64/interrupt/exception.rs
+++ b/src/arch/x86_64/interrupt/exception.rs
@@ -1,6 +1,4 @@
 use crate::{
-    common::unique::Unique,
-    context,
     interrupt::stack_trace,
     ptrace,
     syscall::flag::*
@@ -20,15 +18,7 @@ interrupt_stack!(divide_by_zero, stack, {
 interrupt_stack!(debug, stack, {
     let mut handled = false;
 
-    {
-        let contexts = context::contexts();
-        if let Some(context) = contexts.current() {
-            let mut context = context.write();
-            if let Some(ref mut kstack) = context.kstack {
-                context.regs = Some((kstack.as_mut_ptr() as usize, Unique::new_unchecked(stack)));
-            }
-        }
-    }
+    let guard = ptrace::set_process_regs(stack);
 
     // Disable singlestep before their is a breakpoint, since the
     // breakpoint handler might end up setting it again but unless it
@@ -36,20 +26,14 @@ interrupt_stack!(debug, stack, {
     let had_singlestep = stack.iret.rflags & (1 << 8) == 1 << 8;
     stack.set_singlestep(false);
 
-    if ptrace::breakpoint_callback(true).is_some() {
+    if ptrace::breakpoint_callback(syscall::PTRACE_SINGLESTEP).is_some() {
         handled = true;
     } else {
         // There was no breakpoint, restore original value
         stack.set_singlestep(had_singlestep);
     }
 
-    {
-        let contexts = context::contexts();
-        if let Some(context) = contexts.current() {
-            let mut context = context.write();
-            context.regs = None;
-        }
-    }
+    drop(guard);
 
     if !handled {
         println!("Debug trap");
diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs
index fbc5bb87159574d344a5c9f9faee516aa2830f9d..8c755baa31dd4974fab94ad9c74786c6f2806bf0 100644
--- a/src/arch/x86_64/interrupt/irq.rs
+++ b/src/arch/x86_64/interrupt/irq.rs
@@ -1,13 +1,11 @@
 use core::sync::atomic::{AtomicUsize, Ordering};
 
-use crate::common::unique::Unique;
-use crate::context;
 use crate::context::timeout;
 use crate::device::pic;
 use crate::device::serial::{COM1, COM2};
 use crate::ipi::{ipi, IpiKind, IpiTarget};
 use crate::scheme::debug::debug_input;
-use crate::time;
+use crate::{context, ptrace, time};
 
 //resets to 0 in context::switch()
 pub static PIT_TICKS: AtomicUsize = AtomicUsize::new(0);
@@ -62,25 +60,8 @@ interrupt_stack!(pit, stack, {
     timeout::trigger();
 
     if PIT_TICKS.fetch_add(1, Ordering::SeqCst) >= 10 {
-        {
-            let contexts = crate::context::contexts();
-            if let Some(context) = contexts.current() {
-                let mut context = context.write();
-                // Make all registers available to e.g. the proc:
-                // scheme
-                if let Some(ref mut kstack) = context.kstack {
-                    context.regs = Some((kstack.as_mut_ptr() as usize, Unique::new_unchecked(stack)));
-                }
-            }
-        }
+        let _guard = ptrace::set_process_regs(stack);
         let _ = context::switch();
-        {
-            let contexts = crate::context::contexts();
-            if let Some(context) = contexts.current() {
-                let mut context = context.write();
-                context.regs = None;
-            }
-        }
     }
 });
 
diff --git a/src/arch/x86_64/interrupt/syscall.rs b/src/arch/x86_64/interrupt/syscall.rs
index 6c845cc405a79dbfde23d8e48de7684ebac048e5..ebc3c528c1e72294dd5fc4ade15fa499e9f32729 100644
--- a/src/arch/x86_64/interrupt/syscall.rs
+++ b/src/arch/x86_64/interrupt/syscall.rs
@@ -1,7 +1,6 @@
 use crate::arch::macros::InterruptStack;
 use crate::arch::{gdt, pti};
-use crate::common::unique::Unique;
-use crate::{context, ptrace, syscall};
+use crate::{ptrace, syscall};
 use x86::shared::msr;
 
 pub unsafe fn init() {
@@ -20,18 +19,9 @@ macro_rules! with_interrupt_stack {
     (unsafe fn $wrapped:ident($stack:ident) -> usize $code:block) => {
         #[inline(never)]
         unsafe fn $wrapped(stack: *mut InterruptStack) {
-            let stack = &mut *stack;
-            {
-                let contexts = context::contexts();
-                if let Some(context) = contexts.current() {
-                    let mut context = context.write();
-                    if let Some(ref mut kstack) = context.kstack {
-                        context.regs = Some((kstack.as_mut_ptr() as usize, Unique::new_unchecked(&mut *stack)));
-                    }
-                }
-            }
+            let _guard = ptrace::set_process_regs(stack);
 
-            let is_sysemu = ptrace::breakpoint_callback(false);
+            let is_sysemu = ptrace::breakpoint_callback(::syscall::PTRACE_SYSCALL);
             if !is_sysemu.unwrap_or(false) {
                 // If not on a sysemu breakpoint
                 let $stack = &mut *stack;
@@ -40,15 +30,7 @@ macro_rules! with_interrupt_stack {
                 if is_sysemu.is_some() {
                     // Only callback if there was a pre-syscall
                     // callback too.
-                    ptrace::breakpoint_callback(false);
-                }
-            }
-
-            {
-                let contexts = context::contexts();
-                if let Some(context) = contexts.current() {
-                    let mut context = context.write();
-                    context.regs = None;
+                    ptrace::breakpoint_callback(::syscall::PTRACE_SYSCALL);
                 }
             }
         }
diff --git a/src/common/unique.rs b/src/common/unique.rs
index 214f5b53a3a02dd1ab23f2e3f9e6d79e0f5a9d71..f426c525a0902ca8aa12245c7b9388350d17dc09 100644
--- a/src/common/unique.rs
+++ b/src/common/unique.rs
@@ -17,7 +17,7 @@ unsafe impl<T> Sync for Unique<T> {}
 
 impl<T> Unique<T> {
     pub fn new(ptr: *mut T) -> Self {
-        Self(NonNull::new(ptr).unwrap())
+        Self(NonNull::new(ptr).expect("Did not expect pointer to be null"))
     }
     pub unsafe fn new_unchecked(ptr: *mut T) -> Self {
         Self(NonNull::new_unchecked(ptr))
diff --git a/src/ptrace.rs b/src/ptrace.rs
index 538a2fc8617ce0c66b9c578c678bdb2ee2e0cc97..ae7d9b18a2c480bb53451804df134ec59f1daec5 100644
--- a/src/ptrace.rs
+++ b/src/ptrace.rs
@@ -33,7 +33,7 @@ use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
 use syscall::{
     data::PtraceEvent,
     error::*,
-    flag::{EVENT_READ, EVENT_WRITE}
+    flag::*
 };
 
 //  ____                _
@@ -166,9 +166,7 @@ pub fn recv_events(pid: ContextId, out: &mut [PtraceEvent]) -> Option<usize> {
 struct Breakpoint {
     tracee: Arc<WaitCondition>,
     reached: bool,
-
-    sysemu: bool,
-    singlestep: bool
+    flags: u8
 }
 
 fn inner_cont(pid: ContextId) -> Option<Breakpoint> {
@@ -190,7 +188,7 @@ pub fn cont(pid: ContextId) {
 
 /// Create a new breakpoint for the specified tracee, optionally with
 /// a sysemu flag. Panics if the session is invalid.
-pub fn set_breakpoint(pid: ContextId, sysemu: bool, singlestep: bool) {
+pub fn set_breakpoint(pid: ContextId, flags: u8) {
     let tracee = inner_cont(pid)
         .map(|b| b.tracee)
         .unwrap_or_else(|| Arc::new(WaitCondition::new()));
@@ -200,8 +198,7 @@ pub fn set_breakpoint(pid: ContextId, sysemu: bool, singlestep: bool) {
     session.breakpoint = Some(Breakpoint {
         tracee,
         reached: false,
-        sysemu,
-        singlestep
+        flags
     });
 }
 
@@ -247,7 +244,7 @@ pub fn wait(pid: ContextId) -> Result<Option<PtraceEvent>> {
 
 /// Notify the tracer and await green flag to continue.
 /// Note: Don't call while holding any locks, this will switch contexts
-pub fn breakpoint_callback(singlestep: bool) -> Option<bool> {
+pub fn breakpoint_callback(flags: u8) -> Option<bool> {
     // Can't hold any locks when executing wait()
     let (tracee, sysemu) = {
         let contexts = context::contexts();
@@ -261,8 +258,7 @@ pub fn breakpoint_callback(singlestep: bool) -> Option<bool> {
         // TODO: How should singlesteps interact with syscalls? How
         // does Linux handle this?
 
-        // if singlestep && !breakpoint.singlestep {
-        if breakpoint.singlestep != singlestep {
+        if breakpoint.flags & PTRACE_OPERATIONMASK != flags & PTRACE_OPERATIONMASK {
             return None;
         }
 
@@ -275,7 +271,7 @@ pub fn breakpoint_callback(singlestep: bool) -> Option<bool> {
 
         (
             Arc::clone(&breakpoint.tracee),
-            breakpoint.sysemu
+            breakpoint.flags & PTRACE_SYSEMU == PTRACE_SYSEMU
         )
     };
 
@@ -301,6 +297,43 @@ pub fn close_tracee(pid: ContextId) -> Option<()> {
 // |_| \_\___|\__, |_|___/\__\___|_|  |___/
 //            |___/
 
+pub struct ProcessRegsGuard;
+
+/// Make all registers available to e.g. the proc: scheme
+/// ---
+/// For use inside arch-specific code to assign the pointer of the
+/// interupt stack to the current process. Meant to reduce the amount
+/// of ptrace-related code that has to lie in arch-specific bits.
+/// ```rust,ignore
+/// let _guard = ptrace::set_process_regs(pointer);
+/// ...
+/// // (_guard implicitly dropped)
+/// ```
+pub fn set_process_regs(pointer: *mut InterruptStack) -> Option<ProcessRegsGuard> {
+    let contexts = context::contexts();
+    let context = contexts.current()?;
+    let mut context = context.write();
+
+    let kstack = context.kstack.as_mut()?;
+
+    context.regs = Some((kstack.as_mut_ptr() as usize, Unique::new(pointer)));
+    Some(ProcessRegsGuard)
+}
+
+impl Drop for ProcessRegsGuard {
+    fn drop(&mut self) {
+        fn clear_process_regs() -> Option<()> {
+            let contexts = context::contexts();
+            let context = contexts.current()?;
+            let mut context = context.write();
+
+            context.regs = None;
+            Some(())
+        }
+        clear_process_regs();
+    }
+}
+
 /// Return the InterruptStack pointer, but relative to the specified
 /// stack instead of the original.
 pub unsafe fn rebase_regs_ptr(
diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs
index 76fc9d80b089c22c57fdfceb7938e9db7cc428eb..3e7d34a115650c3c6cb08785b1fad1a05897e864 100644
--- a/src/scheme/proc.rs
+++ b/src/scheme/proc.rs
@@ -130,7 +130,7 @@ impl Scheme for ProcScheme {
                 }
             }
         }
-        
+
         let id = self.next_id.fetch_add(1, Ordering::SeqCst);
 
         if let Operation::Trace { .. } = operation {
@@ -368,7 +368,6 @@ impl Scheme for ProcScheme {
                     return Ok(0);
                 }
                 let op = buf[0];
-                let sysemu = op & PTRACE_SYSEMU == PTRACE_SYSEMU;
 
                 let mut blocking = flags & O_NONBLOCK != O_NONBLOCK;
                 let mut singlestep = false;
@@ -377,7 +376,7 @@ impl Scheme for ProcScheme {
                     PTRACE_CONT => { ptrace::cont(pid); },
                     PTRACE_SYSCALL | PTRACE_SINGLESTEP => { // <- not a bitwise OR
                         singlestep = op & PTRACE_OPERATIONMASK == PTRACE_SINGLESTEP;
-                        ptrace::set_breakpoint(pid, sysemu, singlestep);
+                        ptrace::set_breakpoint(pid, op);
                     },
                     PTRACE_WAIT => blocking = true,
                     _ => return Err(Error::new(EINVAL))