armv7m: Fix condition check for taking exceptions

The M profile condition for when we can take a pending exception or
interrupt is not the same as that for A/R profile. The code
originally copied from the A/R profile version of the
cpu_exec_interrupt function only worked by chance for the
very simple case of exceptions being masked by PRIMASK.
Replace it with a call to a function in the NVIC code that
correctly compares the priority of the pending exception
against the current execution priority of the CPU.

Backports commit 7ecdaa4a9635f1ded0dfa9218c25273b6d4dcd44 from qemu
This commit is contained in:
Peter Maydell 2018-03-02 19:49:57 -05:00 committed by Lioncash
parent 5470bd1763
commit 43ba76cb28
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
2 changed files with 8 additions and 8 deletions

View file

@ -308,14 +308,6 @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
CPUClass *cc = CPU_GET_CLASS(env->uc, cs);
bool ret = false;
if (interrupt_request & CPU_INTERRUPT_FIQ
&& !(env->daif & PSTATE_F)) {
cs->exception_index = EXCP_FIQ;
cc->do_interrupt(cs);
ret = true;
}
/* ARMv7-M interrupt masking works differently than -A or -R.
* There is no FIQ/IRQ distinction. Instead of I and F bits
* masking FIQ and IRQ interrupts, an exception is taken only

View file

@ -1355,6 +1355,14 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
uint32_t cur_el, bool secure);
/* Interface between CPU and Interrupt controller. */
#ifndef CONFIG_USER_ONLY
bool armv7m_nvic_can_take_pending_exception(void *opaque);
#else
static inline bool armv7m_nvic_can_take_pending_exception(void *opaque)
{
return true;
}
#endif
void armv7m_nvic_set_pending(void *opaque, int irq);
void armv7m_nvic_acknowledge_irq(void *opaque);
void armv7m_nvic_complete_irq(void *opaque, int irq);