mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-25 18:46:47 +00:00
target/arm: Split "get pending exception info" from "acknowledge it"
Currently armv7m_nvic_acknowledge_irq() does three things: * make the current highest priority pending interrupt active * return a bool indicating whether that interrupt is targeting Secure or NonSecure state * implicitly tell the caller which is the highest priority pending interrupt by setting env->v7m.exception We need to split these jobs, because v7m_exception_taken() needs to know whether the pending interrupt targets Secure so it can choose to stack callee-saves registers or not, but it must not make the interrupt active until after it has done that stacking, in case the stacking causes a derived exception. Similarly, it needs to know the number of the pending interrupt so it can read the correct vector table entry before the interrupt is made active, because vector table reads might also cause a derived exception. Create a new armv7m_nvic_get_pending_irq_info() function which simply returns information about the highest priority pending interrupt, and use it to rearrange the v7m_exception_taken() code so we don't acknowledge the exception until we've done all the things which could possibly cause a derived exception. Backports part of commit 6c9485188170e11ad31ce477c8ce200b8e8ce59d from qemu
This commit is contained in:
parent
49010633f0
commit
e1349f817a
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue