diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index 109c67e1..db92be4f 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -437,7 +437,7 @@ typedef struct CPUARMState { unsigned mpu_ctrl; /* MPU_CTRL */ int exception; uint32_t primask[2]; - uint32_t faultmask; + uint32_t faultmask[2]; uint32_t secure; /* Is CPU in Secure state? (not guest visible) */ } v7m; @@ -1420,6 +1420,16 @@ void armv7m_nvic_acknowledge_irq(void *opaque); * (Ignoring -1, this is the same as the RETTOBASE value before completion.) */ int armv7m_nvic_complete_irq(void *opaque, int irq); +/** + * armv7m_nvic_raw_execution_priority: return the raw execution priority + * @opaque: the NVIC + * + * Returns: the raw execution priority as defined by the v8M architecture. + * This is the execution priority minus the effects of AIRCR.PRIS, + * and minus any PRIMASK/FAULTMASK/BASEPRI priority boosting. + * (v8M ARM ARM I_PKLD.) + */ +int armv7m_nvic_raw_execution_priority(void *opaque); /* Interface for defining coprocessor registers. * Registers are defined in tables of arm_cp_reginfo structs @@ -2220,7 +2230,7 @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch) * we're in a HardFault or NMI handler. */ if ((env->v7m.exception > 0 && env->v7m.exception <= 3) - || env->v7m.faultmask) { + || env->v7m.faultmask[env->v7m.secure]) { mmu_idx = ARMMMUIdx_MNegPri; } diff --git a/qemu/target/arm/helper.c b/qemu/target/arm/helper.c index d91d2928..baf3dc77 100644 --- a/qemu/target/arm/helper.c +++ b/qemu/target/arm/helper.c @@ -5426,8 +5426,21 @@ static void do_v7m_exception_exit(ARMCPU *cpu) } if (env->v7m.exception != ARMV7M_EXCP_NMI) { - /* Auto-clear FAULTMASK on return from other than NMI */ - env->v7m.faultmask = 0; + /* Auto-clear FAULTMASK on return from other than NMI. + * If the security extension is implemented then this only + * happens if the raw execution priority is >= 0; the + * value of the ES bit in the exception return value indicates + * which security state's faultmask to clear. (v8M ARM ARM R_KBNF.) + */ + /* Unicorn: commented out + if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { + int es = type & 1; + if (armv7m_nvic_raw_execution_priority(env->nvic) >= 0) { + env->v7m.faultmask[es] = 0; + } + } else*/ { + env->v7m.faultmask[M_REG_NS] = 0; + } } // Unicorn: if'd out @@ -8108,7 +8121,7 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) case 18: /* BASEPRI_MAX */ return env->v7m.basepri[env->v7m.secure]; case 19: /* FAULTMASK */ - return env->v7m.faultmask; + return env->v7m.faultmask[env->v7m.secure]; default: /* ??? For debugging only. */ qemu_log_mask(LOG_GUEST_ERROR, "Attempt to read unknown special" @@ -8184,7 +8197,7 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) } break; case 19: /* FAULTMASK */ - env->v7m.faultmask = val & 1; + env->v7m.faultmask[env->v7m.secure] = val & 1; break; case 20: /* CONTROL */ /* Writing to the SPSEL bit only has an effect if we are in