What Happens in Registers and Stack During a Context Switch?
A CPU context switch between two processes is the mechanism an operating system uses to pause one running process and resume another on the same processor core. At the hardware level, this requires saving the current execution state—specifically the CPU registers and stack pointers—of the outgoing process into memory, and loading the previously saved state of the incoming process. By preserving these exact values, the operating system ensures that each process can resume execution as if it were never interrupted.
Entering the Kernel via Trap or Interrupt
A context switch begins when the CPU transitions from user mode to kernel mode. This transition is triggered by a hardware interrupt (such as a timer tick), a system call, or a processor exception.
When this event occurs, the CPU hardware automatically performs the initial state-saving steps before transferring control to the kernel's interrupt or trap handler:
- Privilege Level Switch: The CPU switches its privilege ring (for example, from Ring 3 to Ring 0 on x86-64).
- Stack Pointer Swap: Because user-space stacks
cannot be trusted by the kernel, the hardware switches from the
user-mode stack pointer (
RSPorSP) to a dedicated kernel-mode stack pointer for the current process, typically retrieved from a structure like the Task State Segment (TSS). - Hardware-Pushed Frame: The processor pushes
essential registers onto the new kernel stack. On x86-64, this includes
the user stack segment (
SS), user stack pointer (RSP), processor flags (RFLAGS), code segment (CS), and the instruction pointer (RIP) pointing to the next instruction to execute in user space.
Saving the Full Register Context
Once inside the kernel's trap handler, the operating system must save the remaining CPU registers that the hardware did not automatically push. If these registers were overwritten by kernel code, the outgoing process would lose its working data.
The kernel pushes the general-purpose registers (such as
RAX, RBX, RCX, RDX,
RSI, RDI, RBP, and
R8–R15 on x86-64) onto the process's kernel
stack. Floating-point, SIMD (SSE/AVX), and vector registers are often
saved lazily or only when the process has actively used them, as they
represent a large amount of state.
At this point, the entire execution context of the outgoing process
is stored on its kernel stack, and the current stack pointer
(RSP) points to the top of this saved frame.
Switching Kernel Stacks and Address Spaces
After the scheduler decides which process should run next, the kernel
performs the actual switch between the two processes' contexts. This
happens inside a low-level assembly routine (often called
switch_to or ctx_switch).
The routine performs two critical operations:
- Saving and Restoring the Kernel Stack Pointer: The
kernel saves the current
RSPvalue into the outgoing process's Process Control Block (PCB) or thread control block. It then loads theRSPregister with the saved kernel stack pointer from the incoming process's PCB. - Switching the Virtual Address Space: Because two
different processes have isolated memory spaces, the kernel updates the
page table base register (such as
CR3on x86-64 orTTBR0on ARM64) to point to the incoming process's page tables. This action also flushes or tags entries in the Translation Lookaside Buffer (TLB).
Once RSP is updated, the CPU is now operating on the
incoming process's kernel stack.
Restoring Registers and Returning to User Mode
With the incoming process's kernel stack active, the low-level switch routine pops the saved general-purpose registers off the stack in the reverse order they were pushed. It then returns to the trap handler exit path.
Finally, the kernel executes a special return-from-interrupt
instruction (such as iretq on x86-64 or eret
on ARM64). This instruction atomically pops the hardware-saved frame
(RIP, CS, RFLAGS,
RSP, SS) from the kernel stack, restores the
user-mode stack pointer, drops the CPU privilege level back to user
mode, and jumps to the exact instruction where the incoming process was
previously paused.