diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 2a41e5dab9..a6547929df 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -169,7 +169,7 @@ static inline int nvic_exec_prio(NVICState *s) if (env->v7m.faultmask) { running = -1; - } else if (env->v7m.primask) { + } else if (env->v7m.primask[env->v7m.secure]) { running = 0; } else if (env->v7m.basepri[env->v7m.secure] > 0) { running = env->v7m.basepri[env->v7m.secure] & nvic_gprio_mask(s); diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 273abc3dc5..26ec744af0 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -431,7 +431,7 @@ typedef struct CPUARMState { uint32_t bfar; /* BusFault Address */ unsigned mpu_ctrl; /* MPU_CTRL */ int exception; - uint32_t primask; + uint32_t primask[2]; uint32_t faultmask; uint32_t secure; /* Is CPU in Secure state? (not guest visible) */ } v7m; diff --git a/target/arm/helper.c b/target/arm/helper.c index 70072661b8..9a7ab969b8 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -8830,7 +8830,7 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) return (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) ? env->regs[13] : env->v7m.other_sp; case 16: /* PRIMASK */ - return env->v7m.primask; + return env->v7m.primask[env->v7m.secure]; case 17: /* BASEPRI */ case 18: /* BASEPRI_MAX */ return env->v7m.basepri[env->v7m.secure]; @@ -8890,7 +8890,7 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val) } break; case 16: /* PRIMASK */ - env->v7m.primask = val & 1; + env->v7m.primask[env->v7m.secure] = val & 1; break; case 17: /* BASEPRI */ env->v7m.basepri[env->v7m.secure] = val & 0xff; diff --git a/target/arm/machine.c b/target/arm/machine.c index dbb432d0a8..3c42bf5ac3 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -103,7 +103,7 @@ static const VMStateDescription vmstate_m_faultmask_primask = { .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(env.v7m.faultmask, ARMCPU), - VMSTATE_UINT32(env.v7m.primask, ARMCPU), + VMSTATE_UINT32(env.v7m.primask[M_REG_NS], ARMCPU), VMSTATE_END_OF_LIST() } }; @@ -251,6 +251,7 @@ static const VMStateDescription vmstate_m_security = { .fields = (VMStateField[]) { VMSTATE_UINT32(env.v7m.secure, ARMCPU), VMSTATE_UINT32(env.v7m.basepri[M_REG_S], ARMCPU), + VMSTATE_UINT32(env.v7m.primask[M_REG_S], ARMCPU), VMSTATE_END_OF_LIST() } }; @@ -271,9 +272,13 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size, * differences are that the T bit is not in the same place, the * primask/faultmask info may be in the CPSR I and F bits, and * we do not want the mode bits. + * We know that this cleanup happened before v8M, so there + * is no complication with banked primask/faultmask. */ uint32_t newval = val; + assert(!arm_feature(env, ARM_FEATURE_M_SECURITY)); + newval &= (CPSR_NZCV | CPSR_Q | CPSR_IT | CPSR_GE); if (val & CPSR_T) { newval |= XPSR_T; @@ -287,7 +292,7 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size, env->v7m.faultmask = 1; } if (val & CPSR_I) { - env->v7m.primask = 1; + env->v7m.primask[M_REG_NS] = 1; } val = newval; }