The CPU succesfully switches to EL1h, non-secure. But the el1_entry is never called. I don't know why. If using secure el1, the el1_entry gets called. Compiled using clang -c boot.S -o boot.o, and linked with ld. Any help would be appreciated.
global _Entry
_Entry:
mrs x0, scr_el3
orr x0, x0, #(1 << 10)
orr x0, x0, #(1 << 0)
msr scr_el3, x0
mov x0, #0b00101
msr spsr_el3, x0
adr x1, el1_entry
msr elr_el3, x1
eret
el1_entry:
ldr x15, =0xdeadbeef
b .
I can think of some possible answers it's worth checking:
No, im using qemu to emulate the cortex-a55. On reset, only EL3 registers are initialized to a know value. The MMU and cache is disabled by default. So secure accesses are allowed, the whole ram region is not MMU mapped and no protection rules are set. I think the secure access is denied if the MMU is enabled for the current exception level. EL2 is disabled by default on qemu unless i specify virtualization flag. Maybe i should check the ESR_EL1? Thanks
Ejub Ikovic said:So secure accesses are allowed, the whole ram region is not MMU mapped and no protection rules are set. I think the secure access is denied if the MMU is enabled for the current exception level.
That's not quite right. The Cortex-A55 supports two Physical Address Spaces (PAS); Secure and Non-secure. All accesses by the core will resolve to a physical address in one of those two PASs. In Non-secure state, the output PAS is always Non-secure (doesn't matter if the MMU is on or off). In Secure state, when the MMU is disabled the output PAS is Secure, when the MMU is enabled the output PAS is set via the translation tables.
On real hardware, it's important that the output PAS from the core matches whatever the thing in the memory is. Typically you'd get a bus level fault if you tried to access a memory with the wrong PAS (as strictly, you asked for an address that doesn't exist).
Ejub Ikovic said:EL2 is disabled by default on qemu unless i specify virtualization flag.
I'm not familiar with qemu... when you say it's disabled - what does that mean?
On HW, the EL2 registers would still be there. Qemu might have set them to a known value, but they might not be the ones you want. For example, HCR_EL2.RW controls whether NS_EL1 uses AArch32 or AArch64. You'd need to make sure that matches what you're putting into SPSR_EL3 before doing the ERET into EL1.
Ejub Ikovic said:Maybe i should check the ESR_EL1?
The ESR is a good thing to check. But also look at which EL you're in. As in, did the ERET itself fail (illegal exception return), meaning you are still in EL3 and need to check ESR_EL3. Or, did the ERET succeed, and something went wrong in EL1.
The code started working if i use an ELF file as parameter to the qemu -kernel option. Using binary version, the code doesn't works. I'm not a pro at this, so Any help about what i need to initialize when the CPU is brought out of reset would be fine.