mirror of
				https://github.com/yuzu-emu/unicorn.git
				synced 2025-11-04 13:24:57 +00:00 
			
		
		
		
	target/arm: Update excret sanity checks for v8M
In v8M, more bits are defined in the exception-return magic values; update the code that checks these so we accept the v8M values when the CPU permits them. Backports commit bfb2eb52788b9605ef2fc9bc72683d4299117fde from qemu
This commit is contained in:
		
							parent
							
								
									33d2358c91
								
							
						
					
					
						commit
						2feecbac0d
					
				| 
						 | 
				
			
			@ -5545,8 +5545,9 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
 | 
			
		|||
    uint32_t xpsr;
 | 
			
		||||
 | 
			
		||||
    bool ufault = false;
 | 
			
		||||
    bool return_to_sp_process = false;
 | 
			
		||||
    bool return_to_handler = false;
 | 
			
		||||
    bool sfault = false;
 | 
			
		||||
    bool return_to_sp_process;
 | 
			
		||||
    bool return_to_handler;
 | 
			
		||||
    bool rettobase = false;
 | 
			
		||||
    bool exc_secure = false;
 | 
			
		||||
    bool return_to_secure;
 | 
			
		||||
| 
						 | 
				
			
			@ -5580,6 +5581,19 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
 | 
			
		|||
                      excret);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
 | 
			
		||||
        /* EXC_RETURN.ES validation check (R_SMFL). We must do this before
 | 
			
		||||
         * we pick which FAULTMASK to clear.
 | 
			
		||||
         */
 | 
			
		||||
        if (!env->v7m.secure &&
 | 
			
		||||
            ((excret & R_V7M_EXCRET_ES_MASK) ||
 | 
			
		||||
             !(excret & R_V7M_EXCRET_DCRS_MASK))) {
 | 
			
		||||
            sfault = 1;
 | 
			
		||||
            /* For all other purposes, treat ES as 0 (R_HXSR) */
 | 
			
		||||
            excret &= ~R_V7M_EXCRET_ES_MASK;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (env->v7m.exception != ARMV7M_EXCP_NMI) {
 | 
			
		||||
        /* Auto-clear FAULTMASK on return from other than NMI.
 | 
			
		||||
         * If the security extension is implemented then this only
 | 
			
		||||
| 
						 | 
				
			
			@ -5620,24 +5634,54 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
 | 
			
		|||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return_to_handler = !(excret & R_V7M_EXCRET_MODE_MASK);
 | 
			
		||||
    return_to_sp_process = excret & R_V7M_EXCRET_SPSEL_MASK;
 | 
			
		||||
    return_to_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
 | 
			
		||||
        (excret & R_V7M_EXCRET_S_MASK);
 | 
			
		||||
 | 
			
		||||
    switch (excret & 0xf) {
 | 
			
		||||
    case 1: /* Return to Handler */
 | 
			
		||||
        return_to_handler = true;
 | 
			
		||||
        break;
 | 
			
		||||
    case 13: /* Return to Thread using Process stack */
 | 
			
		||||
        return_to_sp_process = true;
 | 
			
		||||
        /* fall through */
 | 
			
		||||
    case 9: /* Return to Thread using Main stack */
 | 
			
		||||
        if (!rettobase &&
 | 
			
		||||
            !(env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_NONBASETHRDENA_MASK)) {
 | 
			
		||||
    if (arm_feature(env, ARM_FEATURE_V8)) {
 | 
			
		||||
        if (!arm_feature(env, ARM_FEATURE_M_SECURITY)) {
 | 
			
		||||
            /* UNPREDICTABLE if S == 1 or DCRS == 0 or ES == 1 (R_XLCP);
 | 
			
		||||
             * we choose to take the UsageFault.
 | 
			
		||||
             */
 | 
			
		||||
            if ((excret & R_V7M_EXCRET_S_MASK) ||
 | 
			
		||||
                (excret & R_V7M_EXCRET_ES_MASK) ||
 | 
			
		||||
                !(excret & R_V7M_EXCRET_DCRS_MASK)) {
 | 
			
		||||
                ufault = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (excret & R_V7M_EXCRET_RES0_MASK) {
 | 
			
		||||
            ufault = true;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        ufault = true;
 | 
			
		||||
    } else {
 | 
			
		||||
        /* For v7M we only recognize certain combinations of the low bits */
 | 
			
		||||
        switch (excret & 0xf) {
 | 
			
		||||
        case 1: /* Return to Handler */
 | 
			
		||||
            break;
 | 
			
		||||
        case 13: /* Return to Thread using Process stack */
 | 
			
		||||
        case 9: /* Return to Thread using Main stack */
 | 
			
		||||
            /* We only need to check NONBASETHRDENA for v7M, because in
 | 
			
		||||
             * v8M this bit does not exist (it is RES1).
 | 
			
		||||
             */
 | 
			
		||||
            if (!rettobase &&
 | 
			
		||||
                !(env->v7m.ccr[env->v7m.secure] &
 | 
			
		||||
                  R_V7M_CCR_NONBASETHRDENA_MASK)) {
 | 
			
		||||
                ufault = true;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            ufault = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (sfault) {
 | 
			
		||||
        env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
 | 
			
		||||
        // Unicorn: commented out
 | 
			
		||||
        //armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
 | 
			
		||||
        v7m_exception_taken(cpu, excret);
 | 
			
		||||
        qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
 | 
			
		||||
                      "stackframe: failed EXC_RETURN.ES validity check\n");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ufault) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue