diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index 7a344f7e..94167441 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -1473,6 +1473,21 @@ void armv7m_nvic_set_pending(void *opaque, int irq); * a different exception). */ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure); +/** + * armv7m_nvic_get_pending_irq_info: return highest priority pending + * exception, and whether it targets Secure state + * @opaque: the NVIC + * @pirq: set to pending exception number + * @ptargets_secure: set to whether pending exception targets Secure + * + * This function writes the number of the highest priority pending + * exception (the one which would be made active by + * armv7m_nvic_acknowledge_irq()) to @pirq, and sets @ptargets_secure + * to true if the current highest priority pending exception should + * be taken to Secure state, false for NS. + */ +void armv7m_nvic_get_pending_irq_info(void *opaque, int *pirq, + bool *ptargets_secure); /** * armv7m_nvic_acknowledge_irq: make highest priority pending exception active * @opaque: the NVIC diff --git a/qemu/target/arm/helper.c b/qemu/target/arm/helper.c index 1fd6f6e1..cfce4c1b 100644 --- a/qemu/target/arm/helper.c +++ b/qemu/target/arm/helper.c @@ -5645,12 +5645,12 @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode, } } -static uint32_t arm_v7m_load_vector(ARMCPU *cpu, bool targets_secure) +static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure) { CPUState *cs = CPU(cpu); CPUARMState *env = &cpu->env; MemTxResult result; - hwaddr vec = env->v7m.vecbase[targets_secure] + env->v7m.exception * 4; + hwaddr vec = env->v7m.vecbase[targets_secure] + exc * 4; uint32_t addr; addr = address_space_ldl(cs->as, vec, @@ -5712,9 +5712,10 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain) CPUARMState *env = &cpu->env; uint32_t addr; bool targets_secure = false; + int exc; // Unicorn: commented out - //targets_secure = armv7m_nvic_acknowledge_irq(env->nvic); + //armv7m_nvic_get_pending_irq_info(env->nvic, &exc, &targets_secure); if (arm_feature(env, ARM_FEATURE_V8)) { if (arm_feature(env, ARM_FEATURE_M_SECURITY) && @@ -5782,6 +5783,15 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain) } } + addr = arm_v7m_load_vector(cpu, exc, targets_secure); + + /* Now we've done everything that might cause a derived exception + * we can go ahead and activate whichever exception we're going to + * take (which might now be the derived exception). + */ + // Unicorn: commented out + //armv7m_nvic_acknowledge_irq(env->nvic); + /* Switch to target security state -- must do this before writing SPSEL */ switch_v7m_security_state(env, targets_secure); write_v7m_control_spsel(env, 0); @@ -5789,7 +5799,6 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain) /* Clear IT bits */ env->condexec_bits = 0; env->regs[14] = lr; - addr = arm_v7m_load_vector(cpu, targets_secure); env->regs[15] = addr & 0xfffffffe; env->thumb = addr & 1; }