Hi,
I have written two bare-metal programs to run on EL2 and EL1 on Raspberry Pi 3B. The board is boot loaded with U-Boot. The EL2 binary is loaded at 0x1000000. The EL1 binary is loaded at 0x3000000.
The EL2 code initializes the UART and prints a message, then it switches to EL1. The EL1 binary won't print any message if it makes use of the stack. If the stack is not used, it prints the message.
May I know what is wrong with my code?
The EL2 code. It switches to EL1
//Initialisation part Start.S mrs x1, mpidr_el1 and x1, x1, #3 cbz x1, 2f // cpu id > 0, stop 1: wfe b 1b mrs x0, cnthctl_el2 orr x0, x0, #3 msr cnthctl_el2, x0 msr cntvoff_el2, xzr // enable AArch64 in EL1 mov x0, #(1 << 31) // AArch64 orr x0, x0, #(1 << 1) // SWIO hardwired on Pi3 msr hcr_el2, x0 mrs x0, hcr_el2 mov x2, #0x3c4 msr spsr_el2, x2 bl test //test.c void test() { init_uart(); print_message(); __asm volatile ( "movz x2, 0x0000 \n\t" "movk x2, 0x0300, lsl #16 \n\t" "msr elr_el2, x2 \n\t" "movz x0, 0xFFF0 \n\t" "movk x0, 0x2FF, lsl 16 \n\t" "msr sp_el1, x0 \n\t" "eret \n\t" ); }
The code of the EL1 program is given below
.global _start _start: bl el1_test el1_test.c void el1_test() { print_uart(); while(1) { asm volatile("nop"); } }
The disassembly of the el1_test() code is given below
0000000003000280 <el1_test>: 3000280: a9bf7bfd stp x29, x30, [sp, #-16]! 3000284: 910003fd mov x29, sp 3000288: 97ffffa4 bl 3000118 <uart_send1> 300028c: d503201f nop 3000290: d503201f nop 3000294: 17fffffe b 300028c 3000298: d503201f nop
Any hint or help is greatly appreciated
I think your problem is related to uboot's 'go' command as it does not flush the caches before jumping to new address and keeps the mmu enabled. You can verify through reading SCTRL_EL2 register.U-boot also support 'dcache' command. Flushing it before jumping to your code might help.