qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v3 14/32] target-arm: Respect SCR.FW, SCR.AW and SCT


From: Fabian Aggeler
Subject: [Qemu-devel] [PATCH v3 14/32] target-arm: Respect SCR.FW, SCR.AW and SCTLR.NMFI
Date: Wed, 11 Jun 2014 01:54:56 +0200

bits when modifying CPSR.

Signed-off-by: Fabian Aggeler <address@hidden>
---
 target-arm/helper.c | 42 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2fbecfa..f6ff4aa 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3091,9 +3091,6 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t 
mask)
         env->GE = (val >> 16) & 0xf;
     }
 
-    env->daif &= ~(CPSR_AIF & mask);
-    env->daif |= val & CPSR_AIF & mask;
-
     if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
         if (bad_mode_switch(env, val & CPSR_M)) {
             /* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
@@ -3105,6 +3102,45 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t 
mask)
             switch_mode(env, val & CPSR_M);
         }
     }
+
+    /* In an implementation that does not include Virtualization Extensions
+     * the SCR.FW and SCR.AW bit control whether non-secure software is allowed
+     * to change the CPSR_F and CPSR_A bits respectively.
+     */
+    if ((mask & CPSR_A)
+            && (val & CPSR_A) != (env->uncached_cpsr & CPSR_A)
+            && arm_feature(env, ARM_FEATURE_EL3)
+            && !(env->cp15.scr_el3 & SCR_AW) && !arm_is_secure(env)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "Ignoring attempt to switch CPSR_A "
+                "flag from non-secure world with SCR.AW bit set\n");
+        mask &= ~CPSR_A;
+    }
+
+    if ((mask & CPSR_F)) {
+        /* Pre ARMv8: Check whether non-maskable FIQ (NMFI) support is enabled.
+         * If this bit is set software is not allowed to mask FIQs,
+         * but is allowed to set CPSR_F to 0.
+         */
+        if (!arm_feature(env, ARM_FEATURE_V8) &&
+            (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_NMFI) &&
+            (val & CPSR_F)) {
+            qemu_log_mask(LOG_GUEST_ERROR, "Ignoring attempt to enable CPSR_F "
+                    "flag (non-maskable FIQ [NMFI] support enabled)\n");
+            mask &= ~CPSR_F;
+        }
+
+        if ((val & CPSR_F) != (env->uncached_cpsr & CPSR_F)
+                && arm_feature(env, ARM_FEATURE_EL3)
+                && !(env->cp15.scr_el3 & SCR_FW) && !arm_is_secure(env)) {
+            qemu_log_mask(LOG_GUEST_ERROR, "Ignoring attempt to switch CPSR_F "
+                    "flag from non-secure world with SCR.FW bit set\n");
+            mask &= ~CPSR_F;
+        }
+    }
+
+    env->daif &= ~(CPSR_AIF & mask);
+    env->daif |= val & CPSR_AIF & mask;
+
     mask &= ~CACHED_CPSR_BITS;
     env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
 }
-- 
1.8.3.2




reply via email to

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