From nobody Thu May 2 14:34:18 2024 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 1486066676973878.4650939027586; Thu, 2 Feb 2017 12:17:56 -0800 (PST) Received: from localhost ([::1]:58804 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNpK-0005jB-Js for importer@patchew.org; Thu, 02 Feb 2017 15:17:54 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60651) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNae-0000Jz-9U for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZNad-000849-4f for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:44 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48351) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cZNaa-0007un-9c; Thu, 02 Feb 2017 15:02:40 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cZNaK-0001uh-4Q; Thu, 02 Feb 2017 20:02:24 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 2 Feb 2017 20:02:14 +0000 Message-Id: <1486065742-28639-2-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> References: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> 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] [PATCH 1/9] armv7m: Rename nvic_state to NVICState 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: , Cc: Liviu Ionescu , Michael Davidsaver , =?UTF-8?q?Alex=20Benn=C3=A9e?= , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Rename the nvic_state struct to NVICState, to match our naming conventions. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- hw/intc/armv7m_nvic.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index fe5c303..09975f3 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -21,7 +21,7 @@ #include "gic_internal.h" #include "qemu/log.h" =20 -typedef struct { +typedef struct NVICState { GICState gic; ARMCPU *cpu; struct { @@ -35,7 +35,7 @@ typedef struct { MemoryRegion container; uint32_t num_irq; qemu_irq sysresetreq; -} nvic_state; +} NVICState; =20 #define TYPE_NVIC "armv7m_nvic" /** @@ -57,7 +57,7 @@ typedef struct NVICClass { #define NVIC_GET_CLASS(obj) \ OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC) #define NVIC(obj) \ - OBJECT_CHECK(nvic_state, (obj), TYPE_NVIC) + OBJECT_CHECK(NVICState, (obj), TYPE_NVIC) =20 static const uint8_t nvic_id[] =3D { 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1 @@ -74,7 +74,7 @@ static const uint8_t nvic_id[] =3D { int system_clock_scale; =20 /* Conversion factor from qemu timer to SysTick frequencies. */ -static inline int64_t systick_scale(nvic_state *s) +static inline int64_t systick_scale(NVICState *s) { if (s->systick.control & SYSTICK_CLKSOURCE) return system_clock_scale; @@ -82,7 +82,7 @@ static inline int64_t systick_scale(nvic_state *s) return 1000; } =20 -static void systick_reload(nvic_state *s, int reset) +static void systick_reload(NVICState *s, int reset) { /* The Cortex-M3 Devices Generic User Guide says that "When the * ENABLE bit is set to 1, the counter loads the RELOAD value from the @@ -101,7 +101,7 @@ static void systick_reload(nvic_state *s, int reset) =20 static void systick_timer_tick(void * opaque) { - nvic_state *s =3D (nvic_state *)opaque; + NVICState *s =3D (NVICState *)opaque; s->systick.control |=3D SYSTICK_COUNTFLAG; if (s->systick.control & SYSTICK_TICKINT) { /* Trigger the interrupt. */ @@ -114,7 +114,7 @@ static void systick_timer_tick(void * opaque) } } =20 -static void systick_reset(nvic_state *s) +static void systick_reset(NVICState *s) { s->systick.control =3D 0; s->systick.reload =3D 0; @@ -126,7 +126,7 @@ static void systick_reset(nvic_state *s) IRQ is #16. The internal GIC routines use #32 as the first IRQ. */ void armv7m_nvic_set_pending(void *opaque, int irq) { - nvic_state *s =3D (nvic_state *)opaque; + NVICState *s =3D (NVICState *)opaque; if (irq >=3D 16) irq +=3D 16; gic_set_pending_private(&s->gic, 0, irq); @@ -135,7 +135,7 @@ void armv7m_nvic_set_pending(void *opaque, int irq) /* Make pending IRQ active. */ int armv7m_nvic_acknowledge_irq(void *opaque) { - nvic_state *s =3D (nvic_state *)opaque; + NVICState *s =3D (NVICState *)opaque; uint32_t irq; =20 irq =3D gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED); @@ -148,13 +148,13 @@ int armv7m_nvic_acknowledge_irq(void *opaque) =20 void armv7m_nvic_complete_irq(void *opaque, int irq) { - nvic_state *s =3D (nvic_state *)opaque; + NVICState *s =3D (NVICState *)opaque; if (irq >=3D 16) irq +=3D 16; gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED); } =20 -static uint32_t nvic_readl(nvic_state *s, uint32_t offset) +static uint32_t nvic_readl(NVICState *s, uint32_t offset) { ARMCPU *cpu =3D s->cpu; uint32_t val; @@ -294,7 +294,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offs= et) } } =20 -static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value) +static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value) { ARMCPU *cpu =3D s->cpu; uint32_t oldval; @@ -425,7 +425,7 @@ static void nvic_writel(nvic_state *s, uint32_t offset,= uint32_t value) static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr, unsigned size) { - nvic_state *s =3D (nvic_state *)opaque; + NVICState *s =3D (NVICState *)opaque; uint32_t offset =3D addr; int i; uint32_t val; @@ -454,7 +454,7 @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr a= ddr, static void nvic_sysreg_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - nvic_state *s =3D (nvic_state *)opaque; + NVICState *s =3D (NVICState *)opaque; uint32_t offset =3D addr; int i; =20 @@ -486,17 +486,17 @@ static const VMStateDescription vmstate_nvic =3D { .version_id =3D 1, .minimum_version_id =3D 1, .fields =3D (VMStateField[]) { - VMSTATE_UINT32(systick.control, nvic_state), - VMSTATE_UINT32(systick.reload, nvic_state), - VMSTATE_INT64(systick.tick, nvic_state), - VMSTATE_TIMER_PTR(systick.timer, nvic_state), + VMSTATE_UINT32(systick.control, NVICState), + VMSTATE_UINT32(systick.reload, NVICState), + VMSTATE_INT64(systick.tick, NVICState), + VMSTATE_TIMER_PTR(systick.timer, NVICState), VMSTATE_END_OF_LIST() } }; =20 static void armv7m_nvic_reset(DeviceState *dev) { - nvic_state *s =3D NVIC(dev); + NVICState *s =3D NVIC(dev); NVICClass *nc =3D NVIC_GET_CLASS(s); nc->parent_reset(dev); /* Common GIC reset resets to disabled; the NVIC doesn't have @@ -513,7 +513,7 @@ static void armv7m_nvic_reset(DeviceState *dev) =20 static void armv7m_nvic_realize(DeviceState *dev, Error **errp) { - nvic_state *s =3D NVIC(dev); + NVICState *s =3D NVIC(dev); NVICClass *nc =3D NVIC_GET_CLASS(s); Error *local_err =3D NULL; =20 @@ -569,7 +569,7 @@ static void armv7m_nvic_instance_init(Object *obj) */ GICState *s =3D ARM_GIC_COMMON(obj); DeviceState *dev =3D DEVICE(obj); - nvic_state *nvic =3D NVIC(obj); + NVICState *nvic =3D NVIC(obj); /* The ARM v7m may have anything from 0 to 496 external interrupt * IRQ lines. We default to 64. Other boards may differ and should * set the num-irq property appropriately. @@ -594,7 +594,7 @@ static const TypeInfo armv7m_nvic_info =3D { .name =3D TYPE_NVIC, .parent =3D TYPE_ARM_GIC_COMMON, .instance_init =3D armv7m_nvic_instance_init, - .instance_size =3D sizeof(nvic_state), + .instance_size =3D sizeof(NVICState), .class_init =3D armv7m_nvic_class_init, .class_size =3D sizeof(NVICClass), }; --=20 2.7.4 From nobody Thu May 2 14:34:18 2024 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 1486066505416772.1525426205186; Thu, 2 Feb 2017 12:15:05 -0800 (PST) Received: from localhost ([::1]:58780 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNmZ-0003Xe-KL for importer@patchew.org; Thu, 02 Feb 2017 15:15:03 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60679) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNaf-0000LI-6Z for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZNae-00084m-FV for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:45 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48351) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cZNac-0007un-BA; Thu, 02 Feb 2017 15:02:42 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cZNaK-0001us-JG; Thu, 02 Feb 2017 20:02:24 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 2 Feb 2017 20:02:15 +0000 Message-Id: <1486065742-28639-3-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> References: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> 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] [PATCH 2/9] armv7m: Implement reading and writing of PRIGROUP 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: , Cc: Liviu Ionescu , Michael Davidsaver , =?UTF-8?q?Alex=20Benn=C3=A9e?= , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add a state field for the v7M PRIGROUP register and implent reading and writing it. The current NVIC doesn't honour the values written, but the new version will. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- hw/intc/armv7m_nvic.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 09975f3..ce22001 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -24,6 +24,9 @@ typedef struct NVICState { GICState gic; ARMCPU *cpu; + + uint32_t prigroup; + struct { uint32_t control; uint32_t reload; @@ -223,7 +226,7 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offse= t) case 0xd08: /* Vector Table Offset. */ return cpu->env.v7m.vecbase; case 0xd0c: /* Application Interrupt/Reset Control. */ - return 0xfa050000; + return 0xfa050000 | (s->prigroup << 8); case 0xd10: /* System Control. */ /* TODO: Implement SLEEPONEXIT. */ return 0; @@ -362,9 +365,7 @@ static void nvic_writel(NVICState *s, uint32_t offset, = uint32_t value) if (value & 1) { qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented= \n"); } - if (value & 0x700) { - qemu_log_mask(LOG_UNIMP, "PRIGROUP unimplemented\n"); - } + s->prigroup =3D extract32(value, 8, 3); } break; case 0xd10: /* System Control. */ @@ -483,13 +484,14 @@ static const MemoryRegionOps nvic_sysreg_ops =3D { =20 static const VMStateDescription vmstate_nvic =3D { .name =3D "armv7m_nvic", - .version_id =3D 1, - .minimum_version_id =3D 1, + .version_id =3D 2, + .minimum_version_id =3D 2, .fields =3D (VMStateField[]) { VMSTATE_UINT32(systick.control, NVICState), VMSTATE_UINT32(systick.reload, NVICState), VMSTATE_INT64(systick.tick, NVICState), VMSTATE_TIMER_PTR(systick.timer, NVICState), + VMSTATE_UINT32(prigroup, NVICState), VMSTATE_END_OF_LIST() } }; --=20 2.7.4 From nobody Thu May 2 14:34:18 2024 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 1486066820174644.7117557921611; Thu, 2 Feb 2017 12:20:20 -0800 (PST) Received: from localhost ([::1]:58811 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNre-0007Sn-1i for importer@patchew.org; Thu, 02 Feb 2017 15:20:18 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60724) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNam-0000X9-3a for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:55 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZNai-00085q-S9 for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:52 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48351) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cZNab-0007un-68; Thu, 02 Feb 2017 15:02:41 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cZNaL-0001v3-1X; Thu, 02 Feb 2017 20:02:25 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 2 Feb 2017 20:02:16 +0000 Message-Id: <1486065742-28639-4-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> References: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> 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] [PATCH 3/9] armv7m: Rewrite NVIC to not use any GIC code 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: , Cc: Liviu Ionescu , Michael Davidsaver , =?UTF-8?q?Alex=20Benn=C3=A9e?= , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Michael Davidsaver Despite some superficial similarities of register layout, the M-profile NVIC is really very different from the A-profile GIC. Our current attempt to reuse the GIC code means that we have significant bugs in our NVIC. Implement the NVIC as an entirely separate device, to give us somewhere we can get the behaviour correct. This initial commit does not attempt to implement exception priority escalation, since the GIC-based code didn't either. It does fix a few bugs in passing: * ICSR.RETTOBASE polarity was wrong and didn't account for internal exceptions * ICSR.VECTPENDING was 16 too high if the pending exception was for an external interrupt * UsageFault, BusFault and MemFault were not disabled on reset as they are supposed to be Signed-off-by: Michael Davidsaver [PMM: reworked, various bugs and stylistic cleanups] Signed-off-by: Peter Maydell --- hw/intc/armv7m_nvic.c | 721 ++++++++++++++++++++++++++++++++++++++++------= ---- hw/intc/trace-events | 15 ++ 2 files changed, 592 insertions(+), 144 deletions(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index ce22001..e319077 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -17,48 +17,79 @@ #include "hw/sysbus.h" #include "qemu/timer.h" #include "hw/arm/arm.h" +#include "target/arm/cpu.h" #include "exec/address-spaces.h" -#include "gic_internal.h" #include "qemu/log.h" +#include "trace.h" + +/* IRQ number counting: + * + * the num-irq property counts the number of external IRQ lines + * + * NVICState::num_irq counts the total number of exceptions + * (external IRQs, the 15 internal exceptions including reset, + * and one for the unused exception number 0). + * + * NVIC_MAX_IRQ is the highest permitted number of external IRQ lines. + * + * NVIC_MAX_VECTORS is the highest permitted number of exceptions. + * + * Iterating through all exceptions should typically be done with + * for (i =3D 1; i < s->num_irq; i++) to avoid the unused slot 0. + * + * The external qemu_irq lines are the NVIC's external IRQ lines, + * so line 0 is exception 16. + */ +#define NVIC_FIRST_IRQ 16 +#define NVIC_MAX_VECTORS 512 +#define NVIC_MAX_IRQ (NVIC_MAX_VECTORS - NVIC_FIRST_IRQ) + +/* Effective running priority of the CPU when no exception is active + * (higher than the highest possible priority value) + */ +#define NVIC_NOEXC_PRIO 0x100 + +typedef struct VecInfo { + int16_t prio; /* priorities can range from -3 to 255 */ + uint8_t enabled; + uint8_t pending; + uint8_t active; + uint8_t level; /* exceptions <=3D15 never set level */ +} VecInfo; =20 typedef struct NVICState { - GICState gic; + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + ARMCPU *cpu; =20 + VecInfo vectors[NVIC_MAX_VECTORS]; uint32_t prigroup; =20 + /* vectpending and exception_prio are both cached state that can + * be recalculated from the vectors[] array and the prigroup field. + */ + unsigned int vectpending; /* highest prio pending enabled exception */ + int exception_prio; /* group prio of the highest prio active exception= */ + struct { uint32_t control; uint32_t reload; int64_t tick; QEMUTimer *timer; } systick; + MemoryRegion sysregmem; - MemoryRegion gic_iomem_alias; MemoryRegion container; + uint32_t num_irq; + qemu_irq excpout; qemu_irq sysresetreq; } NVICState; =20 #define TYPE_NVIC "armv7m_nvic" -/** - * NVICClass: - * @parent_reset: the parent class' reset handler. - * - * A model of the v7M NVIC and System Controller - */ -typedef struct NVICClass { - /*< private >*/ - ARMGICClass parent_class; - /*< public >*/ - DeviceRealize parent_realize; - void (*parent_reset)(DeviceState *dev); -} NVICClass; - -#define NVIC_CLASS(klass) \ - OBJECT_CLASS_CHECK(NVICClass, (klass), TYPE_NVIC) -#define NVIC_GET_CLASS(obj) \ - OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC) + #define NVIC(obj) \ OBJECT_CHECK(NVICState, (obj), TYPE_NVIC) =20 @@ -125,47 +156,274 @@ static void systick_reset(NVICState *s) timer_del(s->systick.timer); } =20 -/* The external routines use the hardware vector numbering, ie. the first - IRQ is #16. The internal GIC routines use #32 as the first IRQ. */ +static int nvic_pending_prio(NVICState *s) +{ + /* return the priority of the current pending interrupt, + * or NVIC_NOEXC_PRIO if no interrupt is pending + */ + return s->vectpending ? s->vectors[s->vectpending].prio : NVIC_NOEXC_P= RIO; +} + +/* Return the value of the ISCR RETTOBASE bit: + * 1 if there is exactly one active exception + * 0 if there is more than one active exception + * UNKNOWN if there are no active exceptions (we choose 0) + */ +static bool nvic_rettobase(NVICState *s) +{ + int irq, nhand =3D 0; + + for (irq =3D ARMV7M_EXCP_RESET; irq < s->num_irq; irq++) { + if (s->vectors[irq].active) { + nhand++; + if (nhand =3D=3D 2) { + break; + } + } + } + + return nhand =3D=3D 1; +} + +/* Return the value of the ISCR ISRPENDING bit: + * 1 if an external interrupt is pending + * 0 if no external interrupt is pending + */ +static bool nvic_isrpending(NVICState *s) +{ + int irq; + + /* We can shortcut if the highest priority pending interrupt + * happens to be external or if there is nothing pending. + */ + if (s->vectpending > NVIC_FIRST_IRQ) { + return true; + } + if (s->vectpending =3D=3D 0) { + return false; + } + + for (irq =3D NVIC_FIRST_IRQ; irq < s->num_irq; irq++) { + if (s->vectors[irq].pending) { + return true; + } + } + return false; +} + +/* Return a mask word which clears the subpriority bits from + * a priority value for an M-profile exception, leaving only + * the group priority. + */ +static inline uint32_t nvic_gprio_mask(NVICState *s) +{ + return ~0U << (s->prigroup + 1); +} + +/* Recompute vectpending and exception_prio */ +static void nvic_recompute_state(NVICState *s) +{ + int i; + int pend_prio =3D NVIC_NOEXC_PRIO; + int active_prio =3D NVIC_NOEXC_PRIO; + int pend_irq =3D 0; + + for (i =3D 1; i < s->num_irq; i++) { + VecInfo *vec =3D &s->vectors[i]; + + if (vec->enabled && vec->pending && vec->prio < pend_prio) { + pend_prio =3D vec->prio; + pend_irq =3D i; + } + if (vec->active && vec->prio < active_prio) { + active_prio =3D vec->prio; + } + } + + s->vectpending =3D pend_irq; + s->exception_prio =3D active_prio & nvic_gprio_mask(s); + + trace_nvic_recompute_state(s->vectpending, s->exception_prio); +} + +/* Return the current execution priority of the CPU + * (equivalent to the pseudocode ExecutionPriority function). + * This is a value between -2 (NMI priority) and NVIC_NOEXC_PRIO. + */ +static inline int nvic_exec_prio(NVICState *s) +{ + CPUARMState *env =3D &s->cpu->env; + int running; + + if (env->daif & PSTATE_F) { /* FAULTMASK */ + running =3D -1; + } else if (env->daif & PSTATE_I) { /* PRIMASK */ + running =3D 0; + } else if (env->v7m.basepri > 0) { + running =3D env->v7m.basepri & nvic_gprio_mask(s); + } else { + running =3D NVIC_NOEXC_PRIO; /* lower than any possible priority */ + } + /* consider priority of active handler */ + return MIN(running, s->exception_prio); +} + +/* caller must call nvic_irq_update() after this */ +static void set_prio(NVICState *s, unsigned irq, uint8_t prio) +{ + assert(irq > ARMV7M_EXCP_NMI); /* only use for configurable prios */ + assert(irq < s->num_irq); + + s->vectors[irq].prio =3D prio; + + trace_nvic_set_prio(irq, prio); +} + +/* Recompute state and assert irq line accordingly. + * Must be called after changes to: + * vec->active, vec->enabled, vec->pending or vec->prio for any vector + * prigroup + */ +static void nvic_irq_update(NVICState *s) +{ + int lvl; + int pend_prio; + + nvic_recompute_state(s); + pend_prio =3D nvic_pending_prio(s); + + /* Raise NVIC output if this IRQ would be taken, except that we + * ignore the effects of the BASEPRI, FAULTMASK and PRIMASK (which + * will be checked for in arm_v7m_cpu_exec_interrupt()); changes + * to those CPU registers don't cause us to recalculate the NVIC + * pending info. + */ + lvl =3D (pend_prio < s->exception_prio); + trace_nvic_irq_update(s->vectpending, pend_prio, s->exception_prio, lv= l); + qemu_set_irq(s->excpout, lvl); +} + +static void armv7m_nvic_clear_pending(void *opaque, int irq) +{ + NVICState *s =3D (NVICState *)opaque; + VecInfo *vec; + + assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq); + + vec =3D &s->vectors[irq]; + trace_nvic_clear_pending(irq, vec->enabled, vec->prio); + if (vec->pending) { + vec->pending =3D 0; + nvic_irq_update(s); + } +} + void armv7m_nvic_set_pending(void *opaque, int irq) { NVICState *s =3D (NVICState *)opaque; - if (irq >=3D 16) - irq +=3D 16; - gic_set_pending_private(&s->gic, 0, irq); + VecInfo *vec; + + assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq); + + vec =3D &s->vectors[irq]; + trace_nvic_set_pending(irq, vec->enabled, vec->prio); + if (!vec->pending) { + vec->pending =3D 1; + nvic_irq_update(s); + } } =20 /* Make pending IRQ active. */ int armv7m_nvic_acknowledge_irq(void *opaque) { NVICState *s =3D (NVICState *)opaque; - uint32_t irq; - - irq =3D gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED); - if (irq =3D=3D 1023) - hw_error("Interrupt but no vector\n"); - if (irq >=3D 32) - irq -=3D 16; - return irq; + CPUARMState *env =3D &s->cpu->env; + const int pending =3D s->vectpending; + const int running =3D nvic_exec_prio(s); + int pendgroupprio; + VecInfo *vec; + + assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq); + + vec =3D &s->vectors[pending]; + + assert(vec->enabled); + assert(vec->pending); + + pendgroupprio =3D vec->prio & nvic_gprio_mask(s); + assert(pendgroupprio < running); + + trace_nvic_acknowledge_irq(pending, vec->prio); + + vec->active =3D 1; + vec->pending =3D 0; + + env->v7m.exception =3D s->vectpending; + + nvic_irq_update(s); + + return env->v7m.exception; } =20 void armv7m_nvic_complete_irq(void *opaque, int irq) { NVICState *s =3D (NVICState *)opaque; - if (irq >=3D 16) - irq +=3D 16; - gic_complete_irq(&s->gic, 0, irq, MEMTXATTRS_UNSPECIFIED); + VecInfo *vec; + + assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq); + + vec =3D &s->vectors[irq]; + + trace_nvic_complete_irq(irq); + + vec->active =3D 0; + if (vec->level) { + /* Re-pend the exception if it's still held high; only + * happens for extenal IRQs + */ + assert(irq >=3D NVIC_FIRST_IRQ); + vec->pending =3D 1; + } + + nvic_irq_update(s); +} + +/* callback when external interrupt line is changed */ +static void set_irq_level(void *opaque, int n, int level) +{ + NVICState *s =3D opaque; + VecInfo *vec; + + n +=3D NVIC_FIRST_IRQ; + + assert(n >=3D NVIC_FIRST_IRQ && n < s->num_irq); + + trace_nvic_set_irq_level(n, level); + + /* The pending status of an external interrupt is + * latched on rising edge and exception handler return. + * + * Pulsing the IRQ will always run the handler + * once, and the handler will re-run until the + * level is low when the handler completes. + */ + vec =3D &s->vectors[n]; + if (level !=3D vec->level) { + vec->level =3D level; + if (level) { + armv7m_nvic_set_pending(s, n); + } + } } =20 static uint32_t nvic_readl(NVICState *s, uint32_t offset) { ARMCPU *cpu =3D s->cpu; uint32_t val; - int irq; =20 switch (offset) { case 4: /* Interrupt Control Type. */ - return (s->num_irq / 32) - 1; + return ((s->num_irq - NVIC_FIRST_IRQ) / 32) - 1; case 0x10: /* SysTick Control and Status. */ val =3D s->systick.control; s->systick.control &=3D ~SYSTICK_COUNTFLAG; @@ -195,33 +453,29 @@ static uint32_t nvic_readl(NVICState *s, uint32_t off= set) case 0xd04: /* Interrupt Control State. */ /* VECTACTIVE */ val =3D cpu->env.v7m.exception; - if (val =3D=3D 1023) { - val =3D 0; - } else if (val >=3D 32) { - val -=3D 16; - } /* VECTPENDING */ - if (s->gic.current_pending[0] !=3D 1023) - val |=3D (s->gic.current_pending[0] << 12); - /* ISRPENDING and RETTOBASE */ - for (irq =3D 32; irq < s->num_irq; irq++) { - if (s->gic.irq_state[irq].pending) { - val |=3D (1 << 22); - break; - } - if (irq !=3D cpu->env.v7m.exception && s->gic.irq_state[irq].a= ctive) { - val |=3D (1 << 11); - } + val |=3D (s->vectpending & 0xff) << 12; + /* ISRPENDING - set if any external IRQ is pending */ + if (nvic_isrpending(s)) { + val |=3D (1 << 22); + } + /* RETTOBASE - set if only one handler is active */ + if (nvic_rettobase(s)) { + val |=3D (1 << 11); } /* PENDSTSET */ - if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending) + if (s->vectors[ARMV7M_EXCP_SYSTICK].pending) { val |=3D (1 << 26); + } /* PENDSVSET */ - if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending) + if (s->vectors[ARMV7M_EXCP_PENDSV].pending) { val |=3D (1 << 28); + } /* NMIPENDSET */ - if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending) + if (s->vectors[ARMV7M_EXCP_NMI].pending) { val |=3D (1 << 31); + } + /* ISRPREEMPT not implemented */ return val; case 0xd08: /* Vector Table Offset. */ return cpu->env.v7m.vecbase; @@ -234,20 +488,48 @@ static uint32_t nvic_readl(NVICState *s, uint32_t off= set) return cpu->env.v7m.ccr; case 0xd24: /* System Handler Status. */ val =3D 0; - if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |=3D (1 << 0); - if (s->gic.irq_state[ARMV7M_EXCP_BUS].active) val |=3D (1 << 1); - if (s->gic.irq_state[ARMV7M_EXCP_USAGE].active) val |=3D (1 << 3); - if (s->gic.irq_state[ARMV7M_EXCP_SVC].active) val |=3D (1 << 7); - if (s->gic.irq_state[ARMV7M_EXCP_DEBUG].active) val |=3D (1 << 8); - if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].active) val |=3D (1 << 10= ); - if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].active) val |=3D (1 << 1= 1); - if (s->gic.irq_state[ARMV7M_EXCP_USAGE].pending) val |=3D (1 << 12= ); - if (s->gic.irq_state[ARMV7M_EXCP_MEM].pending) val |=3D (1 << 13); - if (s->gic.irq_state[ARMV7M_EXCP_BUS].pending) val |=3D (1 << 14); - if (s->gic.irq_state[ARMV7M_EXCP_SVC].pending) val |=3D (1 << 15); - if (s->gic.irq_state[ARMV7M_EXCP_MEM].enabled) val |=3D (1 << 16); - if (s->gic.irq_state[ARMV7M_EXCP_BUS].enabled) val |=3D (1 << 17); - if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |=3D (1 << 18= ); + if (s->vectors[ARMV7M_EXCP_MEM].active) { + val |=3D (1 << 0); + } + if (s->vectors[ARMV7M_EXCP_BUS].active) { + val |=3D (1 << 1); + } + if (s->vectors[ARMV7M_EXCP_USAGE].active) { + val |=3D (1 << 3); + } + if (s->vectors[ARMV7M_EXCP_SVC].active) { + val |=3D (1 << 7); + } + if (s->vectors[ARMV7M_EXCP_DEBUG].active) { + val |=3D (1 << 8); + } + if (s->vectors[ARMV7M_EXCP_PENDSV].active) { + val |=3D (1 << 10); + } + if (s->vectors[ARMV7M_EXCP_SYSTICK].active) { + val |=3D (1 << 11); + } + if (s->vectors[ARMV7M_EXCP_USAGE].pending) { + val |=3D (1 << 12); + } + if (s->vectors[ARMV7M_EXCP_MEM].pending) { + val |=3D (1 << 13); + } + if (s->vectors[ARMV7M_EXCP_BUS].pending) { + val |=3D (1 << 14); + } + if (s->vectors[ARMV7M_EXCP_SVC].pending) { + val |=3D (1 << 15); + } + if (s->vectors[ARMV7M_EXCP_MEM].enabled) { + val |=3D (1 << 16); + } + if (s->vectors[ARMV7M_EXCP_BUS].enabled) { + val |=3D (1 << 17); + } + if (s->vectors[ARMV7M_EXCP_USAGE].enabled) { + val |=3D (1 << 18); + } return val; case 0xd28: /* Configurable Fault Status. */ return cpu->env.v7m.cfsr; @@ -341,14 +623,12 @@ static void nvic_writel(NVICState *s, uint32_t offset= , uint32_t value) if (value & (1 << 28)) { armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV); } else if (value & (1 << 27)) { - s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending =3D 0; - gic_update(&s->gic); + armv7m_nvic_clear_pending(s, ARMV7M_EXCP_PENDSV); } if (value & (1 << 26)) { armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK); } else if (value & (1 << 25)) { - s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending =3D 0; - gic_update(&s->gic); + armv7m_nvic_clear_pending(s, ARMV7M_EXCP_SYSTICK); } break; case 0xd08: /* Vector Table Offset. */ @@ -366,6 +646,7 @@ static void nvic_writel(NVICState *s, uint32_t offset, = uint32_t value) qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented= \n"); } s->prigroup =3D extract32(value, 8, 3); + nvic_irq_update(s); } break; case 0xd10: /* System Control. */ @@ -386,9 +667,10 @@ static void nvic_writel(NVICState *s, uint32_t offset,= uint32_t value) case 0xd24: /* System Handler Control. */ /* TODO: Real hardware allows you to set/clear the active bits under some circumstances. We don't implement this. */ - s->gic.irq_state[ARMV7M_EXCP_MEM].enabled =3D (value & (1 << 16)) = !=3D 0; - s->gic.irq_state[ARMV7M_EXCP_BUS].enabled =3D (value & (1 << 17)) = !=3D 0; - s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled =3D (value & (1 << 18)= ) !=3D 0; + s->vectors[ARMV7M_EXCP_MEM].enabled =3D (value & (1 << 16)) !=3D 0; + s->vectors[ARMV7M_EXCP_BUS].enabled =3D (value & (1 << 17)) !=3D 0; + s->vectors[ARMV7M_EXCP_USAGE].enabled =3D (value & (1 << 18)) !=3D= 0; + nvic_irq_update(s); break; case 0xd28: /* Configurable Fault Status. */ cpu->env.v7m.cfsr &=3D ~value; /* W1C */ @@ -410,13 +692,16 @@ static void nvic_writel(NVICState *s, uint32_t offset= , uint32_t value) "NVIC: Aux fault status registers unimplemented\n"); break; case 0xf00: /* Software Triggered Interrupt Register */ + { /* user mode can only write to STIR if CCR.USERSETMPEND permits it= */ - if ((value & 0x1ff) < s->num_irq && + int excnum =3D (value & 0x1ff) + NVIC_FIRST_IRQ; + if (excnum < s->num_irq && (arm_current_el(&cpu->env) || (cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK))) { - gic_set_pending_private(&s->gic, 0, value & 0x1ff); + armv7m_nvic_set_pending(s, excnum); } break; + } default: qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad write offset 0x%x\n", offset); @@ -428,28 +713,81 @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr= addr, { NVICState *s =3D (NVICState *)opaque; uint32_t offset =3D addr; - int i; + unsigned i, end; uint32_t val; =20 switch (offset) { + /* reads of set and clear both return the status */ + case 0x100 ... 0x13f: /* NVIC Set enable */ + offset +=3D 0x80; + /* fall through */ + case 0x180 ... 0x1bf: /* NVIC Clear enable */ + val =3D 0; + offset =3D offset - 0x180 + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0, end =3D size * 8; i < end && offset + i < s->num_irq= ; i++) { + if (s->vectors[offset + i].enabled) { + val |=3D (1 << i); + } + } + break; + case 0x200 ... 0x23f: /* NVIC Set pend */ + offset +=3D 0x80; + /* fall through */ + case 0x280 ... 0x2bf: /* NVIC Clear pend */ + val =3D 0; + offset =3D offset - 0x280 + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0, end =3D size * 8; i < end && offset + i < s->num_irq= ; i++) { + if (s->vectors[offset + i].pending) { + val |=3D (1 << i); + } + } + break; + case 0x300 ... 0x33f: /* NVIC Active */ + val =3D 0; + offset =3D offset - 0x300 + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0, end =3D size * 8; i < end && offset + i < s->num_irq= ; i++) { + if (s->vectors[offset + i].active) { + val |=3D (1 << i); + } + } + break; + case 0x400 ... 0x5ef: /* NVIC Priority */ + val =3D 0; + offset =3D offset - 0x400 + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0; i < size && offset + i < s->num_irq; i++) { + val |=3D s->vectors[offset + i].prio << (8 * i); + } + break; case 0xd18 ... 0xd23: /* System Handler Priority. */ val =3D 0; for (i =3D 0; i < size; i++) { - val |=3D s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8); + val |=3D s->vectors[(offset - 0xd14) + i].prio << (i * 8); } - return val; + break; case 0xfe0 ... 0xfff: /* ID. */ if (offset & 3) { - return 0; + val =3D 0; + } else { + val =3D nvic_id[(offset - 0xfe0) >> 2]; + } + break; + default: + if (size =3D=3D 4) { + val =3D nvic_readl(s, offset); + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "NVIC: Bad read of size %d at offset 0x%x\n", + size, offset); + val =3D 0; } - return nvic_id[(offset - 0xfe0) >> 2]; - } - if (size =3D=3D 4) { - return nvic_readl(s, offset); } - qemu_log_mask(LOG_GUEST_ERROR, - "NVIC: Bad read of size %d at offset 0x%x\n", size, offs= et); - return 0; + + trace_nvic_sysreg_read(addr, val, size); + return val; } =20 static void nvic_sysreg_write(void *opaque, hwaddr addr, @@ -457,15 +795,59 @@ static void nvic_sysreg_write(void *opaque, hwaddr ad= dr, { NVICState *s =3D (NVICState *)opaque; uint32_t offset =3D addr; - int i; + unsigned i, end; + unsigned setval =3D 0; + + trace_nvic_sysreg_write(addr, value, size); =20 switch (offset) { + case 0x100 ... 0x13f: /* NVIC Set enable */ + offset +=3D 0x80; + setval =3D 1; + /* fall through */ + case 0x180 ... 0x1bf: /* NVIC Clear enable */ + offset =3D 8 * (offset - 0x180) + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0, end =3D size * 8; i < end && offset + i < s->num_irq= ; i++) { + if (value & (1 << i)) { + s->vectors[offset + i].enabled =3D setval; + } + } + nvic_irq_update(s); + return; + case 0x200 ... 0x23f: /* NVIC Set pend */ + /* the special logic in armv7m_nvic_set_pending() + * is not needed since IRQs are never escalated + */ + offset +=3D 0x80; + setval =3D 1; + /* fall through */ + case 0x280 ... 0x2bf: /* NVIC Clear pend */ + offset =3D 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0, end =3D size * 8; i < end && offset + i < s->num_irq= ; i++) { + if (value & (1 << i)) { + s->vectors[offset + i].pending =3D setval; + } + } + nvic_irq_update(s); + return; + case 0x300 ... 0x33f: /* NVIC Active */ + return; /* R/O */ + case 0x400 ... 0x5ef: /* NVIC Priority */ + offset =3D 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0; i < size; i++) { + set_prio(s, offset + i, (value >> (i * 8)) & 0xff); + } + nvic_irq_update(s); + return; case 0xd18 ... 0xd23: /* System Handler Priority. */ for (i =3D 0; i < size; i++) { - s->gic.priority1[(offset - 0xd14) + i][0] =3D - (value >> (i * 8)) & 0xff; + unsigned hdlidx =3D (offset - 0xd14) + i; + set_prio(s, hdlidx, (value >> (i * 8)) & 0xff); } - gic_update(&s->gic); + nvic_irq_update(s); return; } if (size =3D=3D 4) { @@ -482,11 +864,50 @@ static const MemoryRegionOps nvic_sysreg_ops =3D { .endianness =3D DEVICE_NATIVE_ENDIAN, }; =20 +static int nvic_post_load(void *opaque, int version_id) +{ + NVICState *s =3D opaque; + unsigned i; + + /* Check for out of range priority settings */ + if (s->vectors[ARMV7M_EXCP_RESET].prio !=3D -3 || + s->vectors[ARMV7M_EXCP_NMI].prio !=3D -2 || + s->vectors[ARMV7M_EXCP_HARD].prio !=3D -1) { + return 1; + } + for (i =3D ARMV7M_EXCP_MEM; i < s->num_irq; i++) { + if (s->vectors[i].prio & ~0xff) { + return 1; + } + } + + nvic_recompute_state(s); + + return 0; +} + +static const VMStateDescription vmstate_VecInfo =3D { + .name =3D "armv7m_nvic_info", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_INT16(prio, VecInfo), + VMSTATE_UINT8(enabled, VecInfo), + VMSTATE_UINT8(pending, VecInfo), + VMSTATE_UINT8(active, VecInfo), + VMSTATE_UINT8(level, VecInfo), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_nvic =3D { .name =3D "armv7m_nvic", - .version_id =3D 2, - .minimum_version_id =3D 2, + .version_id =3D 3, + .minimum_version_id =3D 3, + .post_load =3D &nvic_post_load, .fields =3D (VMStateField[]) { + VMSTATE_STRUCT_ARRAY(vectors, NVICState, NVIC_MAX_VECTORS, 1, + vmstate_VecInfo, VecInfo), VMSTATE_UINT32(systick.control, NVICState), VMSTATE_UINT32(systick.reload, NVICState), VMSTATE_INT64(systick.tick, NVICState), @@ -496,48 +917,72 @@ static const VMStateDescription vmstate_nvic =3D { } }; =20 +static Property props_nvic[] =3D { + /* Number of external IRQ lines (so excluding the 16 internal exceptio= ns) */ + DEFINE_PROP_UINT32("num-irq", NVICState, num_irq, 64), + DEFINE_PROP_END_OF_LIST() +}; + static void armv7m_nvic_reset(DeviceState *dev) { NVICState *s =3D NVIC(dev); - NVICClass *nc =3D NVIC_GET_CLASS(s); - nc->parent_reset(dev); - /* Common GIC reset resets to disabled; the NVIC doesn't have - * per-CPU interfaces so mark our non-existent CPU interface - * as enabled by default, and with a priority mask which allows - * all interrupts through. + + s->vectors[ARMV7M_EXCP_NMI].enabled =3D 1; + s->vectors[ARMV7M_EXCP_HARD].enabled =3D 1; + /* MEM, BUS, and USAGE are enabled through + * the System Handler Control register */ - s->gic.cpu_ctlr[0] =3D GICC_CTLR_EN_GRP0; - s->gic.priority_mask[0] =3D 0x100; - /* The NVIC as a whole is always enabled. */ - s->gic.ctlr =3D 1; + s->vectors[ARMV7M_EXCP_SVC].enabled =3D 1; + s->vectors[ARMV7M_EXCP_DEBUG].enabled =3D 1; + s->vectors[ARMV7M_EXCP_PENDSV].enabled =3D 1; + s->vectors[ARMV7M_EXCP_SYSTICK].enabled =3D 1; + + s->vectors[ARMV7M_EXCP_RESET].prio =3D -3; + s->vectors[ARMV7M_EXCP_NMI].prio =3D -2; + s->vectors[ARMV7M_EXCP_HARD].prio =3D -1; + + /* Strictly speaking the reset handler should be enabled. + * However, we don't simulate soft resets through the NVIC, + * and the reset vector should never be pended. + * So we leave it disabled to catch logic errors. + */ + + s->exception_prio =3D NVIC_NOEXC_PRIO; + s->vectpending =3D 0; + systick_reset(s); } =20 static void armv7m_nvic_realize(DeviceState *dev, Error **errp) { NVICState *s =3D NVIC(dev); - NVICClass *nc =3D NVIC_GET_CLASS(s); - Error *local_err =3D NULL; =20 s->cpu =3D ARM_CPU(qemu_get_cpu(0)); assert(s->cpu); - /* The NVIC always has only one CPU */ - s->gic.num_cpu =3D 1; - /* Tell the common code we're an NVIC */ - s->gic.revision =3D 0xffffffff; - s->num_irq =3D s->gic.num_irq; - nc->parent_realize(dev, &local_err); - if (local_err) { - error_propagate(errp, local_err); + + if (s->num_irq > NVIC_MAX_IRQ) { + error_setg(errp, "num-irq %d exceeds NVIC maximum", s->num_irq); return; } - gic_init_irqs_and_distributor(&s->gic); - /* The NVIC and system controller register area looks like this: - * 0..0xff : system control registers, including systick - * 0x100..0xcff : GIC-like registers - * 0xd00..0xfff : system control registers - * We use overlaying to put the GIC like registers - * over the top of the system control register region. + + qdev_init_gpio_in(dev, set_irq_level, s->num_irq); + + /* include space for internal exception vectors */ + s->num_irq +=3D NVIC_FIRST_IRQ; + + /* The NVIC and system controller register area starts at 0xe000e000 + * and looks like this: + * 0x004 - ICTR + * 0x010 - 0x1c - systick + * 0x100..0x7ec - NVIC + * 0x7f0..0xcff - Reserved + * 0xd00..0xd3c - SCS registers + * 0xd40..0xeff - Reserved or Not implemented + * 0xf00 - STIR + * + * At the moment there is only one thing in the container region, + * but we leave it in place to allow us to pull systick out into + * its own device object later. */ memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000); /* The system register region goes at the bottom of the priority @@ -546,14 +991,7 @@ static void armv7m_nvic_realize(DeviceState *dev, Erro= r **errp) memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s, "nvic_sysregs", 0x1000); memory_region_add_subregion(&s->container, 0, &s->sysregmem); - /* Alias the GIC region so we can get only the section of it - * we need, and layer it on top of the system register region. - */ - memory_region_init_alias(&s->gic_iomem_alias, OBJECT(s), - "nvic-gic", &s->gic.iomem, - 0x100, 0xc00); - memory_region_add_subregion_overlap(&s->container, 0x100, - &s->gic_iomem_alias, 1); + /* Map the whole thing into system memory at the location required * by the v7M architecture. */ @@ -569,36 +1007,31 @@ static void armv7m_nvic_instance_init(Object *obj) * any user-specified property setting, so just modify the * value in the GICState struct. */ - GICState *s =3D ARM_GIC_COMMON(obj); DeviceState *dev =3D DEVICE(obj); NVICState *nvic =3D NVIC(obj); - /* The ARM v7m may have anything from 0 to 496 external interrupt - * IRQ lines. We default to 64. Other boards may differ and should - * set the num-irq property appropriately. - */ - s->num_irq =3D 64; + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + sysbus_init_irq(sbd, &nvic->excpout); qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1); } =20 static void armv7m_nvic_class_init(ObjectClass *klass, void *data) { - NVICClass *nc =3D NVIC_CLASS(klass); DeviceClass *dc =3D DEVICE_CLASS(klass); =20 - nc->parent_reset =3D dc->reset; - nc->parent_realize =3D dc->realize; dc->vmsd =3D &vmstate_nvic; + dc->props =3D props_nvic; dc->reset =3D armv7m_nvic_reset; dc->realize =3D armv7m_nvic_realize; } =20 static const TypeInfo armv7m_nvic_info =3D { .name =3D TYPE_NVIC, - .parent =3D TYPE_ARM_GIC_COMMON, + .parent =3D TYPE_SYS_BUS_DEVICE, .instance_init =3D armv7m_nvic_instance_init, .instance_size =3D sizeof(NVICState), .class_init =3D armv7m_nvic_class_init, - .class_size =3D sizeof(NVICClass), + .class_size =3D sizeof(SysBusDeviceClass), }; =20 static void armv7m_nvic_register_types(void) diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 39a538d..729c128 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -161,3 +161,18 @@ gicv3_redist_write(uint32_t cpu, uint64_t offset, uint= 64_t data, unsigned size, gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsign= ed size, bool secure) "GICv3 redistributor %x write: offset 0x%" PRIx64 " d= ata 0x%" PRIx64 " size %u secure %d: error" gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributo= r %x interrupt %d level changed to %d" gicv3_redist_send_sgi(uint32_t cpu, int irq) "GICv3 redistributor %x pendi= ng SGI %d" + +# hw/intc/armv7m_nvic.c +nvic_recompute_state(int vectpending, int exception_prio) "NVIC state reco= mputed: vectpending %d exception_prio %d" +nvic_set_prio(int irq, uint8_t prio) "NVIC set irq %d priority %d" +nvic_irq_update(int vectpending, int pendprio, int exception_prio, int lev= el) "NVIC vectpending %d pending prio %d exception_prio %d: setting irq lin= e to %d" +nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq= %d to HardFault: insufficient priority %d >=3D %d" +nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disa= bled" +nvic_set_pending(int irq, int en, int prio) "NVIC set pending irq %d (enab= led: %d priority %d)" +nvic_clear_pending(int irq, int en, int prio) "NVIC clear pending irq %d (= enabled: %d priority %d)" +nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than= vectpending: setting irq line to 1" +nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now acti= ve (prio %d)" +nvic_complete_irq(int irq) "NVIC complete IRQ %d" +nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to = %d" +nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysre= g read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" +nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysr= eg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" --=20 2.7.4 From nobody Thu May 2 14:34:18 2024 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 1486066425525286.98901628106546; Thu, 2 Feb 2017 12:13:45 -0800 (PST) Received: from localhost ([::1]:58773 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNlH-0002Nt-4Y for importer@patchew.org; Thu, 02 Feb 2017 15:13:43 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60606) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNac-0000FM-M4 for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZNab-000831-Ny for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:42 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48351) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cZNaZ-0007un-Dg; Thu, 02 Feb 2017 15:02:39 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cZNaL-0001vE-H0; Thu, 02 Feb 2017 20:02:25 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 2 Feb 2017 20:02:17 +0000 Message-Id: <1486065742-28639-5-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> References: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> 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] [PATCH 4/9] 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: , Cc: Liviu Ionescu , Michael Davidsaver , =?UTF-8?q?Alex=20Benn=C3=A9e?= , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 39bff86..ac20a56 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1335,6 +1335,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 e319077..3d77cbf 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -268,6 +268,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 e9f10f7..7713d88 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 From nobody Thu May 2 14:34:18 2024 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 1486066266404637.0512488187699; Thu, 2 Feb 2017 12:11:06 -0800 (PST) Received: from localhost ([::1]:58761 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNif-0007ou-Lm for importer@patchew.org; Thu, 02 Feb 2017 15:11:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60637) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNad-0000IR-Bi for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:44 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZNac-00083P-0j for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:43 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48351) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cZNaY-0007un-GY; Thu, 02 Feb 2017 15:02:38 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cZNaM-0001vd-05; Thu, 02 Feb 2017 20:02:26 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 2 Feb 2017 20:02:18 +0000 Message-Id: <1486065742-28639-6-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> References: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> 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] [PATCH 5/9] arm: gic: Remove references to NVIC 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: , Cc: Liviu Ionescu , Michael Davidsaver , =?UTF-8?q?Alex=20Benn=C3=A9e?= , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Michael Davidsaver Now that the NVIC is its own separate implementation, we can clean up the GIC code by removing REV_NVIC and conditionals which use it. Signed-off-by: Michael Davidsaver Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- hw/intc/gic_internal.h | 7 ++----- hw/intc/arm_gic.c | 31 +++++-------------------------- hw/intc/arm_gic_common.c | 23 ++++++++--------------- 3 files changed, 15 insertions(+), 46 deletions(-) diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h index 3f31174..7fe87b1 100644 --- a/hw/intc/gic_internal.h +++ b/hw/intc/gic_internal.h @@ -25,9 +25,7 @@ =20 #define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1))) =20 -/* The NVIC has 16 internal vectors. However these are not exposed - through the normal GIC interface. */ -#define GIC_BASE_IRQ ((s->revision =3D=3D REV_NVIC) ? 32 : 0) +#define GIC_BASE_IRQ 0 =20 #define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |=3D (cm) #define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &=3D ~(cm) @@ -75,7 +73,6 @@ =20 /* The special cases for the revision property: */ #define REV_11MPCORE 0 -#define REV_NVIC 0xffffffff =20 void gic_set_pending_private(GICState *s, int cpu, int irq); uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs); @@ -87,7 +84,7 @@ void gic_set_priority(GICState *s, int cpu, int irq, uint= 8_t val, =20 static inline bool gic_test_pending(GICState *s, int irq, int cm) { - if (s->revision =3D=3D REV_NVIC || s->revision =3D=3D REV_11MPCORE) { + if (s->revision =3D=3D REV_11MPCORE) { return s->irq_state[irq].pending & cm; } else { /* Edge-triggered interrupts are marked pending on a rising edge, = but diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 521aac3..8e5a9d8 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -156,17 +156,6 @@ static void gic_set_irq_11mpcore(GICState *s, int irq,= int level, } } =20 -static void gic_set_irq_nvic(GICState *s, int irq, int level, - int cm, int target) -{ - if (level) { - GIC_SET_LEVEL(irq, cm); - GIC_SET_PENDING(irq, target); - } else { - GIC_CLEAR_LEVEL(irq, cm); - } -} - static void gic_set_irq_generic(GICState *s, int irq, int level, int cm, int target) { @@ -214,8 +203,6 @@ static void gic_set_irq(void *opaque, int irq, int leve= l) =20 if (s->revision =3D=3D REV_11MPCORE) { gic_set_irq_11mpcore(s, irq, level, cm, target); - } else if (s->revision =3D=3D REV_NVIC) { - gic_set_irq_nvic(s, irq, level, cm, target); } else { gic_set_irq_generic(s, irq, level, cm, target); } @@ -367,7 +354,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemT= xAttrs attrs) return 1023; } =20 - if (s->revision =3D=3D REV_11MPCORE || s->revision =3D=3D REV_NVIC) { + if (s->revision =3D=3D REV_11MPCORE) { /* Clear pending flags for both level and edge triggered interrupt= s. * Level triggered IRQs will be reasserted once they become inacti= ve. */ @@ -589,11 +576,6 @@ void gic_complete_irq(GICState *s, int cpu, int irq, M= emTxAttrs attrs) DPRINTF("Set %d pending mask %x\n", irq, cm); GIC_SET_PENDING(irq, cm); } - } else if (s->revision =3D=3D REV_NVIC) { - if (GIC_TEST_LEVEL(irq, cm)) { - DPRINTF("Set nvic %d pending mask %x\n", irq, cm); - GIC_SET_PENDING(irq, cm); - } } =20 group =3D gic_has_groups(s) && GIC_TEST_GROUP(irq, cm); @@ -768,7 +750,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr off= set, MemTxAttrs attrs) } else if (offset < 0xf10) { goto bad_reg; } else if (offset < 0xf30) { - if (s->revision =3D=3D REV_11MPCORE || s->revision =3D=3D REV_NVIC= ) { + if (s->revision =3D=3D REV_11MPCORE) { goto bad_reg; } =20 @@ -802,9 +784,6 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr off= set, MemTxAttrs attrs) case 2: res =3D gic_id_gicv2[(offset - 0xfd0) >> 2]; break; - case REV_NVIC: - /* Shouldn't be able to get here */ - abort(); default: res =3D 0; } @@ -1028,7 +1007,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offs= et, continue; /* Ignore Non-secure access of Group0 IRQ */ } =20 - if (s->revision =3D=3D REV_11MPCORE || s->revision =3D=3D REV_= NVIC) { + if (s->revision =3D=3D REV_11MPCORE) { if (value & (1 << (i * 2))) { GIC_SET_MODEL(irq + i); } else { @@ -1046,7 +1025,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offs= et, goto bad_reg; } else if (offset < 0xf20) { /* GICD_CPENDSGIRn */ - if (s->revision =3D=3D REV_11MPCORE || s->revision =3D=3D REV_NVIC= ) { + if (s->revision =3D=3D REV_11MPCORE) { goto bad_reg; } irq =3D (offset - 0xf10); @@ -1060,7 +1039,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offs= et, } } else if (offset < 0xf30) { /* GICD_SPENDSGIRn */ - if (s->revision =3D=3D REV_11MPCORE || s->revision =3D=3D REV_NVIC= ) { + if (s->revision =3D=3D REV_11MPCORE) { goto bad_reg; } irq =3D (offset - 0xf20); diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index 4a8df44..70f1134 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -99,9 +99,7 @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler= handler, * [N+32..N+63] PPIs for CPU 1 * ... */ - if (s->revision !=3D REV_NVIC) { - i +=3D (GIC_INTERNAL * s->num_cpu); - } + i +=3D (GIC_INTERNAL * s->num_cpu); qdev_init_gpio_in(DEVICE(s), handler, i); =20 for (i =3D 0; i < s->num_cpu; i++) { @@ -121,16 +119,12 @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_han= dler handler, memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000= ); sysbus_init_mmio(sbd, &s->iomem); =20 - if (s->revision !=3D REV_NVIC) { - /* This is the main CPU interface "for this core". It is always - * present because it is required by both software emulation and K= VM. - * NVIC is not handled here because its CPU interface is different, - * neither it can use KVM. - */ - memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : = NULL, - s, "gic_cpu", s->revision =3D=3D 2 ? 0x2000 = : 0x100); - sysbus_init_mmio(sbd, &s->cpuiomem[0]); - } + /* This is the main CPU interface "for this core". It is always + * present because it is required by both software emulation and KVM. + */ + memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL, + s, "gic_cpu", s->revision =3D=3D 2 ? 0x2000 : 0x= 100); + sysbus_init_mmio(sbd, &s->cpuiomem[0]); } =20 static void arm_gic_common_realize(DeviceState *dev, Error **errp) @@ -162,7 +156,7 @@ static void arm_gic_common_realize(DeviceState *dev, Er= ror **errp) } =20 if (s->security_extn && - (s->revision =3D=3D REV_11MPCORE || s->revision =3D=3D REV_NVIC)) { + (s->revision =3D=3D REV_11MPCORE)) { error_setg(errp, "this GIC revision does not implement " "the security extensions"); return; @@ -255,7 +249,6 @@ static Property arm_gic_common_properties[] =3D { DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32), /* Revision can be 1 or 2 for GIC architecture specification * versions 1 or 2, or 0 to indicate the legacy 11MPCore GIC. - * (Internally, 0xffffffff also indicates "not a GIC but an NVIC".) */ DEFINE_PROP_UINT32("revision", GICState, revision, 1), /* True if the GIC should implement the security extensions */ --=20 2.7.4 From nobody Thu May 2 14:34:18 2024 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 1486066171588490.7010661240698; Thu, 2 Feb 2017 12:09:31 -0800 (PST) Received: from localhost ([::1]:58749 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNhB-0006Tp-Em for importer@patchew.org; Thu, 02 Feb 2017 15:09:29 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60598) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNac-0000Er-BA for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZNab-00082a-6U for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:42 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48351) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cZNaX-0007un-L2; Thu, 02 Feb 2017 15:02:37 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cZNaM-0001vt-HU; Thu, 02 Feb 2017 20:02:26 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 2 Feb 2017 20:02:19 +0000 Message-Id: <1486065742-28639-7-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> References: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> 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] [PATCH 6/9] armv7m: Escalate exceptions to HardFault if necessary 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: , Cc: Liviu Ionescu , Michael Davidsaver , =?UTF-8?q?Alex=20Benn=C3=A9e?= , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Michael Davidsaver The v7M exception architecture requires that if a synchronous exception cannot be taken immediately (because it is disabled or at too low a priority) then it should be escalated to HardFault (and the HardFault exception is then taken). Implement this escalation logic. Signed-off-by: Michael Davidsaver [PMM: extracted from another patch] Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- hw/intc/armv7m_nvic.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++= ++++ target/arm/helper.c | 2 -- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 3d77cbf..2eaac3d 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -334,6 +334,59 @@ void armv7m_nvic_set_pending(void *opaque, int irq) =20 vec =3D &s->vectors[irq]; trace_nvic_set_pending(irq, vec->enabled, vec->prio); + + + if (irq >=3D ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) { + /* If a synchronous exception is pending then it may be + * escalated to HardFault if: + * * it is equal or lower priority to current execution + * * it is disabled + * (ie we need to take it immediately but we can't do so). + * Asynchronous exceptions (and interrupts) simply remain pending. + * + * For QEMU, we don't have any imprecise (asynchronous) faults, + * so we can assume that PREFETCH_ABORT and DATA_ABORT are always + * synchronous. + * Debug exceptions are awkward because only Debug exceptions + * resulting from the BKPT instruction should be escalated, + * but we don't currently implement any Debug exceptions other + * than those that result from BKPT, so we treat all debug excepti= ons + * as needing escalation. + * + * This all means we can identify whether to escalate based only on + * the exception number and don't (yet) need the caller to explici= tly + * tell us whether this exception is synchronous or not. + */ + int running =3D nvic_exec_prio(s); + bool escalate =3D false; + + if (vec->prio >=3D running) { + trace_nvic_escalate_prio(irq, vec->prio, running); + escalate =3D true; + } else if (!vec->enabled) { + trace_nvic_escalate_disabled(irq); + escalate =3D true; + } + + if (escalate) { + if (running < 0) { + /* We want to escalate to HardFault but we can't take a + * synchronous HardFault at this point either. This is a + * Lockup condition due to a guest bug. We don't model + * Lockup, so report via cpu_abort() instead. + */ + cpu_abort(&s->cpu->parent_obj, + "Lockup: can't escalate %d to HardFault " + "(current priority %d)\n", irq, running); + } + + /* We can do the escalation, so we take HardFault instead */ + irq =3D ARMV7M_EXCP_HARD; + vec =3D &s->vectors[irq]; + s->cpu->env.v7m.hfsr |=3D R_V7M_HFSR_FORCED_MASK; + } + } + if (!vec->pending) { vec->pending =3D 1; nvic_irq_update(s); diff --git a/target/arm/helper.c b/target/arm/helper.c index c23df1b..6c86eac 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6067,8 +6067,6 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) =20 /* For exceptions we just mark as pending on the NVIC, and let that handle it. */ - /* TODO: Need to escalate if the current priority is higher than the - one we're raising. */ switch (cs->exception_index) { case EXCP_UDEF: armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE); --=20 2.7.4 From nobody Thu May 2 14:34:18 2024 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 1486065897670690.4868599106268; Thu, 2 Feb 2017 12:04:57 -0800 (PST) Received: from localhost ([::1]:58718 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNcl-00020a-V9 for importer@patchew.org; Thu, 02 Feb 2017 15:04:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60503) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNaZ-0000Bx-Oo for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:41 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZNaZ-00081I-2D for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:39 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48351) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cZNaW-0007un-Q1; Thu, 02 Feb 2017 15:02:36 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cZNaN-0001wM-CD; Thu, 02 Feb 2017 20:02:27 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 2 Feb 2017 20:02:20 +0000 Message-Id: <1486065742-28639-8-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> References: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> 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] [PATCH 7/9] armv7m: Remove unused armv7m_nvic_acknowledge_irq() return value 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: , Cc: Liviu Ionescu , Michael Davidsaver , =?UTF-8?q?Alex=20Benn=C3=A9e?= , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Having armv7m_nvic_acknowledge_irq() return the new value of env->v7m.exception and its one caller assign the return value back to env->v7m.exception is pointless. Just make the return type void instead. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- target/arm/cpu.h | 2 +- hw/intc/armv7m_nvic.c | 4 +--- target/arm/helper.c | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index ac20a56..36cccfc 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1344,7 +1344,7 @@ static inline bool armv7m_nvic_can_take_pending_excep= tion(void *opaque) } #endif void armv7m_nvic_set_pending(void *opaque, int irq); -int armv7m_nvic_acknowledge_irq(void *opaque); +void armv7m_nvic_acknowledge_irq(void *opaque); void armv7m_nvic_complete_irq(void *opaque, int irq); =20 /* Interface for defining coprocessor registers. diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 2eaac3d..7b61fe6 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -394,7 +394,7 @@ void armv7m_nvic_set_pending(void *opaque, int irq) } =20 /* Make pending IRQ active. */ -int armv7m_nvic_acknowledge_irq(void *opaque) +void armv7m_nvic_acknowledge_irq(void *opaque) { NVICState *s =3D (NVICState *)opaque; CPUARMState *env =3D &s->cpu->env; @@ -421,8 +421,6 @@ int armv7m_nvic_acknowledge_irq(void *opaque) env->v7m.exception =3D s->vectpending; =20 nvic_irq_update(s); - - return env->v7m.exception; } =20 void armv7m_nvic_complete_irq(void *opaque, int irq) diff --git a/target/arm/helper.c b/target/arm/helper.c index 6c86eac..78bf9ab 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6103,7 +6103,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG); return; case EXCP_IRQ: - env->v7m.exception =3D armv7m_nvic_acknowledge_irq(env->nvic); + armv7m_nvic_acknowledge_irq(env->nvic); break; case EXCP_EXCEPTION_EXIT: do_v7m_exception_exit(env); --=20 2.7.4 From nobody Thu May 2 14:34:18 2024 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 1486065956907264.7284027812834; Thu, 2 Feb 2017 12:05:56 -0800 (PST) Received: from localhost ([::1]:58725 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNdj-0002rJ-7E for importer@patchew.org; Thu, 02 Feb 2017 15:05:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60488) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNaZ-0000BO-77 for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:41 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZNaY-00080c-CG for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:39 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48351) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cZNaV-0007un-Tk; Thu, 02 Feb 2017 15:02:36 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cZNaN-0001wl-S0; Thu, 02 Feb 2017 20:02:27 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 2 Feb 2017 20:02:21 +0000 Message-Id: <1486065742-28639-9-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> References: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> 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] [PATCH 8/9] armv7m: Simpler and faster exception start 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: , Cc: Liviu Ionescu , Michael Davidsaver , =?UTF-8?q?Alex=20Benn=C3=A9e?= , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Michael Davidsaver All the places in armv7m_cpu_do_interrupt() which pend an exception in the NVIC are doing so for synchronous exceptions. We know that we will always take some exception in this case, so we can just acknowledge it immediately, rather than returning and then immediately being called again because the NVIC has raised its outbound IRQ line. Signed-off-by: Michael Davidsaver [PMM: tweaked commit message; added DEBUG to the set of exceptions we handle immediately, since it is synchronous when it results from the BKPT instruction] Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- target/arm/helper.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 78bf9ab..8bdd99c 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6071,22 +6071,22 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) case EXCP_UDEF: armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE); env->v7m.cfsr |=3D R_V7M_CFSR_UNDEFINSTR_MASK; - return; + break; case EXCP_NOCP: armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE); env->v7m.cfsr |=3D R_V7M_CFSR_NOCP_MASK; - return; + break; case EXCP_SWI: /* The PC already points to the next instruction. */ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC); - return; + break; case EXCP_PREFETCH_ABORT: case EXCP_DATA_ABORT: /* TODO: if we implemented the MPU registers, this is where we * should set the MMFAR, etc from exception.fsr and exception.vadd= ress. */ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM); - return; + break; case EXCP_BKPT: if (semihosting_enabled()) { int nr; @@ -6101,9 +6101,8 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) } } armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG); - return; + break; case EXCP_IRQ: - armv7m_nvic_acknowledge_irq(env->nvic); break; case EXCP_EXCEPTION_EXIT: do_v7m_exception_exit(env); @@ -6113,6 +6112,10 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) return; /* Never happens. Keep compiler happy. */ } =20 + armv7m_nvic_acknowledge_irq(env->nvic); + + qemu_log_mask(CPU_LOG_INT, "... as %d\n", env->v7m.exception); + /* Align stack pointer if the guest wants that */ if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) { env->regs[13] -=3D 4; --=20 2.7.4 From nobody Thu May 2 14:34:18 2024 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 1486065992613100.03468607268144; Thu, 2 Feb 2017 12:06:32 -0800 (PST) Received: from localhost ([::1]:58729 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNeI-0003JF-0s for importer@patchew.org; Thu, 02 Feb 2017 15:06:30 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60442) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cZNaY-00009P-6O for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cZNaX-0007z5-74 for qemu-devel@nongnu.org; Thu, 02 Feb 2017 15:02:38 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48351) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cZNaV-0007un-2T; Thu, 02 Feb 2017 15:02:35 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1cZNaO-0001x1-Rn; Thu, 02 Feb 2017 20:02:28 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 2 Feb 2017 20:02:22 +0000 Message-Id: <1486065742-28639-10-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> References: <1486065742-28639-1-git-send-email-peter.maydell@linaro.org> 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] [PATCH 9/9] armv7m: VECTCLRACTIVE and VECTRESET are UNPREDICTABLE 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: , Cc: Liviu Ionescu , Michael Davidsaver , =?UTF-8?q?Alex=20Benn=C3=A9e?= , patches@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Michael Davidsaver The VECTCLRACTIVE and VECTRESET bits in the AIRCR are both documented as UNPREDICTABLE if you write a 1 to them when the processor is not halted in Debug state (ie stopped and under the control of an external JTAG debugger). Since we don't implement Debug state or emulated JTAG these bits are always UNPREDICTABLE for us. Instead of logging them as unimplemented we can simply log writes as guest errors and ignore them. Signed-off-by: Michael Davidsaver [PMM: change extracted from another patch; commit message constructed from scratch] Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- hw/intc/armv7m_nvic.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 7b61fe6..18c0e60 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -698,10 +698,14 @@ static void nvic_writel(NVICState *s, uint32_t offset= , uint32_t value) qemu_irq_pulse(s->sysresetreq); } if (value & 2) { - qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n"); + qemu_log_mask(LOG_GUEST_ERROR, + "Setting VECTCLRACTIVE when not in DEBUG mod= e " + "is UNPREDICTABLE\n"); } if (value & 1) { - qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented= \n"); + qemu_log_mask(LOG_GUEST_ERROR, + "Setting VECTRESET when not in DEBUG mode " + "is UNPREDICTABLE\n"); } s->prigroup =3D extract32(value, 8, 3); nvic_irq_update(s); --=20 2.7.4