Jason Xu 9c5c2813a0 Update QEMU command in all README and Makefile | 2 years ago | |
---|---|---|
.. | ||
Makefile | 5 years ago | |
Makefile.clang | 2 years ago | |
Makefile.gcc | 2 years ago | |
OLVASSEL.md | 2 years ago | |
README.md | 2 years ago | |
exc.c | 6 years ago | |
gpio.h | 6 years ago | |
kernel8.img | 4 years ago | |
link.ld | 6 years ago | |
main.c | 6 years ago | |
mbox.c | 6 years ago | |
mbox.h | 6 years ago | |
mmu.c | 6 years ago | |
mmu.h | 6 years ago | |
start.S | 3 years ago | |
uart.c | 3 years ago | |
uart.h | 6 years ago |
Last time we have used a very simple translation scheme, but in real life you often need more. And it is not easy to write the table blindly, so we're going to add exception handlers this time. This will print out some system registers to identify the problem with our translation tables.
$ qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio
Synchronous: Data abort, same EL, Translation fault at level 2:
ESR_EL1 0000000096000006 ELR_EL1 0000000000080D7C
SPSR_EL1 00000000200003C4 FAR_EL1 FFFFFFFFFF000000
Here ESR_EL1 tells us that it was a Data Abort, caused by a translation table error at level 2. The instruction triggered it is at address 0x80D7C which tried to access memory at 0xFFFFFFFFFF000000.
The vector is very similar to AMD64's IDT, with two exceptions: first, there's no special instruction (like sidt), but a system register stores the address. Second, we don't pass a table with addresses rather the address of the actual code. Therefore each "entry" of the vector table is bigger, small stubs so that you can set up arguments and jump to a common handler.
On AMD64 you have 32 entry points for each exception. On AArch, you only have one, and you can read the excpetion code from a system register. Considering that all OS sets a code for the exception and jumps to a common handler, this makes life easier.
exc_handler()
a simple exception handler that dumps registers and decodes ESR_EL1 (partially). We simply stop
the CPU for now, as we have no means to recover from an exception yet. The full comprehensive description of
Exception Syndrome Register can be found in ARM DDI0487B_b chapter D10.2.28.
Before we switch to supervisor mode, we set up vbar_el1. All handlers must be properly aligned. Qemu is not so picky, but real hardware is.
_vectors
the exception handler's vector table with small assembly stubs, each calling exc_handler()
in C.
We set up page translations, and then we deliberatly reference an unmapped address to trigger an exception.