C function call: compiler has saved x0-x18 (as needed)
Exception Handler
must save ELR - and later SPSR for IRQ
must likely access user SP using SPSel
has access to x0-x30
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 via eret
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.
Mixing C and Assembler
Coding
See various examples file in demo05. Take a look at the compiled .s source
main.c, adder.c - basic argument passing in r0, r1
adder10.c - beyond 8 arguments passed on stack
main.c, asm_adder.S - manual assembler routine working with C caller
main3.c, data_adder.c - memory-based data exchange between C and assembler
asm.c - embed assembler in C code; exchange data with local variables
special register access: msr/mrs
Recommendations
use embedded assembler via asm only for short code sequences that do not access sp
use assembler routine linked as C routine for context-switch code
RPi Initialization
power cycle (10 seconds power-off): all memory reset, devices reset
regular exit (return) from kernel -> reboot
Kernel Start
EL1, working stack, IRQs disabled, caches?
set up (K1): SVC handler
set up (K2): caches
set up (later): timers, SPI/UART, IRQ handler, IRQs, track
create dedicated first user task (init task)
add to ready queue
start kernel loop
Task Management
task creation: need to set up user stack to enable leave_kernel() functionality
handle end of user routine? use dedicate start routine