This is an assembly code from linux arm64 (arch/arm64/kernel/head.S).(kernel source 5.4.21)
__primary_switched:
adrp x4, init_thread_union -- line 1
add sp, x4, #THREAD_SIZE -- line 2
adr_l x5, init_task -- line 3
msr sp_el0, x5 // Save thread_info -- line 4
adr_l x8, vectors // load VBAR_EL1 with virtual -- line5
msr vbar_el1, x8 // vector table address -- line 6
isb -- line7
stp xzr, x30, [sp, #-16]! -- line8
mov x29, sp -- line9
str_l x21, __fdt_pointer, x5 // Save FDT pointer -- line10
I'll try to explain it and someone please give me light and correct me if I'm wrong.
- line 1 : x4 = (page address of init_thread_union). I found init_thread_union is a variable in the kernel linkerscript.(arch/arm64/kernel/vmlinux.lds). this vmlinux.lds is genearted from vmlinux.lds.S during kernel building.
- line 2 : sp = (x4 + #THREAD_SIZE). looks like setting the stack pointer for this thread. (and looks like this thread is using init_thread_union memory region) (to use 4K bytes from location of init_thread_union as stack for this thread)
- line 3 : x5 = (address of init_task struct), I found init_task is a task_struct for init task.(in init/init_task.c). so this struct contains thread info.
- line 4 : sp_el0 = x5. why set the stack pointer of exception level 0 with the thread_info? and is this sp_el0 different from the sp in line 2? (I guess we are now in el 1, so sp in line 2 means sp_el1). and x5 is later used in line 10.
I can't understand exactly what this code is doing. especially line 4. What is this code doing?