We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi,
I am just trying to learn the linux kernel booting process for arm32 Cortex A9 multi core SOC. I had understood the concept of booting in linux, but I am confused about the section where secondary cores enabling from primary core. Can somebody briefly explains me about the assembly instructions in head.S for enabling the secondary cpus from primary cpu and which registers are actually involved during these assembly operations
adr r4, __secondary_data ldmia r4, {r5, r7, r12} sub lr, r4, r5 add r3, r7, lr ldrd r4, [r3, #0] ARM_BE8(eor r4, r4, r5) ARM_BE8(eor r5, r4, r5) ARM_BE8(eor r4, r4, r5) ldr r8, [r3, #8] badr lr, __enable_mmu mov r13, r12 ldr r12, [r10, #PROCINFO_INITFUNC] add r12, r12, r10 ret r12
Thanks, manish
This code snippet extracts data from primary core and based on the info enable MMU, and eventually when the MMU is enabled it return to the __secondary_switched which in turn branches to secondary_start_kernel main C entry point for secondary CPUs. To dive in little bit deeper lets dry run this.
At this time we have processor id in r9. Based on which the registers are populated as follows r3 has cpu_val and r4 cpu_mask and r5 has the pointer to the proc_info structure. For now let's assume everything was fine and we'll never run into an error. Then we load the secondary data in 1st instruction.
Now the secondary data is populated usually by the boot processor/primary CPU and this contains the data such as info for MMU and initial stack to be used. After
ldmia r4, {r5, r7, r12}
(Assuming we are using MMU not MPU) we have pointers for struct secondary_data in r4 we load its fields. Now registers has
r5-> Pointer to Page Directory
r7-> Pointer to Swapper Page Directoryr12-> Pointer to initial stack
Since MMU is not enabled right now we do the translation by ourselves, via these instructions
sub lr, r4, r5 add r3, r7, lr
and we derefence pgdir in r4.ldrd r4, [r3, #0]
after this we swap this in BE mode via these instructions (pgdir is uint64)
ARM_BE8(eor r4, r4, r5) ARM_BE8(eor r5, r4, r5) ARM_BE8(eor r4, r4, r5)
Now we have in r4,r5 page driectory
Next we load Swapper page directory
ldr r8, [r3, #8]
Now in r8 we have swapper page directory.
now load address for __enable_mmu in r14.
Move stack pointer to its right place with
mov r13, r12
Remember in r10 we have the pointer to proc_info_list, so we load the init function pointer to r12 and eventually jump to it initializing the processor. Now we have all pointer set we would just go through all flow described at start of answer.
ldr r12, [r10, #PROCINFO_INITFUNC] add r12, r12, r10 ret r12
Hope this simplifies things for you.