I have a trivial bare-metal app that I launch in Qemu by the next command:
qemu-system-aarch64 -M virt \ -cpu cortex-a72 \ -bios "$(QEMU_PATH)/share/qemu/edk2-aarch64-code.fd" \ -m 128M \ -nographic \ -device loader,file=$(BUILD_DIR)/kernel.elf \ -device loader,addr=0x40100000,cpu-num=0
Now I'm trying to handle exceptions and interrupts but, unfortunately, the more I read about this topic the less I understand how to handle them.
aarch64 offers us 4 levels: EL3 -> EL0. I've checked my app is launched in Qemu at EL1 level, okay, OS level, everything is right.
Next, various tutorials in the Internet show us a something as below:
.text .global vector_table .balign 2048 vector_table: b . .balign 0x80 b . .balign 0x80 b . .balign 0x80 b . ... adr x0, vector_table msr VBAR_EL2, x0
From this listing I got that I need to load address of my
VBAR_EL1 register (cuz my app works at EL1 level).
As I understand the CPU will use VBAR_EL1 register to find an address of the suitable handler and execute it.
That's all, unfortunately! My understanding finishes at this moment and there are only questions next...
If someone can explain in simple words I will be very grateful.
- Why does the author align table at 2048?
Because the manual says the lower 11 bits are
RES0, so the table has to be aligned to 0x800 bytes:
- Why does he offset entrypoints by 0x80 although there are other offsets on the official table?
Because 0x80+0x80 = 0x100, 0x80+0x80+0x80 = 0x180, etc.
- Which exceptions and interrupts should I handle at EL1 level?
All of them?
If you don't expect to get any exceptions ever, you should at the very least make all exception handlers invoke some sort of "fatal" action (kernel panic, trapping to debugger, or possibly just spinning indefinitely), just so you'll be made aware of violated assumptions. As long as you're not making active use of interrupts, EL0, page faults, etc., you can run entirely without causing exceptions. As you start making use of more CPU features, you'll have to add exception handlers one by one. You'll then have to check
ESR_EL1 for the specific exceptions you want to handle, and dispatch them to your handler functions, but those will become obvious once you get there.