CS 452/652 Winter 2022 - Lecture 6
January 19, 2022
prev next
Context Switch
- "execution state" = context
- save / restore execution state
- similar to and presents as subroutine call
ARM Instructions
- mov - copy register values
- str/ldr - store/load registers ↔ memory
- stm/ldm - store/load multiple registers
- special case: access user registers from exception modes
- special case: cpsr := spsr (ldm only)
- RISC architecture: instructions + operands encoded in 32 bits
Subroutine Call
- starting point for context switch considerations
- call to subroutine: branch-and-link (lr := pc + 4)
bl <immediate>, OR
blx <register>
- return from subroutine (pc := lr)
bx lr
- other branching and returning instructions
mov pc, lr
ldr pc, [mem]
ldm [mem], {...,pc,...}
- Application Binary Interface (ABI) defines rules for subroutine call: ARM Call Standard
- stack pointer alignment: 8 bytes
- argument passing: r0-r3, rest on stack
- caller-saved registers (subroutine can overwrite): r0-r3, r12, psr
- callee-saved registers (subroutine must preserve): r4-r11, sp
- lr is special: both caller- and callee-saved
Stack Switch
Mode Switch
- SP is banked: automatic stack switch
- CPSR saved to SPSR
- rest of context still needs saving!
- asymmetric: enter_kernel() vs. leave_kernel()
- potentially multiple variants of enter_kernel() for system call, interrupt...
- system call: synchronous (ABI rules apply)
- interrupt: asynchronous (no ABI guarantees)
SWI Instruction
- user call into kernel ("software interrupt"); implements system calls
swi N
- hard-coded branch to 0x08
- after-reset contents of 0x08: ldr pc, [pc, #0x18]
- branches to value from pc-relative memory location
- evaluating pc in ARM's pipeline results in pc+8
- i.e., branch to destination stored in 0x28
- set up SWI: change instruction at 0x08 or branch destination at 0x28
- branch to your hard-coded enter_kernel() handler
After SWI
- starting your enter_kernel() handler
- processor in supervisor mode
- user sp, lr saved in respective banks
- user cpsr saved in spsr
- sp set to dedicated stack pointer
- lr holds user return address (location following swi instruction)
- must be saved (as part of user context) for later return to user task
- choices for getting user context:
- enter system mode, or
- use special version of stm instruction
- choices for storing user context:
- on user stack, or
- in task descriptor
- then restore kernel context
Kernel Exit
- store kernel context (similar to voluntary stack switch)
- restore given user context (next task to be run)
- return to user mode, for example
movs pc, lr
- variant of mov that changes processor mode
System Call Processing
- these are suggestions - other implementations are possible...
- SWI argument N can be retrieved as follows
- kernel needs access to system call parameters
- leave first four arguments in r0-r3: save during context switch
- additional arguments on user stack; see ABI
Additional Information
An earlier document by Bill Cowan is available here.
This is certainly not the only way to write a context switch and I do not necessarily recommend (or not recommend) this particular approach, but I figure every bit of information can help.