target/arm: Implement MSR/MRS access to NS banked registers

In v8M the MSR and MRS instructions have extra register value
encodings to allow secure code to access the non-secure banked
version of various special registers.

(We don't implement the MSPLIM_NS or PSPLIM_NS aliases, because
we don't currently implement the stack limit registers at all.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 1505240046-11454-2-git-send-email-peter.maydell@linaro.org
This commit is contained in:
Peter Maydell 2017-09-12 19:13:48 +01:00
parent 9ee660e7c1
commit 50f11062d4

View File

@ -8892,12 +8892,68 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
break; break;
case 20: /* CONTROL */ case 20: /* CONTROL */
return env->v7m.control[env->v7m.secure]; return env->v7m.control[env->v7m.secure];
case 0x94: /* CONTROL_NS */
/* We have to handle this here because unprivileged Secure code
* can read the NS CONTROL register.
*/
if (!env->v7m.secure) {
return 0;
}
return env->v7m.control[M_REG_NS];
} }
if (el == 0) { if (el == 0) {
return 0; /* unprivileged reads others as zero */ return 0; /* unprivileged reads others as zero */
} }
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
switch (reg) {
case 0x88: /* MSP_NS */
if (!env->v7m.secure) {
return 0;
}
return env->v7m.other_ss_msp;
case 0x89: /* PSP_NS */
if (!env->v7m.secure) {
return 0;
}
return env->v7m.other_ss_psp;
case 0x90: /* PRIMASK_NS */
if (!env->v7m.secure) {
return 0;
}
return env->v7m.primask[M_REG_NS];
case 0x91: /* BASEPRI_NS */
if (!env->v7m.secure) {
return 0;
}
return env->v7m.basepri[M_REG_NS];
case 0x93: /* FAULTMASK_NS */
if (!env->v7m.secure) {
return 0;
}
return env->v7m.faultmask[M_REG_NS];
case 0x98: /* SP_NS */
{
/* This gives the non-secure SP selected based on whether we're
* currently in handler mode or not, using the NS CONTROL.SPSEL.
*/
bool spsel = env->v7m.control[M_REG_NS] & R_V7M_CONTROL_SPSEL_MASK;
if (!env->v7m.secure) {
return 0;
}
if (!arm_v7m_is_handler_mode(env) && spsel) {
return env->v7m.other_ss_psp;
} else {
return env->v7m.other_ss_msp;
}
}
default:
break;
}
}
switch (reg) { switch (reg) {
case 8: /* MSP */ case 8: /* MSP */
return (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK) ? return (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_SPSEL_MASK) ?
@ -8936,6 +8992,60 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
return; return;
} }
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
switch (reg) {
case 0x88: /* MSP_NS */
if (!env->v7m.secure) {
return;
}
env->v7m.other_ss_msp = val;
return;
case 0x89: /* PSP_NS */
if (!env->v7m.secure) {
return;
}
env->v7m.other_ss_psp = val;
return;
case 0x90: /* PRIMASK_NS */
if (!env->v7m.secure) {
return;
}
env->v7m.primask[M_REG_NS] = val & 1;
return;
case 0x91: /* BASEPRI_NS */
if (!env->v7m.secure) {
return;
}
env->v7m.basepri[M_REG_NS] = val & 0xff;
return;
case 0x93: /* FAULTMASK_NS */
if (!env->v7m.secure) {
return;
}
env->v7m.faultmask[M_REG_NS] = val & 1;
return;
case 0x98: /* SP_NS */
{
/* This gives the non-secure SP selected based on whether we're
* currently in handler mode or not, using the NS CONTROL.SPSEL.
*/
bool spsel = env->v7m.control[M_REG_NS] & R_V7M_CONTROL_SPSEL_MASK;
if (!env->v7m.secure) {
return;
}
if (!arm_v7m_is_handler_mode(env) && spsel) {
env->v7m.other_ss_psp = val;
} else {
env->v7m.other_ss_msp = val;
}
return;
}
default:
break;
}
}
switch (reg) { switch (reg) {
case 0 ... 7: /* xPSR sub-fields */ case 0 ... 7: /* xPSR sub-fields */
/* only APSR is actually writable */ /* only APSR is actually writable */