December 14, 2025

The GIC adventures - switching to EL1

I want to do this for the RK3399. I may do it for all of my aarch64 boards. I think that U-boot transfers control in EL2 just in case you are a hypervisor, but expects you to drop to EL1 if you are an actual OS.

I looked at the Fire3 where I have notes that say "interrupts just worked". Those notes were wrong. It is running at EL2 and interrupts do not work.

Useless example code from ARM

ARM provides what looks like nice example code, but you will find that a few things are missing, and that it simply doesn't work.

More useful information

Mike is a great source.

Back to basics

We know that the ERET instruction gets used to drop to a lower EL. It only makes sense to get the details on how ERET works. It is super simple! I had some memory of several different complex stack frames. The stack doesn't get involved at all (though it is important that a valid stack gets set up by and for code running at the new EL). Only two registers get involved.
ELR_el2 -- has the address to branch to
SPSR_el2 -- has the values to be loaded into the PSR
Note the _el2 suffixes. This is for a transition from EL2 to EL1. The level is part of what goes into the SPSR register (saved PSR).

SPSR is a 64 bit register. For our purposes, the entire upper 32 bits can be zero.

bits 31:27 -- condition codes NZCVQ (can all be zero)
bit 9 - D bit (debug)
bit 8 - A bit (SError)
bit 7 - I bit (IRQ mask)
bit 6 - F bit (FIQ mask)
bit 5 - 0
bit 4 - M bit (1 selects 32 bit aarch32 state)
bits 3:0 -- EL and selected stack
Here are the values for the last 4 bits (EL)
0000 - EL0
0100 - EL1 with SP_EL0
0101 - EL1 with SP_EL1
1000 - EL2 with SP_EL0
1001 - EL2 with SP_EL2
There are values to select EL3, but they will just cause exceptions if they are attempted for ERET from EL2.

The whole business of choosing which stack gets used is peculiar (if you ask me). We do have 4 different stack pointers (for EL0,1,2, and 3), but we can decide to always use the EL0 stack for all levels, if that is what we want to do.

I learned by experiment on the RK3328 that U-boot hands the processor to us running at EL2 with SP_EL0, so I will continue with that for EL1.

Continued

See the next page.
Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org