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:
parent
9ee660e7c1
commit
50f11062d4
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user