When I try to execute code from a region mapped as read/write (AP[2] == 0), the CPU issues a permission fault (exception class == 0b100001, instruction fault status code == 0b001111). When I change the mapping to read-only (AP[2] == 1), the permission fault goes away. Is this expected behavior from the MMU? I thought executing code from a region mapped as read/write was allowed. Could someone point me to a section in the "Arm Architecture Reference Manual" that explains this?
For reference:
ARM DDI 0487I.a, page D8-5142 has the answer.
Preventing execution from writable locations There are register control fields that can be used to force writable memory to be treated as XN, PXN, or UXN, regardless of the value of the corresponding descriptor fields. For a stage 1 translation in a translation regime that supports two Exception levels, the corresponding SCTLR_ELx.WXN field does all of the following: * If the value is 0, then there is no effect on access permissions. * If the value is 1, then all of the following apply: * If the memory region is writable from EL0, then it is treated as Unprivileged execute-never, regardless of the value of the Block descriptor or Page descriptor UXN field. * If the memory region is writable from the higher Exception level, ELx, then it is treated as Privileged execute-never, regardless of the value of the Block descriptor or Page descriptor PXN field.
Preventing execution from writable locations
There are register control fields that can be used to force writable memory to be treated as XN, PXN, or UXN, regardless of the value of the corresponding descriptor fields.
For a stage 1 translation in a translation regime that supports two Exception levels, the corresponding SCTLR_ELx.WXN field does all of the following:
* If the value is 0, then there is no effect on access permissions.
* If the value is 1, then all of the following apply:
* If the memory region is writable from EL0, then it is treated as Unprivileged execute-never, regardless of the value of the Block descriptor or Page descriptor UXN field.
* If the memory region is writable from the higher Exception level, ELx, then it is treated as Privileged execute-never, regardless of the value of the Block descriptor or Page descriptor PXN field.
Yes, probably.
Any page which is write-able at EL0 will always be non-executable to EL1 (or EL2 with E2H=1).
For pages write-able at EL1/2/3, whether they are automatically treated as non-executable is controlled by SCTLR_ELx.WXN
In the latest Arm ARM, you want info statement WXKKQ (Table D8-42) and info statement LJHZZ (Table D8-43)
Thanks Martin. Where can I find info statements WXKKQ and LJHZZ?
If you grab a copy of the latest Arm ARM (rev I.a) from here https://developer.arm.com/documentation/ddi0487/ia/?lang=enThen you should be able to ctrl+F for the IDs. It's part of the new style documentation, each chunk of the spec is given an ID so you can refer to it more specifically than just the chapter number. Not all the chapters are covered yet, but the chapters covering permissions are.
Got it. I didn't realize they were inside ARM DDI 0487I.a