@@ -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;
}
}
}