mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-24 22:15:07 +00:00
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.) Backports commit 50f11062d4c896408731d6a286bcd116d1e08465 from qemu
This commit is contained in:
parent
f31c3b32fb
commit
4b8bdda695
|
@ -8165,12 +8165,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) ?
|
||||||
|
@ -8210,6 +8266,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:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
|
|
Loading…
Reference in a new issue