armv7m: MRS/MSR: handle unprivileged access

The MRS and MSR instruction handling has a number of flaws:
* unprivileged accesses should only be able to read
CONTROL and the xPSR subfields, and only write APSR
(others RAZ/WI)
* privileged access should not be able to write xPSR
subfields other than APSR
* accesses to unimplemented registers should log as
guest errors, not abort QEMU

Backports commit 58117c9bb429cd9552d998687aa99088eb1d8528 from qemu
This commit is contained in:
Michael Davidsaver 2018-03-02 13:29:56 -05:00 committed by Lioncash
parent 2769c6ada0
commit 8828b4e595
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -7627,23 +7627,39 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg) uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
{ {
ARMCPU *cpu = arm_env_get_cpu(env); uint32_t mask;
unsigned el = arm_current_el(env);
/* First handle registers which unprivileged can read */
switch (reg) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7: /* xPSR sub-fields */
mask = 0;
if ((reg & 1) && el) {
mask |= 0x000001ff; /* IPSR (unpriv. reads as zero) */
}
if (!(reg & 4)) {
mask |= 0xf8000000; /* APSR */
}
/* EPSR reads as zero */
return xpsr_read(env) & mask;
break;
case 20: /* CONTROL */
return env->v7m.control;
}
if (el == 0) {
return 0; /* unprivileged reads others as zero */
}
switch (reg) { switch (reg) {
case 0: /* APSR */
return xpsr_read(env) & 0xf8000000;
case 1: /* IAPSR */
return xpsr_read(env) & 0xf80001ff;
case 2: /* EAPSR */
return xpsr_read(env) & 0xff00fc00;
case 3: /* xPSR */
return xpsr_read(env) & 0xff00fdff;
case 5: /* IPSR */
return xpsr_read(env) & 0x000001ff;
case 6: /* EPSR */
return xpsr_read(env) & 0x0700fc00;
case 7: /* IEPSR */
return xpsr_read(env) & 0x0700edff;
case 8: /* MSP */ case 8: /* MSP */
return (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) ? return (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) ?
env->v7m.other_sp : env->regs[13]; env->v7m.other_sp : env->regs[13];
@ -7657,40 +7673,34 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
return env->v7m.basepri; return env->v7m.basepri;
case 19: /* FAULTMASK */ case 19: /* FAULTMASK */
return (env->daif & PSTATE_F) != 0; return (env->daif & PSTATE_F) != 0;
case 20: /* CONTROL */
return env->v7m.control;
default: default:
/* ??? For debugging only. */ /* ??? For debugging only. */
cpu_abort(CPU(cpu), "Unimplemented system register read (%d)\n", reg); qemu_log_mask(LOG_GUEST_ERROR, "Attempt to read unknown special"
" register %d\n", reg);
return 0; return 0;
} }
} }
void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val) void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
{ {
ARMCPU *cpu = arm_env_get_cpu(env); if (arm_current_el(env) == 0 && reg > 7) {
/* only xPSR sub-fields may be written by unprivileged */
return;
}
switch (reg) { switch (reg) {
case 0: /* APSR */ case 0:
xpsr_write(env, val, 0xf8000000); case 1:
break; case 2:
case 1: /* IAPSR */ case 3:
xpsr_write(env, val, 0xf8000000); case 4:
break; case 5:
case 2: /* EAPSR */ case 6:
xpsr_write(env, val, 0xfe00fc00); case 7: /* xPSR sub-fields */
break; /* only APSR is actually writable */
case 3: /* xPSR */ if (reg & 4) {
xpsr_write(env, val, 0xfe00fc00); xpsr_write(env, val, 0xf8000000); /* APSR */
break; }
case 5: /* IPSR */
/* IPSR bits are readonly. */
break;
case 6: /* EPSR */
xpsr_write(env, val, 0x0600fc00);
break;
case 7: /* IEPSR */
xpsr_write(env, val, 0x0600fc00);
break; break;
case 8: /* MSP */ case 8: /* MSP */
if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) { if (env->v7m.control & R_V7M_CONTROL_SPSEL_MASK) {
@ -7734,8 +7744,8 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
R_V7M_CONTROL_NPRIV_MASK); R_V7M_CONTROL_NPRIV_MASK);
break; break;
default: default:
/* ??? For debugging only. */ qemu_log_mask(LOG_GUEST_ERROR, "Attempt to write unknown special"
cpu_abort(CPU(cpu), "Unimplemented system register write (%d)\n", reg); " register %d\n", reg);
return; return;
} }
} }