From nobody Tue Apr 15 15:33:19 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1488219363809842.5911123938631; Mon, 27 Feb 2017 10:16:03 -0800 (PST) Received: from localhost ([::1]:55548 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPq5-00039X-FE for importer@patchew.org; Mon, 27 Feb 2017 13:16:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52016) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPff-0002MP-LG for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:18 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfe-0001te-1A for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:15 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48677) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfd-0001lG-NV for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:13 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfX-0002Nk-Se for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:07 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:44 +0000 Message-Id: <1488218699-31035-16-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1488218699-31035-1-git-send-email-peter.maydell@linaro.org> References: <1488218699-31035-1-git-send-email-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PULL 15/30] armv7m: Fix condition check for taking exceptions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 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. [Michael Davidsaver's patchset had a patch to do something similar but the implementation ended up being a rewrite.] Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- target/arm/cpu.h | 8 ++++++++ hw/intc/armv7m_nvic.c | 7 +++++++ target/arm/cpu.c | 16 ++++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 38a8e00..649f237 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1356,6 +1356,14 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint3= 2_t excp_idx, uint32_t cur_el, bool secure); =20 /* 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); int armv7m_nvic_acknowledge_irq(void *opaque); void armv7m_nvic_complete_irq(void *opaque, int irq); diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index fb4c985..6a03e2c 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -286,6 +286,13 @@ static inline int nvic_exec_prio(NVICState *s) return MIN(running, s->exception_prio); } =20 +bool armv7m_nvic_can_take_pending_exception(void *opaque) +{ + NVICState *s =3D opaque; + + return nvic_exec_prio(s) > nvic_pending_prio(s); +} + /* caller must call nvic_irq_update() after this */ static void set_prio(NVICState *s, unsigned irq, uint8_t prio) { diff --git a/target/arm/cpu.c b/target/arm/cpu.c index f7157dc..04b062c 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -338,13 +338,6 @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, i= nt interrupt_request) CPUARMState *env =3D &cpu->env; bool ret =3D false; =20 - - if (interrupt_request & CPU_INTERRUPT_FIQ - && !(env->daif & PSTATE_F)) { - cs->exception_index =3D EXCP_FIQ; - cc->do_interrupt(cs); - ret =3D true; - } /* ARMv7-M interrupt return works by loading a magic value * into the PC. On real hardware the load causes the * return to occur. The qemu implementation performs the @@ -354,9 +347,16 @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, i= nt interrupt_request) * the stack if an interrupt occurred at the wrong time. * We avoid this by disabling interrupts when * pc contains a magic address. + * + * 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 + * if it is higher priority than the current execution priority + * (which depends on state like BASEPRI, FAULTMASK and the + * currently active exception). */ if (interrupt_request & CPU_INTERRUPT_HARD - && !(env->daif & PSTATE_I) + && (armv7m_nvic_can_take_pending_exception(env->nvic)) && (env->regs[15] < 0xfffffff0)) { cs->exception_index =3D EXCP_IRQ; cc->do_interrupt(cs); --=20 2.7.4