@@ -8768,9 +8768,16 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
}
break;
case 20: /* CONTROL */
- switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
- env->v7m.control = val & (R_V7M_CONTROL_SPSEL_MASK |
- R_V7M_CONTROL_NPRIV_MASK);
+ /* Writing to the SPSEL bit only has an effect if we are in
+ * thread mode; other bits can be updated by any privileged code.
+ * switch_v7m_sp() deals with updating the SPSEL bit in
+ * env->v7m.control, so we only need update the others.
+ */
+ if (env->v7m.exception == 0) {
+ switch_v7m_sp(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
+ }
+ env->v7m.control &= ~R_V7M_CONTROL_NPRIV_MASK;
+ env->v7m.control |= val & R_V7M_CONTROL_NPRIV_MASK;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "Attempt to write unknown special"