From nobody Tue Apr 15 15:24:57 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 1488219108437939.3926647754862; Mon, 27 Feb 2017 10:11:48 -0800 (PST) Received: from localhost ([::1]:55527 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPlx-0007h7-Uq for importer@patchew.org; Mon, 27 Feb 2017 13:11:45 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51876) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfc-0002I9-IY for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfZ-0001qJ-WC for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:11 -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 1ciPfZ-0001lG-Mf for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:09 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfQ-0002IT-Ux for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:00 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:30 +0000 Message-Id: <1488218699-31035-2-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> 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 01/30] target-arm: Implement BCM2835 hardware RNG 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Marcin Chojnacki Recent vanilla Raspberry Pi kernels started to make use of the hardware random number generator in BCM2835 SoC. As a result, those kernels wouldn't work anymore under QEMU but rather just freeze during the boot process. This patch implements a trivial BCM2835 compatible RNG, and adds it as a peripheral to BCM2835 platform, which allows to boot a vanilla Raspberry Pi kernel under Qemu. Changes since v1: * Prevented guest from writing [31..20] bits in rng_status * Removed redundant minimum_version_id_old * Added field entries for the state * Changed realize function to reset Signed-off-by: Marcin Chojnacki Message-id: 20170210210857.47893-1-marcinch7@gmail.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/misc/Makefile.objs | 1 + include/hw/arm/bcm2835_peripherals.h | 2 + include/hw/misc/bcm2835_rng.h | 27 ++++++++ hw/arm/bcm2835_peripherals.c | 15 +++++ hw/misc/bcm2835_rng.c | 124 +++++++++++++++++++++++++++++++= ++++ 5 files changed, 169 insertions(+) create mode 100644 include/hw/misc/bcm2835_rng.h create mode 100644 hw/misc/bcm2835_rng.c diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 898e4cc..57a4406 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -42,6 +42,7 @@ obj-$(CONFIG_OMAP) +=3D omap_sdrc.o obj-$(CONFIG_OMAP) +=3D omap_tap.o obj-$(CONFIG_RASPI) +=3D bcm2835_mbox.o obj-$(CONFIG_RASPI) +=3D bcm2835_property.o +obj-$(CONFIG_RASPI) +=3D bcm2835_rng.o obj-$(CONFIG_SLAVIO) +=3D slavio_misc.o obj-$(CONFIG_ZYNQ) +=3D zynq_slcr.o obj-$(CONFIG_ZYNQ) +=3D zynq-xadc.o diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_= peripherals.h index e12ae37..31241c7 100644 --- a/include/hw/arm/bcm2835_peripherals.h +++ b/include/hw/arm/bcm2835_peripherals.h @@ -19,6 +19,7 @@ #include "hw/dma/bcm2835_dma.h" #include "hw/intc/bcm2835_ic.h" #include "hw/misc/bcm2835_property.h" +#include "hw/misc/bcm2835_rng.h" #include "hw/misc/bcm2835_mbox.h" #include "hw/sd/sdhci.h" =20 @@ -41,6 +42,7 @@ typedef struct BCM2835PeripheralState { BCM2835DMAState dma; BCM2835ICState ic; BCM2835PropertyState property; + BCM2835RngState rng; BCM2835MboxState mboxes; SDHCIState sdhci; } BCM2835PeripheralState; diff --git a/include/hw/misc/bcm2835_rng.h b/include/hw/misc/bcm2835_rng.h new file mode 100644 index 0000000..41a531b --- /dev/null +++ b/include/hw/misc/bcm2835_rng.h @@ -0,0 +1,27 @@ +/* + * BCM2835 Random Number Generator emulation + * + * Copyright (C) 2017 Marcin Chojnacki + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef BCM2835_RNG_H +#define BCM2835_RNG_H + +#include "hw/sysbus.h" + +#define TYPE_BCM2835_RNG "bcm2835-rng" +#define BCM2835_RNG(obj) \ + OBJECT_CHECK(BCM2835RngState, (obj), TYPE_BCM2835_RNG) + +typedef struct { + SysBusDevice busdev; + MemoryRegion iomem; + + uint32_t rng_ctrl; + uint32_t rng_status; +} BCM2835RngState; + +#endif diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index 2e641a3..9ed22d5 100644 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -86,6 +86,11 @@ static void bcm2835_peripherals_init(Object *obj) object_property_add_const_link(OBJECT(&s->property), "dma-mr", OBJECT(&s->gpu_bus_mr), &error_abort); =20 + /* Random Number Generator */ + object_initialize(&s->rng, sizeof(s->rng), TYPE_BCM2835_RNG); + object_property_add_child(obj, "rng", OBJECT(&s->rng), NULL); + qdev_set_parent_bus(DEVICE(&s->rng), sysbus_get_default()); + /* Extended Mass Media Controller */ object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI); object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL); @@ -226,6 +231,16 @@ static void bcm2835_peripherals_realize(DeviceState *d= ev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPE= RTY)); =20 + /* Random Number Generator */ + object_property_set_bool(OBJECT(&s->rng), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + memory_region_add_subregion(&s->peri_mr, RNG_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0)); + /* Extended Mass Media Controller */ object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capa= reg", &err); diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c new file mode 100644 index 0000000..2242bc5 --- /dev/null +++ b/hw/misc/bcm2835_rng.c @@ -0,0 +1,124 @@ +/* + * BCM2835 Random Number Generator emulation + * + * Copyright (C) 2017 Marcin Chojnacki + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/misc/bcm2835_rng.h" + +static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset, + unsigned size) +{ + BCM2835RngState *s =3D (BCM2835RngState *)opaque; + uint32_t res =3D 0; + + assert(size =3D=3D 4); + + switch (offset) { + case 0x0: /* rng_ctrl */ + res =3D s->rng_ctrl; + break; + case 0x4: /* rng_status */ + res =3D s->rng_status | (1 << 24); + break; + case 0x8: /* rng_data */ + res =3D rand(); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "bcm2835_rng_read: Bad offset %x\n", + (int)offset); + res =3D 0; + break; + } + + return res; +} + +static void bcm2835_rng_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + BCM2835RngState *s =3D (BCM2835RngState *)opaque; + + assert(size =3D=3D 4); + + switch (offset) { + case 0x0: /* rng_ctrl */ + s->rng_ctrl =3D value; + break; + case 0x4: /* rng_status */ + /* we shouldn't let the guest write to bits [31..20] */ + s->rng_status &=3D ~0xFFFFF; /* clear 20 lower bits */ + s->rng_status |=3D value & 0xFFFFF; /* set them to new value */ + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, + "bcm2835_rng_write: Bad offset %x\n", + (int)offset); + break; + } +} + +static const MemoryRegionOps bcm2835_rng_ops =3D { + .read =3D bcm2835_rng_read, + .write =3D bcm2835_rng_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static const VMStateDescription vmstate_bcm2835_rng =3D { + .name =3D TYPE_BCM2835_RNG, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(rng_ctrl, BCM2835RngState), + VMSTATE_UINT32(rng_status, BCM2835RngState), + VMSTATE_END_OF_LIST() + } +}; + +static void bcm2835_rng_init(Object *obj) +{ + BCM2835RngState *s =3D BCM2835_RNG(obj); + + memory_region_init_io(&s->iomem, obj, &bcm2835_rng_ops, s, + TYPE_BCM2835_RNG, 0x10); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); +} + +static void bcm2835_rng_reset(DeviceState *dev) +{ + BCM2835RngState *s =3D BCM2835_RNG(dev); + + s->rng_ctrl =3D 0; + s->rng_status =3D 0; +} + +static void bcm2835_rng_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->reset =3D bcm2835_rng_reset; + dc->vmsd =3D &vmstate_bcm2835_rng; +} + +static TypeInfo bcm2835_rng_info =3D { + .name =3D TYPE_BCM2835_RNG, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(BCM2835RngState), + .class_init =3D bcm2835_rng_class_init, + .instance_init =3D bcm2835_rng_init, +}; + +static void bcm2835_rng_register_types(void) +{ + type_register_static(&bcm2835_rng_info); +} + +type_init(bcm2835_rng_register_types) --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488220496910817.9070174268135; Mon, 27 Feb 2017 10:34:56 -0800 (PST) Received: from localhost ([::1]:55645 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQ8M-0002hd-G8 for importer@patchew.org; Mon, 27 Feb 2017 13:34:54 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52241) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfk-0002Rb-GT for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfh-0001xI-Ho for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:20 -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 1ciPfh-0001lG-6m for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:17 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfR-0002If-DA for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:01 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:31 +0000 Message-Id: <1488218699-31035-3-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> 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 02/30] bcm2835_rng: Use qcrypto_random_bytes() rather than rand() 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Switch to using qcrypto_random_bytes() rather than rand() as our source of randomness for the BCM2835 RNG. If qcrypto_random_bytes() fails, we don't want to return the guest a non-random value in case they're really using it for cryptographic purposes, so the best we can do is a fatal error. This shouldn't happen unless something's broken, though. In theory we could implement this device's full FIFO and interrupt semantics and then just stop filling the FIFO. That's a lot of work, though, and doesn't really give a very nice diagnostic to the user since the guest will just seem to hang. Signed-off-by: Peter Maydell Reviewed-by: Daniel P. Berrange --- hw/misc/bcm2835_rng.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/hw/misc/bcm2835_rng.c b/hw/misc/bcm2835_rng.c index 2242bc5..4d62143 100644 --- a/hw/misc/bcm2835_rng.c +++ b/hw/misc/bcm2835_rng.c @@ -9,8 +9,33 @@ =20 #include "qemu/osdep.h" #include "qemu/log.h" +#include "qapi/error.h" +#include "crypto/random.h" #include "hw/misc/bcm2835_rng.h" =20 +static uint32_t get_random_bytes(void) +{ + uint32_t res; + Error *err =3D NULL; + + if (qcrypto_random_bytes((uint8_t *)&res, sizeof(res), &err) < 0) { + /* On failure we don't want to return the guest a non-random + * value in case they're really using it for cryptographic + * purposes, so the best we can do is die here. + * This shouldn't happen unless something's broken. + * In theory we could implement this device's full FIFO + * and interrupt semantics and then just stop filling the + * FIFO. That's a lot of work, though, so we assume any + * errors are systematic problems and trust that if we didn't + * fail as the guest inited then we won't fail later on + * mid-run. + */ + error_report_err(err); + exit(1); + } + return res; +} + static uint64_t bcm2835_rng_read(void *opaque, hwaddr offset, unsigned size) { @@ -27,7 +52,7 @@ static uint64_t bcm2835_rng_read(void *opaque, hwaddr off= set, res =3D s->rng_status | (1 << 24); break; case 0x8: /* rng_data */ - res =3D rand(); + res =3D get_random_bytes(); break; =20 default: --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488220697010349.1316296116096; Mon, 27 Feb 2017 10:38:17 -0800 (PST) Received: from localhost ([::1]:55682 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQBa-0005V4-Mj for importer@patchew.org; Mon, 27 Feb 2017 13:38:14 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52219) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfk-0002R4-1a for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfh-0001x0-C5 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:20 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48679) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfh-0001rj-27 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:17 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfR-0002JF-S4 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:01 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:32 +0000 Message-Id: <1488218699-31035-4-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> 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 03/30] sd: sdhci: mask transfer mode register 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: , 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: Prasad J Pandit In SDHCI protocol, the transfer mode register is defined to be of 6 bits. Mask its value with '0x0037' so that an invalid value could not be assigned. Signed-off-by: Prasad J Pandit Reviewed-by: Alistair Francis Message-id: 20170214185225.7994-2-ppandit@redhat.com Signed-off-by: Peter Maydell --- hw/sd/sdhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index da32b5f..a65c77d 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -119,6 +119,7 @@ (SDHC_CAPAB_BASECLKFREQ << 8) | (SDHC_CAPAB_TOUNIT << 7) | \ (SDHC_CAPAB_TOCLKFREQ)) =20 +#define MASK_TRNMOD 0x0037 #define MASKED_WRITE(reg, mask, val) (reg =3D (reg & (mask)) | (val)) =20 static uint8_t sdhci_slotint(SDHCIState *s) @@ -1050,7 +1051,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val= , unsigned size) if (!(s->capareg & SDHC_CAN_DO_DMA)) { value &=3D ~SDHC_TRNS_DMA; } - MASKED_WRITE(s->trnmod, mask, value); + MASKED_WRITE(s->trnmod, mask, value & MASK_TRNMOD); MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16); =20 /* Writing to the upper byte of CMDREG triggers SD command generat= ion */ --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 148822044344632.536224831804816; Mon, 27 Feb 2017 10:34:03 -0800 (PST) Received: from localhost ([::1]:55642 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQ7V-000213-8l for importer@patchew.org; Mon, 27 Feb 2017 13:34:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52233) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfk-0002RX-DI for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfh-0001x4-Bj for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:20 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48678) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfh-0001qs-2E for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:17 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfS-0002Jd-FP for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:02 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:33 +0000 Message-Id: <1488218699-31035-5-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> 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 04/30] sd: sdhci: check transfer mode register in multi block transfer 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Prasad J Pandit In the SDHCI protocol, the transfer mode register value is used during multi block transfer to check if block count register is enabled and should be updated. Transfer mode register could be set such that, block count register would not be updated, thus leading to an infinite loop. Add check to avoid it. Reported-by: Wjjzhang Reported-by: Jiang Xin Signed-off-by: Prasad J Pandit Message-id: 20170214185225.7994-3-ppandit@redhat.com Reviewed-by: Alistair Francis Signed-off-by: Peter Maydell --- hw/sd/sdhci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index a65c77d..5adeab6 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -487,6 +487,11 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIStat= e *s) uint32_t boundary_chk =3D 1 << (((s->blksize & 0xf000) >> 12) + 12); uint32_t boundary_count =3D boundary_chk - (s->sdmasysad % boundary_ch= k); =20 + if (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || !s->blkcnt) { + qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n"); + return; + } + /* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account f= or * possible stop at page boundary if initial address is not page align= ed, * allow them to work properly */ @@ -798,11 +803,6 @@ static void sdhci_data_transfer(void *opaque) if (s->trnmod & SDHC_TRNS_DMA) { switch (SDHC_DMA_TYPE(s->hostctl)) { case SDHC_CTRL_SDMA: - if ((s->trnmod & SDHC_TRNS_MULTI) && - (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt =3D= =3D 0)) { - break; - } - if ((s->blkcnt =3D=3D 1) || !(s->trnmod & SDHC_TRNS_MULTI)) { sdhci_sdma_transfer_single_block(s); } else { --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488219496439532.6116029560357; Mon, 27 Feb 2017 10:18:16 -0800 (PST) Received: from localhost ([::1]:55558 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPsE-0004t7-UK for importer@patchew.org; Mon, 27 Feb 2017 13:18:14 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52192) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfj-0002QC-Du for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfh-0001wn-2f for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:19 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48680) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfg-0001ss-R5 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfS-0002K0-Te for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:02 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:34 +0000 Message-Id: <1488218699-31035-6-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> 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 05/30] sd: sdhci: conditionally invoke multi block transfer 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Prasad J Pandit In sdhci_write invoke multi block transfer if it is enabled in the transfer mode register 's->trnmod'. Signed-off-by: Prasad J Pandit Message-id: 20170214185225.7994-4-ppandit@redhat.com Reviewed-by: Alistair Francis Signed-off-by: Peter Maydell --- hw/sd/sdhci.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 5adeab6..c270e09 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1023,7 +1023,11 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t va= l, unsigned size) /* Writing to last byte of sdmasysad might trigger transfer */ if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blk= cnt && s->blksize && SDHC_DMA_TYPE(s->hostctl) =3D=3D SDHC_CTRL_S= DMA) { - sdhci_sdma_transfer_multi_blocks(s); + if (s->trnmod & SDHC_TRNS_MULTI) { + sdhci_sdma_transfer_multi_blocks(s); + } else { + sdhci_sdma_transfer_single_block(s); + } } break; case SDHC_BLKSIZE: --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488219771659584.1450458959406; Mon, 27 Feb 2017 10:22:51 -0800 (PST) Received: from localhost ([::1]:55581 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPwg-0000fH-CD for importer@patchew.org; Mon, 27 Feb 2017 13:22:50 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52199) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfj-0002QR-HW for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfg-0001wV-NL for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:19 -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 1ciPfg-0001lG-Dm for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfT-0002KN-DF for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:03 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:35 +0000 Message-Id: <1488218699-31035-7-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> 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 06/30] sd: sdhci: Remove block count enable check in single block transfers 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Prasad J Pandit In SDHCI protocol, the 'Block count enable' bit of the Transfer Mode register is relevant only in multi block transfers. We need not check it in single block transfers. Signed-off-by: Prasad J Pandit Message-id: 20170214185225.7994-5-ppandit@redhat.com Reviewed-by: Alistair Francis Signed-off-by: Peter Maydell --- hw/sd/sdhci.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index c270e09..6d6a791 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -570,7 +570,6 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState= *s) } =20 /* single block SDMA transfer */ - static void sdhci_sdma_transfer_single_block(SDHCIState *s) { int n; @@ -589,10 +588,7 @@ static void sdhci_sdma_transfer_single_block(SDHCIStat= e *s) sdbus_write_data(&s->sdbus, s->fifo_buffer[n]); } } - - if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) { - s->blkcnt--; - } + s->blkcnt--; =20 sdhci_end_transfer(s); } --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488219647050601.5503744557492; Mon, 27 Feb 2017 10:20:47 -0800 (PST) Received: from localhost ([::1]:55574 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPuf-0006yP-Ey for importer@patchew.org; Mon, 27 Feb 2017 13:20:45 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52141) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfi-0002PM-MP for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfg-0001wK-Kz for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:18 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48679) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfg-0001rj-Av for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfT-0002Kk-Rr for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:03 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:36 +0000 Message-Id: <1488218699-31035-8-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> 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 07/30] hw/arm/virt: fix cpu object reference leak 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Igor Mammedov object_new(FOO) returns an object with ref_cnt =3D=3D 1 and following object_property_set_bool(cpuobj, true, "realized", NULL) set parent of cpuobj to '/machine/unattached' which makes ref_cnt =3D=3D 2. Since machvirt_init() doesn't take ownership of cpuobj returned by object_new() it should explicitly drop reference to cpuobj when dangling pointer is about to go out of scope like it's done pc_new_cpu() to avoid object leak. Signed-off-by: Igor Mammedov Message-id: 1487253461-269218-1-git-send-email-imammedo@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index f3440f2..0c270b8 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1378,6 +1378,7 @@ static void machvirt_init(MachineState *machine) } =20 object_property_set_bool(cpuobj, true, "realized", NULL); + object_unref(cpuobj); } fdt_add_timer_nodes(vms); fdt_add_cpu_nodes(vms); --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488220225673349.4146626972713; Mon, 27 Feb 2017 10:30:25 -0800 (PST) Received: from localhost ([::1]:55621 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQ3z-0007Ek-BJ for importer@patchew.org; Mon, 27 Feb 2017 13:30:23 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52140) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfi-0002PK-Ll for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfg-0001w6-GL for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:18 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48678) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfg-0001qs-6u for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfU-0002L8-FE for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:04 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:37 +0000 Message-Id: <1488218699-31035-9-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> 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 08/30] Add missing fp_access_check() to aarch64 crypto instructions 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Nick Reilly The aarch64 crypto instructions for AES and SHA are missing the check for if the FPU is enabled. Signed-off-by: Nick Reilly Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/translate-a64.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index e15eae6..24de30d 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -10933,6 +10933,10 @@ static void disas_crypto_aes(DisasContext *s, uint= 32_t insn) return; } =20 + if (!fp_access_check(s)) { + return; + } + /* Note that we convert the Vx register indexes into the * index within the vfp.regs[] array, so we can share the * helper with the AArch32 instructions. @@ -10997,6 +11001,10 @@ static void disas_crypto_three_reg_sha(DisasContex= t *s, uint32_t insn) return; } =20 + if (!fp_access_check(s)) { + return; + } + tcg_rd_regno =3D tcg_const_i32(rd << 1); tcg_rn_regno =3D tcg_const_i32(rn << 1); tcg_rm_regno =3D tcg_const_i32(rm << 1); @@ -11060,6 +11068,10 @@ static void disas_crypto_two_reg_sha(DisasContext = *s, uint32_t insn) return; } =20 + if (!fp_access_check(s)) { + return; + } + tcg_rd_regno =3D tcg_const_i32(rd << 1); tcg_rn_regno =3D tcg_const_i32(rn << 1); =20 --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488220959711467.554070498735; Mon, 27 Feb 2017 10:42:39 -0800 (PST) Received: from localhost ([::1]:55707 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQFq-00019W-Bf for importer@patchew.org; Mon, 27 Feb 2017 13:42:38 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52166) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfj-0002Pg-3E for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPff-0001vk-Ui for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:19 -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 1ciPff-0001lG-Kf for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:15 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfU-0002LV-Tp for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:04 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:38 +0000 Message-Id: <1488218699-31035-10-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> 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 09/30] cputlb: Don't assume do_unassigned_access() never returns 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" In get_page_addr_code(), if the guest PC doesn't correspond to RAM then we currently run the CPU's do_unassigned_access() hook if it has one, and otherwise we give up and exit QEMU with a more-or-less useful message. This code assumes that the do_unassigned_access hook will never return, because if it does then we'll plough on attempting to use a non-RAM TLB entry to get a RAM address and will abort() in qemu_ram_addr_from_host_nofail(). Unfortunately some CPU implementations of this hook do return: Microblaze, SPARC and the ARM v7M. Change the code to call report_bad_exec() if the hook returns, as well as if it didn't have one. This means we can tidy it up to use the cpu_unassigned_access() function which wraps the "get the CPU class and call the hook if it has one" work, since we aren't trying to distinguish "no hook" from "hook existed and returned" any more. This brings the handling of this hook into line with the handling used for data accesses, where "hook returned" is treated the same as "no hook existed" and gets you the default behaviour. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson --- cputlb.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/cputlb.c b/cputlb.c index 7fa7fef..f5d056c 100644 --- a/cputlb.c +++ b/cputlb.c @@ -769,14 +769,13 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1,= target_ulong addr) pd =3D iotlbentry->addr & ~TARGET_PAGE_MASK; mr =3D iotlb_to_region(cpu, pd, iotlbentry->attrs); if (memory_region_is_unassigned(mr)) { - CPUClass *cc =3D CPU_GET_CLASS(cpu); - - if (cc->do_unassigned_access) { - cc->do_unassigned_access(cpu, addr, false, true, 0, 4); - } else { - report_bad_exec(cpu, addr); - exit(1); - } + cpu_unassigned_access(cpu, addr, false, true, 0, 4); + /* The CPU's unassigned access hook might have longjumped out + * with an exception. If it didn't (or there was no hook) then + * we can't proceed further. + */ + report_bad_exec(cpu, addr); + exit(1); } p =3D (void *)((uintptr_t)addr + env1->tlb_table[mmu_idx][page_index].= addend); return qemu_ram_addr_from_host_nofail(p); --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488219231845499.4993470738914; Mon, 27 Feb 2017 10:13:51 -0800 (PST) Received: from localhost ([::1]:55534 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPnv-0001EN-EA for importer@patchew.org; Mon, 27 Feb 2017 13:13:47 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52131) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfi-0002PA-HS for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPff-0001vS-PK for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:18 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48679) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPff-0001rj-EK for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:15 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfV-0002Ls-Cj for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:05 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:39 +0000 Message-Id: <1488218699-31035-11-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> 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 10/30] hw/arm/virt: Add a user option to disallow ITS instantiation 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Eric Auger In 2.9 ITS will block save/restore and migration use cases. As such, let's introduce a user option that allows to turn its instantiation off, along with GICv3. With the "its" option turned false, migration will be possible, obviously at the expense of MSI support (with GICv3). Signed-off-by: Eric Auger Message-id: 1487681108-14452-1-git-send-email-eric.auger@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- include/hw/arm/virt.h | 1 + hw/arm/virt.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 58ce74e..33b0ff3 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -93,6 +93,7 @@ typedef struct { FWCfgState *fw_cfg; bool secure; bool highmem; + bool its; bool virt; int32_t gic_version; struct arm_boot_info bootinfo; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 0c270b8..5f62a03 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -535,7 +535,6 @@ static void create_v2m(VirtMachineState *vms, qemu_irq = *pic) static void create_gic(VirtMachineState *vms, qemu_irq *pic) { /* We create a standalone GIC */ - VirtMachineClass *vmc =3D VIRT_MACHINE_GET_CLASS(vms); DeviceState *gicdev; SysBusDevice *gicbusdev; const char *gictype; @@ -605,7 +604,7 @@ static void create_gic(VirtMachineState *vms, qemu_irq = *pic) =20 fdt_add_gic_node(vms); =20 - if (type =3D=3D 3 && !vmc->no_its) { + if (type =3D=3D 3 && vms->its) { create_its(vms, gicdev); } else if (type =3D=3D 2) { create_v2m(vms, pic); @@ -1481,6 +1480,20 @@ static void virt_set_highmem(Object *obj, bool value= , Error **errp) vms->highmem =3D value; } =20 +static bool virt_get_its(Object *obj, Error **errp) +{ + VirtMachineState *vms =3D VIRT_MACHINE(obj); + + return vms->its; +} + +static void virt_set_its(Object *obj, bool value, Error **errp) +{ + VirtMachineState *vms =3D VIRT_MACHINE(obj); + + vms->its =3D value; +} + static char *virt_get_gic_version(Object *obj, Error **errp) { VirtMachineState *vms =3D VIRT_MACHINE(obj); @@ -1541,6 +1554,7 @@ type_init(machvirt_machine_init); static void virt_2_9_instance_init(Object *obj) { VirtMachineState *vms =3D VIRT_MACHINE(obj); + VirtMachineClass *vmc =3D VIRT_MACHINE_GET_CLASS(vms); =20 /* EL3 is disabled by default on virt: this makes us consistent * between KVM and TCG for this board, and it also allows us to @@ -1580,6 +1594,19 @@ static void virt_2_9_instance_init(Object *obj) "Set GIC version. " "Valid values are 2, 3 and host", NULL= ); =20 + if (vmc->no_its) { + vms->its =3D false; + } else { + /* Default allows ITS instantiation */ + vms->its =3D true; + object_property_add_bool(obj, "its", virt_get_its, + virt_set_its, NULL); + object_property_set_description(obj, "its", + "Set on/off to enable/disable " + "ITS instantiation", + NULL); + } + vms->memmap =3D a15memmap; vms->irqmap =3D a15irqmap; } --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488219915929221.683179291172; Mon, 27 Feb 2017 10:25:15 -0800 (PST) Received: from localhost ([::1]:55591 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPz0-0002Zr-DW for importer@patchew.org; Mon, 27 Feb 2017 13:25:14 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52113) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfh-0002Oe-UR for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPff-0001vB-Hn for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:17 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48678) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPff-0001qs-A1 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:15 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfV-0002MF-R2 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:05 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:40 +0000 Message-Id: <1488218699-31035-12-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> 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 11/30] ARM i.MX timers: fix reset handling 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Kurban Mallachiev The i.MX timer device can be reset by writing to the SWR bit of the CR register. This has to behave differently from hard (power-on) reset because it does not reset all of the bits in the CR register. We were incorrectly implementing soft reset and hard reset the same way, and in addition had a logic error which meant that we were clearing the bits that soft-reset is supposed to preserve and not touching the bits that soft-reset clears. This was not correct behaviour for either kind of reset. Separate out the soft reset and hard reset code paths, and correct the handling of reset of the CR register so that it is correct in both cases. Signed-off-by: Kurban Mallachiev [PMM: rephrased commit message, spacing on operators; use bool rather than int for is_soft_reset] Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/timer/imx_gpt.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c index 010ccbf..4b9b54b 100644 --- a/hw/timer/imx_gpt.c +++ b/hw/timer/imx_gpt.c @@ -296,18 +296,23 @@ static uint64_t imx_gpt_read(void *opaque, hwaddr off= set, unsigned size) return reg_value; } =20 -static void imx_gpt_reset(DeviceState *dev) -{ - IMXGPTState *s =3D IMX_GPT(dev); =20 +static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset) +{ /* stop timer */ ptimer_stop(s->timer); =20 - /* - * Soft reset doesn't touch some bits; hard reset clears them + /* Soft reset and hard reset differ only in their handling of the CR + * register -- soft reset preserves the values of some bits there. */ - s->cr &=3D ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN| - GPT_CR_WAITEN|GPT_CR_DBGEN); + if (is_soft_reset) { + /* Clear all CR bits except those that are preserved by soft reset= . */ + s->cr &=3D GPT_CR_EN | GPT_CR_ENMOD | GPT_CR_STOPEN | GPT_CR_DOZEN= | + GPT_CR_WAITEN | GPT_CR_DBGEN | + (GPT_CR_CLKSRC_MASK << GPT_CR_CLKSRC_SHIFT); + } else { + s->cr =3D 0; + } s->sr =3D 0; s->pr =3D 0; s->ir =3D 0; @@ -333,6 +338,18 @@ static void imx_gpt_reset(DeviceState *dev) } } =20 +static void imx_gpt_soft_reset(DeviceState *dev) +{ + IMXGPTState *s =3D IMX_GPT(dev); + imx_gpt_reset_common(s, true); +} + +static void imx_gpt_reset(DeviceState *dev) +{ + IMXGPTState *s =3D IMX_GPT(dev); + imx_gpt_reset_common(s, false); +} + static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { @@ -348,7 +365,7 @@ static void imx_gpt_write(void *opaque, hwaddr offset, = uint64_t value, s->cr =3D value & ~0x7c14; if (s->cr & GPT_CR_SWR) { /* force reset */ /* handle the reset */ - imx_gpt_reset(DEVICE(s)); + imx_gpt_soft_reset(DEVICE(s)); } else { /* set our freq, as the source might have changed */ imx_gpt_set_freq(s); --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488219917336748.9799734784311; Mon, 27 Feb 2017 10:25:17 -0800 (PST) Received: from localhost ([::1]:55592 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPz2-0002ai-0q for importer@patchew.org; Mon, 27 Feb 2017 13:25:16 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52118) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfh-0002Of-Vw for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPff-0001uz-CD for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:17 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48680) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPff-0001ss-1U for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:15 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfW-0002Mc-E9 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:06 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:41 +0000 Message-Id: <1488218699-31035-13-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 12/30] 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Rename the nvic_state struct to NVICState, to match our naming conventions. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Alex Benn=C3=A9e --- 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 Tue Apr 15 15:24:57 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 1488219912232208.87513357688442; Mon, 27 Feb 2017 10:25:12 -0800 (PST) Received: from localhost ([::1]:55590 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPyw-0002W1-UE for importer@patchew.org; Mon, 27 Feb 2017 13:25:10 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52065) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfg-0002NN-Nf for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:19 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPff-0001un-32 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -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 1ciPfe-0001lG-Pg for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:14 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfW-0002Mz-T9 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:06 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:42 +0000 Message-Id: <1488218699-31035-14-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 13/30] 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 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: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Alex Benn=C3=A9e --- 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 Tue Apr 15 15:24:57 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 1488221179632459.0703336255724; Mon, 27 Feb 2017 10:46:19 -0800 (PST) Received: from localhost ([::1]:55725 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQJM-0003wf-1v for importer@patchew.org; Mon, 27 Feb 2017 13:46:16 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52321) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfm-0002Sx-ML for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfe-0001uA-Mo for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:22 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48678) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfd-0001qs-V9 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:14 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfX-0002NN-Cd 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:43 +0000 Message-Id: <1488218699-31035-15-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 14/30] 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 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 Reviewed-by: Alex Benn=C3=A9e --- hw/intc/armv7m_nvic.c | 738 ++++++++++++++++++++++++++++++++++++++++------= ---- hw/intc/trace-events | 15 + 2 files changed, 609 insertions(+), 144 deletions(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index ce22001..fb4c985 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -17,48 +17,88 @@ #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. + * + * In the terminology of the architecture manual, "interrupts" are + * a subcategory of exception referring to the external interrupts + * (which are exception numbers NVIC_FIRST_IRQ and upward). + * For historical reasons QEMU tends to use "interrupt" and + * "exception" more or less interchangeably. + */ +#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 { + /* Exception priorities can range from -3 to 255; only the unmodifiable + * priority values for RESET, NMI and HardFault can be negative. + */ + int16_t prio; + 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 +165,283 @@ 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 1, + * which matches the choice Cortex-M3 is documented as making). + * + * NB: some versions of the documentation talk about this + * counting "active exceptions other than the one shown by IPSR"; + * this is only different in the obscure corner case where guest + * code has manually deactivated an exception and is about + * to fail an exception-return integrity check. The definition + * above is the one from the v8M ARM ARM and is also in line + * with the behaviour documented for the Cortex-M3. + */ +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) { + return 0; + } + } + } + + return 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 +471,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 +506,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 +641,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 +664,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 +685,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 +710,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 +731,80 @@ static uint64_t nvic_sysreg_read(void *opaque, hwaddr= addr, { NVICState *s =3D (NVICState *)opaque; uint32_t offset =3D addr; - int i; + unsigned i, startvec, 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; + startvec =3D offset - 0x180 + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0, end =3D size * 8; i < end && startvec + i < s->num_i= rq; i++) { + if (s->vectors[startvec + 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; + startvec =3D offset - 0x280 + NVIC_FIRST_IRQ; /* vector # */ + for (i =3D 0, end =3D size * 8; i < end && startvec + i < s->num_i= rq; i++) { + if (s->vectors[startvec + i].pending) { + val |=3D (1 << i); + } + } + break; + case 0x300 ... 0x33f: /* NVIC Active */ + val =3D 0; + startvec =3D offset - 0x300 + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0, end =3D size * 8; i < end && startvec + i < s->num_i= rq; i++) { + if (s->vectors[startvec + i].active) { + val |=3D (1 << i); + } + } + break; + case 0x400 ... 0x5ef: /* NVIC Priority */ + val =3D 0; + startvec =3D offset - 0x400 + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0; i < size && startvec + i < s->num_irq; i++) { + val |=3D s->vectors[startvec + 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 +812,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, startvec, 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 */ + startvec =3D 8 * (offset - 0x180) + NVIC_FIRST_IRQ; + + for (i =3D 0, end =3D size * 8; i < end && startvec + i < s->num_i= rq; i++) { + if (value & (1 << i)) { + s->vectors[startvec + 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 */ + startvec =3D 8 * (offset - 0x280) + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0, end =3D size * 8; i < end && startvec + i < s->num_i= rq; i++) { + if (value & (1 << i)) { + s->vectors[startvec + i].pending =3D setval; + } + } + nvic_irq_update(s); + return; + case 0x300 ... 0x33f: /* NVIC Active */ + return; /* R/O */ + case 0x400 ... 0x5ef: /* NVIC Priority */ + startvec =3D 8 * (offset - 0x400) + NVIC_FIRST_IRQ; /* vector # */ + + for (i =3D 0; i < size && startvec + i < s->num_irq; i++) { + set_prio(s, startvec + 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 +881,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 +934,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 Control Space (SCS) 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 +1008,7 @@ static void armv7m_nvic_realize(DeviceState *dev, Err= or **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 +1024,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 Tue Apr 15 15:24:57 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 From nobody Tue Apr 15 15:24:57 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 1488219647048573.4924080992022; Mon, 27 Feb 2017 10:20:47 -0800 (PST) Received: from localhost ([::1]:55573 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPud-0006u1-Iq for importer@patchew.org; Mon, 27 Feb 2017 13:20:43 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52046) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfg-0002N7-BB for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:19 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfd-0001sy-Cv for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48678) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfd-0001qs-3y 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 1ciPfY-0002O7-Bv for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:08 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:45 +0000 Message-Id: <1488218699-31035-17-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 16/30] 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 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 --- 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 Tue Apr 15 15:24:57 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 14882196427681015.1288523300937; Mon, 27 Feb 2017 10:20:42 -0800 (PST) Received: from localhost ([::1]:55567 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPub-0006rJ-06 for importer@patchew.org; Mon, 27 Feb 2017 13:20:41 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52010) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPff-0002MF-G5 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfd-0001se-4h 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 1ciPfc-0001lG-UU 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 1ciPfY-0002OU-QR for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:08 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:46 +0000 Message-Id: <1488218699-31035-18-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 17/30] 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 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 6a03e2c..479acfc 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -352,6 +352,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 bcedb4a..2fc6802 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6106,8 +6106,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 Tue Apr 15 15:24:57 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 1488218841946963.9720751103918; Mon, 27 Feb 2017 10:07:21 -0800 (PST) Received: from localhost ([::1]:55502 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPhf-0003Xe-Hf for importer@patchew.org; Mon, 27 Feb 2017 13:07:19 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51875) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfc-0002I8-IK for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfa-0001qo-Oi for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:11 -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 1ciPfa-0001lG-In for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:10 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfZ-0002Os-Dx for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:09 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:47 +0000 Message-Id: <1488218699-31035-19-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 18/30] 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 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 649f237..68ad00c 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1365,7 +1365,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 479acfc..9336bca 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -412,7 +412,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; @@ -439,8 +439,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 2fc6802..85d1364 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6142,7 +6142,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 Tue Apr 15 15:24:57 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 148821884309491.83884783441692; Mon, 27 Feb 2017 10:07:23 -0800 (PST) Received: from localhost ([::1]:55503 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPhh-0003bK-Py for importer@patchew.org; Mon, 27 Feb 2017 13:07:21 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51900) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfc-0002IA-IN for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfb-0001rH-HH for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:12 -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 1ciPfb-0001lG-Ag for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:11 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfZ-0002PF-UA for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:09 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:48 +0000 Message-Id: <1488218699-31035-20-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 19/30] 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 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 85d1364..664f030 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6110,22 +6110,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; @@ -6140,9 +6140,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); @@ -6152,6 +6151,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 Tue Apr 15 15:24:57 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 1488219105037256.90424905011935; Mon, 27 Feb 2017 10:11:45 -0800 (PST) Received: from localhost ([::1]:55526 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPlu-0007er-J9 for importer@patchew.org; Mon, 27 Feb 2017 13:11:42 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51901) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfc-0002IB-IS for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfb-0001rQ-JX for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:12 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48678) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfb-0001qs-De for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:11 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfa-0002Pg-HJ for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:10 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:49 +0000 Message-Id: <1488218699-31035-21-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 20/30] 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 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: Philippe Mathieu-Daud=C3=A9 Reviewed-by: Alex Benn=C3=A9e --- 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 9336bca..456480a 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -716,10 +716,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 From nobody Tue Apr 15 15:24:57 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 1488219363081943.5830683219997; Mon, 27 Feb 2017 10:16:03 -0800 (PST) Received: from localhost ([::1]:55547 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPq4-00038h-LS for importer@patchew.org; Mon, 27 Feb 2017 13:16:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51960) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfd-0002Kw-TS for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfc-0001rr-9V for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:13 -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 1ciPfc-0001lG-2s for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:12 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfb-0002Pw-02 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:11 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:50 +0000 Message-Id: <1488218699-31035-22-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 21/30] armv7m: Extract "exception taken" code into functions 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 Extract the code from the tail end of arm_v7m_do_interrupt() which enters the exception handler into a pair of utility functions v7m_exception_taken() and v7m_push_stack(), which correspond roughly to the pseudocode PushStack() and ExceptionTaken(). This also requires us to move the arm_v7m_load_vector() utility routine up so we can call it. Handling illegal exception returns has some cases where we want to take a UsageFault either on an existing stack frame or with a new stack frame but with a specific LR value, so we want to be able to call these without having to go via arm_v7m_cpu_do_interrupt(). Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- target/arm/helper.c | 118 ++++++++++++++++++++++++++++++------------------= ---- 1 file changed, 68 insertions(+), 50 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 664f030..be731dc 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6002,6 +6002,72 @@ static void switch_v7m_sp(CPUARMState *env, bool new= _spsel) } } =20 +static uint32_t arm_v7m_load_vector(ARMCPU *cpu) +{ + CPUState *cs =3D CPU(cpu); + CPUARMState *env =3D &cpu->env; + MemTxResult result; + hwaddr vec =3D env->v7m.vecbase + env->v7m.exception * 4; + uint32_t addr; + + addr =3D address_space_ldl(cs->as, vec, + MEMTXATTRS_UNSPECIFIED, &result); + if (result !=3D MEMTX_OK) { + /* Architecturally this should cause a HardFault setting HSFR.VECT= TBL, + * which would then be immediately followed by our failing to load + * the entry vector for that HardFault, which is a Lockup case. + * Since we don't model Lockup, we just report this guest error + * via cpu_abort(). + */ + cpu_abort(cs, "Failed to read from exception vector table " + "entry %08x\n", (unsigned)vec); + } + return addr; +} + +static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr) +{ + /* Do the "take the exception" parts of exception entry, + * but not the pushing of state to the stack. This is + * similar to the pseudocode ExceptionTaken() function. + */ + CPUARMState *env =3D &cpu->env; + uint32_t addr; + + armv7m_nvic_acknowledge_irq(env->nvic); + switch_v7m_sp(env, 0); + /* Clear IT bits */ + env->condexec_bits =3D 0; + env->regs[14] =3D lr; + addr =3D arm_v7m_load_vector(cpu); + env->regs[15] =3D addr & 0xfffffffe; + env->thumb =3D addr & 1; +} + +static void v7m_push_stack(ARMCPU *cpu) +{ + /* Do the "set up stack frame" part of exception entry, + * similar to pseudocode PushStack(). + */ + CPUARMState *env =3D &cpu->env; + uint32_t xpsr =3D xpsr_read(env); + + /* 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; + xpsr |=3D 0x200; + } + /* Switch to the handler mode. */ + v7m_push(env, xpsr); + v7m_push(env, env->regs[15]); + v7m_push(env, env->regs[14]); + v7m_push(env, env->regs[12]); + v7m_push(env, env->regs[3]); + v7m_push(env, env->regs[2]); + v7m_push(env, env->regs[1]); + v7m_push(env, env->regs[0]); +} + static void do_v7m_exception_exit(CPUARMState *env) { uint32_t type; @@ -6063,37 +6129,11 @@ static void arm_log_exception(int idx) } } =20 -static uint32_t arm_v7m_load_vector(ARMCPU *cpu) - -{ - CPUState *cs =3D CPU(cpu); - CPUARMState *env =3D &cpu->env; - MemTxResult result; - hwaddr vec =3D env->v7m.vecbase + env->v7m.exception * 4; - uint32_t addr; - - addr =3D address_space_ldl(cs->as, vec, - MEMTXATTRS_UNSPECIFIED, &result); - if (result !=3D MEMTX_OK) { - /* Architecturally this should cause a HardFault setting HSFR.VECT= TBL, - * which would then be immediately followed by our failing to load - * the entry vector for that HardFault, which is a Lockup case. - * Since we don't model Lockup, we just report this guest error - * via cpu_abort(). - */ - cpu_abort(cs, "Failed to read from exception vector table " - "entry %08x\n", (unsigned)vec); - } - return addr; -} - void arm_v7m_cpu_do_interrupt(CPUState *cs) { ARMCPU *cpu =3D ARM_CPU(cs); CPUARMState *env =3D &cpu->env; - uint32_t xpsr =3D xpsr_read(env); uint32_t lr; - uint32_t addr; =20 arm_log_exception(cs->exception_index); =20 @@ -6151,31 +6191,9 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) return; /* Never happens. Keep compiler happy. */ } =20 - armv7m_nvic_acknowledge_irq(env->nvic); - + v7m_push_stack(cpu); + v7m_exception_taken(cpu, lr); 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; - xpsr |=3D 0x200; - } - /* Switch to the handler mode. */ - v7m_push(env, xpsr); - v7m_push(env, env->regs[15]); - v7m_push(env, env->regs[14]); - v7m_push(env, env->regs[12]); - v7m_push(env, env->regs[3]); - v7m_push(env, env->regs[2]); - v7m_push(env, env->regs[1]); - v7m_push(env, env->regs[0]); - switch_v7m_sp(env, 0); - /* Clear IT bits */ - env->condexec_bits =3D 0; - env->regs[14] =3D lr; - addr =3D arm_v7m_load_vector(cpu); - env->regs[15] =3D addr & 0xfffffffe; - env->thumb =3D addr & 1; } =20 /* Function used to synchronize QEMU's AArch64 register set with AArch32 --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488219102271907.6090023369293; Mon, 27 Feb 2017 10:11:42 -0800 (PST) Received: from localhost ([::1]:55525 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPlr-0007dA-Mp for importer@patchew.org; Mon, 27 Feb 2017 13:11:39 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51970) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfe-0002LG-8s for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfc-0001s8-Fm for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:14 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48678) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfc-0001qs-7x for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:12 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfb-0002QA-Ew for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:11 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:51 +0000 Message-Id: <1488218699-31035-23-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 22/30] armv7m: Check exception return consistency 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 Implement the exception return consistency checks described in the v7M pseudocode ExceptionReturn(). Inspired by a patch from Michael Davidsaver's series, but this is a reimplementation from scratch based on the ARM ARM pseudocode. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- target/arm/cpu.h | 12 +++++- hw/intc/armv7m_nvic.c | 12 +++++- target/arm/helper.c | 112 +++++++++++++++++++++++++++++++++++++++++++++-= ---- 3 files changed, 123 insertions(+), 13 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 68ad00c..045830a 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1366,7 +1366,17 @@ static inline bool armv7m_nvic_can_take_pending_exce= ption(void *opaque) #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); +/** + * armv7m_nvic_complete_irq: complete specified interrupt or exception + * @opaque: the NVIC + * @irq: the exception number to complete + * + * Returns: -1 if the irq was not active + * 1 if completing this irq brought us back to base (no active i= rqs) + * 0 if there is still an irq active after this one was completed + * (Ignoring -1, this is the same as the RETTOBASE value before completion= .) + */ +int armv7m_nvic_complete_irq(void *opaque, int irq); =20 /* Interface for defining coprocessor registers. * Registers are defined in tables of arm_cp_reginfo structs diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 456480a..718b1a1 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -441,10 +441,11 @@ void armv7m_nvic_acknowledge_irq(void *opaque) nvic_irq_update(s); } =20 -void armv7m_nvic_complete_irq(void *opaque, int irq) +int armv7m_nvic_complete_irq(void *opaque, int irq) { NVICState *s =3D (NVICState *)opaque; VecInfo *vec; + int ret; =20 assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq); =20 @@ -452,6 +453,13 @@ void armv7m_nvic_complete_irq(void *opaque, int irq) =20 trace_nvic_complete_irq(irq); =20 + if (!vec->active) { + /* Tell the caller this was an illegal exception return */ + return -1; + } + + ret =3D nvic_rettobase(s); + vec->active =3D 0; if (vec->level) { /* Re-pend the exception if it's still held high; only @@ -462,6 +470,8 @@ void armv7m_nvic_complete_irq(void *opaque, int irq) } =20 nvic_irq_update(s); + + return ret; } =20 /* callback when external interrupt line is changed */ diff --git a/target/arm/helper.c b/target/arm/helper.c index be731dc..9081771 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6068,22 +6068,99 @@ static void v7m_push_stack(ARMCPU *cpu) v7m_push(env, env->regs[0]); } =20 -static void do_v7m_exception_exit(CPUARMState *env) +static void do_v7m_exception_exit(ARMCPU *cpu) { + CPUARMState *env =3D &cpu->env; uint32_t type; uint32_t xpsr; - + bool ufault =3D false; + bool return_to_sp_process =3D false; + bool return_to_handler =3D false; + bool rettobase =3D false; + + /* We can only get here from an EXCP_EXCEPTION_EXIT, and + * arm_v7m_do_unassigned_access() enforces the architectural rule + * that jumps to magic addresses don't have magic behaviour unless + * we're in Handler mode (compare pseudocode BXWritePC()). + */ + assert(env->v7m.exception !=3D 0); + + /* In the spec pseudocode ExceptionReturn() is called directly + * from BXWritePC() and gets the full target PC value including + * bit zero. In QEMU's implementation we treat it as a normal + * jump-to-register (which is then caught later on), and so split + * the target value up between env->regs[15] and env->thumb in + * gen_bx(). Reconstitute it. + */ type =3D env->regs[15]; + if (env->thumb) { + type |=3D 1; + } + + qemu_log_mask(CPU_LOG_INT, "Exception return: magic PC %" PRIx32 + " previous exception %d\n", + type, env->v7m.exception); + + if (extract32(type, 5, 23) !=3D extract32(-1, 5, 23)) { + qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero high bits in excep= tion " + "exit PC value 0x%" PRIx32 " are UNPREDICTABLE\n", t= ype); + } + if (env->v7m.exception !=3D ARMV7M_EXCP_NMI) { /* Auto-clear FAULTMASK on return from other than NMI */ env->daif &=3D ~PSTATE_F; } - if (env->v7m.exception !=3D 0) { - armv7m_nvic_complete_irq(env->nvic, env->v7m.exception); + + switch (armv7m_nvic_complete_irq(env->nvic, env->v7m.exception)) { + case -1: + /* attempt to exit an exception that isn't active */ + ufault =3D true; + break; + case 0: + /* still an irq active now */ + break; + case 1: + /* we returned to base exception level, no nesting. + * (In the pseudocode this is written using "NestedActivation !=3D= 1" + * where we have 'rettobase =3D=3D false'.) + */ + rettobase =3D true; + break; + default: + g_assert_not_reached(); + } + + switch (type & 0xf) { + case 1: /* Return to Handler */ + return_to_handler =3D true; + break; + case 13: /* Return to Thread using Process stack */ + return_to_sp_process =3D true; + /* fall through */ + case 9: /* Return to Thread using Main stack */ + if (!rettobase && + !(env->v7m.ccr & R_V7M_CCR_NONBASETHRDENA_MASK)) { + ufault =3D true; + } + break; + default: + ufault =3D true; + } + + if (ufault) { + /* Bad exception return: instead of popping the exception + * stack, directly take a usage fault on the current stack. + */ + env->v7m.cfsr |=3D R_V7M_CFSR_INVPC_MASK; + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE); + v7m_exception_taken(cpu, type | 0xf0000000); + qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing " + "stackframe: failed exception return integrity check= \n"); + return; } =20 /* Switch to the target stack. */ - switch_v7m_sp(env, (type & 4) !=3D 0); + switch_v7m_sp(env, return_to_sp_process); /* Pop registers. */ env->regs[0] =3D v7m_pop(env); env->regs[1] =3D v7m_pop(env); @@ -6107,11 +6184,24 @@ static void do_v7m_exception_exit(CPUARMState *env) /* Undo stack alignment. */ if (xpsr & 0x200) env->regs[13] |=3D 4; - /* ??? The exception return type specifies Thread/Handler mode. Howev= er - this is also implied by the xPSR value. Not sure what to do - if there is a mismatch. */ - /* ??? Likewise for mismatches between the CONTROL register and the st= ack - pointer. */ + + /* The restored xPSR exception field will be zero if we're + * resuming in Thread mode. If that doesn't match what the + * exception return type specified then this is a UsageFault. + */ + if (return_to_handler =3D=3D (env->v7m.exception =3D=3D 0)) { + /* Take an INVPC UsageFault by pushing the stack again. */ + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE); + env->v7m.cfsr |=3D R_V7M_CFSR_INVPC_MASK; + v7m_push_stack(cpu); + v7m_exception_taken(cpu, type | 0xf0000000); + qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on new stackframe= : " + "failed exception return integrity check\n"); + return; + } + + /* Otherwise, we have a successful exception exit. */ + qemu_log_mask(CPU_LOG_INT, "...successful exception return\n"); } =20 static void arm_log_exception(int idx) @@ -6184,7 +6274,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) case EXCP_IRQ: break; case EXCP_EXCEPTION_EXIT: - do_v7m_exception_exit(env); + do_v7m_exception_exit(cpu); return; default: cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 14882189709091013.5997338926218; Mon, 27 Feb 2017 10:09:30 -0800 (PST) Received: from localhost ([::1]:55512 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPjl-0005kg-D3 for importer@patchew.org; Mon, 27 Feb 2017 13:09:29 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51988) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfe-0002Lf-NJ for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfd-0001sX-1K for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:14 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48679) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfc-0001rj-Q5 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:12 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfb-0002Qf-UM for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:11 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:52 +0000 Message-Id: <1488218699-31035-24-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 23/30] armv7m: Raise correct kind of UsageFault for attempts to execute ARM 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 M profile doesn't implement ARM, and the architecturally required behaviour for attempts to execute with the Thumb bit clear is to generate a UsageFault with the CFSR INVSTATE bit set. We were incorrectly implementing this as generating an UNDEFINSTR UsageFault; fix this. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- target/arm/cpu.h | 1 + linux-user/main.c | 1 + target/arm/helper.c | 4 ++++ target/arm/translate.c | 8 ++++++-- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 045830a..9e7b2df 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -57,6 +57,7 @@ #define EXCP_VFIQ 15 #define EXCP_SEMIHOST 16 /* semihosting call */ #define EXCP_NOCP 17 /* v7M NOCP UsageFault */ +#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */ =20 #define ARMV7M_EXCP_RESET 1 #define ARMV7M_EXCP_NMI 2 diff --git a/linux-user/main.c b/linux-user/main.c index 9645122..10a3bb3 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -574,6 +574,7 @@ void cpu_loop(CPUARMState *env) switch(trapnr) { case EXCP_UDEF: case EXCP_NOCP: + case EXCP_INVSTATE: { TaskState *ts =3D cs->opaque; uint32_t opcode; diff --git a/target/arm/helper.c b/target/arm/helper.c index 9081771..3f4211b 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6245,6 +6245,10 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE); env->v7m.cfsr |=3D R_V7M_CFSR_NOCP_MASK; break; + case EXCP_INVSTATE: + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE); + env->v7m.cfsr |=3D R_V7M_CFSR_INVSTATE_MASK; + break; case EXCP_SWI: /* The PC already points to the next instruction. */ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC); diff --git a/target/arm/translate.c b/target/arm/translate.c index abc1f77..b859f10 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -7990,9 +7990,13 @@ static void disas_arm_insn(DisasContext *s, unsigned= int insn) TCGv_i32 addr; TCGv_i64 tmp64; =20 - /* M variants do not implement ARM mode. */ + /* M variants do not implement ARM mode; this must raise the INVSTATE + * UsageFault exception. + */ if (arm_dc_feature(s, ARM_FEATURE_M)) { - goto illegal_op; + gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(), + default_exception_el(s)); + return; } cond =3D insn >> 28; if (cond =3D=3D 0xf){ --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488218850635336.3205408087945; Mon, 27 Feb 2017 10:07:30 -0800 (PST) Received: from localhost ([::1]:55504 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPhk-0003dU-BL for importer@patchew.org; Mon, 27 Feb 2017 13:07:24 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52004) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPff-0002M8-CA for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfd-0001tO-R8 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:15 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48679) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfd-0001rj-JJ 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 1ciPfc-0002Qv-I4 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:12 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:53 +0000 Message-Id: <1488218699-31035-25-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 24/30] armv7m: Allow SHCSR writes to change pending and active bits 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 Implement the NVIC SHCSR write behaviour which allows pending and active status of some exceptions to be changed. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- hw/intc/armv7m_nvic.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 718b1a1..76097b4 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -755,8 +755,17 @@ static void nvic_writel(NVICState *s, uint32_t offset,= uint32_t value) cpu->env.v7m.ccr =3D value; break; 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->vectors[ARMV7M_EXCP_MEM].active =3D (value & (1 << 0)) !=3D 0; + s->vectors[ARMV7M_EXCP_BUS].active =3D (value & (1 << 1)) !=3D 0; + s->vectors[ARMV7M_EXCP_USAGE].active =3D (value & (1 << 3)) !=3D 0; + s->vectors[ARMV7M_EXCP_SVC].active =3D (value & (1 << 7)) !=3D 0; + s->vectors[ARMV7M_EXCP_DEBUG].active =3D (value & (1 << 8)) !=3D 0; + s->vectors[ARMV7M_EXCP_PENDSV].active =3D (value & (1 << 10)) !=3D= 0; + s->vectors[ARMV7M_EXCP_SYSTICK].active =3D (value & (1 << 11)) != =3D 0; + s->vectors[ARMV7M_EXCP_USAGE].pending =3D (value & (1 << 12)) !=3D= 0; + s->vectors[ARMV7M_EXCP_MEM].pending =3D (value & (1 << 13)) !=3D 0; + s->vectors[ARMV7M_EXCP_BUS].pending =3D (value & (1 << 14)) !=3D 0; + s->vectors[ARMV7M_EXCP_SVC].pending =3D (value & (1 << 15)) !=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; --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488220175028933.2857334741543; Mon, 27 Feb 2017 10:29:35 -0800 (PST) Received: from localhost ([::1]:55618 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQ3A-0006Ug-Bs for importer@patchew.org; Mon, 27 Feb 2017 13:29:32 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52187) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfj-0002QA-Bv for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfe-0001tu-Fr for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:19 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48680) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfd-0001ss-T2 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:14 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfd-0002RM-1I for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:13 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:54 +0000 Message-Id: <1488218699-31035-26-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> 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 25/30] bcm2835_sdhost: add bcm2835 sdhost controller 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Clement Deschamps This adds the BCM2835 SDHost controller from Arasan. Signed-off-by: Clement Deschamps Message-id: 20170224164021.9066-2-clement.deschamps@antfield.fr Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/sd/Makefile.objs | 1 + include/hw/sd/bcm2835_sdhost.h | 48 +++++ hw/sd/bcm2835_sdhost.c | 429 +++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 478 insertions(+) create mode 100644 include/hw/sd/bcm2835_sdhost.h create mode 100644 hw/sd/bcm2835_sdhost.c diff --git a/hw/sd/Makefile.objs b/hw/sd/Makefile.objs index 31c8330..c2b7664 100644 --- a/hw/sd/Makefile.objs +++ b/hw/sd/Makefile.objs @@ -6,3 +6,4 @@ common-obj-$(CONFIG_SDHCI) +=3D sdhci.o obj-$(CONFIG_MILKYMIST) +=3D milkymist-memcard.o obj-$(CONFIG_OMAP) +=3D omap_mmc.o obj-$(CONFIG_PXA2XX) +=3D pxa2xx_mmci.o +obj-$(CONFIG_RASPI) +=3D bcm2835_sdhost.o diff --git a/include/hw/sd/bcm2835_sdhost.h b/include/hw/sd/bcm2835_sdhost.h new file mode 100644 index 0000000..7520dd6 --- /dev/null +++ b/include/hw/sd/bcm2835_sdhost.h @@ -0,0 +1,48 @@ +/* + * Raspberry Pi (BCM2835) SD Host Controller + * + * Copyright (c) 2017 Antfield SAS + * + * Authors: + * Clement Deschamps + * Luc Michel + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef BCM2835_SDHOST_H +#define BCM2835_SDHOST_H + +#include "hw/sysbus.h" +#include "hw/sd/sd.h" + +#define TYPE_BCM2835_SDHOST "bcm2835-sdhost" +#define BCM2835_SDHOST(obj) \ + OBJECT_CHECK(BCM2835SDHostState, (obj), TYPE_BCM2835_SDHOST) + +#define BCM2835_SDHOST_FIFO_LEN 16 + +typedef struct { + SysBusDevice busdev; + SDBus sdbus; + MemoryRegion iomem; + + uint32_t cmd; + uint32_t cmdarg; + uint32_t status; + uint32_t rsp[4]; + uint32_t config; + uint32_t edm; + uint32_t vdd; + uint32_t hbct; + uint32_t hblc; + int32_t fifo_pos; + int32_t fifo_len; + uint32_t fifo[BCM2835_SDHOST_FIFO_LEN]; + uint32_t datacnt; + + qemu_irq irq; +} BCM2835SDHostState; + +#endif diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c new file mode 100644 index 0000000..f7f4e65 --- /dev/null +++ b/hw/sd/bcm2835_sdhost.c @@ -0,0 +1,429 @@ +/* + * Raspberry Pi (BCM2835) SD Host Controller + * + * Copyright (c) 2017 Antfield SAS + * + * Authors: + * Clement Deschamps + * Luc Michel + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "sysemu/blockdev.h" +#include "hw/sd/bcm2835_sdhost.h" + +#define TYPE_BCM2835_SDHOST_BUS "bcm2835-sdhost-bus" +#define BCM2835_SDHOST_BUS(obj) \ + OBJECT_CHECK(SDBus, (obj), TYPE_BCM2835_SDHOST_BUS) + +#define SDCMD 0x00 /* Command to SD card - 16 R/W */ +#define SDARG 0x04 /* Argument to SD card - 32 R/W */ +#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */ +#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */ +#define SDRSP0 0x10 /* SD card rsp (31:0) - 32 R */ +#define SDRSP1 0x14 /* SD card rsp (63:32) - 32 R */ +#define SDRSP2 0x18 /* SD card rsp (95:64) - 32 R */ +#define SDRSP3 0x1c /* SD card rsp (127:96) - 32 R */ +#define SDHSTS 0x20 /* SD host status - 11 R */ +#define SDVDD 0x30 /* SD card power control - 1 R/W */ +#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */ +#define SDHCFG 0x38 /* Host configuration - 2 R/W */ +#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */ +#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */ +#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */ + +#define SDCMD_NEW_FLAG 0x8000 +#define SDCMD_FAIL_FLAG 0x4000 +#define SDCMD_BUSYWAIT 0x800 +#define SDCMD_NO_RESPONSE 0x400 +#define SDCMD_LONG_RESPONSE 0x200 +#define SDCMD_WRITE_CMD 0x80 +#define SDCMD_READ_CMD 0x40 +#define SDCMD_CMD_MASK 0x3f + +#define SDCDIV_MAX_CDIV 0x7ff + +#define SDHSTS_BUSY_IRPT 0x400 +#define SDHSTS_BLOCK_IRPT 0x200 +#define SDHSTS_SDIO_IRPT 0x100 +#define SDHSTS_REW_TIME_OUT 0x80 +#define SDHSTS_CMD_TIME_OUT 0x40 +#define SDHSTS_CRC16_ERROR 0x20 +#define SDHSTS_CRC7_ERROR 0x10 +#define SDHSTS_FIFO_ERROR 0x08 +/* Reserved */ +/* Reserved */ +#define SDHSTS_DATA_FLAG 0x01 + +#define SDHCFG_BUSY_IRPT_EN (1 << 10) +#define SDHCFG_BLOCK_IRPT_EN (1 << 8) +#define SDHCFG_SDIO_IRPT_EN (1 << 5) +#define SDHCFG_DATA_IRPT_EN (1 << 4) +#define SDHCFG_SLOW_CARD (1 << 3) +#define SDHCFG_WIDE_EXT_BUS (1 << 2) +#define SDHCFG_WIDE_INT_BUS (1 << 1) +#define SDHCFG_REL_CMD_LINE (1 << 0) + +#define SDEDM_FORCE_DATA_MODE (1 << 19) +#define SDEDM_CLOCK_PULSE (1 << 20) +#define SDEDM_BYPASS (1 << 21) + +#define SDEDM_WRITE_THRESHOLD_SHIFT 9 +#define SDEDM_READ_THRESHOLD_SHIFT 14 +#define SDEDM_THRESHOLD_MASK 0x1f + +#define SDEDM_FSM_MASK 0xf +#define SDEDM_FSM_IDENTMODE 0x0 +#define SDEDM_FSM_DATAMODE 0x1 +#define SDEDM_FSM_READDATA 0x2 +#define SDEDM_FSM_WRITEDATA 0x3 +#define SDEDM_FSM_READWAIT 0x4 +#define SDEDM_FSM_READCRC 0x5 +#define SDEDM_FSM_WRITECRC 0x6 +#define SDEDM_FSM_WRITEWAIT1 0x7 +#define SDEDM_FSM_POWERDOWN 0x8 +#define SDEDM_FSM_POWERUP 0x9 +#define SDEDM_FSM_WRITESTART1 0xa +#define SDEDM_FSM_WRITESTART2 0xb +#define SDEDM_FSM_GENPULSES 0xc +#define SDEDM_FSM_WRITEWAIT2 0xd +#define SDEDM_FSM_STARTPOWDOWN 0xf + +#define SDDATA_FIFO_WORDS 16 + +static void bcm2835_sdhost_update_irq(BCM2835SDHostState *s) +{ + uint32_t irq =3D s->status & + (SDHSTS_BUSY_IRPT | SDHSTS_BLOCK_IRPT | SDHSTS_SDIO_IRPT); + qemu_set_irq(s->irq, !!irq); +} + +static void bcm2835_sdhost_send_command(BCM2835SDHostState *s) +{ + SDRequest request; + uint8_t rsp[16]; + int rlen; + + request.cmd =3D s->cmd & SDCMD_CMD_MASK; + request.arg =3D s->cmdarg; + + rlen =3D sdbus_do_command(&s->sdbus, &request, rsp); + if (rlen < 0) { + goto error; + } + if (!(s->cmd & SDCMD_NO_RESPONSE)) { +#define RWORD(n) (((uint32_t)rsp[n] << 24) | (rsp[n + 1] << 16) \ + | (rsp[n + 2] << 8) | rsp[n + 3]) + if (rlen =3D=3D 0 || (rlen =3D=3D 4 && (s->cmd & SDCMD_LONG_RESPON= SE))) { + goto error; + } + if (rlen !=3D 4 && rlen !=3D 16) { + goto error; + } + if (rlen =3D=3D 4) { + s->rsp[0] =3D RWORD(0); + s->rsp[1] =3D s->rsp[2] =3D s->rsp[3] =3D 0; + } else { + s->rsp[0] =3D RWORD(12); + s->rsp[1] =3D RWORD(8); + s->rsp[2] =3D RWORD(4); + s->rsp[3] =3D RWORD(0); + } +#undef RWORD + } + return; + +error: + s->cmd |=3D SDCMD_FAIL_FLAG; + s->status |=3D SDHSTS_CMD_TIME_OUT; +} + +static void bcm2835_sdhost_fifo_push(BCM2835SDHostState *s, uint32_t value) +{ + int n; + + if (s->fifo_len =3D=3D BCM2835_SDHOST_FIFO_LEN) { + /* FIFO overflow */ + return; + } + n =3D (s->fifo_pos + s->fifo_len) & (BCM2835_SDHOST_FIFO_LEN - 1); + s->fifo_len++; + s->fifo[n] =3D value; +} + +static uint32_t bcm2835_sdhost_fifo_pop(BCM2835SDHostState *s) +{ + uint32_t value; + + if (s->fifo_len =3D=3D 0) { + /* FIFO underflow */ + return 0; + } + value =3D s->fifo[s->fifo_pos]; + s->fifo_len--; + s->fifo_pos =3D (s->fifo_pos + 1) & (BCM2835_SDHOST_FIFO_LEN - 1); + return value; +} + +static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s) +{ + uint32_t value =3D 0; + int n; + int is_read; + + is_read =3D (s->cmd & SDCMD_READ_CMD) !=3D 0; + if (s->datacnt !=3D 0 && (!is_read || sdbus_data_ready(&s->sdbus))) { + if (is_read) { + n =3D 0; + while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) { + value |=3D (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8); + s->datacnt--; + n++; + if (n =3D=3D 4) { + bcm2835_sdhost_fifo_push(s, value); + n =3D 0; + value =3D 0; + } + } + if (n !=3D 0) { + bcm2835_sdhost_fifo_push(s, value); + } + } else { /* write */ + n =3D 0; + while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) { + if (n =3D=3D 0) { + value =3D bcm2835_sdhost_fifo_pop(s); + n =3D 4; + } + n--; + s->datacnt--; + sdbus_write_data(&s->sdbus, value & 0xff); + value >>=3D 8; + } + } + } + if (s->datacnt =3D=3D 0) { + s->status |=3D SDHSTS_DATA_FLAG; + + s->edm &=3D ~0xf; + s->edm |=3D SDEDM_FSM_DATAMODE; + + if (s->config & SDHCFG_DATA_IRPT_EN) { + s->status |=3D SDHSTS_SDIO_IRPT; + } + + if ((s->cmd & SDCMD_BUSYWAIT) && (s->config & SDHCFG_BUSY_IRPT_EN)= ) { + s->status |=3D SDHSTS_BUSY_IRPT; + } + + if ((s->cmd & SDCMD_WRITE_CMD) && (s->config & SDHCFG_BLOCK_IRPT_E= N)) { + s->status |=3D SDHSTS_BLOCK_IRPT; + } + + bcm2835_sdhost_update_irq(s); + } + + s->edm &=3D ~(0x1f << 4); + s->edm |=3D ((s->fifo_len & 0x1f) << 4); +} + +static uint64_t bcm2835_sdhost_read(void *opaque, hwaddr offset, + unsigned size) +{ + BCM2835SDHostState *s =3D (BCM2835SDHostState *)opaque; + uint32_t res =3D 0; + + switch (offset) { + case SDCMD: + res =3D s->cmd; + break; + case SDHSTS: + res =3D s->status; + break; + case SDRSP0: + res =3D s->rsp[0]; + break; + case SDRSP1: + res =3D s->rsp[1]; + break; + case SDRSP2: + res =3D s->rsp[2]; + break; + case SDRSP3: + res =3D s->rsp[3]; + break; + case SDEDM: + res =3D s->edm; + break; + case SDVDD: + res =3D s->vdd; + break; + case SDDATA: + res =3D bcm2835_sdhost_fifo_pop(s); + bcm2835_sdhost_fifo_run(s); + break; + case SDHBCT: + res =3D s->hbct; + break; + case SDHBLC: + res =3D s->hblc; + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", + __func__, offset); + res =3D 0; + break; + } + + return res; +} + +static void bcm2835_sdhost_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + BCM2835SDHostState *s =3D (BCM2835SDHostState *)opaque; + + switch (offset) { + case SDCMD: + s->cmd =3D value; + if (value & SDCMD_NEW_FLAG) { + bcm2835_sdhost_send_command(s); + bcm2835_sdhost_fifo_run(s); + s->cmd &=3D ~SDCMD_NEW_FLAG; + } + break; + case SDTOUT: + break; + case SDCDIV: + break; + case SDHSTS: + s->status &=3D ~value; + bcm2835_sdhost_update_irq(s); + break; + case SDARG: + s->cmdarg =3D value; + break; + case SDEDM: + if ((value & 0xf) =3D=3D 0xf) { + /* power down */ + value &=3D ~0xf; + } + s->edm =3D value; + break; + case SDHCFG: + s->config =3D value; + bcm2835_sdhost_fifo_run(s); + break; + case SDVDD: + s->vdd =3D value; + break; + case SDDATA: + bcm2835_sdhost_fifo_push(s, value); + bcm2835_sdhost_fifo_run(s); + break; + case SDHBCT: + s->hbct =3D value; + break; + case SDHBLC: + s->hblc =3D value; + s->datacnt =3D s->hblc * s->hbct; + bcm2835_sdhost_fifo_run(s); + break; + + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", + __func__, offset); + break; + } +} + +static const MemoryRegionOps bcm2835_sdhost_ops =3D { + .read =3D bcm2835_sdhost_read, + .write =3D bcm2835_sdhost_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static const VMStateDescription vmstate_bcm2835_sdhost =3D { + .name =3D TYPE_BCM2835_SDHOST, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(cmd, BCM2835SDHostState), + VMSTATE_UINT32(cmdarg, BCM2835SDHostState), + VMSTATE_UINT32(status, BCM2835SDHostState), + VMSTATE_UINT32_ARRAY(rsp, BCM2835SDHostState, 4), + VMSTATE_UINT32(config, BCM2835SDHostState), + VMSTATE_UINT32(edm, BCM2835SDHostState), + VMSTATE_UINT32(vdd, BCM2835SDHostState), + VMSTATE_UINT32(hbct, BCM2835SDHostState), + VMSTATE_UINT32(hblc, BCM2835SDHostState), + VMSTATE_INT32(fifo_pos, BCM2835SDHostState), + VMSTATE_INT32(fifo_len, BCM2835SDHostState), + VMSTATE_UINT32_ARRAY(fifo, BCM2835SDHostState, BCM2835_SDHOST_FIFO= _LEN), + VMSTATE_UINT32(datacnt, BCM2835SDHostState), + VMSTATE_END_OF_LIST() + } +}; + +static void bcm2835_sdhost_init(Object *obj) +{ + BCM2835SDHostState *s =3D BCM2835_SDHOST(obj); + + qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), + TYPE_BCM2835_SDHOST_BUS, DEVICE(s), "sd-bus"); + + memory_region_init_io(&s->iomem, obj, &bcm2835_sdhost_ops, s, + TYPE_BCM2835_SDHOST, 0x1000); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); +} + +static void bcm2835_sdhost_reset(DeviceState *dev) +{ + BCM2835SDHostState *s =3D BCM2835_SDHOST(dev); + + s->cmd =3D 0; + s->cmdarg =3D 0; + s->edm =3D 0x0000c60f; + s->config =3D 0; + s->hbct =3D 0; + s->hblc =3D 0; + s->datacnt =3D 0; + s->fifo_pos =3D 0; + s->fifo_len =3D 0; +} + +static void bcm2835_sdhost_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->reset =3D bcm2835_sdhost_reset; + dc->vmsd =3D &vmstate_bcm2835_sdhost; +} + +static TypeInfo bcm2835_sdhost_info =3D { + .name =3D TYPE_BCM2835_SDHOST, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(BCM2835SDHostState), + .class_init =3D bcm2835_sdhost_class_init, + .instance_init =3D bcm2835_sdhost_init, +}; + +static const TypeInfo bcm2835_sdhost_bus_info =3D { + .name =3D TYPE_BCM2835_SDHOST_BUS, + .parent =3D TYPE_SD_BUS, + .instance_size =3D sizeof(SDBus), +}; + +static void bcm2835_sdhost_register_types(void) +{ + type_register_static(&bcm2835_sdhost_info); + type_register_static(&bcm2835_sdhost_bus_info); +} + +type_init(bcm2835_sdhost_register_types) --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 148821936899244.634030425335936; Mon, 27 Feb 2017 10:16:08 -0800 (PST) Received: from localhost ([::1]:55549 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPqA-0003Dn-GJ for importer@patchew.org; Mon, 27 Feb 2017 13:16:06 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52057) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfg-0002NG-JM for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:19 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfe-0001ub-UQ for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48679) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfe-0001rj-L7 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:14 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfd-0002Rk-Hb for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:13 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:55 +0000 Message-Id: <1488218699-31035-27-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> 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 26/30] hw/sd: add card-reparenting function 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Clement Deschamps Provide a new function sdbus_reparent_card() in sd core for reparenting a card from a SDBus to another one. This function is required by the raspi platform, where the two SD controllers can be dynamically switched. Signed-off-by: Clement Deschamps Message-id: 20170224164021.9066-3-clement.deschamps@antfield.fr Reviewed-by: Peter Maydell [PMM: added a doc comment to the header file] Signed-off-by: Peter Maydell --- include/hw/sd/sd.h | 11 +++++++++++ hw/sd/core.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h index 79909b2..96caefe 100644 --- a/include/hw/sd/sd.h +++ b/include/hw/sd/sd.h @@ -140,6 +140,17 @@ uint8_t sdbus_read_data(SDBus *sd); bool sdbus_data_ready(SDBus *sd); bool sdbus_get_inserted(SDBus *sd); bool sdbus_get_readonly(SDBus *sd); +/** + * sdbus_reparent_card: Reparent an SD card from one controller to another + * @from: controller bus to remove card from + * @to: controller bus to move card to + * + * Reparent an SD card, effectively unplugging it from one controller + * and inserting it into another. This is useful for SoCs like the + * bcm2835 which have two SD controllers and connect a single SD card + * to them, selected by the guest reprogramming GPIO line routing. + */ +void sdbus_reparent_card(SDBus *from, SDBus *to); =20 /* Functions to be used by SD devices to report back to qdevified controll= ers */ void sdbus_set_inserted(SDBus *sd, bool inserted); diff --git a/hw/sd/core.c b/hw/sd/core.c index 14c2bdf..a8f24f5 100644 --- a/hw/sd/core.c +++ b/hw/sd/core.c @@ -131,6 +131,36 @@ void sdbus_set_readonly(SDBus *sdbus, bool readonly) } } =20 +void sdbus_reparent_card(SDBus *from, SDBus *to) +{ + BusChild *kid =3D QTAILQ_FIRST(&from->qbus.children); + SDState *card; + SDCardClass *sc; + bool readonly; + + /* We directly reparent the card object rather than implementing this + * as a hotpluggable connection because we don't want to expose SD car= ds + * to users as being hotpluggable, and we can get away with it in this + * limited use case. This could perhaps be implemented more cleanly in + * future by adding support to the hotplug infrastructure for "device + * can be hotplugged only via code, not by user". + */ + + if (!kid) { + return; + } + + card =3D SD_CARD(kid->child); + sc =3D SD_CARD_GET_CLASS(card); + readonly =3D sc->get_readonly(card); + + sdbus_set_inserted(from, false); + object_unparent(OBJECT(kid)); + qdev_set_parent_bus(DEVICE(card), &to->qbus); + sdbus_set_inserted(to, true); + sdbus_set_readonly(to, readonly); +} + static const TypeInfo sd_bus_info =3D { .name =3D TYPE_SD_BUS, .parent =3D TYPE_BUS, --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488220174191809.072568839021; Mon, 27 Feb 2017 10:29:34 -0800 (PST) Received: from localhost ([::1]:55619 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQ3A-0006Uq-S1 for importer@patchew.org; Mon, 27 Feb 2017 13:29:32 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52211) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfj-0002Qk-RK for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPff-0001ve-Sg for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:19 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48681) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPff-0001uO-B2 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:15 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfe-0002SF-Fe for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:14 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:56 +0000 Message-Id: <1488218699-31035-28-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> 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 27/30] bcm2835_gpio: add bcm2835 gpio controller 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Clement Deschamps This adds the BCM2835 GPIO controller. It currently implements: - The 54 GPIOs as outputs (qemu_irq) - The SD controller selection via alternate function of GPIOs 48-53 Signed-off-by: Clement Deschamps Message-id: 20170224164021.9066-4-clement.deschamps@antfield.fr Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/gpio/Makefile.objs | 1 + include/hw/gpio/bcm2835_gpio.h | 39 +++++ hw/gpio/bcm2835_gpio.c | 353 +++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 393 insertions(+) create mode 100644 include/hw/gpio/bcm2835_gpio.h create mode 100644 hw/gpio/bcm2835_gpio.c diff --git a/hw/gpio/Makefile.objs b/hw/gpio/Makefile.objs index a43c7cf..fa0a72e 100644 --- a/hw/gpio/Makefile.objs +++ b/hw/gpio/Makefile.objs @@ -7,3 +7,4 @@ common-obj-$(CONFIG_GPIO_KEY) +=3D gpio_key.o =20 obj-$(CONFIG_OMAP) +=3D omap_gpio.o obj-$(CONFIG_IMX) +=3D imx_gpio.o +obj-$(CONFIG_RASPI) +=3D bcm2835_gpio.o diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h new file mode 100644 index 0000000..9f8e0c7 --- /dev/null +++ b/include/hw/gpio/bcm2835_gpio.h @@ -0,0 +1,39 @@ +/* + * Raspberry Pi (BCM2835) GPIO Controller + * + * Copyright (c) 2017 Antfield SAS + * + * Authors: + * Clement Deschamps + * Luc Michel + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#ifndef BCM2835_GPIO_H +#define BCM2835_GPIO_H + +#include "hw/sd/sd.h" + +typedef struct BCM2835GpioState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + + /* SDBus selector */ + SDBus sdbus; + SDBus *sdbus_sdhci; + SDBus *sdbus_sdhost; + + uint8_t fsel[54]; + uint32_t lev0, lev1; + uint8_t sd_fsel; + qemu_irq out[54]; +} BCM2835GpioState; + +#define TYPE_BCM2835_GPIO "bcm2835_gpio" +#define BCM2835_GPIO(obj) \ + OBJECT_CHECK(BCM2835GpioState, (obj), TYPE_BCM2835_GPIO) + +#endif diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c new file mode 100644 index 0000000..acc2e3c --- /dev/null +++ b/hw/gpio/bcm2835_gpio.c @@ -0,0 +1,353 @@ +/* + * Raspberry Pi (BCM2835) GPIO Controller + * + * Copyright (c) 2017 Antfield SAS + * + * Authors: + * Clement Deschamps + * Luc Michel + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/timer.h" +#include "qapi/error.h" +#include "hw/sysbus.h" +#include "hw/sd/sd.h" +#include "hw/gpio/bcm2835_gpio.h" + +#define GPFSEL0 0x00 +#define GPFSEL1 0x04 +#define GPFSEL2 0x08 +#define GPFSEL3 0x0C +#define GPFSEL4 0x10 +#define GPFSEL5 0x14 +#define GPSET0 0x1C +#define GPSET1 0x20 +#define GPCLR0 0x28 +#define GPCLR1 0x2C +#define GPLEV0 0x34 +#define GPLEV1 0x38 +#define GPEDS0 0x40 +#define GPEDS1 0x44 +#define GPREN0 0x4C +#define GPREN1 0x50 +#define GPFEN0 0x58 +#define GPFEN1 0x5C +#define GPHEN0 0x64 +#define GPHEN1 0x68 +#define GPLEN0 0x70 +#define GPLEN1 0x74 +#define GPAREN0 0x7C +#define GPAREN1 0x80 +#define GPAFEN0 0x88 +#define GPAFEN1 0x8C +#define GPPUD 0x94 +#define GPPUDCLK0 0x98 +#define GPPUDCLK1 0x9C + +static uint32_t gpfsel_get(BCM2835GpioState *s, uint8_t reg) +{ + int i; + uint32_t value =3D 0; + for (i =3D 0; i < 10; i++) { + uint32_t index =3D 10 * reg + i; + if (index < sizeof(s->fsel)) { + value |=3D (s->fsel[index] & 0x7) << (3 * i); + } + } + return value; +} + +static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, uint32_t value) +{ + int i; + for (i =3D 0; i < 10; i++) { + uint32_t index =3D 10 * reg + i; + if (index < sizeof(s->fsel)) { + int fsel =3D (value >> (3 * i)) & 0x7; + s->fsel[index] =3D fsel; + } + } + + /* SD controller selection (48-53) */ + if (s->sd_fsel !=3D 0 + && (s->fsel[48] =3D=3D 0) /* SD_CLK_R */ + && (s->fsel[49] =3D=3D 0) /* SD_CMD_R */ + && (s->fsel[50] =3D=3D 0) /* SD_DATA0_R */ + && (s->fsel[51] =3D=3D 0) /* SD_DATA1_R */ + && (s->fsel[52] =3D=3D 0) /* SD_DATA2_R */ + && (s->fsel[53] =3D=3D 0) /* SD_DATA3_R */ + ) { + /* SDHCI controller selected */ + sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci); + s->sd_fsel =3D 0; + } else if (s->sd_fsel !=3D 4 + && (s->fsel[48] =3D=3D 4) /* SD_CLK_R */ + && (s->fsel[49] =3D=3D 4) /* SD_CMD_R */ + && (s->fsel[50] =3D=3D 4) /* SD_DATA0_R */ + && (s->fsel[51] =3D=3D 4) /* SD_DATA1_R */ + && (s->fsel[52] =3D=3D 4) /* SD_DATA2_R */ + && (s->fsel[53] =3D=3D 4) /* SD_DATA3_R */ + ) { + /* SDHost controller selected */ + sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost); + s->sd_fsel =3D 4; + } +} + +static int gpfsel_is_out(BCM2835GpioState *s, int index) +{ + if (index >=3D 0 && index < 54) { + return s->fsel[index] =3D=3D 1; + } + return 0; +} + +static void gpset(BCM2835GpioState *s, + uint32_t val, uint8_t start, uint8_t count, uint32_t *lev) +{ + uint32_t changes =3D val & ~*lev; + uint32_t cur =3D 1; + + int i; + for (i =3D 0; i < count; i++) { + if ((changes & cur) && (gpfsel_is_out(s, start + i))) { + qemu_set_irq(s->out[start + i], 1); + } + cur <<=3D 1; + } + + *lev |=3D val; +} + +static void gpclr(BCM2835GpioState *s, + uint32_t val, uint8_t start, uint8_t count, uint32_t *lev) +{ + uint32_t changes =3D val & *lev; + uint32_t cur =3D 1; + + int i; + for (i =3D 0; i < count; i++) { + if ((changes & cur) && (gpfsel_is_out(s, start + i))) { + qemu_set_irq(s->out[start + i], 0); + } + cur <<=3D 1; + } + + *lev &=3D ~val; +} + +static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset, + unsigned size) +{ + BCM2835GpioState *s =3D (BCM2835GpioState *)opaque; + + switch (offset) { + case GPFSEL0: + case GPFSEL1: + case GPFSEL2: + case GPFSEL3: + case GPFSEL4: + case GPFSEL5: + return gpfsel_get(s, offset / 4); + case GPSET0: + case GPSET1: + /* Write Only */ + return 0; + case GPCLR0: + case GPCLR1: + /* Write Only */ + return 0; + case GPLEV0: + return s->lev0; + case GPLEV1: + return s->lev1; + case GPEDS0: + case GPEDS1: + case GPREN0: + case GPREN1: + case GPFEN0: + case GPFEN1: + case GPHEN0: + case GPHEN1: + case GPLEN0: + case GPLEN1: + case GPAREN0: + case GPAREN1: + case GPAFEN0: + case GPAFEN1: + case GPPUD: + case GPPUDCLK0: + case GPPUDCLK1: + /* Not implemented */ + return 0; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", + __func__, offset); + break; + } + + return 0; +} + +static void bcm2835_gpio_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + BCM2835GpioState *s =3D (BCM2835GpioState *)opaque; + + switch (offset) { + case GPFSEL0: + case GPFSEL1: + case GPFSEL2: + case GPFSEL3: + case GPFSEL4: + case GPFSEL5: + gpfsel_set(s, offset / 4, value); + break; + case GPSET0: + gpset(s, value, 0, 32, &s->lev0); + break; + case GPSET1: + gpset(s, value, 32, 22, &s->lev1); + break; + case GPCLR0: + gpclr(s, value, 0, 32, &s->lev0); + break; + case GPCLR1: + gpclr(s, value, 32, 22, &s->lev1); + break; + case GPLEV0: + case GPLEV1: + /* Read Only */ + break; + case GPEDS0: + case GPEDS1: + case GPREN0: + case GPREN1: + case GPFEN0: + case GPFEN1: + case GPHEN0: + case GPHEN1: + case GPLEN0: + case GPLEN1: + case GPAREN0: + case GPAREN1: + case GPAFEN0: + case GPAFEN1: + case GPPUD: + case GPPUDCLK0: + case GPPUDCLK1: + /* Not implemented */ + break; + default: + goto err_out; + } + return; + +err_out: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", + __func__, offset); +} + +static void bcm2835_gpio_reset(DeviceState *dev) +{ + BCM2835GpioState *s =3D BCM2835_GPIO(dev); + + int i; + for (i =3D 0; i < 6; i++) { + gpfsel_set(s, i, 0); + } + + s->sd_fsel =3D 0; + + /* SDHCI is selected by default */ + sdbus_reparent_card(&s->sdbus, s->sdbus_sdhci); + + s->lev0 =3D 0; + s->lev1 =3D 0; +} + +static const MemoryRegionOps bcm2835_gpio_ops =3D { + .read =3D bcm2835_gpio_read, + .write =3D bcm2835_gpio_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static const VMStateDescription vmstate_bcm2835_gpio =3D { + .name =3D "bcm2835_gpio", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54), + VMSTATE_UINT32(lev0, BCM2835GpioState), + VMSTATE_UINT32(lev1, BCM2835GpioState), + VMSTATE_UINT8(sd_fsel, BCM2835GpioState), + VMSTATE_END_OF_LIST() + } +}; + +static void bcm2835_gpio_init(Object *obj) +{ + BCM2835GpioState *s =3D BCM2835_GPIO(obj); + DeviceState *dev =3D DEVICE(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + + qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), + TYPE_SD_BUS, DEVICE(s), "sd-bus"); + + memory_region_init_io(&s->iomem, obj, + &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + qdev_init_gpio_out(dev, s->out, 54); +} + +static void bcm2835_gpio_realize(DeviceState *dev, Error **errp) +{ + BCM2835GpioState *s =3D BCM2835_GPIO(dev); + Object *obj; + Error *err =3D NULL; + + obj =3D object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err); + if (obj =3D=3D NULL) { + error_setg(errp, "%s: required sdhci link not found: %s", + __func__, error_get_pretty(err)); + return; + } + s->sdbus_sdhci =3D SD_BUS(obj); + + obj =3D object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err); + if (obj =3D=3D NULL) { + error_setg(errp, "%s: required sdhost link not found: %s", + __func__, error_get_pretty(err)); + return; + } + s->sdbus_sdhost =3D SD_BUS(obj); +} + +static void bcm2835_gpio_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->vmsd =3D &vmstate_bcm2835_gpio; + dc->realize =3D &bcm2835_gpio_realize; + dc->reset =3D &bcm2835_gpio_reset; +} + +static const TypeInfo bcm2835_gpio_info =3D { + .name =3D TYPE_BCM2835_GPIO, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(BCM2835GpioState), + .instance_init =3D bcm2835_gpio_init, + .class_init =3D bcm2835_gpio_class_init, +}; + +static void bcm2835_gpio_register_types(void) +{ + type_register_static(&bcm2835_gpio_info); +} + +type_init(bcm2835_gpio_register_types) --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488221126533394.1276974698069; Mon, 27 Feb 2017 10:45:26 -0800 (PST) Received: from localhost ([::1]:55717 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQIV-0003J4-Vd for importer@patchew.org; Mon, 27 Feb 2017 13:45:24 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52177) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfj-0002Q3-84 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfg-0001vs-8c for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:19 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48680) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPff-0001ss-Uw for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfe-0002Sc-VZ for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:14 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:57 +0000 Message-Id: <1488218699-31035-29-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> 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 28/30] bcm2835: add sdhost and gpio controllers 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Clement Deschamps This adds the bcm2835_sdhost and bcm2835_gpio to the BCM2835 platform. For supporting the SD controller selection (alternate function of GPIOs 48-53), the bcm2835_gpio now exposes an sdbus. It also has a link to both the sdbus of sdhci and sdhost controllers, and the card is reparented from one bus to another when the alternate function of GPIOs 48-53 is modified. Signed-off-by: Clement Deschamps Message-id: 20170224164021.9066-5-clement.deschamps@antfield.fr Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- include/hw/arm/bcm2835_peripherals.h | 4 ++++ hw/arm/bcm2835_peripherals.c | 43 ++++++++++++++++++++++++++++++++= ++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_= peripherals.h index 31241c7..122b286 100644 --- a/include/hw/arm/bcm2835_peripherals.h +++ b/include/hw/arm/bcm2835_peripherals.h @@ -22,6 +22,8 @@ #include "hw/misc/bcm2835_rng.h" #include "hw/misc/bcm2835_mbox.h" #include "hw/sd/sdhci.h" +#include "hw/sd/bcm2835_sdhost.h" +#include "hw/gpio/bcm2835_gpio.h" =20 #define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals" #define BCM2835_PERIPHERALS(obj) \ @@ -45,6 +47,8 @@ typedef struct BCM2835PeripheralState { BCM2835RngState rng; BCM2835MboxState mboxes; SDHCIState sdhci; + BCM2835SDHostState sdhost; + BCM2835GpioState gpio; } BCM2835PeripheralState; =20 #endif /* BCM2835_PERIPHERALS_H */ diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index 9ed22d5..369ef1e 100644 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -96,6 +96,11 @@ static void bcm2835_peripherals_init(Object *obj) object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL); qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default()); =20 + /* SDHOST */ + object_initialize(&s->sdhost, sizeof(s->sdhost), TYPE_BCM2835_SDHOST); + object_property_add_child(obj, "sdhost", OBJECT(&s->sdhost), NULL); + qdev_set_parent_bus(DEVICE(&s->sdhost), sysbus_get_default()); + /* DMA Channels */ object_initialize(&s->dma, sizeof(s->dma), TYPE_BCM2835_DMA); object_property_add_child(obj, "dma", OBJECT(&s->dma), NULL); @@ -103,6 +108,16 @@ static void bcm2835_peripherals_init(Object *obj) =20 object_property_add_const_link(OBJECT(&s->dma), "dma-mr", OBJECT(&s->gpu_bus_mr), &error_abort); + + /* GPIO */ + object_initialize(&s->gpio, sizeof(s->gpio), TYPE_BCM2835_GPIO); + object_property_add_child(obj, "gpio", OBJECT(&s->gpio), NULL); + qdev_set_parent_bus(DEVICE(&s->gpio), sysbus_get_default()); + + object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci", + OBJECT(&s->sdhci.sdbus), &error_abort); + object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost", + OBJECT(&s->sdhost.sdbus), &error_abort); } =20 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) @@ -267,13 +282,20 @@ static void bcm2835_peripherals_realize(DeviceState *= dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_ARASANSDIO)); - object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->sdhci), "sd-= bus", - &err); + + /* SDHOST */ + object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err); if (err) { error_propagate(errp, err); return; } =20 + memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0, + qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, + INTERRUPT_SDIO)); + /* DMA Channels */ object_property_set_bool(OBJECT(&s->dma), true, "realized", &err); if (err) { @@ -292,6 +314,23 @@ static void bcm2835_peripherals_realize(DeviceState *d= ev, Error **errp) BCM2835_IC_GPU_IRQ, INTERRUPT_DMA0 + n)); } + + /* GPIO */ + object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0)); + + object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-b= us", + &err); + if (err) { + error_propagate(errp, err); + return; + } } =20 static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data) --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488220925129631.2165313576181; Mon, 27 Feb 2017 10:42:05 -0800 (PST) Received: from localhost ([::1]:55704 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQFF-0000Oe-OS for importer@patchew.org; Mon, 27 Feb 2017 13:42:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52257) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfl-0002SF-3Z for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfg-0001wd-O7 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:21 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48681) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfg-0001uO-Aw for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:16 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPff-0002Sz-J5 for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:15 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:58 +0000 Message-Id: <1488218699-31035-30-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> 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 29/30] hw/arm/exynos: Fix Linux kernel division by zero for PLLs 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Krzysztof Kozlowski Without any clock controller, the Linux kernel was hitting division by zero during boot or with clk_summary: [ 0.000000] [] (unwind_backtrace) from [] (show_stac= k+0x10/0x14) [ 0.000000] [] (show_stack) from [] (dump_stack+0x88= /0x9c) [ 0.000000] [] (dump_stack) from [] (Ldiv0+0x8/0x10) [ 0.000000] [] (Ldiv0) from [] (samsung_pll45xx_reca= lc_rate+0x58/0x74) [ 0.000000] [] (samsung_pll45xx_recalc_rate) from []= (clk_register+0x39c/0x63c) [ 0.000000] [] (clk_register) from [] (samsung_clk_r= egister_pll+0x2e0/0x3d4) [ 0.000000] [] (samsung_clk_register_pll) from [] (e= xynos4_clk_init+0x1b0/0x5e4) [ 0.000000] [] (exynos4_clk_init) from [] (of_clk_in= it+0x17c/0x210) [ 0.000000] [] (of_clk_init) from [] (time_init+0x24= /0x2c) [ 0.000000] [] (time_init) from [] (start_kernel+0x2= 4c/0x38c) [ 0.000000] [] (start_kernel) from [<4020807c>] (0x4020807c) Provide stub for clock controller returning reset values for PLLs. Signed-off-by: Krzysztof Kozlowski Message-id: 20170226200142.31169-1-krzk@kernel.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/misc/Makefile.objs | 2 +- hw/arm/exynos4210.c | 6 ++ hw/misc/exynos4210_clk.c | 164 +++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 hw/misc/exynos4210_clk.c diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 57a4406..c8b4893 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -26,7 +26,7 @@ obj-$(CONFIG_IVSHMEM) +=3D ivshmem.o obj-$(CONFIG_REALVIEW) +=3D arm_sysctl.o obj-$(CONFIG_NSERIES) +=3D cbus.o obj-$(CONFIG_ECCMEMCTL) +=3D eccmemctl.o -obj-$(CONFIG_EXYNOS4) +=3D exynos4210_pmu.o +obj-$(CONFIG_EXYNOS4) +=3D exynos4210_pmu.o exynos4210_clk.o obj-$(CONFIG_IMX) +=3D imx_ccm.o obj-$(CONFIG_IMX) +=3D imx31_ccm.o obj-$(CONFIG_IMX) +=3D imx25_ccm.o diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index be3c96d..a0ecbe8 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" +#include "qemu/log.h" #include "cpu.h" #include "hw/boards.h" #include "sysemu/sysemu.h" @@ -74,6 +75,9 @@ /* PMU SFR base address */ #define EXYNOS4210_PMU_BASE_ADDR 0x10020000 =20 +/* Clock controller SFR base address */ +#define EXYNOS4210_CLK_BASE_ADDR 0x10030000 + /* Display controllers (FIMD) */ #define EXYNOS4210_FIMD0_BASE_ADDR 0x11C00000 =20 @@ -297,6 +301,8 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_m= em, */ sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL); =20 + sysbus_create_simple("exynos4210.clk", EXYNOS4210_CLK_BASE_ADDR, NULL); + /* PWM */ sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR, s->irq_table[exynos4210_get_irq(22, 0)], diff --git a/hw/misc/exynos4210_clk.c b/hw/misc/exynos4210_clk.c new file mode 100644 index 0000000..81862c0 --- /dev/null +++ b/hw/misc/exynos4210_clk.c @@ -0,0 +1,164 @@ +/* + * Exynos4210 Clock Controller Emulation + * + * Copyright (c) 2017 Krzysztof Kozlowski + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WI= THOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "qemu/log.h" + +#define TYPE_EXYNOS4210_CLK "exynos4210.clk" +#define EXYNOS4210_CLK(obj) \ + OBJECT_CHECK(Exynos4210ClkState, (obj), TYPE_EXYNOS4210_CLK) + +#define CLK_PLL_LOCKED BIT(29) + +#define EXYNOS4210_CLK_REGS_MEM_SIZE 0x15104 + +typedef struct Exynos4210Reg { + const char *name; /* for debug only */ + uint32_t offset; + uint32_t reset_value; +} Exynos4210Reg; + +/* Clock controller register base: 0x10030000 */ +static const Exynos4210Reg exynos4210_clk_regs[] =3D { + {"EPLL_LOCK", 0xc010, 0x00000fff}, + {"VPLL_LOCK", 0xc020, 0x00000fff}, + {"EPLL_CON0", 0xc110, 0x00300301 | CLK_PLL_LOCKED}, + {"EPLL_CON1", 0xc114, 0x00000000}, + {"VPLL_CON0", 0xc120, 0x00240201 | CLK_PLL_LOCKED}, + {"VPLL_CON1", 0xc124, 0x66010464}, + {"APLL_LOCK", 0x14000, 0x00000fff}, + {"MPLL_LOCK", 0x14004, 0x00000fff}, + {"APLL_CON0", 0x14100, 0x00c80601 | CLK_PLL_LOCKED}, + {"APLL_CON1", 0x14104, 0x0000001c}, + {"MPLL_CON0", 0x14108, 0x00c80601 | CLK_PLL_LOCKED}, + {"MPLL_CON1", 0x1410c, 0x0000001c}, +}; + +#define EXYNOS4210_REGS_NUM ARRAY_SIZE(exynos4210_clk_regs) + +typedef struct Exynos4210ClkState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + uint32_t reg[EXYNOS4210_REGS_NUM]; +} Exynos4210ClkState; + +static uint64_t exynos4210_clk_read(void *opaque, hwaddr offset, + unsigned size) +{ + const Exynos4210ClkState *s =3D (Exynos4210ClkState *)opaque; + const Exynos4210Reg *regs =3D exynos4210_clk_regs; + unsigned int i; + + for (i =3D 0; i < EXYNOS4210_REGS_NUM; i++) { + if (regs->offset =3D=3D offset) { + return s->reg[i]; + } + regs++; + } + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read offset 0x%04x\n", + __func__, (uint32_t)offset); + return 0; +} + +static void exynos4210_clk_write(void *opaque, hwaddr offset, + uint64_t val, unsigned size) +{ + Exynos4210ClkState *s =3D (Exynos4210ClkState *)opaque; + const Exynos4210Reg *regs =3D exynos4210_clk_regs; + unsigned int i; + + for (i =3D 0; i < EXYNOS4210_REGS_NUM; i++) { + if (regs->offset =3D=3D offset) { + s->reg[i] =3D val; + return; + } + regs++; + } + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write offset 0x%04x\n", + __func__, (uint32_t)offset); +} + +static const MemoryRegionOps exynos4210_clk_ops =3D { + .read =3D exynos4210_clk_read, + .write =3D exynos4210_clk_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + .unaligned =3D false + } +}; + +static void exynos4210_clk_reset(DeviceState *dev) +{ + Exynos4210ClkState *s =3D EXYNOS4210_CLK(dev); + unsigned int i; + + /* Set default values for registers */ + for (i =3D 0; i < EXYNOS4210_REGS_NUM; i++) { + s->reg[i] =3D exynos4210_clk_regs[i].reset_value; + } +} + +static void exynos4210_clk_init(Object *obj) +{ + Exynos4210ClkState *s =3D EXYNOS4210_CLK(obj); + SysBusDevice *dev =3D SYS_BUS_DEVICE(obj); + + /* memory mapping */ + memory_region_init_io(&s->iomem, obj, &exynos4210_clk_ops, s, + TYPE_EXYNOS4210_CLK, EXYNOS4210_CLK_REGS_MEM_SIZ= E); + sysbus_init_mmio(dev, &s->iomem); +} + +static const VMStateDescription exynos4210_clk_vmstate =3D { + .name =3D TYPE_EXYNOS4210_CLK, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32_ARRAY(reg, Exynos4210ClkState, EXYNOS4210_REGS_NUM), + VMSTATE_END_OF_LIST() + } +}; + +static void exynos4210_clk_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->reset =3D exynos4210_clk_reset; + dc->vmsd =3D &exynos4210_clk_vmstate; +} + +static const TypeInfo exynos4210_clk_info =3D { + .name =3D TYPE_EXYNOS4210_CLK, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(Exynos4210ClkState), + .instance_init =3D exynos4210_clk_init, + .class_init =3D exynos4210_clk_class_init, +}; + +static void exynos4210_clk_register(void) +{ + qemu_log_mask(LOG_GUEST_ERROR, "Clock init\n"); + type_register_static(&exynos4210_clk_info); +} + +type_init(exynos4210_clk_register) --=20 2.7.4 From nobody Tue Apr 15 15:24:57 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 1488220737844869.6673742982457; Mon, 27 Feb 2017 10:38:57 -0800 (PST) Received: from localhost ([::1]:55684 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciQCF-00063R-LS for importer@patchew.org; Mon, 27 Feb 2017 13:38:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52224) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ciPfk-0002RN-7X for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ciPfh-0001xB-EL for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:20 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:48682) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ciPfh-0001wE-4Z for qemu-devel@nongnu.org; Mon, 27 Feb 2017 13:05:17 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1ciPfg-0002Tc-7A for qemu-devel@nongnu.org; Mon, 27 Feb 2017 18:05:16 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 27 Feb 2017 18:04:59 +0000 Message-Id: <1488218699-31035-31-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> 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 30/30] hw/arm/exynos: Fix proper mapping of CPUs by providing real cluster ID 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 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Krzysztof Kozlowski The Exynos4210 has cluster ID 0x9 in its MPIDR register (raw value 0x8000090x). If this cluster ID is not provided, then Linux kernel cannot map DeviceTree nodes to MPIDR values resulting in kernel warning and lack of any secondary CPUs: DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map ... smp: Bringing up secondary CPUs ... smp: Brought up 1 node, 1 CPU SMP: Total of 1 processors activated (24.00 BogoMIPS). Provide a cluster ID so Linux will see proper MPIDR and will try to bring the secondary CPU online. Signed-off-by: Krzysztof Kozlowski Message-id: 20170226200142.31169-2-krzk@kernel.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/exynos4210.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index a0ecbe8..1d2b50c 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -142,6 +142,16 @@ void exynos4210_write_secondary(ARMCPU *cpu, info->smp_loader_start); } =20 +static uint64_t exynos4210_calc_affinity(int cpu) +{ + uint64_t mp_affinity; + + /* Exynos4210 has 0x9 as cluster ID */ + mp_affinity =3D (0x9 << ARM_AFF1_SHIFT) | cpu; + + return mp_affinity; +} + Exynos4210State *exynos4210_init(MemoryRegion *system_mem, unsigned long ram_size) { @@ -167,6 +177,8 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_m= em, } =20 s->cpu[n] =3D ARM_CPU(cpuobj); + object_property_set_int(cpuobj, exynos4210_calc_affinity(n), + "mp-affinity", &error_abort); object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR, "reset-cbar", &error_abort); object_property_set_bool(cpuobj, true, "realized", &error_fatal); --=20 2.7.4