I'm trying to wrap my head around the MMU configuration for Cortex A53 armv8 architecture (AArch64). Specifically, I'm programming for Raspberry Pi 3 (Bare Metal).
I've successfully setup the page tables for two levels covering 2GB of memory with 2MB blocks, with a 1 to 1 mapping. Every memory block has the same permission settings.
At EL1 everything works normally, but I'd like to run at EL0 as well. Since I had ignored the AP field of the block descriptor up until now it was cleared (value 0, no access at EL0) and running at EL0 fires a permission fault on write. That was more or less expected, so I set AP to 1 (no access limitation) for every page table entry, expecting it to work; however this time the processor ends up stuck in a synchronous permission fault (I found it out by debugging it, it never got past the interrupt vector), same execution level (ISS encoding 100001 and IFSC 001110), immediately after setting the sctlr register.
The problem seems to be some kind of Privileged Access Never setting that prevent access at EL1 of memory writable by EL0. This is purely a speculation due to the fact that EL1 stops with a permission fault when setting the AP field to unlimited access for EL0.
I've studied the ARM ARM various configuration registers and made sure that none of those are in the way:
- PSTATE.PAN is 0
- SCTLR.SPAN is 0
- SCTLR.WXN is 0
- XN and PXN fields in the page descriptors are cleared
- AP field in block descriptors is set to 1
Does my speculation make sense? In that case, am I missing something that might fire the permission fault?
For reference, this is my mmu setup github.com/.../mmu.c
The manual says: "For a translation regime that applies to EL0 and a higher Exception level, if the value of the AP[2:1] bits is 0b01, permitting write access from EL0, then the PXN field is treated as if it has the value 1, regardless of its actual value".
Despite that, the code in mmu.c does take care of setting AP[2:1] to 0b00 for the first 2MB (which looks to be where the kernel/hal is loaded), so execution in that region should not be affected by the statement quoted above (unless I am missing the hierarchical table-bits).
I missed that. Yes, I changed the APbits to 0b00 for the first block precisely to check whether it would work.
So, a situation where I want to be able to execute (and write) a part of memory both with EL0 and EL1 permissions is simply not contemplated by the MMU? It sounds very restrictive, but then again in a practical scenario it just doesn't make sense to allow privileged execution for memory that can be written by EL0.
I probably read that part but didn't understand it because it felt off. Thank you for the clarification!
I had a similar problem and your answer kind of solved it for me.