qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PULL 2/7] target-arm: fix get_phys_addr_v6/SCTLR_AFE acces


From: Peter Maydell
Subject: [Qemu-devel] [PULL 2/7] target-arm: fix get_phys_addr_v6/SCTLR_AFE access check
Date: Mon, 16 Mar 2015 12:40:13 +0000

From: Andrew Jones <address@hidden>

Introduce simple_ap_to_rw_prot(), which has the same behavior as
ap_to_rw_prot(), but takes the 2-bit simple AP[2:1] instead of
the 3-bit AP[2:0]. Use this in get_phys_addr_v6 when SCTLR_AFE
is set, as that bit indicates we should be using the simple AP
format.

It's unlikely this path is getting used. I don't see CR_AFE
getting used by Linux, so possibly not. If it had been, then
the check would have been wrong for all but AP[2:1] = 0b11.
Anyway, this should fix it up, in case it ever does get used.

Signed-off-by: Andrew Jones <address@hidden>
Reviewed-by: Peter Maydell <address@hidden>
Message-id: address@hidden
Signed-off-by: Peter Maydell <address@hidden>
---
 target-arm/helper.c | 49 ++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 42 insertions(+), 7 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index d1e70a8..d996659 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -4905,6 +4905,11 @@ static inline bool regime_is_user(CPUARMState *env, 
ARMMMUIdx mmu_idx)
 
 /* Translate section/page access permissions to page
  * R/W protection flags
+ *
+ * @env:         CPUARMState
+ * @mmu_idx:     MMU index indicating required translation regime
+ * @ap:          The 3-bit access permissions (AP[2:0])
+ * @domain_prot: The 2-bit domain access permissions
  */
 static inline int ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx,
                                 int ap, int domain_prot)
@@ -4954,6 +4959,32 @@ static inline int ap_to_rw_prot(CPUARMState *env, 
ARMMMUIdx mmu_idx,
     }
 }
 
+/* Translate section/page access permissions to page
+ * R/W protection flags.
+ *
+ * @env:     CPUARMState
+ * @mmu_idx: MMU index indicating required translation regime
+ * @ap:      The 2-bit simple AP (AP[2:1])
+ */
+static inline int
+simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap)
+{
+    bool is_user = regime_is_user(env, mmu_idx);
+
+    switch (ap) {
+    case 0:
+        return is_user ? 0 : PAGE_READ | PAGE_WRITE;
+    case 1:
+        return PAGE_READ | PAGE_WRITE;
+    case 2:
+        return is_user ? 0 : PAGE_READ;
+    case 3:
+        return PAGE_READ;
+    default:
+        g_assert_not_reached();
+    }
+}
+
 static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
                                      uint32_t *table, uint32_t address)
 {
@@ -5186,14 +5217,18 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t 
address, int access_type,
         if (xn && access_type == 2)
             goto do_fault;
 
-        /* The simplified model uses AP[0] as an access control bit.  */
-        if ((regime_sctlr(env, mmu_idx) & SCTLR_AFE)
-                && (ap & 1) == 0) {
-            /* Access flag fault.  */
-            code = (code == 15) ? 6 : 3;
-            goto do_fault;
+        if (arm_feature(env, ARM_FEATURE_V6K) &&
+                (regime_sctlr(env, mmu_idx) & SCTLR_AFE)) {
+            /* The simplified model uses AP[0] as an access control bit.  */
+            if ((ap & 1) == 0) {
+                /* Access flag fault.  */
+                code = (code == 15) ? 6 : 3;
+                goto do_fault;
+            }
+            *prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1);
+        } else {
+            *prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
         }
-        *prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
         if (*prot && !xn) {
             *prot |= PAGE_EXEC;
         }
-- 
1.9.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]