I am learning the ARM architecture via bare metal programming on the Raspberry Pi 3. I have a booting "kernel" that prints out some info. I have reached a point that I don't understand what is happening. I have two pieces of boot code below, one works and one doesn't. I don't understand the difference. My gut says there is some sort of alignment thing I've missed in the documentation, but I can't put my finger on it.
I'm PXE booting my Pi 3, and have kernel_old=1 set in the config.txt so that it runs cores from 0x0, if this matters.
This boot.S works and I get into kernel_main and the other cores get into aux_core_main:
// File: boot.S
// Platform: Raspberry Pi 3
// Date: 05/20/2018
//
//
//
// To keep this in the first portion of the binary.
.section ".text.boot"
#define __BOOT_CODE__
#include "identifiers.h"
// GLOBALS
// Make _start global.
.globl _start
_start:
///
// all cores setup code
//
// setup the VM midr/mipdr
mrs x0, mpidr_el1 // Read MIPDR
mrs x1, midr_el1 // Read MIDR
msr vpidr_el2, x1 // set the VM versions of these
msr vmpidr_el2, x0 // same
// start core specific code
and x0, x0, #0x03 // mask off cpu ID bits
cbz x0, _core0_start // start cpu0
cmp x0, #0x1 // compare and branch
beq _core1_start
cmp x0, #0x2 // compare and branch
beq _core2_start
b _core3_start // last core, just go there
_core0_start:
// get out of EL3 and into EL2
//
mrs x0, CurrentEL // read current EL
and x0, x0, #0x0C // clear reserved bits
cmp x0, 0x0C // are the two bits set (0b11 = EL3)
bne _exit_el3
// chaging from el3 to el2
mov x2, #0x5b1 // Secure Configuration Register
msr scr_el3, x2 //
mov x2, #0x3c9
msr spsr_el3, x2 // Program Status Registers
adr x2, _exit_el3
msr elr_el3, x2
eret // go!
// So we're now in EL2, proceed with setup
_exit_el3:
mov x0, #0
mov x1, #ARCH_AARCH64
mov x2, #PLATFORM_RASPI3
ldr x3, =__dtb_start
ldr x4, =__core_0_el2_stack_end
mov sp, x4
ldr x4, =__core_0_el1_stack_end
msr sp_el1, x4
ldr x4, =__core_0_el0_stack_end
msr sp_el0, x4
bl kernel_main
b __halt__
_core1_start:
ldr x4, =__core_1_el2_stack_end
mov sp, x4
ldr x4, =__core_1_el1_stack_end
msr sp_el1, x4
ldr x4, =__core_1_el0_stack_end
msr sp_el0, x4
bl aux_core_main
b __halt__
_core2_start:
ldr x4, =__core_2_el2_stack_end
mov sp, x4
ldr x4, =__core_2_el1_stack_end
msr sp_el1, x4
ldr x4, =__core_2_el0_stack_end
msr sp_el0, x4
bl aux_core_main
b __halt__
_core3_start:
ldr x4, =__core_3_el2_stack_end
mov sp, x4
ldr x4, =__core_3_el1_stack_end
msr sp_el1, x4
ldr x4, =__core_3_el0_stack_end
msr sp_el0, x4
bl aux_core_main
b __halt__
.globl __halt__
__halt__:
wfe
b __halt__
While adding a nop before the very first instruction breaks the whole thing:
// File: boot.S
// Platform: Raspberry Pi 3
// Date: 05/20/2018
//
//
//
// To keep this in the first portion of the binary.
.section ".text.boot"
#define __BOOT_CODE__
#include "identifiers.h"
// GLOBALS
// Make _start global.
.globl _start
_start:
///
// all cores setup code
//
// setup the VM midr/mipdr
nop
mrs x0, mpidr_el1 // Read MIPDR
mrs x1, midr_el1 // Read MIDR
msr vpidr_el2, x1 // set the VM versions of these
msr vmpidr_el2, x0 // same
// start core specific code
and x0, x0, #0x03 // mask off cpu ID bits
cbz x0, _core0_start // start cpu0
cmp x0, #0x1 // compare and branch
beq _core1_start
cmp x0, #0x2 // compare and branch
beq _core2_start
b _core3_start // last core, just go there
_core0_start:
// get out of EL3 and into EL2
//
mrs x0, CurrentEL // read current EL
and x0, x0, #0x0C // clear reserved bits
cmp x0, 0x0C // are the two bits set (0b11 = EL3)
bne _exit_el3
// chaging from el3 to el2
mov x2, #0x5b1 // Secure Configuration Register
msr scr_el3, x2 //
mov x2, #0x3c9
msr spsr_el3, x2 // Program Status Registers
adr x2, _exit_el3
msr elr_el3, x2
eret // go!
// So we're now in EL2, proceed with setup
_exit_el3:
mov x0, #0
mov x1, #ARCH_AARCH64
mov x2, #PLATFORM_RASPI3
ldr x3, =__dtb_start
ldr x4, =__core_0_el2_stack_end
mov sp, x4
ldr x4, =__core_0_el1_stack_end
msr sp_el1, x4
ldr x4, =__core_0_el0_stack_end
msr sp_el0, x4
bl kernel_main
b __halt__
_core1_start:
ldr x4, =__core_1_el2_stack_end
mov sp, x4
ldr x4, =__core_1_el1_stack_end
msr sp_el1, x4
ldr x4, =__core_1_el0_stack_end
msr sp_el0, x4
bl aux_core_main
b __halt__
_core2_start:
ldr x4, =__core_2_el2_stack_end
mov sp, x4
ldr x4, =__core_2_el1_stack_end
msr sp_el1, x4
ldr x4, =__core_2_el0_stack_end
msr sp_el0, x4
bl aux_core_main
b __halt__
_core3_start:
ldr x4, =__core_3_el2_stack_end
mov sp, x4
ldr x4, =__core_3_el1_stack_end
msr sp_el1, x4
ldr x4, =__core_3_el0_stack_end
msr sp_el0, x4
bl aux_core_main
b __halt__
.globl __halt__
__halt__:
wfe
b __halt__