aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Campbell <ijc@hellion.org.uk>2014-06-09 15:43:23 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-06-19 14:22:36 +0100
commita7a28289410f7227ac922a785cffb33483058b58 (patch)
tree769734cc8c397d059d7e7d831b6d500433fc3f77
parentf9d7856dbe85404955aa18e860af3e02473267bb (diff)
downloadqemu-arm-a7a28289410f7227ac922a785cffb33483058b58.tar.gz
target-arm: Correct handling of UXN bit in ARMv8 LPAE page tables
[Cherry pick of master commit d615efac7c4dc.] In v8 page tables bit 54 in the PTE is UXN in the EL0/EL1 translation regimes and XN elsewhere. In v7 the bit is always XN. Since we only emulate EL0/EL1 we can just treat this bit as UXN whenever we are in v8 mode. Also correctly extract the upper attributes from the PTE entry, the v8 version tried to avoid extracting the CONTIG bit and ended up with the upper bits being off-by-one. Instead behave the same as v7 and extract (but ignore) the CONTIG bit. This fixes "Bad mode in Synchronous Abort handler detected, code 0x8400000f" seen when modprobing modules under Linux. Signed-off-by: Ian Campbell <ijc@hellion.org.uk> Cc: Peter Maydell <peter.maydell@linaro.org> Cc: Claudio Fontana <claudio.fontana@huawei.com> Cc: Rob Herring <robherring2@gmail.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--target-arm/helper.c17
1 files changed, 8 insertions, 9 deletions
diff --git a/target-arm/helper.c b/target-arm/helper.c
index b6f1b21cb9..a0e57cdbce 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3842,13 +3842,8 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
page_size = (1 << ((granule_sz * (4 - level)) + 3));
descaddr |= (address & (page_size - 1));
/* Extract attributes from the descriptor and merge with table attrs */
- if (arm_feature(env, ARM_FEATURE_V8)) {
- attrs = extract64(descriptor, 2, 10)
- | (extract64(descriptor, 53, 11) << 10);
- } else {
- attrs = extract64(descriptor, 2, 10)
- | (extract64(descriptor, 52, 12) << 10);
- }
+ attrs = extract64(descriptor, 2, 10)
+ | (extract64(descriptor, 52, 12) << 10);
attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
attrs |= extract32(tableattrs, 3, 1) << 5; /* APTable[1] => AP[2] */
/* The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
@@ -3874,8 +3869,12 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
goto do_fault;
}
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- if (attrs & (1 << 12) || (!is_user && (attrs & (1 << 11)))) {
- /* XN or PXN */
+ if ((arm_feature(env, ARM_FEATURE_V8) && is_user && (attrs & (1 << 12))) ||
+ (!arm_feature(env, ARM_FEATURE_V8) && (attrs & (1 << 12))) ||
+ (!is_user && (attrs & (1 << 11)))) {
+ /* XN/UXN or PXN. Since we only implement EL0/EL1 we unconditionally
+ * treat XN/UXN as UXN for v8.
+ */
if (access_type == 2) {
goto do_fault;
}