diff mbox

[v4,10/33] target-arm: extend Aarch64 SCR.{FIQ|IRQ} handling

Message ID 1404169773-20264-11-git-send-email-greg.bellows@linaro.org
State New
Headers show

Commit Message

Greg Bellows June 30, 2014, 11:09 p.m. UTC
From: Fabian Aggeler <aggelerf@ethz.ch>

If EL3 is using Aarch64 IRQ/FIQ masking is ignored in
all exception levels other than EL3 if SCR.{FIQ|IRQ} is
set to 1 (routed to EL3).

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
---
 target-arm/cpu.h | 98 +++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 72 insertions(+), 26 deletions(-)
diff mbox

Patch

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index fbd7cad..7b2817c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1211,20 +1211,43 @@  static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
      * (table G1-18/G1-19) */
     switch (excp_idx) {
     case EXCP_FIQ:
+        if (arm_feature(env, ARM_FEATURE_EL3) && arm_el_is_aa64(env, 3)) {
+            /* If EL3 is using Aarch64 and FIQs are routed to EL3 masking is
+             * ignored in all exception levels except EL3.
+             */
+            if ((env->cp15.scr_el3 & SCR_FIQ) && cur_el < 3) {
+                return true;
+            }
+            /* If we are in EL3 but FIQs are not routed to EL3 the exception
+             * is not taken but remains pending.
+             */
+            if (!(env->cp15.scr_el3 & SCR_FIQ) && cur_el == 3) {
+                return false;
+            }
+        }
         if (!secure) {
-            if (arm_feature(env, ARM_FEATURE_EL2) &&
-                    (env->cp15.hcr_el2 & HCR_FMO)) {
-                /* CPSR.F/PSTATE.F ignored if
-                 *  - exception is taken from Non-secure state
-                 *  - HCR.FMO == 1
-                 *  - either:  - not in Hyp mode
-                 *             - SCR.FIQ routes exception to monitor mode
-                 */
-                if (cur_el < 2) {
-                    return true;
-                } else if (arm_feature(env, ARM_FEATURE_EL3) &&
-                        (env->cp15.scr_el3 & SCR_FIQ)) {
-                    return true;
+            if (arm_feature(env, ARM_FEATURE_EL2)) {
+                if (env->cp15.hcr_el2 & HCR_FMO) {
+                    /* CPSR.F/PSTATE.F ignored if
+                     *  - exception is taken from Non-secure state
+                     *  - HCR.FMO == 1
+                     *  - either:  - not in Hyp mode
+                     *             - SCR.FIQ routes exception to monitor mode
+                     *               (EL3 in Aarch32)
+                     */
+                    if (cur_el < 2) {
+                        return true;
+                    } else if (arm_feature(env, ARM_FEATURE_EL3) &&
+                            (env->cp15.scr_el3 & SCR_FIQ) &&
+                            !arm_el_is_aa64(env, 3)) {
+                        return true;
+                    }
+                } else if (arm_el_is_aa64(env, 3) &&
+                          (env->cp15.scr_el3 & SCR_RW) &&
+                          cur_el == 2) {
+                    /* FIQs not routed to EL2 but currently in EL2 (A64).
+                     * Exception is not taken but remains pending. */
+                    return false;
                 }
             }
             /* In ARMv7 only applies if both Security Extensions (EL3) and
@@ -1252,20 +1275,43 @@  static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx)
         }
         return !(env->daif & PSTATE_F);
     case EXCP_IRQ:
+        if (arm_feature(env, ARM_FEATURE_EL3) && arm_el_is_aa64(env, 3)) {
+            /* If EL3 is using Aarch64 and IRQs are routed to EL3 masking is
+             * ignored in all exception levels except EL3.
+             */
+            if ((env->cp15.scr_el3 & SCR_IRQ) && cur_el < 3) {
+                return true;
+            }
+            /* If we are in EL3 but IRQ s are not routed to EL3 the exception
+             * is not taken but remains pending.
+             */
+            if (!(env->cp15.scr_el3 & SCR_IRQ) && cur_el == 3) {
+                return false;
+            }
+        }
         if (!secure) {
-            if (arm_feature(env, ARM_FEATURE_EL2) &&
-                    (env->cp15.hcr_el2 & HCR_IMO)) {
-                /* CPSR.I/PSTATE.I ignored if
-                 *  - exception is taken from Non-secure state
-                 *  - HCR.IMO == 1
-                 *  - either:  - not in Hyp mode
-                 *             - SCR.IRQ routes exception to monitor mode
-                 */
-                if (cur_el < 2) {
-                    return true;
-                } else if (arm_feature(env, ARM_FEATURE_EL3) &&
-                        (env->cp15.scr_el3 & SCR_IRQ)) {
-                    return true;
+            if (arm_feature(env, ARM_FEATURE_EL2)) {
+                if (env->cp15.hcr_el2 & HCR_IMO) {
+                    /* CPSR.I/PSTATE.I ignored if
+                     *  - exception is taken from Non-secure state
+                     *  - HCR.IMO == 1
+                     *  - either:  - not in Hyp mode
+                     *             - SCR.IRQ routes exception to monitor mode
+                     *                (EL3 in Aarch32)
+                     */
+                    if (cur_el < 2) {
+                        return true;
+                    } else if (arm_feature(env, ARM_FEATURE_EL3) &&
+                            (env->cp15.scr_el3 & SCR_IRQ) &&
+                            !arm_el_is_aa64(env, 3)) {
+                        return true;
+                    }
+                } else if (arm_el_is_aa64(env, 3) &&
+                          (env->cp15.scr_el3 & SCR_RW) &&
+                          cur_el == 2) {
+                    /* IRQs not routed to EL2 but currently in EL2 (A64).
+                     * Exception is not taken but remains pending. */
+                    return false;
                 }
             }
         }