From 43ba76cb2815c598647a477c1d9729a28b2dd39d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 2 Mar 2018 19:49:57 -0500 Subject: [PATCH] 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 --- qemu/target/arm/cpu.c | 8 -------- qemu/target/arm/cpu.h | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/qemu/target/arm/cpu.c b/qemu/target/arm/cpu.c index 240b12e7..5f931e3a 100644 --- a/qemu/target/arm/cpu.c +++ b/qemu/target/arm/cpu.c @@ -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 diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index 34dabc7c..6ecfce99 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -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);