mirror of
				https://github.com/yuzu-emu/unicorn.git
				synced 2025-11-04 03:35:00 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									2769c6ada0
								
							
						
					
					
						commit
						8828b4e595
					
				| 
						 | 
					@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue