This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Bare metal - EL2 to EL1 - SP behaviour

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 

Parents Reply Children