qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/47] target-arm queue
@ 2019-02-01 16:06 Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 01/47] hw/arm/nrf51_soc: set object owner in memory_region_init_ram Peter Maydell
                   ` (48 more replies)
  0 siblings, 49 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

As promised, more Arm patches. The big thing in here is the
MPS2-AN521 board model.

thanks
-- PMM

The following changes since commit cfe6c547690b06fbce54a6d0f7b05dd7f18e36ea:

  Merge remote-tracking branch 'remotes/xanclic/tags/pull-block-2019-01-31' into staging (2019-01-31 19:26:09 +0000)

are available in the Git repository at:

  https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190201

for you to fetch changes up to 7743b70ffe7a8ce168adce2cf50ad156b1fefb8c:

  tests/microbit-test: Add tests for nRF51 NVMC (2019-02-01 15:32:17 +0000)

----------------------------------------------------------------
target-arm queue:
 * New machine mps2-an521 -- this is a model of the AN521 FPGA image for the MPS2 devboard
 * Fix various places where we failed to UNDEF invalid A64 instructions
 * Don't UNDEF a valid FCMLA on 32-bit inputs
 * Fix some bugs in the newly-added PAuth implementation
 * microbit: Implement NVMC non-volatile memory controller

----------------------------------------------------------------
Aaron Lindsay OS (2):
      target/arm: Send interrupts on PMU counter overflow
      target/arm: Add a timer to predict PMU counter overflow

Julia Suvorova (1):
      arm: Clarify the logic of set_pc()

Peter Maydell (33):
      armv7m: Don't assume the NVIC's CPU is CPU 0
      armv7m: Make cpu object a child of the armv7m container
      armv7m: Pass through start-powered-off CPU property
      hw/arm/iotkit: Rename IoTKit to ARMSSE
      hw/arm/iotkit: Refactor into abstract base class and subclass
      hw/arm/iotkit: Rename 'iotkit' local variables and functions
      hw/arm/iotkit: Rename files to hw/arm/armsse.[ch]
      hw/misc/iotkit-secctl: Support 4 internal MPCs
      hw/arm/armsse: Make number of SRAM banks parameterised
      hw/arm/armsse: Make SRAM bank size configurable
      hw/arm/armsse: Support dual-CPU configuration
      hw/arm/armsse: Give each CPU its own view of memory
      hw/arm/armsse: Put each CPU in its own cluster object
      iotkit-sysinfo: Make SYS_VERSION and SYS_CONFIG configurable
      hw/arm/armsse: Add unimplemented-device stubs for MHUs
      hw/arm/armsse: Add unimplemented-device stubs for PPUs
      hw/arm/armsse: Add unimplemented-device stub for cache control registers
      hw/arm/armsse: Add unimplemented-device stub for CPU local control registers
      hw/misc/armsse-cpuid: Implement SSE-200 CPU_IDENTITY register block
      hw/arm/armsse: Add CPU_IDENTITY block to SSE-200
      hw/arm/armsse: Add SSE-200 model
      hw/arm/mps2-tz: Add IRQ infrastructure to support SSE-200
      hw/arm/mps2-tz: Add mps2-an521 model
      target/arm/translate-a64: Don't underdecode system instructions
      target/arm/translate-a64: Don't underdecode PRFM
      target/arm/translate-a64: Don't underdecode SIMD ld/st multiple
      target/arm/translate-a64: Don't underdecode SIMD ld/st single
      target/arm/translate-a64: Don't underdecode add/sub extended register
      target/arm/translate-a64: Don't underdecode FP insns
      target/arm/translate-a64: Don't underdecode SDOT and UDOT
      exec.c: Don't reallocate IOMMUNotifiers that are in use
      target/arm/translate-a64: Fix FCMLA decoding error
      target/arm/translate-a64: Fix mishandling of size in FCMLA decode

Remi Denis-Courmont (2):
      target/arm: fix AArch64 virtual address space size
      target/arm: fix decoding of B{,L}RA{A,B}

Richard Henderson (5):
      target/arm: Enable API, APK bits in SCR, HCR
      target/arm: Always enable pac keys for user-only
      aarch64-linux-user: Update HWCAP bits from linux 5.0-rc1
      aarch64-linux-user: Enable HWCAP bits for PAuth
      linux-user: Initialize aarch64 pac keys

Steffen Görtz (3):
      hw/nvram/nrf51_nvm: Add nRF51 non-volatile memories
      arm: Instantiate NRF51 special NVM's and NVMC
      tests/microbit-test: Add tests for nRF51 NVMC

kumar sourav (1):
      hw/arm/nrf51_soc: set object owner in memory_region_init_ram

 hw/arm/Makefile.objs                  |    2 +-
 hw/misc/Makefile.objs                 |    1 +
 hw/nvram/Makefile.objs                |    1 +
 include/hw/arm/{iotkit.h => armsse.h} |  113 ++-
 include/hw/arm/armv7m.h               |    1 +
 include/hw/arm/nrf51_soc.h            |    2 +
 include/hw/misc/armsse-cpuid.h        |   41 ++
 include/hw/misc/iotkit-secctl.h       |    6 +-
 include/hw/misc/iotkit-sysinfo.h      |    6 +
 include/hw/nvram/nrf51_nvm.h          |   64 ++
 include/qom/cpu.h                     |   16 +-
 linux-user/aarch64/target_syscall.h   |    2 +
 target/arm/cpu.h                      |   12 +-
 exec.c                                |   10 +-
 hw/arm/armsse.c                       | 1241 +++++++++++++++++++++++++++++++++
 hw/arm/armv7m.c                       |   23 +-
 hw/arm/boot.c                         |    4 -
 hw/arm/iotkit.c                       |  759 --------------------
 hw/arm/mps2-tz.c                      |  121 +++-
 hw/arm/nrf51_soc.c                    |   44 +-
 hw/intc/armv7m_nvic.c                 |    3 +-
 hw/misc/armsse-cpuid.c                |  134 ++++
 hw/misc/iotkit-secctl.c               |    5 +-
 hw/misc/iotkit-sysinfo.c              |   15 +-
 hw/nvram/nrf51_nvm.c                  |  388 +++++++++++
 linux-user/aarch64/cpu_loop.c         |   31 +-
 linux-user/elfload.c                  |   10 +
 target/arm/arm-powerctl.c             |    3 -
 target/arm/cpu.c                      |   41 +-
 target/arm/cpu64.c                    |   75 --
 target/arm/helper.c                   |  139 +++-
 target/arm/translate-a64.c            |   59 +-
 tests/microbit-test.c                 |  108 +++
 MAINTAINERS                           |    6 +-
 default-configs/arm-softmmu.mak       |    3 +-
 hw/misc/trace-events                  |    4 +
 36 files changed, 2552 insertions(+), 941 deletions(-)
 rename include/hw/arm/{iotkit.h => armsse.h} (53%)
 create mode 100644 include/hw/misc/armsse-cpuid.h
 create mode 100644 include/hw/nvram/nrf51_nvm.h
 create mode 100644 hw/arm/armsse.c
 delete mode 100644 hw/arm/iotkit.c
 create mode 100644 hw/misc/armsse-cpuid.c
 create mode 100644 hw/nvram/nrf51_nvm.c

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 01/47] hw/arm/nrf51_soc: set object owner in memory_region_init_ram
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 02/47] armv7m: Don't assume the NVIC's CPU is CPU 0 Peter Maydell
                   ` (47 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: kumar sourav <sourav.jb1988@gmail.com>

set object owner in memory_region_init_ram() instead
of NULL.

Signed-off-by: kumar sourav <sourav.jb1988@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20190125155630.17430-1-sourav.jb1988@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm/nrf51_soc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index 1630c275940..3a1c7e200cc 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -89,7 +89,8 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
     }
     memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
 
-    memory_region_init_ram(&s->sram, NULL, "nrf51.sram", s->sram_size, &err);
+    memory_region_init_ram(&s->sram, OBJECT(s), "nrf51.sram", s->sram_size,
+                           &err);
     if (err) {
         error_propagate(errp, err);
         return;
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 02/47] armv7m: Don't assume the NVIC's CPU is CPU 0
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 01/47] hw/arm/nrf51_soc: set object owner in memory_region_init_ram Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 03/47] armv7m: Make cpu object a child of the armv7m container Peter Maydell
                   ` (46 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Currently the ARMv7M NVIC object's realize method assumes that the
CPU the NVIC is attached to is CPU 0, because it thinks there can
only ever be one CPU in the system. To allow a dual-Cortex-M33
setup we need to remove this assumption; instead the armv7m
wrapper object tells the NVIC its CPU, in the same way that it
already tells the CPU what the NVIC is.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-2-peter.maydell@linaro.org
---
 hw/arm/armv7m.c       | 6 ++++--
 hw/intc/armv7m_nvic.c | 3 +--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index f4446528307..f9aa83d20ef 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -178,10 +178,12 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
         }
     }
 
-    /* Tell the CPU where the NVIC is; it will fail realize if it doesn't
-     * have one.
+    /*
+     * Tell the CPU where the NVIC is; it will fail realize if it doesn't
+     * have one. Similarly, tell the NVIC where its CPU is.
      */
     s->cpu->env.nvic = &s->nvic;
+    s->nvic.cpu = s->cpu;
 
     object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
     if (err != NULL) {
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 0beefb05d44..790a3d95849 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -2274,8 +2274,7 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
     Error *err = NULL;
     int regionlen;
 
-    s->cpu = ARM_CPU(qemu_get_cpu(0));
-
+    /* The armv7m container object will have set our CPU pointer */
     if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
         error_setg(errp, "The NVIC can only be used with a Cortex-M CPU");
         return;
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 03/47] armv7m: Make cpu object a child of the armv7m container
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 01/47] hw/arm/nrf51_soc: set object owner in memory_region_init_ram Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 02/47] armv7m: Don't assume the NVIC's CPU is CPU 0 Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 04/47] armv7m: Pass through start-powered-off CPU property Peter Maydell
                   ` (45 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Rather than just creating the CPUs with object_new, make them child
objects of the armv7m container. This will allow the cluster code to
find the CPUs if an armv7m object is made a child of a cluster object.
object_new_with_props() will do the parenting for us.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-3-peter.maydell@linaro.org
---
 hw/arm/armv7m.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index f9aa83d20ef..0f2c8e066cf 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -158,7 +158,12 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
 
     memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
 
-    s->cpu = ARM_CPU(object_new(s->cpu_type));
+    s->cpu = ARM_CPU(object_new_with_props(s->cpu_type, OBJECT(s), "cpu",
+                                           &err, NULL));
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
 
     object_property_set_link(OBJECT(s->cpu), OBJECT(&s->container), "memory",
                              &error_abort);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 04/47] armv7m: Pass through start-powered-off CPU property
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (2 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 03/47] armv7m: Make cpu object a child of the armv7m container Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 05/47] hw/arm/iotkit: Rename IoTKit to ARMSSE Peter Maydell
                   ` (44 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Expose "start-powered-off" as a property of the ARMv7M container,
which we just pass through to the CPU object in the same way that we
do for "init-svtor" and "idau". (We want this for the SSE-200, which
powers up only the first CPU at reset and leaves the second powered
down.)

As with the other CPU properties here, we can't just use alias
properties, because the CPU QOM object is not created until armv7m
realize time.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-4-peter.maydell@linaro.org
---
 include/hw/arm/armv7m.h |  1 +
 hw/arm/armv7m.c         | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
index 2ba24953b63..e96a98f8093 100644
--- a/include/hw/arm/armv7m.h
+++ b/include/hw/arm/armv7m.h
@@ -65,6 +65,7 @@ typedef struct ARMv7MState {
     Object *idau;
     uint32_t init_svtor;
     bool enable_bitband;
+    bool start_powered_off;
 } ARMv7MState;
 
 #endif
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 0f2c8e066cf..adae11e76ed 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -182,6 +182,14 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
             return;
         }
     }
+    if (object_property_find(OBJECT(s->cpu), "start-powered-off", NULL)) {
+        object_property_set_bool(OBJECT(s->cpu), s->start_powered_off,
+                                 "start-powered-off", &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+    }
 
     /*
      * Tell the CPU where the NVIC is; it will fail realize if it doesn't
@@ -250,6 +258,8 @@ static Property armv7m_properties[] = {
     DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
     DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
     DEFINE_PROP_BOOL("enable-bitband", ARMv7MState, enable_bitband, false),
+    DEFINE_PROP_BOOL("start-powered-off", ARMv7MState, start_powered_off,
+                     false),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 05/47] hw/arm/iotkit: Rename IoTKit to ARMSSE
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (3 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 04/47] armv7m: Pass through start-powered-off CPU property Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 06/47] hw/arm/iotkit: Refactor into abstract base class and subclass Peter Maydell
                   ` (43 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The Arm IoTKit was effectively the forerunner of a series of
subsystems for embedded SoCs, named the SSE-050, SSE-100 and SSE-200:
https://developer.arm.com/products/system-design/subsystems
These are generally quite similar, though later iterations have
extra devices that earlier ones do not.

We want to add a model of the SSE-200, which means refactoring the
IoTKit code into an abstract base class and subclasses (using the
same design that the bcm283x SoC and Aspeed SoC family
implementations do). As a first step, rename the IoTKit struct and
QOM macros to ARMSSE, which is what we're going to name the base
class. We temporarily retain TYPE_IOTKIT to avoid changing the
code that instantiates a TYPE_IOTKIT device here and then changing
it back again when it is re-introduced as a subclass.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-5-peter.maydell@linaro.org
---
 include/hw/arm/iotkit.h | 22 ++++++++++-----
 hw/arm/iotkit.c         | 59 +++++++++++++++++++++--------------------
 hw/arm/mps2-tz.c        |  2 +-
 3 files changed, 47 insertions(+), 36 deletions(-)

diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
index 3a8ee639085..9701738ec75 100644
--- a/include/hw/arm/iotkit.h
+++ b/include/hw/arm/iotkit.h
@@ -1,5 +1,5 @@
 /*
- * ARM IoT Kit
+ * ARM SSE (Subsystems for Embedded): IoTKit
  *
  * Copyright (c) 2018 Linaro Limited
  * Written by Peter Maydell
@@ -9,7 +9,10 @@
  * (at your option) any later version.
  */
 
-/* This is a model of the Arm IoT Kit which is documented in
+/*
+ * This is a model of the Arm "Subsystems for Embedded" family of
+ * hardware, which include the IoT Kit and the SSE-050, SSE-100 and
+ * SSE-200. Currently we model only the Arm IoT Kit which is documented in
  * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
  * It contains:
  *  a Cortex-M33
@@ -71,8 +74,15 @@
 #include "hw/or-irq.h"
 #include "hw/core/split-irq.h"
 
-#define TYPE_IOTKIT "iotkit"
-#define IOTKIT(obj) OBJECT_CHECK(IoTKit, (obj), TYPE_IOTKIT)
+#define TYPE_ARMSSE "iotkit"
+#define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
+
+/*
+ * For the moment TYPE_IOTKIT is a synonym for TYPE_ARMSSE (and the
+ * latter's underlying name is left as "iotkit"); in a later
+ * commit it will become a subclass of TYPE_ARMSSE.
+ */
+#define TYPE_IOTKIT TYPE_ARMSSE
 
 /* We have an IRQ splitter and an OR gate input for each external PPC
  * and the 2 internal PPCs
@@ -80,7 +90,7 @@
 #define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
 #define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
 
-typedef struct IoTKit {
+typedef struct ARMSSE {
     /*< private >*/
     SysBusDevice parent_obj;
 
@@ -131,6 +141,6 @@ typedef struct IoTKit {
     MemoryRegion *board_memory;
     uint32_t exp_numirq;
     uint32_t mainclk_frq;
-} IoTKit;
+} ARMSSE;
 
 #endif
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
index 8742200fb42..9360053184e 100644
--- a/hw/arm/iotkit.c
+++ b/hw/arm/iotkit.c
@@ -1,5 +1,5 @@
 /*
- * Arm IoT Kit
+ * Arm SSE (Subsystems for Embedded): IoTKit
  *
  * Copyright (c) 2018 Linaro Limited
  * Written by Peter Maydell
@@ -24,7 +24,7 @@
 /* Create an alias region of @size bytes starting at @base
  * which mirrors the memory starting at @orig.
  */
-static void make_alias(IoTKit *s, MemoryRegion *mr, const char *name,
+static void make_alias(ARMSSE *s, MemoryRegion *mr, const char *name,
                        hwaddr base, hwaddr size, hwaddr orig)
 {
     memory_region_init_alias(mr, NULL, name, &s->container, orig, size);
@@ -41,18 +41,18 @@ static void irq_status_forwarder(void *opaque, int n, int level)
 
 static void nsccfg_handler(void *opaque, int n, int level)
 {
-    IoTKit *s = IOTKIT(opaque);
+    ARMSSE *s = ARMSSE(opaque);
 
     s->nsccfg = level;
 }
 
-static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
+static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
 {
     /* Each of the 4 AHB and 4 APB PPCs that might be present in a
-     * system using the IoTKit has a collection of control lines which
+     * system using the ARMSSE has a collection of control lines which
      * are provided by the security controller and which we want to
-     * expose as control lines on the IoTKit device itself, so the
-     * code using the IoTKit can wire them up to the PPCs.
+     * expose as control lines on the ARMSSE device itself, so the
+     * code using the ARMSSE can wire them up to the PPCs.
      */
     SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
     DeviceState *iotkitdev = DEVICE(s);
@@ -91,7 +91,7 @@ static void iotkit_forward_ppc(IoTKit *s, const char *ppcname, int ppcnum)
     g_free(name);
 }
 
-static void iotkit_forward_sec_resp_cfg(IoTKit *s)
+static void iotkit_forward_sec_resp_cfg(ARMSSE *s)
 {
     /* Forward the 3rd output from the splitter device as a
      * named GPIO output of the iotkit object.
@@ -107,7 +107,7 @@ static void iotkit_forward_sec_resp_cfg(IoTKit *s)
 
 static void iotkit_init(Object *obj)
 {
-    IoTKit *s = IOTKIT(obj);
+    ARMSSE *s = ARMSSE(obj);
     int i;
 
     memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
@@ -175,20 +175,20 @@ static void iotkit_init(Object *obj)
 
 static void iotkit_exp_irq(void *opaque, int n, int level)
 {
-    IoTKit *s = IOTKIT(opaque);
+    ARMSSE *s = ARMSSE(opaque);
 
     qemu_set_irq(s->exp_irqs[n], level);
 }
 
 static void iotkit_mpcexp_status(void *opaque, int n, int level)
 {
-    IoTKit *s = IOTKIT(opaque);
+    ARMSSE *s = ARMSSE(opaque);
     qemu_set_irq(s->mpcexp_status_in[n], level);
 }
 
 static void iotkit_realize(DeviceState *dev, Error **errp)
 {
-    IoTKit *s = IOTKIT(dev);
+    ARMSSE *s = ARMSSE(dev);
     int i;
     MemoryRegion *mr;
     Error *err = NULL;
@@ -215,9 +215,9 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
      * devices exist in both address spaces but with hard-wired security
      * permissions that will cause the CPU to fault for non-secure accesses.
      *
-     * The IoTKit has an IDAU (Implementation Defined Access Unit),
+     * The ARMSSE has an IDAU (Implementation Defined Access Unit),
      * which specifies hard-wired security permissions for different
-     * areas of the physical address space. For the IoTKit IDAU, the
+     * areas of the physical address space. For the ARMSSE IDAU, the
      * top 4 bits of the physical address are the IDAU region ID, and
      * if bit 28 (ie the lowest bit of the ID) is 0 then this is an NS
      * region, otherwise it is an S region.
@@ -239,7 +239,7 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
      * 0x20000000..0x2007ffff  32KB FPGA block RAM
      * 0x30000000..0x3fffffff  alias of 0x20000000..0x2fffffff
      * 0x40000000..0x4000ffff  base peripheral region 1
-     * 0x40010000..0x4001ffff  CPU peripherals (none for IoTKit)
+     * 0x40010000..0x4001ffff  CPU peripherals (none for ARMSSE)
      * 0x40020000..0x4002ffff  system control element peripherals
      * 0x40080000..0x400fffff  base peripheral region 2
      * 0x50000000..0x5fffffff  alias of 0x40000000..0x4fffffff
@@ -306,8 +306,8 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
     qdev_connect_gpio_out_named(dev_secctl, "nsc_cfg", 0, s->nsc_cfg_in);
 
     /* The sec_resp_cfg output from the security controller must be split into
-     * multiple lines, one for each of the PPCs within the IoTKit and one
-     * that will be an output from the IoTKit to the system.
+     * multiple lines, one for each of the PPCs within the ARMSSE and one
+     * that will be an output from the ARMSSE to the system.
      */
     object_property_set_int(OBJECT(&s->sec_resp_splitter), 3,
                             "num-lines", &err);
@@ -475,7 +475,7 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
 
     /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
 
-    /* 0x40020000 .. 0x4002ffff : IoTKit system control peripheral region */
+    /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
     /* Devices behind APB PPC1:
      *   0x4002f000: S32K timer
      */
@@ -558,7 +558,7 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
                        qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
 
-    /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */
+    /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
 
     qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk_frq);
     object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &err);
@@ -678,7 +678,7 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
      * Expose our container region to the board model; this corresponds
      * to the AHB Slave Expansion ports which allow bus master devices
      * (eg DMA controllers) in the board model to make transactions into
-     * devices in the IoTKit.
+     * devices in the ARMSSE.
      */
     sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
 
@@ -688,11 +688,12 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
 static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
                               int *iregion, bool *exempt, bool *ns, bool *nsc)
 {
-    /* For IoTKit systems the IDAU responses are simple logical functions
+    /*
+     * For ARMSSE systems the IDAU responses are simple logical functions
      * of the address bits. The NSC attribute is guest-adjustable via the
      * NSCCFG register in the security controller.
      */
-    IoTKit *s = IOTKIT(ii);
+    ARMSSE *s = ARMSSE(ii);
     int region = extract32(address, 28, 4);
 
     *ns = !(region & 1);
@@ -707,22 +708,22 @@ static const VMStateDescription iotkit_vmstate = {
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32(nsccfg, IoTKit),
+        VMSTATE_UINT32(nsccfg, ARMSSE),
         VMSTATE_END_OF_LIST()
     }
 };
 
 static Property iotkit_properties[] = {
-    DEFINE_PROP_LINK("memory", IoTKit, board_memory, TYPE_MEMORY_REGION,
+    DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
                      MemoryRegion *),
-    DEFINE_PROP_UINT32("EXP_NUMIRQ", IoTKit, exp_numirq, 64),
-    DEFINE_PROP_UINT32("MAINCLK", IoTKit, mainclk_frq, 0),
+    DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
+    DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
     DEFINE_PROP_END_OF_LIST()
 };
 
 static void iotkit_reset(DeviceState *dev)
 {
-    IoTKit *s = IOTKIT(dev);
+    ARMSSE *s = ARMSSE(dev);
 
     s->nsccfg = 0;
 }
@@ -740,9 +741,9 @@ static void iotkit_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo iotkit_info = {
-    .name = TYPE_IOTKIT,
+    .name = TYPE_ARMSSE,
     .parent = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(IoTKit),
+    .instance_size = sizeof(ARMSSE),
     .instance_init = iotkit_init,
     .class_init = iotkit_class_init,
     .interfaces = (InterfaceInfo[]) {
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 82b1d020a58..5824335b4fb 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -66,7 +66,7 @@ typedef struct {
 typedef struct {
     MachineState parent;
 
-    IoTKit iotkit;
+    ARMSSE iotkit;
     MemoryRegion psram;
     MemoryRegion ssram[3];
     MemoryRegion ssram1_m;
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 06/47] hw/arm/iotkit: Refactor into abstract base class and subclass
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (4 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 05/47] hw/arm/iotkit: Rename IoTKit to ARMSSE Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 07/47] hw/arm/iotkit: Rename 'iotkit' local variables and functions Peter Maydell
                   ` (42 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The Arm SSE-200 Subsystem for Embedded is a revised and
extended version of the older IoTKit SoC. Prepare for
adding a model of it by refactoring the IoTKit code into
an abstract base class which contains the functionality,
driven by a class data block specific to each subclass.
(This is the same approach used by the existing bcm283x
SoC family implementation.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-6-peter.maydell@linaro.org
---
 include/hw/arm/iotkit.h | 22 +++++++++++++++++-----
 hw/arm/iotkit.c         | 34 +++++++++++++++++++++++++++++-----
 2 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
index 9701738ec75..521d1f73757 100644
--- a/include/hw/arm/iotkit.h
+++ b/include/hw/arm/iotkit.h
@@ -74,15 +74,15 @@
 #include "hw/or-irq.h"
 #include "hw/core/split-irq.h"
 
-#define TYPE_ARMSSE "iotkit"
+#define TYPE_ARMSSE "arm-sse"
 #define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
 
 /*
- * For the moment TYPE_IOTKIT is a synonym for TYPE_ARMSSE (and the
- * latter's underlying name is left as "iotkit"); in a later
- * commit it will become a subclass of TYPE_ARMSSE.
+ * These type names are for specific IoTKit subsystems; other than
+ * instantiating them, code using these devices should always handle
+ * them via the ARMSSE base class, so they have no IOTKIT() etc macros.
  */
-#define TYPE_IOTKIT TYPE_ARMSSE
+#define TYPE_IOTKIT "iotkit"
 
 /* We have an IRQ splitter and an OR gate input for each external PPC
  * and the 2 internal PPCs
@@ -143,4 +143,16 @@ typedef struct ARMSSE {
     uint32_t mainclk_frq;
 } ARMSSE;
 
+typedef struct ARMSSEInfo ARMSSEInfo;
+
+typedef struct ARMSSEClass {
+    DeviceClass parent_class;
+    const ARMSSEInfo *info;
+} ARMSSEClass;
+
+#define ARMSSE_CLASS(klass) \
+    OBJECT_CLASS_CHECK(ARMSSEClass, (klass), TYPE_ARMSSE)
+#define ARMSSE_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(ARMSSEClass, (obj), TYPE_ARMSSE)
+
 #endif
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
index 9360053184e..d5b172933c3 100644
--- a/hw/arm/iotkit.c
+++ b/hw/arm/iotkit.c
@@ -18,6 +18,16 @@
 #include "hw/arm/iotkit.h"
 #include "hw/arm/arm.h"
 
+struct ARMSSEInfo {
+    const char *name;
+};
+
+static const ARMSSEInfo armsse_variants[] = {
+    {
+        .name = TYPE_IOTKIT,
+    },
+};
+
 /* Clock frequency in HZ of the 32KHz "slow clock" */
 #define S32KCLK (32 * 1000)
 
@@ -732,29 +742,43 @@ static void iotkit_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
+    ARMSSEClass *asc = ARMSSE_CLASS(klass);
 
     dc->realize = iotkit_realize;
     dc->vmsd = &iotkit_vmstate;
     dc->props = iotkit_properties;
     dc->reset = iotkit_reset;
     iic->check = iotkit_idau_check;
+    asc->info = data;
 }
 
-static const TypeInfo iotkit_info = {
+static const TypeInfo armsse_info = {
     .name = TYPE_ARMSSE,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(ARMSSE),
     .instance_init = iotkit_init,
-    .class_init = iotkit_class_init,
+    .abstract = true,
     .interfaces = (InterfaceInfo[]) {
         { TYPE_IDAU_INTERFACE },
         { }
     }
 };
 
-static void iotkit_register_types(void)
+static void armsse_register_types(void)
 {
-    type_register_static(&iotkit_info);
+    int i;
+
+    type_register_static(&armsse_info);
+
+    for (i = 0; i < ARRAY_SIZE(armsse_variants); i++) {
+        TypeInfo ti = {
+            .name = armsse_variants[i].name,
+            .parent = TYPE_ARMSSE,
+            .class_init = iotkit_class_init,
+            .class_data = (void *)&armsse_variants[i],
+        };
+        type_register(&ti);
+    }
 }
 
-type_init(iotkit_register_types);
+type_init(armsse_register_types);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 07/47] hw/arm/iotkit: Rename 'iotkit' local variables and functions
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (5 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 06/47] hw/arm/iotkit: Refactor into abstract base class and subclass Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 08/47] hw/arm/iotkit: Rename files to hw/arm/armsse.[ch] Peter Maydell
                   ` (41 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Rename various internal uses of 'iotkit' in hw/arm/iotkit.c to
'armsse', for consistency. The remaining occurences are:
 * related to the devices TYPE_IOTKIT_SYSCTL, TYPE_IOTKIT_SYSINFO,
   etc, which this refactor is not touching
 * references that apply specifically to the IoTKit (like
   the lack of a private CPU region)
 * the vmstate, which keeps its old "iotkit" name for
   migration compatibility reasons

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-7-peter.maydell@linaro.org
---
 hw/arm/iotkit.c | 68 ++++++++++++++++++++++++-------------------------
 1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
index d5b172933c3..7ff14fd5aef 100644
--- a/hw/arm/iotkit.c
+++ b/hw/arm/iotkit.c
@@ -56,7 +56,7 @@ static void nsccfg_handler(void *opaque, int n, int level)
     s->nsccfg = level;
 }
 
-static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
+static void armsse_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
 {
     /* Each of the 4 AHB and 4 APB PPCs that might be present in a
      * system using the ARMSSE has a collection of control lines which
@@ -65,22 +65,22 @@ static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
      * code using the ARMSSE can wire them up to the PPCs.
      */
     SplitIRQ *splitter = &s->ppc_irq_splitter[ppcnum];
-    DeviceState *iotkitdev = DEVICE(s);
+    DeviceState *armssedev = DEVICE(s);
     DeviceState *dev_secctl = DEVICE(&s->secctl);
     DeviceState *dev_splitter = DEVICE(splitter);
     char *name;
 
     name = g_strdup_printf("%s_nonsec", ppcname);
-    qdev_pass_gpios(dev_secctl, iotkitdev, name);
+    qdev_pass_gpios(dev_secctl, armssedev, name);
     g_free(name);
     name = g_strdup_printf("%s_ap", ppcname);
-    qdev_pass_gpios(dev_secctl, iotkitdev, name);
+    qdev_pass_gpios(dev_secctl, armssedev, name);
     g_free(name);
     name = g_strdup_printf("%s_irq_enable", ppcname);
-    qdev_pass_gpios(dev_secctl, iotkitdev, name);
+    qdev_pass_gpios(dev_secctl, armssedev, name);
     g_free(name);
     name = g_strdup_printf("%s_irq_clear", ppcname);
-    qdev_pass_gpios(dev_secctl, iotkitdev, name);
+    qdev_pass_gpios(dev_secctl, armssedev, name);
     g_free(name);
 
     /* irq_status is a little more tricky, because we need to
@@ -96,15 +96,15 @@ static void iotkit_forward_ppc(ARMSSE *s, const char *ppcname, int ppcnum)
     qdev_connect_gpio_out(dev_splitter, 1,
                           qdev_get_gpio_in(DEVICE(&s->ppc_irq_orgate), ppcnum));
     s->irq_status_in[ppcnum] = qdev_get_gpio_in(dev_splitter, 0);
-    qdev_init_gpio_in_named_with_opaque(iotkitdev, irq_status_forwarder,
+    qdev_init_gpio_in_named_with_opaque(armssedev, irq_status_forwarder,
                                         s->irq_status_in[ppcnum], name, 1);
     g_free(name);
 }
 
-static void iotkit_forward_sec_resp_cfg(ARMSSE *s)
+static void armsse_forward_sec_resp_cfg(ARMSSE *s)
 {
     /* Forward the 3rd output from the splitter device as a
-     * named GPIO output of the iotkit object.
+     * named GPIO output of the armsse object.
      */
     DeviceState *dev = DEVICE(s);
     DeviceState *dev_splitter = DEVICE(&s->sec_resp_splitter);
@@ -115,12 +115,12 @@ static void iotkit_forward_sec_resp_cfg(ARMSSE *s)
     qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
 }
 
-static void iotkit_init(Object *obj)
+static void armsse_init(Object *obj)
 {
     ARMSSE *s = ARMSSE(obj);
     int i;
 
-    memory_region_init(&s->container, obj, "iotkit-container", UINT64_MAX);
+    memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
 
     sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
                           TYPE_ARMV7M);
@@ -160,9 +160,9 @@ static void iotkit_init(Object *obj)
                           sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG);
     sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog,
                           sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG);
-    sysbus_init_child_obj(obj, "iotkit-sysctl", &s->sysctl,
+    sysbus_init_child_obj(obj, "armsse-sysctl", &s->sysctl,
                           sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
-    sysbus_init_child_obj(obj, "iotkit-sysinfo", &s->sysinfo,
+    sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo,
                           sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
     object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
                             sizeof(s->nmi_orgate), TYPE_OR_IRQ,
@@ -183,20 +183,20 @@ static void iotkit_init(Object *obj)
     }
 }
 
-static void iotkit_exp_irq(void *opaque, int n, int level)
+static void armsse_exp_irq(void *opaque, int n, int level)
 {
     ARMSSE *s = ARMSSE(opaque);
 
     qemu_set_irq(s->exp_irqs[n], level);
 }
 
-static void iotkit_mpcexp_status(void *opaque, int n, int level)
+static void armsse_mpcexp_status(void *opaque, int n, int level)
 {
     ARMSSE *s = ARMSSE(opaque);
     qemu_set_irq(s->mpcexp_status_in[n], level);
 }
 
-static void iotkit_realize(DeviceState *dev, Error **errp)
+static void armsse_realize(DeviceState *dev, Error **errp)
 {
     ARMSSE *s = ARMSSE(dev);
     int i;
@@ -287,7 +287,7 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
     for (i = 0; i < s->exp_numirq; i++) {
         s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
     }
-    qdev_init_gpio_in_named(dev, iotkit_exp_irq, "EXP_IRQ", s->exp_numirq);
+    qdev_init_gpio_in_named(dev, armsse_exp_irq, "EXP_IRQ", s->exp_numirq);
 
     /* Set up the big aliases first */
     make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
@@ -336,7 +336,7 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
                                 qdev_get_gpio_in(dev_splitter, 0));
 
     /* This RAM lives behind the Memory Protection Controller */
-    memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
+    memory_region_init_ram(&s->sram0, NULL, "armsse.sram0", 0x00008000, &err);
     if (err) {
         error_propagate(errp, err);
         return;
@@ -608,14 +608,14 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
     for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
         char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
 
-        iotkit_forward_ppc(s, ppcname, i);
+        armsse_forward_ppc(s, ppcname, i);
         g_free(ppcname);
     }
 
     for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
         char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
 
-        iotkit_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
+        armsse_forward_ppc(s, ppcname, i + IOTS_NUM_AHB_EXP_PPC);
         g_free(ppcname);
     }
 
@@ -672,10 +672,10 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
     /* Create GPIO inputs which will pass the line state for our
      * mpcexp_irq inputs to the correct splitter devices.
      */
-    qdev_init_gpio_in_named(dev, iotkit_mpcexp_status, "mpcexp_status",
+    qdev_init_gpio_in_named(dev, armsse_mpcexp_status, "mpcexp_status",
                             IOTS_NUM_EXP_MPC);
 
-    iotkit_forward_sec_resp_cfg(s);
+    armsse_forward_sec_resp_cfg(s);
 
     /* Forward the MSC related signals */
     qdev_pass_gpios(dev_secctl, dev, "mscexp_status");
@@ -695,7 +695,7 @@ static void iotkit_realize(DeviceState *dev, Error **errp)
     system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
 }
 
-static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
+static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
                               int *iregion, bool *exempt, bool *ns, bool *nsc)
 {
     /*
@@ -713,7 +713,7 @@ static void iotkit_idau_check(IDAUInterface *ii, uint32_t address,
     *iregion = region;
 }
 
-static const VMStateDescription iotkit_vmstate = {
+static const VMStateDescription armsse_vmstate = {
     .name = "iotkit",
     .version_id = 1,
     .minimum_version_id = 1,
@@ -723,7 +723,7 @@ static const VMStateDescription iotkit_vmstate = {
     }
 };
 
-static Property iotkit_properties[] = {
+static Property armsse_properties[] = {
     DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
                      MemoryRegion *),
     DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
@@ -731,24 +731,24 @@ static Property iotkit_properties[] = {
     DEFINE_PROP_END_OF_LIST()
 };
 
-static void iotkit_reset(DeviceState *dev)
+static void armsse_reset(DeviceState *dev)
 {
     ARMSSE *s = ARMSSE(dev);
 
     s->nsccfg = 0;
 }
 
-static void iotkit_class_init(ObjectClass *klass, void *data)
+static void armsse_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(klass);
     ARMSSEClass *asc = ARMSSE_CLASS(klass);
 
-    dc->realize = iotkit_realize;
-    dc->vmsd = &iotkit_vmstate;
-    dc->props = iotkit_properties;
-    dc->reset = iotkit_reset;
-    iic->check = iotkit_idau_check;
+    dc->realize = armsse_realize;
+    dc->vmsd = &armsse_vmstate;
+    dc->props = armsse_properties;
+    dc->reset = armsse_reset;
+    iic->check = armsse_idau_check;
     asc->info = data;
 }
 
@@ -756,7 +756,7 @@ static const TypeInfo armsse_info = {
     .name = TYPE_ARMSSE,
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(ARMSSE),
-    .instance_init = iotkit_init,
+    .instance_init = armsse_init,
     .abstract = true,
     .interfaces = (InterfaceInfo[]) {
         { TYPE_IDAU_INTERFACE },
@@ -774,7 +774,7 @@ static void armsse_register_types(void)
         TypeInfo ti = {
             .name = armsse_variants[i].name,
             .parent = TYPE_ARMSSE,
-            .class_init = iotkit_class_init,
+            .class_init = armsse_class_init,
             .class_data = (void *)&armsse_variants[i],
         };
         type_register(&ti);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 08/47] hw/arm/iotkit: Rename files to hw/arm/armsse.[ch]
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (6 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 07/47] hw/arm/iotkit: Rename 'iotkit' local variables and functions Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 09/47] hw/misc/iotkit-secctl: Support 4 internal MPCs Peter Maydell
                   ` (40 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Rename the files that used to be iotkit.[ch] to
armsse.[ch] to reflect the fact they new cover
multiple Arm subsystems for embedded.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-8-peter.maydell@linaro.org
---
 hw/arm/Makefile.objs                  | 2 +-
 include/hw/arm/{iotkit.h => armsse.h} | 4 ++--
 hw/arm/{iotkit.c => armsse.c}         | 2 +-
 hw/arm/mps2-tz.c                      | 2 +-
 MAINTAINERS                           | 4 ++--
 default-configs/arm-softmmu.mak       | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)
 rename include/hw/arm/{iotkit.h => armsse.h} (99%)
 rename hw/arm/{iotkit.c => armsse.c} (99%)

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 50c7b4a927d..22b7f0ed0ba 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -34,7 +34,7 @@ obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
 obj-$(CONFIG_MPS2) += mps2.o
 obj-$(CONFIG_MPS2) += mps2-tz.o
 obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
-obj-$(CONFIG_IOTKIT) += iotkit.o
+obj-$(CONFIG_ARMSSE) += armsse.o
 obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
 obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o
 obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o mcimx6ul-evk.o
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/armsse.h
similarity index 99%
rename from include/hw/arm/iotkit.h
rename to include/hw/arm/armsse.h
index 521d1f73757..ff512054988 100644
--- a/include/hw/arm/iotkit.h
+++ b/include/hw/arm/armsse.h
@@ -58,8 +58,8 @@
  *  + named GPIO outputs mscexp_ns[0..15]
  */
 
-#ifndef IOTKIT_H
-#define IOTKIT_H
+#ifndef ARMSSE_H
+#define ARMSSE_H
 
 #include "hw/sysbus.h"
 #include "hw/arm/armv7m.h"
diff --git a/hw/arm/iotkit.c b/hw/arm/armsse.c
similarity index 99%
rename from hw/arm/iotkit.c
rename to hw/arm/armsse.c
index 7ff14fd5aef..8554be14128 100644
--- a/hw/arm/iotkit.c
+++ b/hw/arm/armsse.c
@@ -15,7 +15,7 @@
 #include "trace.h"
 #include "hw/sysbus.h"
 #include "hw/registerfields.h"
-#include "hw/arm/iotkit.h"
+#include "hw/arm/armsse.h"
 #include "hw/arm/arm.h"
 
 struct ARMSSEInfo {
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 5824335b4fb..3859f17d98b 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -46,7 +46,7 @@
 #include "hw/misc/mps2-fpgaio.h"
 #include "hw/misc/tz-mpc.h"
 #include "hw/misc/tz-msc.h"
-#include "hw/arm/iotkit.h"
+#include "hw/arm/armsse.h"
 #include "hw/dma/pl080.h"
 #include "hw/ssi/pl022.h"
 #include "hw/devices.h"
diff --git a/MAINTAINERS b/MAINTAINERS
index 234e5c413bd..c2ad4e52c9d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -623,8 +623,8 @@ F: hw/arm/mps2.c
 F: hw/arm/mps2-tz.c
 F: hw/misc/mps2-*.c
 F: include/hw/misc/mps2-*.h
-F: hw/arm/iotkit.c
-F: include/hw/arm/iotkit.h
+F: hw/arm/armsse.c
+F: include/hw/arm/armsse.h
 F: hw/misc/iotkit-secctl.c
 F: include/hw/misc/iotkit-secctl.h
 F: hw/misc/iotkit-sysctl.c
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 2420491aacd..3f200157879 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -114,7 +114,7 @@ CONFIG_MPS2_SCC=y
 CONFIG_TZ_MPC=y
 CONFIG_TZ_MSC=y
 CONFIG_TZ_PPC=y
-CONFIG_IOTKIT=y
+CONFIG_ARMSSE=y
 CONFIG_IOTKIT_SECCTL=y
 CONFIG_IOTKIT_SYSCTL=y
 CONFIG_IOTKIT_SYSINFO=y
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 09/47] hw/misc/iotkit-secctl: Support 4 internal MPCs
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (7 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 08/47] hw/arm/iotkit: Rename files to hw/arm/armsse.[ch] Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 10/47] hw/arm/armsse: Make number of SRAM banks parameterised Peter Maydell
                   ` (39 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The SSE-200 has 4 banks of SRAM, each with its own internal
Memory Protection Controller. The interrupt status for these
extra MPCs appears in the same security controller SECMPCINTSTATUS
register as the MPC for the IoTKit's single SRAM bank. Enhance the
iotkit-secctl device to allow 4 MPCs. (If the particular IoTKit/SSE
variant in use does not have all 4 MPCs then the unused inputs will
simply result in the SECMPCINTSTATUS bits being zero as required.)

The hardcoded constant "1"s in armsse.c indicate the actual number
of SRAM MPCs the IoTKit has, and will be replaced in the following
commit.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-9-peter.maydell@linaro.org
---
 include/hw/misc/iotkit-secctl.h | 6 +++---
 hw/arm/armsse.c                 | 6 +++---
 hw/misc/iotkit-secctl.c         | 5 +++--
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
index 1a193b306f1..bcb0437be5b 100644
--- a/include/hw/misc/iotkit-secctl.h
+++ b/include/hw/misc/iotkit-secctl.h
@@ -40,8 +40,8 @@
  *  + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
  *  + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
  *  + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
- * Controlling the MPC in the IoTKit:
- *  + named GPIO input mpc_status
+ * Controlling the (up to) 4 MPCs in the IoTKit/SSE:
+ *  + named GPIO inputs mpc_status[0..3]
  * Controlling each of the 16 expansion MPCs which a system using the IoTKit
  * might provide:
  *  + named GPIO inputs mpcexp_status[0..15]
@@ -67,7 +67,7 @@
 #define IOTS_NUM_APB_EXP_PPC 4
 #define IOTS_NUM_AHB_EXP_PPC 4
 #define IOTS_NUM_EXP_MPC 16
-#define IOTS_NUM_MPC 1
+#define IOTS_NUM_MPC 4
 #define IOTS_NUM_EXP_MSC 16
 
 typedef struct IoTKitSecCtl IoTKitSecCtl;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 8554be14128..074c1d3a6cf 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -138,7 +138,7 @@ static void armsse_init(Object *obj)
                             sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ,
                             &error_abort, NULL);
 
-    for (i = 0; i < ARRAY_SIZE(s->mpc_irq_splitter); i++) {
+    for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
         char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
         SplitIRQ *splitter = &s->mpc_irq_splitter[i];
 
@@ -363,7 +363,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
 
     /* We must OR together lines from the MPC splitters to go to the NVIC */
     object_property_set_int(OBJECT(&s->mpc_irq_orgate),
-                            IOTS_NUM_EXP_MPC + IOTS_NUM_MPC, "num-lines", &err);
+                            IOTS_NUM_EXP_MPC + 1, "num-lines", &err);
     if (err) {
         error_propagate(errp, err);
         return;
@@ -636,7 +636,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     }
 
     /* Wire up the splitters for the MPC IRQs */
-    for (i = 0; i < IOTS_NUM_EXP_MPC + IOTS_NUM_MPC; i++) {
+    for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
         SplitIRQ *splitter = &s->mpc_irq_splitter[i];
         DeviceState *dev_splitter = DEVICE(splitter);
 
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
index 2222b3e147d..537601cd53f 100644
--- a/hw/misc/iotkit-secctl.c
+++ b/hw/misc/iotkit-secctl.c
@@ -600,7 +600,7 @@ static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
 {
     IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
 
-    s->mpcintstatus = deposit32(s->mpcintstatus, 0, 1, !!level);
+    s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
 }
 
 static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
@@ -686,7 +686,8 @@ static void iotkit_secctl_init(Object *obj)
     qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
     qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
 
-    qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status", 1);
+    qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
+                            IOTS_NUM_MPC);
     qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
                             "mpcexp_status", IOTS_NUM_EXP_MPC);
 
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 10/47] hw/arm/armsse: Make number of SRAM banks parameterised
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (8 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 09/47] hw/misc/iotkit-secctl: Support 4 internal MPCs Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 11/47] hw/arm/armsse: Make SRAM bank size configurable Peter Maydell
                   ` (38 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The SSE-200 has four banks of SRAM, each with its own
Memory Protection Controller, where the IoTKit has only one.
Make the number of SRAM banks a field in ARMSSEInfo.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-10-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  9 +++--
 hw/arm/armsse.c         | 78 ++++++++++++++++++++++++++---------------
 2 files changed, 56 insertions(+), 31 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index ff512054988..99714aa63cd 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -90,6 +90,11 @@
 #define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
 #define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
 
+#define MAX_SRAM_BANKS 4
+#if MAX_SRAM_BANKS > IOTS_NUM_MPC
+#error Too many SRAM banks
+#endif
+
 typedef struct ARMSSE {
     /*< private >*/
     SysBusDevice parent_obj;
@@ -99,7 +104,7 @@ typedef struct ARMSSE {
     IoTKitSecCtl secctl;
     TZPPC apb_ppc0;
     TZPPC apb_ppc1;
-    TZMPC mpc;
+    TZMPC mpc[IOTS_NUM_MPC];
     CMSDKAPBTIMER timer0;
     CMSDKAPBTIMER timer1;
     CMSDKAPBTIMER s32ktimer;
@@ -123,7 +128,7 @@ typedef struct ARMSSE {
     MemoryRegion alias1;
     MemoryRegion alias2;
     MemoryRegion alias3;
-    MemoryRegion sram0;
+    MemoryRegion sram[MAX_SRAM_BANKS];
 
     qemu_irq *exp_irqs;
     qemu_irq ppc0_irq;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 074c1d3a6cf..b639b54e0db 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -20,11 +20,13 @@
 
 struct ARMSSEInfo {
     const char *name;
+    int sram_banks;
 };
 
 static const ARMSSEInfo armsse_variants[] = {
     {
         .name = TYPE_IOTKIT,
+        .sram_banks = 1,
     },
 };
 
@@ -118,8 +120,12 @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
 static void armsse_init(Object *obj)
 {
     ARMSSE *s = ARMSSE(obj);
+    ARMSSEClass *asc = ARMSSE_GET_CLASS(obj);
+    const ARMSSEInfo *info = asc->info;
     int i;
 
+    assert(info->sram_banks <= MAX_SRAM_BANKS);
+
     memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
 
     sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
@@ -133,12 +139,17 @@ static void armsse_init(Object *obj)
                           TYPE_TZ_PPC);
     sysbus_init_child_obj(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
                           TYPE_TZ_PPC);
-    sysbus_init_child_obj(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC);
+    for (i = 0; i < info->sram_banks; i++) {
+        char *name = g_strdup_printf("mpc%d", i);
+        sysbus_init_child_obj(obj, name, &s->mpc[i],
+                              sizeof(s->mpc[i]), TYPE_TZ_MPC);
+        g_free(name);
+    }
     object_initialize_child(obj, "mpc-irq-orgate", &s->mpc_irq_orgate,
                             sizeof(s->mpc_irq_orgate), TYPE_OR_IRQ,
                             &error_abort, NULL);
 
-    for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
+    for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
         char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
         SplitIRQ *splitter = &s->mpc_irq_splitter[i];
 
@@ -199,6 +210,8 @@ static void armsse_mpcexp_status(void *opaque, int n, int level)
 static void armsse_realize(DeviceState *dev, Error **errp)
 {
     ARMSSE *s = ARMSSE(dev);
+    ARMSSEClass *asc = ARMSSE_GET_CLASS(dev);
+    const ARMSSEInfo *info = asc->info;
     int i;
     MemoryRegion *mr;
     Error *err = NULL;
@@ -335,35 +348,41 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
                                 qdev_get_gpio_in(dev_splitter, 0));
 
-    /* This RAM lives behind the Memory Protection Controller */
-    memory_region_init_ram(&s->sram0, NULL, "armsse.sram0", 0x00008000, &err);
-    if (err) {
-        error_propagate(errp, err);
-        return;
+    /* Each SRAM bank lives behind its own Memory Protection Controller */
+    for (i = 0; i < info->sram_banks; i++) {
+        char *ramname = g_strdup_printf("armsse.sram%d", i);
+        SysBusDevice *sbd_mpc;
+
+        memory_region_init_ram(&s->sram[i], NULL, ramname, 0x00008000, &err);
+        g_free(ramname);
+        if (err) {
+            error_propagate(errp, err);
+            return;
+        }
+        object_property_set_link(OBJECT(&s->mpc[i]), OBJECT(&s->sram[i]),
+                                 "downstream", &err);
+        if (err) {
+            error_propagate(errp, err);
+            return;
+        }
+        object_property_set_bool(OBJECT(&s->mpc[i]), true, "realized", &err);
+        if (err) {
+            error_propagate(errp, err);
+            return;
+        }
+        /* Map the upstream end of the MPC into the right place... */
+        sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
+        memory_region_add_subregion(&s->container, 0x20000000 + i * 0x8000,
+                                    sysbus_mmio_get_region(sbd_mpc, 1));
+        /* ...and its register interface */
+        memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
+                                    sysbus_mmio_get_region(sbd_mpc, 0));
     }
-    object_property_set_link(OBJECT(&s->mpc), OBJECT(&s->sram0),
-                             "downstream", &err);
-    if (err) {
-        error_propagate(errp, err);
-        return;
-    }
-    object_property_set_bool(OBJECT(&s->mpc), true, "realized", &err);
-    if (err) {
-        error_propagate(errp, err);
-        return;
-    }
-    /* Map the upstream end of the MPC into the right place... */
-    memory_region_add_subregion(&s->container, 0x20000000,
-                                sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
-                                                       1));
-    /* ...and its register interface */
-    memory_region_add_subregion(&s->container, 0x50083000,
-                                sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
-                                                       0));
 
     /* We must OR together lines from the MPC splitters to go to the NVIC */
     object_property_set_int(OBJECT(&s->mpc_irq_orgate),
-                            IOTS_NUM_EXP_MPC + 1, "num-lines", &err);
+                            IOTS_NUM_EXP_MPC + info->sram_banks,
+                            "num-lines", &err);
     if (err) {
         error_propagate(errp, err);
         return;
@@ -636,7 +655,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     }
 
     /* Wire up the splitters for the MPC IRQs */
-    for (i = 0; i < IOTS_NUM_EXP_MPC + 1; i++) {
+    for (i = 0; i < IOTS_NUM_EXP_MPC + info->sram_banks; i++) {
         SplitIRQ *splitter = &s->mpc_irq_splitter[i];
         DeviceState *dev_splitter = DEVICE(splitter);
 
@@ -659,7 +678,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                                                          "mpcexp_status", i));
         } else {
             /* Splitter input is from our own MPC */
-            qdev_connect_gpio_out_named(DEVICE(&s->mpc), "irq", 0,
+            qdev_connect_gpio_out_named(DEVICE(&s->mpc[i - IOTS_NUM_EXP_MPC]),
+                                        "irq", 0,
                                         qdev_get_gpio_in(dev_splitter, 0));
             qdev_connect_gpio_out(dev_splitter, 0,
                                   qdev_get_gpio_in_named(dev_secctl,
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 11/47] hw/arm/armsse: Make SRAM bank size configurable
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (9 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 10/47] hw/arm/armsse: Make number of SRAM banks parameterised Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 12/47] hw/arm/armsse: Support dual-CPU configuration Peter Maydell
                   ` (37 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

For the IoTKit the SRAM bank size is always 32K (15 bits); for the
SSE-200 this is a configurable parameter, which defaults to 32K but
can be changed when it is built into a particular SoC. For instance
the Musca-B1 board sets it to 128K (17 bits).

Make the bank size a QOM property. We follow the SSE-200 hardware in
naming the parameter SRAM_ADDR_WIDTH, which specifies the number of
address bits of a single SRAM bank.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-11-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  1 +
 hw/arm/armsse.c         | 18 ++++++++++++++++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 99714aa63cd..e4a05013316 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -146,6 +146,7 @@ typedef struct ARMSSE {
     MemoryRegion *board_memory;
     uint32_t exp_numirq;
     uint32_t mainclk_frq;
+    uint32_t sram_addr_width;
 } ARMSSE;
 
 typedef struct ARMSSEInfo ARMSSEInfo;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index b639b54e0db..a2ae5d3c4b9 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -221,6 +221,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     DeviceState *dev_apb_ppc1;
     DeviceState *dev_secctl;
     DeviceState *dev_splitter;
+    uint32_t addr_width_max;
 
     if (!s->board_memory) {
         error_setg(errp, "memory property was not set");
@@ -232,6 +233,15 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    /* max SRAM_ADDR_WIDTH: 24 - log2(SRAM_NUM_BANK) */
+    assert(is_power_of_2(info->sram_banks));
+    addr_width_max = 24 - ctz32(info->sram_banks);
+    if (s->sram_addr_width < 1 || s->sram_addr_width > addr_width_max) {
+        error_setg(errp, "SRAM_ADDR_WIDTH must be between 1 and %d",
+                   addr_width_max);
+        return;
+    }
+
     /* Handling of which devices should be available only to secure
      * code is usually done differently for M profile than for A profile.
      * Instead of putting some devices only into the secure address space,
@@ -352,8 +362,10 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     for (i = 0; i < info->sram_banks; i++) {
         char *ramname = g_strdup_printf("armsse.sram%d", i);
         SysBusDevice *sbd_mpc;
+        uint32_t sram_bank_size = 1 << s->sram_addr_width;
 
-        memory_region_init_ram(&s->sram[i], NULL, ramname, 0x00008000, &err);
+        memory_region_init_ram(&s->sram[i], NULL, ramname,
+                               sram_bank_size, &err);
         g_free(ramname);
         if (err) {
             error_propagate(errp, err);
@@ -372,7 +384,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         }
         /* Map the upstream end of the MPC into the right place... */
         sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
-        memory_region_add_subregion(&s->container, 0x20000000 + i * 0x8000,
+        memory_region_add_subregion(&s->container,
+                                    0x20000000 + i * sram_bank_size,
                                     sysbus_mmio_get_region(sbd_mpc, 1));
         /* ...and its register interface */
         memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
@@ -748,6 +761,7 @@ static Property armsse_properties[] = {
                      MemoryRegion *),
     DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
     DEFINE_PROP_UINT32("MAINCLK", ARMSSE, mainclk_frq, 0),
+    DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
     DEFINE_PROP_END_OF_LIST()
 };
 
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 12/47] hw/arm/armsse: Support dual-CPU configuration
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (10 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 11/47] hw/arm/armsse: Make SRAM bank size configurable Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 13/47] hw/arm/armsse: Give each CPU its own view of memory Peter Maydell
                   ` (36 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The SSE-200 has two Cortex-M33 CPUs. These see the same view
of memory, with the exception of the "private CPU region" which
has per-CPU devices. Internal device interrupts for SSE-200
devices are mostly wired up to both CPUs, with the exception of
a few per-CPU devices. External GPIO inputs on the SSE-200
device are provided for the second CPU's interrupts above 32,
as is already the case for the first CPU.

Refactor the code to support creation of multiple CPUs.
For the moment we leave all CPUs with the same view of
memory: this will not work in the multiple-CPU case, but
we will fix this in the following commit.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-12-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  21 +++-
 hw/arm/armsse.c         | 206 ++++++++++++++++++++++++++++++++--------
 2 files changed, 180 insertions(+), 47 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index e4a05013316..faf5dfed252 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -28,9 +28,16 @@
  *  + QOM property "memory" is a MemoryRegion containing the devices provided
  *    by the board model.
  *  + QOM property "MAINCLK" is the frequency of the main system clock
- *  + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts
- *  + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which
- *    are wired to the NVIC lines 32 .. n+32
+ *  + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts.
+ *    (In hardware, the SSE-200 permits the number of expansion interrupts
+ *    for the two CPUs to be configured separately, but we restrict it to
+ *    being the same for both, to avoid having to have separate Property
+ *    lists for different variants. This restriction can be relaxed later
+ *    if necessary.)
+ *  + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts for CPU 0,
+ *    which are wired to its NVIC lines 32 .. n+32
+ *  + Named GPIO inputs "EXP_CPU1_IRQ" 0..n are the expansion interrupts for
+ *    CPU 1, which are wired to its NVIC lines 32 .. n+32
  *  + sysbus MMIO region 0 is the "AHB Slave Expansion" which allows
  *    bus master devices in the board model to make transactions into
  *    all the devices and memory areas in the IoTKit
@@ -95,12 +102,14 @@
 #error Too many SRAM banks
 #endif
 
+#define SSE_MAX_CPUS 2
+
 typedef struct ARMSSE {
     /*< private >*/
     SysBusDevice parent_obj;
 
     /*< public >*/
-    ARMv7MState armv7m;
+    ARMv7MState armv7m[SSE_MAX_CPUS];
     IoTKitSecCtl secctl;
     TZPPC apb_ppc0;
     TZPPC apb_ppc1;
@@ -115,6 +124,8 @@ typedef struct ARMSSE {
     qemu_or_irq mpc_irq_orgate;
     qemu_or_irq nmi_orgate;
 
+    SplitIRQ cpu_irq_splitter[32];
+
     CMSDKAPBDualTimer dualtimer;
 
     CMSDKAPBWatchdog s32kwatchdog;
@@ -130,7 +141,7 @@ typedef struct ARMSSE {
     MemoryRegion alias3;
     MemoryRegion sram[MAX_SRAM_BANKS];
 
-    qemu_irq *exp_irqs;
+    qemu_irq *exp_irqs[SSE_MAX_CPUS];
     qemu_irq ppc0_irq;
     qemu_irq ppc1_irq;
     qemu_irq sec_resp_cfg;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index a2ae5d3c4b9..5cb2b78b1fc 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -21,18 +21,35 @@
 struct ARMSSEInfo {
     const char *name;
     int sram_banks;
+    int num_cpus;
 };
 
 static const ARMSSEInfo armsse_variants[] = {
     {
         .name = TYPE_IOTKIT,
         .sram_banks = 1,
+        .num_cpus = 1,
     },
 };
 
 /* Clock frequency in HZ of the 32KHz "slow clock" */
 #define S32KCLK (32 * 1000)
 
+/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
+static bool irq_is_common[32] = {
+    [0 ... 5] = true,
+    /* 6, 7: per-CPU MHU interrupts */
+    [8 ... 12] = true,
+    /* 13: per-CPU icache interrupt */
+    /* 14: reserved */
+    [15 ... 20] = true,
+    /* 21: reserved */
+    [22 ... 26] = true,
+    /* 27: reserved */
+    /* 28, 29: per-CPU CTI interrupts */
+    /* 30, 31: reserved */
+};
+
 /* Create an alias region of @size bytes starting at @base
  * which mirrors the memory starting at @orig.
  */
@@ -125,13 +142,18 @@ static void armsse_init(Object *obj)
     int i;
 
     assert(info->sram_banks <= MAX_SRAM_BANKS);
+    assert(info->num_cpus <= SSE_MAX_CPUS);
 
     memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
 
-    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
-                          TYPE_ARMV7M);
-    qdev_prop_set_string(DEVICE(&s->armv7m), "cpu-type",
-                         ARM_CPU_TYPE_NAME("cortex-m33"));
+    for (i = 0; i < info->num_cpus; i++) {
+        char *name = g_strdup_printf("armv7m%d", i);
+        sysbus_init_child_obj(obj, name, &s->armv7m[i], sizeof(s->armv7m),
+                              TYPE_ARMV7M);
+        qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
+                             ARM_CPU_TYPE_NAME("cortex-m33"));
+        g_free(name);
+    }
 
     sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl),
                           TYPE_IOTKIT_SECCTL);
@@ -192,13 +214,25 @@ static void armsse_init(Object *obj)
                                 TYPE_SPLIT_IRQ, &error_abort, NULL);
         g_free(name);
     }
+    if (info->num_cpus > 1) {
+        for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
+            if (irq_is_common[i]) {
+                char *name = g_strdup_printf("cpu-irq-splitter%d", i);
+                SplitIRQ *splitter = &s->cpu_irq_splitter[i];
+
+                object_initialize_child(obj, name, splitter, sizeof(*splitter),
+                                        TYPE_SPLIT_IRQ, &error_abort, NULL);
+                g_free(name);
+            }
+        }
+    }
 }
 
 static void armsse_exp_irq(void *opaque, int n, int level)
 {
-    ARMSSE *s = ARMSSE(opaque);
+    qemu_irq *irqarray = opaque;
 
-    qemu_set_irq(s->exp_irqs[n], level);
+    qemu_set_irq(irqarray[n], level);
 }
 
 static void armsse_mpcexp_status(void *opaque, int n, int level)
@@ -207,6 +241,26 @@ static void armsse_mpcexp_status(void *opaque, int n, int level)
     qemu_set_irq(s->mpcexp_status_in[n], level);
 }
 
+static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
+{
+    /*
+     * Return a qemu_irq which can be used to signal IRQ n to
+     * all CPUs in the SSE.
+     */
+    ARMSSEClass *asc = ARMSSE_GET_CLASS(s);
+    const ARMSSEInfo *info = asc->info;
+
+    assert(irq_is_common[irqno]);
+
+    if (info->num_cpus == 1) {
+        /* Only one CPU -- just connect directly to it */
+        return qdev_get_gpio_in(DEVICE(&s->armv7m[0]), irqno);
+    } else {
+        /* Connect to the splitter which feeds all CPUs */
+        return qdev_get_gpio_in(DEVICE(&s->cpu_irq_splitter[irqno]), 0);
+    }
+}
+
 static void armsse_realize(DeviceState *dev, Error **errp)
 {
     ARMSSE *s = ARMSSE(dev);
@@ -280,37 +334,105 @@ static void armsse_realize(DeviceState *dev, Error **errp)
 
     memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
 
-    qdev_prop_set_uint32(DEVICE(&s->armv7m), "num-irq", s->exp_numirq + 32);
-    /* In real hardware the initial Secure VTOR is set from the INITSVTOR0
-     * register in the IoT Kit System Control Register block, and the
-     * initial value of that is in turn specifiable by the FPGA that
-     * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
-     * and simply set the CPU's init-svtor to the IoT Kit default value.
-     */
-    qdev_prop_set_uint32(DEVICE(&s->armv7m), "init-svtor", 0x10000000);
-    object_property_set_link(OBJECT(&s->armv7m), OBJECT(&s->container),
-                             "memory", &err);
-    if (err) {
-        error_propagate(errp, err);
-        return;
-    }
-    object_property_set_link(OBJECT(&s->armv7m), OBJECT(s), "idau", &err);
-    if (err) {
-        error_propagate(errp, err);
-        return;
-    }
-    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
-    if (err) {
-        error_propagate(errp, err);
-        return;
+    for (i = 0; i < info->num_cpus; i++) {
+        DeviceState *cpudev = DEVICE(&s->armv7m[i]);
+        Object *cpuobj = OBJECT(&s->armv7m[i]);
+        int j;
+        char *gpioname;
+
+        qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
+        /*
+         * In real hardware the initial Secure VTOR is set from the INITSVTOR0
+         * register in the IoT Kit System Control Register block, and the
+         * initial value of that is in turn specifiable by the FPGA that
+         * instantiates the IoT Kit. In QEMU we don't implement this wrinkle,
+         * and simply set the CPU's init-svtor to the IoT Kit default value.
+         * In SSE-200 the situation is similar, except that the default value
+         * is a reset-time signal input. Typically a board using the SSE-200
+         * will have a system control processor whose boot firmware initializes
+         * the INITSVTOR* registers before powering up the CPUs in any case,
+         * so the hardware's default value doesn't matter. QEMU doesn't emulate
+         * the control processor, so instead we behave in the way that the
+         * firmware does. All boards currently known about have firmware that
+         * sets the INITSVTOR0 and INITSVTOR1 registers to 0x10000000, like the
+         * IoTKit default. We can make this more configurable if necessary.
+         */
+        qdev_prop_set_uint32(cpudev, "init-svtor", 0x10000000);
+        /*
+         * Start all CPUs except CPU0 powered down. In real hardware it is
+         * a configurable property of the SSE-200 which CPUs start powered up
+         * (via the CPUWAIT0_RST and CPUWAIT1_RST parameters), but since all
+         * the boards we care about start CPU0 and leave CPU1 powered off,
+         * we hard-code that for now. We can add QOM properties for this
+         * later if necessary.
+         */
+        if (i > 0) {
+            object_property_set_bool(cpuobj, true, "start-powered-off", &err);
+            if (err) {
+                error_propagate(errp, err);
+                return;
+            }
+        }
+        object_property_set_link(cpuobj, OBJECT(&s->container), "memory", &err);
+        if (err) {
+            error_propagate(errp, err);
+            return;
+        }
+        object_property_set_link(cpuobj, OBJECT(s), "idau", &err);
+        if (err) {
+            error_propagate(errp, err);
+            return;
+        }
+        object_property_set_bool(cpuobj, true, "realized", &err);
+        if (err) {
+            error_propagate(errp, err);
+            return;
+        }
+
+        /* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
+        s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
+        for (j = 0; j < s->exp_numirq; j++) {
+            s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, i + 32);
+        }
+        if (i == 0) {
+            gpioname = g_strdup("EXP_IRQ");
+        } else {
+            gpioname = g_strdup_printf("EXP_CPU%d_IRQ", i);
+        }
+        qdev_init_gpio_in_named_with_opaque(dev, armsse_exp_irq,
+                                            s->exp_irqs[i],
+                                            gpioname, s->exp_numirq);
+        g_free(gpioname);
     }
 
-    /* Connect our EXP_IRQ GPIOs to the NVIC's lines 32 and up. */
-    s->exp_irqs = g_new(qemu_irq, s->exp_numirq);
-    for (i = 0; i < s->exp_numirq; i++) {
-        s->exp_irqs[i] = qdev_get_gpio_in(DEVICE(&s->armv7m), i + 32);
+    /* Wire up the splitters that connect common IRQs to all CPUs */
+    if (info->num_cpus > 1) {
+        for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
+            if (irq_is_common[i]) {
+                Object *splitter = OBJECT(&s->cpu_irq_splitter[i]);
+                DeviceState *devs = DEVICE(splitter);
+                int cpunum;
+
+                object_property_set_int(splitter, info->num_cpus,
+                                        "num-lines", &err);
+                if (err) {
+                    error_propagate(errp, err);
+                    return;
+                }
+                object_property_set_bool(splitter, true, "realized", &err);
+                if (err) {
+                    error_propagate(errp, err);
+                    return;
+                }
+                for (cpunum = 0; cpunum < info->num_cpus; cpunum++) {
+                    DeviceState *cpudev = DEVICE(&s->armv7m[cpunum]);
+
+                    qdev_connect_gpio_out(devs, cpunum,
+                                          qdev_get_gpio_in(cpudev, i));
+                }
+            }
+        }
     }
-    qdev_init_gpio_in_named(dev, armsse_exp_irq, "EXP_IRQ", s->exp_numirq);
 
     /* Set up the big aliases first */
     make_alias(s, &s->alias1, "alias 1", 0x10000000, 0x10000000, 0x00000000);
@@ -407,7 +529,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         return;
     }
     qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
-                          qdev_get_gpio_in(DEVICE(&s->armv7m), 9));
+                          armsse_get_common_irq_in(s, 9));
 
     /* Devices behind APB PPC0:
      *   0x40000000: timer0
@@ -424,7 +546,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         return;
     }
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
-                       qdev_get_gpio_in(DEVICE(&s->armv7m), 3));
+                       armsse_get_common_irq_in(s, 3));
     mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer0), 0);
     object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[0]", &err);
     if (err) {
@@ -439,7 +561,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         return;
     }
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
-                       qdev_get_gpio_in(DEVICE(&s->armv7m), 4));
+                       armsse_get_common_irq_in(s, 4));
     mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer1), 0);
     object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[1]", &err);
     if (err) {
@@ -455,7 +577,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         return;
     }
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
-                       qdev_get_gpio_in(DEVICE(&s->armv7m), 5));
+                       armsse_get_common_irq_in(s, 5));
     mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dualtimer), 0);
     object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr), "port[2]", &err);
     if (err) {
@@ -513,7 +635,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         return;
     }
     qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
-                          qdev_get_gpio_in(DEVICE(&s->armv7m), 10));
+                          armsse_get_common_irq_in(s, 10));
 
     /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
 
@@ -528,7 +650,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         return;
     }
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
-                       qdev_get_gpio_in(DEVICE(&s->armv7m), 2));
+                       armsse_get_common_irq_in(s, 2));
     mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0);
     object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", &err);
     if (err) {
@@ -609,7 +731,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         return;
     }
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
-                       qdev_get_gpio_in(DEVICE(&s->armv7m), 1));
+                       armsse_get_common_irq_in(s, 1));
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
 
     qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_frq);
@@ -715,7 +837,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     qdev_pass_gpios(dev_secctl, dev, "mscexp_clear");
     qdev_pass_gpios(dev_secctl, dev, "mscexp_ns");
     qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0,
-                                qdev_get_gpio_in(DEVICE(&s->armv7m), 11));
+                                armsse_get_common_irq_in(s, 11));
 
     /*
      * Expose our container region to the board model; this corresponds
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 13/47] hw/arm/armsse: Give each CPU its own view of memory
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (11 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 12/47] hw/arm/armsse: Support dual-CPU configuration Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 14/47] hw/arm/armsse: Put each CPU in its own cluster object Peter Maydell
                   ` (35 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Give each CPU its own container memory region. This is necessary
for two reasons:
 * some devices are instantiated one per CPU and the CPU sees only
   its own device
 * since a memory region can only be put into one container, we must
   give each armv7m object a different MemoryRegion as its 'memory'
   property, or a dual-CPU configuration will assert on realize when
   the second armv7m object tries to put the MR into a container when
   it is already in the first armv7m object's container

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-13-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h | 10 ++++++++++
 hw/arm/armsse.c         | 22 ++++++++++++++++++++--
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index faf5dfed252..89f19a971f4 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -135,7 +135,17 @@ typedef struct ARMSSE {
     IoTKitSysCtl sysctl;
     IoTKitSysCtl sysinfo;
 
+    /*
+     * 'container' holds all devices seen by all CPUs.
+     * 'cpu_container[i]' is the view that CPU i has: this has the
+     * per-CPU devices of that CPU, plus as the background 'container'
+     * (or an alias of it, since we can only use it directly once).
+     * container_alias[i] is the alias of 'container' used by CPU i+1;
+     * CPU 0 can use 'container' directly.
+     */
     MemoryRegion container;
+    MemoryRegion container_alias[SSE_MAX_CPUS - 1];
+    MemoryRegion cpu_container[SSE_MAX_CPUS];
     MemoryRegion alias1;
     MemoryRegion alias2;
     MemoryRegion alias3;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 5cb2b78b1fc..2472dfef3a1 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -153,6 +153,15 @@ static void armsse_init(Object *obj)
         qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
                              ARM_CPU_TYPE_NAME("cortex-m33"));
         g_free(name);
+        name = g_strdup_printf("arm-sse-cpu-container%d", i);
+        memory_region_init(&s->cpu_container[i], obj, name, UINT64_MAX);
+        g_free(name);
+        if (i > 0) {
+            name = g_strdup_printf("arm-sse-container-alias%d", i);
+            memory_region_init_alias(&s->container_alias[i - 1], obj,
+                                     name, &s->container, 0, UINT64_MAX);
+            g_free(name);
+        }
     }
 
     sysbus_init_child_obj(obj, "secctl", &s->secctl, sizeof(s->secctl),
@@ -332,7 +341,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
      * 0x50000000..0x5fffffff  alias of 0x40000000..0x4fffffff
      */
 
-    memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
+    memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -2);
 
     for (i = 0; i < info->num_cpus; i++) {
         DeviceState *cpudev = DEVICE(&s->armv7m[i]);
@@ -373,7 +382,16 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                 return;
             }
         }
-        object_property_set_link(cpuobj, OBJECT(&s->container), "memory", &err);
+
+        if (i > 0) {
+            memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
+                                                &s->container_alias[i - 1], -1);
+        } else {
+            memory_region_add_subregion_overlap(&s->cpu_container[i], 0,
+                                                &s->container, -1);
+        }
+        object_property_set_link(cpuobj, OBJECT(&s->cpu_container[i]),
+                                 "memory", &err);
         if (err) {
             error_propagate(errp, err);
             return;
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 14/47] hw/arm/armsse: Put each CPU in its own cluster object
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (12 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 13/47] hw/arm/armsse: Give each CPU its own view of memory Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 15/47] iotkit-sysinfo: Make SYS_VERSION and SYS_CONFIG configurable Peter Maydell
                   ` (34 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Create a cluster object to hold each CPU in the SSE. They are
logically distinct and may be configured differently (for instance
one may not have an FPU where the other does).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-14-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  2 ++
 hw/arm/armsse.c         | 31 ++++++++++++++++++++++++++++---
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 89f19a971f4..999c2e4f7e5 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -80,6 +80,7 @@
 #include "hw/misc/iotkit-sysinfo.h"
 #include "hw/or-irq.h"
 #include "hw/core/split-irq.h"
+#include "hw/cpu/cluster.h"
 
 #define TYPE_ARMSSE "arm-sse"
 #define ARMSSE(obj) OBJECT_CHECK(ARMSSE, (obj), TYPE_ARMSSE)
@@ -110,6 +111,7 @@ typedef struct ARMSSE {
 
     /*< public >*/
     ARMv7MState armv7m[SSE_MAX_CPUS];
+    CPUClusterState cluster[SSE_MAX_CPUS];
     IoTKitSecCtl secctl;
     TZPPC apb_ppc0;
     TZPPC apb_ppc1;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 2472dfef3a1..2eb4ea3bfe0 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -147,9 +147,22 @@ static void armsse_init(Object *obj)
     memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
 
     for (i = 0; i < info->num_cpus; i++) {
-        char *name = g_strdup_printf("armv7m%d", i);
-        sysbus_init_child_obj(obj, name, &s->armv7m[i], sizeof(s->armv7m),
-                              TYPE_ARMV7M);
+        /*
+         * We put each CPU in its own cluster as they are logically
+         * distinct and may be configured differently.
+         */
+        char *name;
+
+        name = g_strdup_printf("cluster%d", i);
+        object_initialize_child(obj, name, &s->cluster[i],
+                                sizeof(s->cluster[i]), TYPE_CPU_CLUSTER,
+                                &error_abort, NULL);
+        qdev_prop_set_uint32(DEVICE(&s->cluster[i]), "cluster-id", i);
+        g_free(name);
+
+        name = g_strdup_printf("armv7m%d", i);
+        sysbus_init_child_obj(OBJECT(&s->cluster[i]), name,
+                              &s->armv7m[i], sizeof(s->armv7m), TYPE_ARMV7M);
         qdev_prop_set_string(DEVICE(&s->armv7m[i]), "cpu-type",
                              ARM_CPU_TYPE_NAME("cortex-m33"));
         g_free(name);
@@ -406,6 +419,18 @@ static void armsse_realize(DeviceState *dev, Error **errp)
             error_propagate(errp, err);
             return;
         }
+        /*
+         * The cluster must be realized after the armv7m container, as
+         * the container's CPU object is only created on realize, and the
+         * CPU must exist and have been parented into the cluster before
+         * the cluster is realized.
+         */
+        object_property_set_bool(OBJECT(&s->cluster[i]),
+                                 true, "realized", &err);
+        if (err) {
+            error_propagate(errp, err);
+            return;
+        }
 
         /* Connect EXP_IRQ/EXP_CPUn_IRQ GPIOs to the NVIC's lines 32 and up */
         s->exp_irqs[i] = g_new(qemu_irq, s->exp_numirq);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 15/47] iotkit-sysinfo: Make SYS_VERSION and SYS_CONFIG configurable
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (13 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 14/47] hw/arm/armsse: Put each CPU in its own cluster object Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 16/47] hw/arm/armsse: Add unimplemented-device stubs for MHUs Peter Maydell
                   ` (33 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The SYS_VERSION and SYS_CONFIG register values differ between the
IoTKit and SSE-200. Make them configurable via QOM properties rather
than hard-coded, and set them appropriately in the ARMSSE code that
instantiates the IOTKIT_SYSINFO device.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-15-peter.maydell@linaro.org
---
 include/hw/misc/iotkit-sysinfo.h |  6 ++++
 hw/arm/armsse.c                  | 51 ++++++++++++++++++++++++++++++++
 hw/misc/iotkit-sysinfo.c         | 15 ++++++++--
 3 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
index 7b2e1a5e48b..d84eb203b90 100644
--- a/include/hw/misc/iotkit-sysinfo.h
+++ b/include/hw/misc/iotkit-sysinfo.h
@@ -14,6 +14,8 @@
  * Arm IoTKit and documented in
  * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
  * QEMU interface:
+ *  + QOM property "SYS_VERSION": value to use for SYS_VERSION register
+ *  + QOM property "SYS_CONFIG": value to use for SYS_CONFIG register
  *  + sysbus MMIO region 0: the system information register bank
  */
 
@@ -32,6 +34,10 @@ typedef struct IoTKitSysInfo {
 
     /*< public >*/
     MemoryRegion iomem;
+
+    /* Properties */
+    uint32_t sys_version;
+    uint32_t sys_config;
 } IoTKitSysInfo;
 
 #endif
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 2eb4ea3bfe0..19cae77e770 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -18,10 +18,18 @@
 #include "hw/arm/armsse.h"
 #include "hw/arm/arm.h"
 
+/* Format of the System Information block SYS_CONFIG register */
+typedef enum SysConfigFormat {
+    IoTKitFormat,
+    SSE200Format,
+} SysConfigFormat;
+
 struct ARMSSEInfo {
     const char *name;
     int sram_banks;
     int num_cpus;
+    uint32_t sys_version;
+    SysConfigFormat sys_config_format;
 };
 
 static const ARMSSEInfo armsse_variants[] = {
@@ -29,9 +37,39 @@ static const ARMSSEInfo armsse_variants[] = {
         .name = TYPE_IOTKIT,
         .sram_banks = 1,
         .num_cpus = 1,
+        .sys_version = 0x41743,
+        .sys_config_format = IoTKitFormat,
     },
 };
 
+static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
+{
+    /* Return the SYS_CONFIG value for this SSE */
+    uint32_t sys_config;
+
+    switch (info->sys_config_format) {
+    case IoTKitFormat:
+        sys_config = 0;
+        sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
+        sys_config = deposit32(sys_config, 4, 4, s->sram_addr_width - 12);
+        break;
+    case SSE200Format:
+        sys_config = 0;
+        sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
+        sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
+        sys_config = deposit32(sys_config, 24, 4, 2);
+        if (info->num_cpus > 1) {
+            sys_config = deposit32(sys_config, 10, 1, 1);
+            sys_config = deposit32(sys_config, 20, 4, info->sram_banks - 1);
+            sys_config = deposit32(sys_config, 28, 4, 2);
+        }
+        break;
+    default:
+        g_assert_not_reached();
+    }
+    return sys_config;
+}
+
 /* Clock frequency in HZ of the 32KHz "slow clock" */
 #define S32KCLK (32 * 1000)
 
@@ -726,6 +764,19 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                           qdev_get_gpio_in_named(dev_apb_ppc1,
                                                  "cfg_sec_resp", 0));
 
+    object_property_set_int(OBJECT(&s->sysinfo), info->sys_version,
+                            "SYS_VERSION", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+    object_property_set_int(OBJECT(&s->sysinfo),
+                            armsse_sys_config_value(s, info),
+                            "SYS_CONFIG", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
     object_property_set_bool(OBJECT(&s->sysinfo), true, "realized", &err);
     if (err) {
         error_propagate(errp, err);
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
index 78955bc45f5..026ba942613 100644
--- a/hw/misc/iotkit-sysinfo.c
+++ b/hw/misc/iotkit-sysinfo.c
@@ -51,15 +51,16 @@ static const int sysinfo_id[] = {
 static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
                                     unsigned size)
 {
+    IoTKitSysInfo *s = IOTKIT_SYSINFO(opaque);
     uint64_t r;
 
     switch (offset) {
     case A_SYS_VERSION:
-        r = 0x41743;
+        r = s->sys_version;
         break;
 
     case A_SYS_CONFIG:
-        r = 0x31;
+        r = s->sys_config;
         break;
     case A_PID4 ... A_CID3:
         r = sysinfo_id[(offset - A_PID4) / 4];
@@ -94,6 +95,12 @@ static const MemoryRegionOps iotkit_sysinfo_ops = {
     .valid.max_access_size = 4,
 };
 
+static Property iotkit_sysinfo_props[] = {
+    DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysInfo, sys_version, 0),
+    DEFINE_PROP_UINT32("SYS_CONFIG", IoTKitSysInfo, sys_config, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
 static void iotkit_sysinfo_init(Object *obj)
 {
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@@ -106,10 +113,14 @@ static void iotkit_sysinfo_init(Object *obj)
 
 static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
 {
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
     /*
      * This device has no guest-modifiable state and so it
      * does not need a reset function or VMState.
      */
+
+    dc->props = iotkit_sysinfo_props;
 }
 
 static const TypeInfo iotkit_sysinfo_info = {
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 16/47] hw/arm/armsse: Add unimplemented-device stubs for MHUs
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (14 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 15/47] iotkit-sysinfo: Make SYS_VERSION and SYS_CONFIG configurable Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 17/47] hw/arm/armsse: Add unimplemented-device stubs for PPUs Peter Maydell
                   ` (32 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The SSE-200 has two Message Handling Units (MHUs), which sit behind
the APB PPC0. Wire up some unimplemented-device stubs for these,
since we don't yet implement a real model of this device.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-16-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  3 +++
 hw/arm/armsse.c         | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 999c2e4f7e5..dbfcb280605 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -78,6 +78,7 @@
 #include "hw/watchdog/cmsdk-apb-watchdog.h"
 #include "hw/misc/iotkit-sysctl.h"
 #include "hw/misc/iotkit-sysinfo.h"
+#include "hw/misc/unimp.h"
 #include "hw/or-irq.h"
 #include "hw/core/split-irq.h"
 #include "hw/cpu/cluster.h"
@@ -137,6 +138,8 @@ typedef struct ARMSSE {
     IoTKitSysCtl sysctl;
     IoTKitSysCtl sysinfo;
 
+    UnimplementedDeviceState mhu[2];
+
     /*
      * 'container' holds all devices seen by all CPUs.
      * 'cpu_container[i]' is the view that CPU i has: this has the
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 19cae77e770..1f3dc89c8e8 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -30,6 +30,7 @@ struct ARMSSEInfo {
     int num_cpus;
     uint32_t sys_version;
     SysConfigFormat sys_config_format;
+    bool has_mhus;
 };
 
 static const ARMSSEInfo armsse_variants[] = {
@@ -39,6 +40,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .num_cpus = 1,
         .sys_version = 0x41743,
         .sys_config_format = IoTKitFormat,
+        .has_mhus = false,
     },
 };
 
@@ -257,6 +259,12 @@ static void armsse_init(Object *obj)
                           sizeof(s->sysctl), TYPE_IOTKIT_SYSCTL);
     sysbus_init_child_obj(obj, "armsse-sysinfo", &s->sysinfo,
                           sizeof(s->sysinfo), TYPE_IOTKIT_SYSINFO);
+    if (info->has_mhus) {
+        sysbus_init_child_obj(obj, "mhu0", &s->mhu[0], sizeof(s->mhu[0]),
+                              TYPE_UNIMPLEMENTED_DEVICE);
+        sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]),
+                              TYPE_UNIMPLEMENTED_DEVICE);
+    }
     object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
                             sizeof(s->nmi_orgate), TYPE_OR_IRQ,
                             &error_abort, NULL);
@@ -616,6 +624,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
      *   0x40000000: timer0
      *   0x40001000: timer1
      *   0x40002000: dual timer
+     *   0x40003000: MHU0 (SSE-200 only)
+     *   0x40004000: MHU1 (SSE-200 only)
      * We must configure and realize each downstream device and connect
      * it to the appropriate PPC port; then we can realize the PPC and
      * map its upstream ends to the right place in the container.
@@ -666,6 +676,31 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    if (info->has_mhus) {
+        for (i = 0; i < ARRAY_SIZE(s->mhu); i++) {
+            char *name = g_strdup_printf("MHU%d", i);
+            char *port = g_strdup_printf("port[%d]", i + 3);
+
+            qdev_prop_set_string(DEVICE(&s->mhu[i]), "name", name);
+            qdev_prop_set_uint64(DEVICE(&s->mhu[i]), "size", 0x1000);
+            object_property_set_bool(OBJECT(&s->mhu[i]), true,
+                                     "realized", &err);
+            if (err) {
+                error_propagate(errp, err);
+                return;
+            }
+            mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mhu[i]), 0);
+            object_property_set_link(OBJECT(&s->apb_ppc0), OBJECT(mr),
+                                     port, &err);
+            if (err) {
+                error_propagate(errp, err);
+                return;
+            }
+            g_free(name);
+            g_free(port);
+        }
+    }
+
     object_property_set_bool(OBJECT(&s->apb_ppc0), true, "realized", &err);
     if (err) {
         error_propagate(errp, err);
@@ -681,6 +716,12 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     memory_region_add_subregion(&s->container, 0x40001000, mr);
     mr = sysbus_mmio_get_region(sbd_apb_ppc0, 2);
     memory_region_add_subregion(&s->container, 0x40002000, mr);
+    if (info->has_mhus) {
+        mr = sysbus_mmio_get_region(sbd_apb_ppc0, 3);
+        memory_region_add_subregion(&s->container, 0x40003000, mr);
+        mr = sysbus_mmio_get_region(sbd_apb_ppc0, 4);
+        memory_region_add_subregion(&s->container, 0x40004000, mr);
+    }
     for (i = 0; i < IOTS_APB_PPC0_NUM_PORTS; i++) {
         qdev_connect_gpio_out_named(dev_secctl, "apb_ppc0_nonsec", i,
                                     qdev_get_gpio_in_named(dev_apb_ppc0,
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 17/47] hw/arm/armsse: Add unimplemented-device stubs for PPUs
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (15 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 16/47] hw/arm/armsse: Add unimplemented-device stubs for MHUs Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 18/47] hw/arm/armsse: Add unimplemented-device stub for cache control registers Peter Maydell
                   ` (31 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Add unimplemented-device stubs for the various Power Policy Unit
devices that the SSE-200 has.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-17-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h | 11 ++++++++
 hw/arm/armsse.c         | 58 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index dbfcb280605..9855ec5f269 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -106,6 +106,16 @@
 
 #define SSE_MAX_CPUS 2
 
+/* These define what each PPU in the ppu[] index is for */
+#define CPU0CORE_PPU 0
+#define CPU1CORE_PPU 1
+#define DBG_PPU 2
+#define RAM0_PPU 3
+#define RAM1_PPU 4
+#define RAM2_PPU 5
+#define RAM3_PPU 6
+#define NUM_PPUS 7
+
 typedef struct ARMSSE {
     /*< private >*/
     SysBusDevice parent_obj;
@@ -139,6 +149,7 @@ typedef struct ARMSSE {
     IoTKitSysCtl sysinfo;
 
     UnimplementedDeviceState mhu[2];
+    UnimplementedDeviceState ppu[NUM_PPUS];
 
     /*
      * 'container' holds all devices seen by all CPUs.
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 1f3dc89c8e8..280ba5c78be 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -31,6 +31,7 @@ struct ARMSSEInfo {
     uint32_t sys_version;
     SysConfigFormat sys_config_format;
     bool has_mhus;
+    bool has_ppus;
 };
 
 static const ARMSSEInfo armsse_variants[] = {
@@ -41,6 +42,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .sys_version = 0x41743,
         .sys_config_format = IoTKitFormat,
         .has_mhus = false,
+        .has_ppus = false,
     },
 };
 
@@ -265,6 +267,29 @@ static void armsse_init(Object *obj)
         sysbus_init_child_obj(obj, "mhu1", &s->mhu[1], sizeof(s->mhu[1]),
                               TYPE_UNIMPLEMENTED_DEVICE);
     }
+    if (info->has_ppus) {
+        for (i = 0; i < info->num_cpus; i++) {
+            char *name = g_strdup_printf("CPU%dCORE_PPU", i);
+            int ppuidx = CPU0CORE_PPU + i;
+
+            sysbus_init_child_obj(obj, name, &s->ppu[ppuidx],
+                                  sizeof(s->ppu[ppuidx]),
+                                  TYPE_UNIMPLEMENTED_DEVICE);
+            g_free(name);
+        }
+        sysbus_init_child_obj(obj, "DBG_PPU", &s->ppu[DBG_PPU],
+                              sizeof(s->ppu[DBG_PPU]),
+                              TYPE_UNIMPLEMENTED_DEVICE);
+        for (i = 0; i < info->sram_banks; i++) {
+            char *name = g_strdup_printf("RAM%d_PPU", i);
+            int ppuidx = RAM0_PPU + i;
+
+            sysbus_init_child_obj(obj, name, &s->ppu[ppuidx],
+                                  sizeof(s->ppu[ppuidx]),
+                                  TYPE_UNIMPLEMENTED_DEVICE);
+            g_free(name);
+        }
+    }
     object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
                             sizeof(s->nmi_orgate), TYPE_OR_IRQ,
                             &error_abort, NULL);
@@ -329,6 +354,17 @@ static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
     }
 }
 
+static void map_ppu(ARMSSE *s, int ppuidx, const char *name, hwaddr addr)
+{
+    /* Map a PPU unimplemented device stub */
+    DeviceState *dev = DEVICE(&s->ppu[ppuidx]);
+
+    qdev_prop_set_string(dev, "name", name);
+    qdev_prop_set_uint64(dev, "size", 0x1000);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ppu[ppuidx]), 0, addr);
+}
+
 static void armsse_realize(DeviceState *dev, Error **errp)
 {
     ARMSSE *s = ARMSSE(dev);
@@ -833,6 +869,28 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     }
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x50021000);
 
+    if (info->has_ppus) {
+        /* CPUnCORE_PPU for each CPU */
+        for (i = 0; i < info->num_cpus; i++) {
+            char *name = g_strdup_printf("CPU%dCORE_PPU", i);
+
+            map_ppu(s, CPU0CORE_PPU + i, name, 0x50023000 + i * 0x2000);
+            /*
+             * We don't support CPU debug so don't create the
+             * CPU0DEBUG_PPU at 0x50024000 and 0x50026000.
+             */
+            g_free(name);
+        }
+        map_ppu(s, DBG_PPU, "DBG_PPU", 0x50029000);
+
+        for (i = 0; i < info->sram_banks; i++) {
+            char *name = g_strdup_printf("RAM%d_PPU", i);
+
+            map_ppu(s, RAM0_PPU + i, name, 0x5002a000 + i * 0x1000);
+            g_free(name);
+        }
+    }
+
     /* This OR gate wires together outputs from the secure watchdogs to NMI */
     object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err);
     if (err) {
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 18/47] hw/arm/armsse: Add unimplemented-device stub for cache control registers
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (16 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 17/47] hw/arm/armsse: Add unimplemented-device stubs for PPUs Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 19/47] hw/arm/armsse: Add unimplemented-device stub for CPU local " Peter Maydell
                   ` (30 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The SSE-200 gives each CPU a register bank to use to control its
L1 instruction cache. Put in an unimplemented-device stub for this.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-18-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  1 +
 hw/arm/armsse.c         | 39 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 9855ec5f269..9d830057d5c 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -150,6 +150,7 @@ typedef struct ARMSSE {
 
     UnimplementedDeviceState mhu[2];
     UnimplementedDeviceState ppu[NUM_PPUS];
+    UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
 
     /*
      * 'container' holds all devices seen by all CPUs.
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 280ba5c78be..41e4a781e11 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -32,6 +32,7 @@ struct ARMSSEInfo {
     SysConfigFormat sys_config_format;
     bool has_mhus;
     bool has_ppus;
+    bool has_cachectrl;
 };
 
 static const ARMSSEInfo armsse_variants[] = {
@@ -43,6 +44,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .sys_config_format = IoTKitFormat,
         .has_mhus = false,
         .has_ppus = false,
+        .has_cachectrl = false,
     },
 };
 
@@ -290,6 +292,16 @@ static void armsse_init(Object *obj)
             g_free(name);
         }
     }
+    if (info->has_cachectrl) {
+        for (i = 0; i < info->num_cpus; i++) {
+            char *name = g_strdup_printf("cachectrl%d", i);
+
+            sysbus_init_child_obj(obj, name, &s->cachectrl[i],
+                                  sizeof(s->cachectrl[i]),
+                                  TYPE_UNIMPLEMENTED_DEVICE);
+            g_free(name);
+        }
+    }
     object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
                             sizeof(s->nmi_orgate), TYPE_OR_IRQ,
                             &error_abort, NULL);
@@ -795,7 +807,32 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     qdev_connect_gpio_out(DEVICE(&s->ppc_irq_orgate), 0,
                           armsse_get_common_irq_in(s, 10));
 
-    /* 0x40010000 .. 0x4001ffff: private CPU region: unused in IoTKit */
+    /*
+     * 0x40010000 .. 0x4001ffff (and the 0x5001000... secure-only alias):
+     * private per-CPU region (all these devices are SSE-200 only):
+     *  0x50010000: L1 icache control registers
+     *  0x50011000: CPUSECCTRL (CPU local security control registers)
+     *  0x4001f000 and 0x5001f000: CPU_IDENTITY register block
+     */
+    if (info->has_cachectrl) {
+        for (i = 0; i < info->num_cpus; i++) {
+            char *name = g_strdup_printf("cachectrl%d", i);
+            MemoryRegion *mr;
+
+            qdev_prop_set_string(DEVICE(&s->cachectrl[i]), "name", name);
+            g_free(name);
+            qdev_prop_set_uint64(DEVICE(&s->cachectrl[i]), "size", 0x1000);
+            object_property_set_bool(OBJECT(&s->cachectrl[i]), true,
+                                     "realized", &err);
+            if (err) {
+                error_propagate(errp, err);
+                return;
+            }
+
+            mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cachectrl[i]), 0);
+            memory_region_add_subregion(&s->cpu_container[i], 0x50010000, mr);
+        }
+    }
 
     /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
     /* Devices behind APB PPC1:
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 19/47] hw/arm/armsse: Add unimplemented-device stub for CPU local control registers
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (17 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 18/47] hw/arm/armsse: Add unimplemented-device stub for cache control registers Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 20/47] hw/misc/armsse-cpuid: Implement SSE-200 CPU_IDENTITY register block Peter Maydell
                   ` (29 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The SSE-200 has a "CPU local security control" register bank; add an
unimplemented-device stub for it. (The register bank has only one
interesting register, which allows the guest to lock down changes
to various CPU registers so they cannot be modified further. We
don't support that in our Cortex-M33 model anyway.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-19-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  1 +
 hw/arm/armsse.c         | 31 +++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 9d830057d5c..961dbb3032a 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -151,6 +151,7 @@ typedef struct ARMSSE {
     UnimplementedDeviceState mhu[2];
     UnimplementedDeviceState ppu[NUM_PPUS];
     UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
+    UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
 
     /*
      * 'container' holds all devices seen by all CPUs.
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 41e4a781e11..9c111ac6a40 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -33,6 +33,7 @@ struct ARMSSEInfo {
     bool has_mhus;
     bool has_ppus;
     bool has_cachectrl;
+    bool has_cpusecctrl;
 };
 
 static const ARMSSEInfo armsse_variants[] = {
@@ -45,6 +46,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_mhus = false,
         .has_ppus = false,
         .has_cachectrl = false,
+        .has_cpusecctrl = false,
     },
 };
 
@@ -302,6 +304,16 @@ static void armsse_init(Object *obj)
             g_free(name);
         }
     }
+    if (info->has_cpusecctrl) {
+        for (i = 0; i < info->num_cpus; i++) {
+            char *name = g_strdup_printf("cpusecctrl%d", i);
+
+            sysbus_init_child_obj(obj, name, &s->cpusecctrl[i],
+                                  sizeof(s->cpusecctrl[i]),
+                                  TYPE_UNIMPLEMENTED_DEVICE);
+            g_free(name);
+        }
+    }
     object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
                             sizeof(s->nmi_orgate), TYPE_OR_IRQ,
                             &error_abort, NULL);
@@ -833,6 +845,25 @@ static void armsse_realize(DeviceState *dev, Error **errp)
             memory_region_add_subregion(&s->cpu_container[i], 0x50010000, mr);
         }
     }
+    if (info->has_cpusecctrl) {
+        for (i = 0; i < info->num_cpus; i++) {
+            char *name = g_strdup_printf("CPUSECCTRL%d", i);
+            MemoryRegion *mr;
+
+            qdev_prop_set_string(DEVICE(&s->cpusecctrl[i]), "name", name);
+            g_free(name);
+            qdev_prop_set_uint64(DEVICE(&s->cpusecctrl[i]), "size", 0x1000);
+            object_property_set_bool(OBJECT(&s->cpusecctrl[i]), true,
+                                     "realized", &err);
+            if (err) {
+                error_propagate(errp, err);
+                return;
+            }
+
+            mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpusecctrl[i]), 0);
+            memory_region_add_subregion(&s->cpu_container[i], 0x50011000, mr);
+        }
+    }
 
     /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
     /* Devices behind APB PPC1:
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 20/47] hw/misc/armsse-cpuid: Implement SSE-200 CPU_IDENTITY register block
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (18 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 19/47] hw/arm/armsse: Add unimplemented-device stub for CPU local " Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 21/47] hw/arm/armsse: Add CPU_IDENTITY block to SSE-200 Peter Maydell
                   ` (28 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The SSE-200 has a CPU_IDENTITY register block, which is a set of
read-only registers. As well as the usual PID/CID registers, there
is a single CPUID register which indicates whether the CPU is CPU 0
or CPU 1. Implement a model of this register block.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-20-peter.maydell@linaro.org
---
 hw/misc/Makefile.objs           |   1 +
 include/hw/misc/armsse-cpuid.h  |  41 ++++++++++
 hw/misc/armsse-cpuid.c          | 134 ++++++++++++++++++++++++++++++++
 MAINTAINERS                     |   2 +
 default-configs/arm-softmmu.mak |   1 +
 hw/misc/trace-events            |   4 +
 6 files changed, 183 insertions(+)
 create mode 100644 include/hw/misc/armsse-cpuid.h
 create mode 100644 hw/misc/armsse-cpuid.c

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 04f3bfa516e..74c91d250c8 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -69,6 +69,7 @@ obj-$(CONFIG_TZ_PPC) += tz-ppc.o
 obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
 obj-$(CONFIG_IOTKIT_SYSCTL) += iotkit-sysctl.o
 obj-$(CONFIG_IOTKIT_SYSINFO) += iotkit-sysinfo.o
+obj-$(CONFIG_ARMSSE_CPUID) += armsse-cpuid.o
 
 obj-$(CONFIG_PVPANIC) += pvpanic.o
 obj-$(CONFIG_AUX) += auxbus.o
diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h
new file mode 100644
index 00000000000..0ef33fcaba2
--- /dev/null
+++ b/include/hw/misc/armsse-cpuid.h
@@ -0,0 +1,41 @@
+/*
+ * ARM SSE-200 CPU_IDENTITY register block
+ *
+ * Copyright (c) 2019 Linaro Limited
+ * Written by Peter Maydell
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 or
+ *  (at your option) any later version.
+ */
+
+/*
+ * This is a model of the "CPU_IDENTITY" register block which is part of the
+ * Arm SSE-200 and documented in
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ *
+ * QEMU interface:
+ *  + QOM property "CPUID": the value to use for the CPUID register
+ *  + sysbus MMIO region 0: the system information register bank
+ */
+
+#ifndef HW_MISC_ARMSSE_CPUID_H
+#define HW_MISC_ARMSSE_CPUID_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_ARMSSE_CPUID "armsse-cpuid"
+#define ARMSSE_CPUID(obj) OBJECT_CHECK(ARMSSECPUID, (obj), TYPE_ARMSSE_CPUID)
+
+typedef struct ARMSSECPUID {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    MemoryRegion iomem;
+
+    /* Properties */
+    uint32_t cpuid;
+} ARMSSECPUID;
+
+#endif
diff --git a/hw/misc/armsse-cpuid.c b/hw/misc/armsse-cpuid.c
new file mode 100644
index 00000000000..7788f6ced6a
--- /dev/null
+++ b/hw/misc/armsse-cpuid.c
@@ -0,0 +1,134 @@
+/*
+ * ARM SSE-200 CPU_IDENTITY register block
+ *
+ * Copyright (c) 2019 Linaro Limited
+ * Written by Peter Maydell
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 or
+ *  (at your option) any later version.
+ */
+
+/*
+ * This is a model of the "CPU_IDENTITY" register block which is part of the
+ * Arm SSE-200 and documented in
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ *
+ * It consists of one read-only CPUID register (set by QOM property), plus the
+ * usual ID registers.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "qapi/error.h"
+#include "sysemu/sysemu.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/misc/armsse-cpuid.h"
+
+REG32(CPUID, 0x0)
+REG32(PID4, 0xfd0)
+REG32(PID5, 0xfd4)
+REG32(PID6, 0xfd8)
+REG32(PID7, 0xfdc)
+REG32(PID0, 0xfe0)
+REG32(PID1, 0xfe4)
+REG32(PID2, 0xfe8)
+REG32(PID3, 0xfec)
+REG32(CID0, 0xff0)
+REG32(CID1, 0xff4)
+REG32(CID2, 0xff8)
+REG32(CID3, 0xffc)
+
+/* PID/CID values */
+static const int sysinfo_id[] = {
+    0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+    0x58, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
+    0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
+static uint64_t armsse_cpuid_read(void *opaque, hwaddr offset,
+                                    unsigned size)
+{
+    ARMSSECPUID *s = ARMSSE_CPUID(opaque);
+    uint64_t r;
+
+    switch (offset) {
+    case A_CPUID:
+        r = s->cpuid;
+        break;
+    case A_PID4 ... A_CID3:
+        r = sysinfo_id[(offset - A_PID4) / 4];
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE CPU_IDENTITY read: bad offset 0x%x\n", (int)offset);
+        r = 0;
+        break;
+    }
+    trace_armsse_cpuid_read(offset, r, size);
+    return r;
+}
+
+static void armsse_cpuid_write(void *opaque, hwaddr offset,
+                                 uint64_t value, unsigned size)
+{
+    trace_armsse_cpuid_write(offset, value, size);
+
+    qemu_log_mask(LOG_GUEST_ERROR,
+                  "SSE CPU_IDENTITY: write to RO offset 0x%x\n", (int)offset);
+}
+
+static const MemoryRegionOps armsse_cpuid_ops = {
+    .read = armsse_cpuid_read,
+    .write = armsse_cpuid_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    /* byte/halfword accesses are just zero-padded on reads and writes */
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 4,
+};
+
+static Property armsse_cpuid_props[] = {
+    DEFINE_PROP_UINT32("CPUID", ARMSSECPUID, cpuid, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void armsse_cpuid_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    ARMSSECPUID *s = ARMSSE_CPUID(obj);
+
+    memory_region_init_io(&s->iomem, obj, &armsse_cpuid_ops,
+                          s, "armsse-cpuid", 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void armsse_cpuid_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    /*
+     * This device has no guest-modifiable state and so it
+     * does not need a reset function or VMState.
+     */
+
+    dc->props = armsse_cpuid_props;
+}
+
+static const TypeInfo armsse_cpuid_info = {
+    .name = TYPE_ARMSSE_CPUID,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(ARMSSECPUID),
+    .instance_init = armsse_cpuid_init,
+    .class_init = armsse_cpuid_class_init,
+};
+
+static void armsse_cpuid_register_types(void)
+{
+    type_register_static(&armsse_cpuid_info);
+}
+
+type_init(armsse_cpuid_register_types);
diff --git a/MAINTAINERS b/MAINTAINERS
index c2ad4e52c9d..a70ecb1a696 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -631,6 +631,8 @@ F: hw/misc/iotkit-sysctl.c
 F: include/hw/misc/iotkit-sysctl.h
 F: hw/misc/iotkit-sysinfo.c
 F: include/hw/misc/iotkit-sysinfo.h
+F: hw/misc/armsse-cpuid.c
+F: include/hw/misc/armsse-cpuid.h
 
 Musicpal
 M: Jan Kiszka <jan.kiszka@web.de>
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 3f200157879..be88870799c 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -118,6 +118,7 @@ CONFIG_ARMSSE=y
 CONFIG_IOTKIT_SECCTL=y
 CONFIG_IOTKIT_SYSCTL=y
 CONFIG_IOTKIT_SYSINFO=y
+CONFIG_ARMSSE_CPUID=y
 
 CONFIG_VERSATILE=y
 CONFIG_VERSATILE_PCI=y
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 52466c77c4e..b0701bddd3c 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -132,3 +132,7 @@ iotkit_sysinfo_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysI
 iotkit_sysctl_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
 iotkit_sysctl_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
 iotkit_sysctl_reset(void) "IoTKit SysCtl: reset"
+
+# hw/misc/armsse-cpuid.c
+armsse_cpuid_read(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+armsse_cpuid_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 CPU_IDENTITY write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 21/47] hw/arm/armsse: Add CPU_IDENTITY block to SSE-200
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (19 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 20/47] hw/misc/armsse-cpuid: Implement SSE-200 CPU_IDENTITY register block Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 22/47] hw/arm/armsse: Add SSE-200 model Peter Maydell
                   ` (27 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Instantiate a copy of the CPU_IDENTITY register block for each CPU
in an SSE-200.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-21-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  3 +++
 hw/arm/armsse.c         | 28 ++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 961dbb3032a..3914e8e4bf2 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -78,6 +78,7 @@
 #include "hw/watchdog/cmsdk-apb-watchdog.h"
 #include "hw/misc/iotkit-sysctl.h"
 #include "hw/misc/iotkit-sysinfo.h"
+#include "hw/misc/armsse-cpuid.h"
 #include "hw/misc/unimp.h"
 #include "hw/or-irq.h"
 #include "hw/core/split-irq.h"
@@ -153,6 +154,8 @@ typedef struct ARMSSE {
     UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
     UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
 
+    ARMSSECPUID cpuid[SSE_MAX_CPUS];
+
     /*
      * 'container' holds all devices seen by all CPUs.
      * 'cpu_container[i]' is the view that CPU i has: this has the
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 9c111ac6a40..eb691faf720 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -34,6 +34,7 @@ struct ARMSSEInfo {
     bool has_ppus;
     bool has_cachectrl;
     bool has_cpusecctrl;
+    bool has_cpuid;
 };
 
 static const ARMSSEInfo armsse_variants[] = {
@@ -47,6 +48,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_ppus = false,
         .has_cachectrl = false,
         .has_cpusecctrl = false,
+        .has_cpuid = false,
     },
 };
 
@@ -314,6 +316,16 @@ static void armsse_init(Object *obj)
             g_free(name);
         }
     }
+    if (info->has_cpuid) {
+        for (i = 0; i < info->num_cpus; i++) {
+            char *name = g_strdup_printf("cpuid%d", i);
+
+            sysbus_init_child_obj(obj, name, &s->cpuid[i],
+                                  sizeof(s->cpuid[i]),
+                                  TYPE_ARMSSE_CPUID);
+            g_free(name);
+        }
+    }
     object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate,
                             sizeof(s->nmi_orgate), TYPE_OR_IRQ,
                             &error_abort, NULL);
@@ -864,6 +876,22 @@ static void armsse_realize(DeviceState *dev, Error **errp)
             memory_region_add_subregion(&s->cpu_container[i], 0x50011000, mr);
         }
     }
+    if (info->has_cpuid) {
+        for (i = 0; i < info->num_cpus; i++) {
+            MemoryRegion *mr;
+
+            qdev_prop_set_uint32(DEVICE(&s->cpuid[i]), "CPUID", i);
+            object_property_set_bool(OBJECT(&s->cpuid[i]), true,
+                                     "realized", &err);
+            if (err) {
+                error_propagate(errp, err);
+                return;
+            }
+
+            mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpuid[i]), 0);
+            memory_region_add_subregion(&s->cpu_container[i], 0x4001F000, mr);
+        }
+    }
 
     /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
     /* Devices behind APB PPC1:
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 22/47] hw/arm/armsse: Add SSE-200 model
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (20 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 21/47] hw/arm/armsse: Add CPU_IDENTITY block to SSE-200 Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 23/47] hw/arm/mps2-tz: Add IRQ infrastructure to support SSE-200 Peter Maydell
                   ` (26 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Add a model of the SSE-200, now we have put in all
the code that lets us make it different from the IoTKit.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-22-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h | 19 ++++++++++++++++---
 hw/arm/armsse.c         | 12 ++++++++++++
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 3914e8e4bf2..f800bafb14a 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -1,5 +1,5 @@
 /*
- * ARM SSE (Subsystems for Embedded): IoTKit
+ * ARM SSE (Subsystems for Embedded): IoTKit, SSE-200
  *
  * Copyright (c) 2018 Linaro Limited
  * Written by Peter Maydell
@@ -12,9 +12,13 @@
 /*
  * This is a model of the Arm "Subsystems for Embedded" family of
  * hardware, which include the IoT Kit and the SSE-050, SSE-100 and
- * SSE-200. Currently we model only the Arm IoT Kit which is documented in
+ * SSE-200. Currently we model:
+ *  - the Arm IoT Kit which is documented in
  * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
- * It contains:
+ *  - the SSE-200 which is documented in
+ * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ *
+ * The IoTKit contains:
  *  a Cortex-M33
  *  the IDAU
  *  some timers and watchdogs
@@ -23,6 +27,14 @@
  *  a security controller
  *  a bus fabric which arranges that some parts of the address
  *  space are secure and non-secure aliases of each other
+ * The SSE-200 additionally contains:
+ *  a second Cortex-M33
+ *  two Message Handling Units (MHUs)
+ *  an optional CryptoCell (which we do not model)
+ *  more SRAM banks with associated MPCs
+ *  multiple Power Policy Units (PPUs)
+ *  a control interface for an icache for each CPU
+ *  per-CPU identity and control register blocks
  *
  * QEMU interface:
  *  + QOM property "memory" is a MemoryRegion containing the devices provided
@@ -93,6 +105,7 @@
  * them via the ARMSSE base class, so they have no IOTKIT() etc macros.
  */
 #define TYPE_IOTKIT "iotkit"
+#define TYPE_SSE200 "sse-200"
 
 /* We have an IRQ splitter and an OR gate input for each external PPC
  * and the 2 internal PPCs
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index eb691faf720..5d53071a5a0 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -50,6 +50,18 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_cpusecctrl = false,
         .has_cpuid = false,
     },
+    {
+        .name = TYPE_SSE200,
+        .sram_banks = 4,
+        .num_cpus = 2,
+        .sys_version = 0x22041743,
+        .sys_config_format = SSE200Format,
+        .has_mhus = true,
+        .has_ppus = true,
+        .has_cachectrl = true,
+        .has_cpusecctrl = true,
+        .has_cpuid = true,
+    },
 };
 
 static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 23/47] hw/arm/mps2-tz: Add IRQ infrastructure to support SSE-200
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (21 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 22/47] hw/arm/armsse: Add SSE-200 model Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 24/47] hw/arm/mps2-tz: Add mps2-an521 model Peter Maydell
                   ` (25 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

In preparation for adding support for the AN521 MPS2 image, we need
to handle wiring up the MPS2 device interrupt lines to both CPUs in
the SSE-200, rather than just the one that the IoTKit has.

Abstract out a "connect to the IoTKit interrupt line" function
and make it connect to a splitter which feeds both sets of inputs
for the SSE-200 case.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-23-peter.maydell@linaro.org
---
 hw/arm/mps2-tz.c | 79 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 59 insertions(+), 20 deletions(-)

diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 3859f17d98b..95adcd478ab 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -53,8 +53,11 @@
 #include "net/net.h"
 #include "hw/core/split-irq.h"
 
+#define MPS2TZ_NUMIRQ 92
+
 typedef enum MPS2TZFPGAType {
     FPGA_AN505,
+    FPGA_AN521,
 } MPS2TZFPGAType;
 
 typedef struct {
@@ -85,6 +88,7 @@ typedef struct {
     SplitIRQ sec_resp_splitter;
     qemu_or_irq uart_irq_orgate;
     DeviceState *lan9118;
+    SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
 } MPS2TZMachineState;
 
 #define TYPE_MPS2TZ_MACHINE "mps2tz"
@@ -111,6 +115,23 @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
     memory_region_add_subregion(get_system_memory(), base, mr);
 }
 
+static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
+{
+    /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
+    MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
+
+    assert(irqno < MPS2TZ_NUMIRQ);
+
+    switch (mmc->fpga_type) {
+    case FPGA_AN505:
+        return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
+    case FPGA_AN521:
+        return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
+    default:
+        g_assert_not_reached();
+    }
+}
+
 /* Most of the devices in the AN505 FPGA image sit behind
  * Peripheral Protection Controllers. These data structures
  * define the layout of which devices sit behind which PPCs.
@@ -161,7 +182,6 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
     int txirqno = i * 2 + 1;
     int combirqno = i + 10;
     SysBusDevice *s;
-    DeviceState *iotkitdev = DEVICE(&mms->iotkit);
     DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
 
     sysbus_init_child_obj(OBJECT(mms), name, uart, sizeof(mms->uart[0]),
@@ -170,14 +190,11 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
     qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
     object_property_set_bool(OBJECT(uart), true, "realized", &error_fatal);
     s = SYS_BUS_DEVICE(uart);
-    sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
-                                                    "EXP_IRQ", txirqno));
-    sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
-                                                    "EXP_IRQ", rxirqno));
+    sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
+    sysbus_connect_irq(s, 1, get_sse_irq_in(mms, rxirqno));
     sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
     sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
-    sysbus_connect_irq(s, 4, qdev_get_gpio_in_named(iotkitdev,
-                                                    "EXP_IRQ", combirqno));
+    sysbus_connect_irq(s, 4, get_sse_irq_in(mms, combirqno));
     return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
 }
 
@@ -213,7 +230,6 @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
                                   const char *name, hwaddr size)
 {
     SysBusDevice *s;
-    DeviceState *iotkitdev = DEVICE(&mms->iotkit);
     NICInfo *nd = &nd_table[0];
 
     /* In hardware this is a LAN9220; the LAN9118 is software compatible
@@ -225,7 +241,7 @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
     qdev_init_nofail(mms->lan9118);
 
     s = SYS_BUS_DEVICE(mms->lan9118);
-    sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
+    sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 16));
     return sysbus_mmio_get_region(s, 0);
 }
 
@@ -315,12 +331,9 @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
 
     s = SYS_BUS_DEVICE(dma);
     /* Wire up DMACINTR, DMACINTERR, DMACINTTC */
-    sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev,
-                                                    "EXP_IRQ", 58 + i * 3));
-    sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev,
-                                                    "EXP_IRQ", 56 + i * 3));
-    sysbus_connect_irq(s, 2, qdev_get_gpio_in_named(iotkitdev,
-                                                    "EXP_IRQ", 57 + i * 3));
+    sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 58 + i * 3));
+    sysbus_connect_irq(s, 1, get_sse_irq_in(mms, 56 + i * 3));
+    sysbus_connect_irq(s, 2, get_sse_irq_in(mms, 57 + i * 3));
 
     g_free(mscname);
     return sysbus_mmio_get_region(s, 0);
@@ -339,21 +352,20 @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
      */
     PL022State *spi = opaque;
     int i = spi - &mms->spi[0];
-    DeviceState *iotkitdev = DEVICE(&mms->iotkit);
     SysBusDevice *s;
 
     sysbus_init_child_obj(OBJECT(mms), name, spi, sizeof(mms->spi[0]),
                           TYPE_PL022);
     object_property_set_bool(OBJECT(spi), true, "realized", &error_fatal);
     s = SYS_BUS_DEVICE(spi);
-    sysbus_connect_irq(s, 0,
-                       qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 51 + i));
+    sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 51 + i));
     return sysbus_mmio_get_region(s, 0);
 }
 
 static void mps2tz_common_init(MachineState *machine)
 {
     MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
+    MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
     MachineClass *mc = MACHINE_GET_CLASS(machine);
     MemoryRegion *system_memory = get_system_memory();
     DeviceState *iotkitdev;
@@ -371,11 +383,38 @@ static void mps2tz_common_init(MachineState *machine)
     iotkitdev = DEVICE(&mms->iotkit);
     object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
                              "memory", &error_abort);
-    qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", 92);
+    qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
     qdev_prop_set_uint32(iotkitdev, "MAINCLK", SYSCLK_FRQ);
     object_property_set_bool(OBJECT(&mms->iotkit), true, "realized",
                              &error_fatal);
 
+    /*
+     * The AN521 needs us to create splitters to feed the IRQ inputs
+     * for each CPU in the SSE-200 from each device in the board.
+     */
+    if (mmc->fpga_type == FPGA_AN521) {
+        for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
+            char *name = g_strdup_printf("mps2-irq-splitter%d", i);
+            SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
+
+            object_initialize_child(OBJECT(machine), name,
+                                    splitter, sizeof(*splitter),
+                                    TYPE_SPLIT_IRQ, &error_fatal, NULL);
+            g_free(name);
+
+            object_property_set_int(OBJECT(splitter), 2, "num-lines",
+                                    &error_fatal);
+            object_property_set_bool(OBJECT(splitter), true, "realized",
+                                     &error_fatal);
+            qdev_connect_gpio_out(DEVICE(splitter), 0,
+                                  qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
+                                                         "EXP_IRQ", i));
+            qdev_connect_gpio_out(DEVICE(splitter), 1,
+                                  qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
+                                                         "EXP_CPU1_IRQ", i));
+        }
+    }
+
     /* The sec_resp_cfg output from the IoTKit must be split into multiple
      * lines, one for each of the PPCs we create here, plus one per MSC.
      */
@@ -426,7 +465,7 @@ static void mps2tz_common_init(MachineState *machine)
     object_property_set_bool(OBJECT(&mms->uart_irq_orgate), true,
                              "realized", &error_fatal);
     qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
-                          qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 15));
+                          get_sse_irq_in(mms, 15));
 
     /* Most of the devices in the FPGA are behind Peripheral Protection
      * Controllers. The required order for initializing things is:
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 24/47] hw/arm/mps2-tz: Add mps2-an521 model
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (22 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 23/47] hw/arm/mps2-tz: Add IRQ infrastructure to support SSE-200 Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 25/47] target/arm/translate-a64: Don't underdecode system instructions Peter Maydell
                   ` (24 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

Add a model of the MPS2 FPGA image described in Application Note
AN521. This is identical to the AN505 image, except that it uses
the SSE-200 rather than the IoTKit and so has two Cortex-M33 CPUs.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190121185118.18550-24-peter.maydell@linaro.org
---
 hw/arm/mps2-tz.c | 38 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 95adcd478ab..f5f0b0e0fa5 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -15,6 +15,7 @@
  * as seen by the guest depend significantly on the FPGA image.
  * This source file covers the following FPGA images, for TrustZone cores:
  *  "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
+ *  "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
  *
  * Links to the TRM for the board itself and to the various Application
  * Notes which document the FPGA images can be found here:
@@ -24,10 +25,16 @@
  * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
  * Application Note AN505:
  * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
+ * Application Note AN521:
+ * http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
  *
  * The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
  * (ARM ECM0601256) for the details of some of the device layout:
  *   http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
+ * Similarly, the AN521 uses the SSE-200, and the SSE-200 TRM defines
+ * most of the device layout:
+ *  http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
+ *
  */
 
 #include "qemu/osdep.h"
@@ -64,6 +71,7 @@ typedef struct {
     MachineClass parent;
     MPS2TZFPGAType fpga_type;
     uint32_t scc_id;
+    const char *armsse_type;
 } MPS2TZMachineClass;
 
 typedef struct {
@@ -93,6 +101,7 @@ typedef struct {
 
 #define TYPE_MPS2TZ_MACHINE "mps2tz"
 #define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
+#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
 
 #define MPS2TZ_MACHINE(obj) \
     OBJECT_CHECK(MPS2TZMachineState, obj, TYPE_MPS2TZ_MACHINE)
@@ -379,7 +388,7 @@ static void mps2tz_common_init(MachineState *machine)
     }
 
     sysbus_init_child_obj(OBJECT(machine), "iotkit", &mms->iotkit,
-                          sizeof(mms->iotkit), TYPE_IOTKIT);
+                          sizeof(mms->iotkit), mmc->armsse_type);
     iotkitdev = DEVICE(&mms->iotkit);
     object_property_set_link(OBJECT(&mms->iotkit), OBJECT(system_memory),
                              "memory", &error_abort);
@@ -632,7 +641,6 @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
     IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
 
     mc->init = mps2tz_common_init;
-    mc->max_cpus = 1;
     iic->check = mps2_tz_idau_check;
 }
 
@@ -642,9 +650,28 @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
     MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
 
     mc->desc = "ARM MPS2 with AN505 FPGA image for Cortex-M33";
+    mc->default_cpus = 1;
+    mc->min_cpus = mc->default_cpus;
+    mc->max_cpus = mc->default_cpus;
     mmc->fpga_type = FPGA_AN505;
     mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
     mmc->scc_id = 0x41045050;
+    mmc->armsse_type = TYPE_IOTKIT;
+}
+
+static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+    MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
+
+    mc->desc = "ARM MPS2 with AN521 FPGA image for dual Cortex-M33";
+    mc->default_cpus = 2;
+    mc->min_cpus = mc->default_cpus;
+    mc->max_cpus = mc->default_cpus;
+    mmc->fpga_type = FPGA_AN521;
+    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
+    mmc->scc_id = 0x41045210;
+    mmc->armsse_type = TYPE_SSE200;
 }
 
 static const TypeInfo mps2tz_info = {
@@ -666,10 +693,17 @@ static const TypeInfo mps2tz_an505_info = {
     .class_init = mps2tz_an505_class_init,
 };
 
+static const TypeInfo mps2tz_an521_info = {
+    .name = TYPE_MPS2TZ_AN521_MACHINE,
+    .parent = TYPE_MPS2TZ_MACHINE,
+    .class_init = mps2tz_an521_class_init,
+};
+
 static void mps2tz_machine_init(void)
 {
     type_register_static(&mps2tz_info);
     type_register_static(&mps2tz_an505_info);
+    type_register_static(&mps2tz_an521_info);
 }
 
 type_init(mps2tz_machine_init);
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 25/47] target/arm/translate-a64: Don't underdecode system instructions
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (23 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 24/47] hw/arm/mps2-tz: Add mps2-an521 model Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 26/47] target/arm/translate-a64: Don't underdecode PRFM Peter Maydell
                   ` (23 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The "system instructions" and "system register move" subcategories
of "branches, exception generating and system instructions" for A64
only apply if bits [23:22] are zero; other values are currently
unallocated. Correctly UNDEF these unallocated encodings.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20190125182626.9221-2-peter.maydell@linaro.org
---
 target/arm/translate-a64.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 4d28a27c3bd..e6df303e321 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -2144,7 +2144,11 @@ static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
         break;
     case 0x6a: /* Exception generation / System */
         if (insn & (1 << 24)) {
-            disas_system(s, insn);
+            if (extract32(insn, 22, 2) == 0) {
+                disas_system(s, insn);
+            } else {
+                unallocated_encoding(s);
+            }
         } else {
             disas_exc(s, insn);
         }
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 26/47] target/arm/translate-a64: Don't underdecode PRFM
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (24 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 25/47] target/arm/translate-a64: Don't underdecode system instructions Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 27/47] target/arm/translate-a64: Don't underdecode SIMD ld/st multiple Peter Maydell
                   ` (22 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The PRFM prefetch insn in the load/store with imm9 encodings
requires idx field 0b00; we were underdecoding this by
only checking !is_unpriv (which is equivalent to idx != 2).
Correctly UNDEF the unallocated encodings where idx == 0b01
and 0b11 as well as 0b10.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20190125182626.9221-3-peter.maydell@linaro.org
---
 target/arm/translate-a64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index e6df303e321..8e081758e03 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -2803,7 +2803,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
     } else {
         if (size == 3 && opc == 2) {
             /* PRFM - prefetch */
-            if (is_unpriv) {
+            if (idx != 0) {
                 unallocated_encoding(s);
                 return;
             }
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 27/47] target/arm/translate-a64: Don't underdecode SIMD ld/st multiple
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (25 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 26/47] target/arm/translate-a64: Don't underdecode PRFM Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 28/47] target/arm/translate-a64: Don't underdecode SIMD ld/st single Peter Maydell
                   ` (21 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

In the AdvSIMD load/store multiple structures encodings,
the non-post-indexed case should have zeroes in [20:16]
(which is the Rm field for the post-indexed case).
Correctly UNDEF the currently unallocated encodings which
have non-zeroes in those bits.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20190125182626.9221-4-peter.maydell@linaro.org
---
 target/arm/translate-a64.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 8e081758e03..c1f0cad7691 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -3249,6 +3249,7 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
 {
     int rt = extract32(insn, 0, 5);
     int rn = extract32(insn, 5, 5);
+    int rm = extract32(insn, 16, 5);
     int size = extract32(insn, 10, 2);
     int opcode = extract32(insn, 12, 4);
     bool is_store = !extract32(insn, 22, 1);
@@ -3268,6 +3269,11 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
         return;
     }
 
+    if (!is_postidx && rm != 0) {
+        unallocated_encoding(s);
+        return;
+    }
+
     /* From the shared decode logic */
     switch (opcode) {
     case 0x0:
@@ -3367,7 +3373,6 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
     }
 
     if (is_postidx) {
-        int rm = extract32(insn, 16, 5);
         if (rm == 31) {
             tcg_gen_mov_i64(tcg_rn, tcg_addr);
         } else {
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 28/47] target/arm/translate-a64: Don't underdecode SIMD ld/st single
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (26 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 27/47] target/arm/translate-a64: Don't underdecode SIMD ld/st multiple Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 29/47] target/arm/translate-a64: Don't underdecode add/sub extended register Peter Maydell
                   ` (20 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

In the AdvSIMD load/store single structure encodings, the
non-post-indexed case should have zeroes in [20:16] (which is the
Rm field for the post-indexed case). Bit 31 must also be zero
(a check we got right in ldst_multiple but not here). Correctly
UNDEF these unallocated encodings.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20190125182626.9221-5-peter.maydell@linaro.org
---
 target/arm/translate-a64.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index c1f0cad7691..2cade64ed25 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -3409,6 +3409,7 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
 {
     int rt = extract32(insn, 0, 5);
     int rn = extract32(insn, 5, 5);
+    int rm = extract32(insn, 16, 5);
     int size = extract32(insn, 10, 2);
     int S = extract32(insn, 12, 1);
     int opc = extract32(insn, 13, 3);
@@ -3424,6 +3425,15 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
     int ebytes, xs;
     TCGv_i64 tcg_addr, tcg_rn, tcg_ebytes;
 
+    if (extract32(insn, 31, 1)) {
+        unallocated_encoding(s);
+        return;
+    }
+    if (!is_postidx && rm != 0) {
+        unallocated_encoding(s);
+        return;
+    }
+
     switch (scale) {
     case 3:
         if (!is_load || S) {
@@ -3501,7 +3511,6 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
     }
 
     if (is_postidx) {
-        int rm = extract32(insn, 16, 5);
         if (rm == 31) {
             tcg_gen_mov_i64(tcg_rn, tcg_addr);
         } else {
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 29/47] target/arm/translate-a64: Don't underdecode add/sub extended register
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (27 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 28/47] target/arm/translate-a64: Don't underdecode SIMD ld/st single Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 30/47] target/arm/translate-a64: Don't underdecode FP insns Peter Maydell
                   ` (19 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

In the "add/subtract (extended register)" encoding group, the "opt"
field in bits [23:22] must be zero. Correctly UNDEF the unallocated
encodings where this field is not zero.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20190125182626.9221-6-peter.maydell@linaro.org
---
 target/arm/translate-a64.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 2cade64ed25..94907f0ae97 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -4201,6 +4201,7 @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
     int imm3 = extract32(insn, 10, 3);
     int option = extract32(insn, 13, 3);
     int rm = extract32(insn, 16, 5);
+    int opt = extract32(insn, 22, 2);
     bool setflags = extract32(insn, 29, 1);
     bool sub_op = extract32(insn, 30, 1);
     bool sf = extract32(insn, 31, 1);
@@ -4209,7 +4210,7 @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
     TCGv_i64 tcg_rd;
     TCGv_i64 tcg_result;
 
-    if (imm3 > 4) {
+    if (imm3 > 4 || opt != 0) {
         unallocated_encoding(s);
         return;
     }
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 30/47] target/arm/translate-a64: Don't underdecode FP insns
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (28 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 29/47] target/arm/translate-a64: Don't underdecode add/sub extended register Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 31/47] target/arm/translate-a64: Don't underdecode SDOT and UDOT Peter Maydell
                   ` (18 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

In the encoding groups
 * floating-point data-processing (1 source)
 * floating-point data-processing (2 source)
 * floating-point data-processing (3 source)
 * floating-point immediate
 * floating-point compare
 * floating-ponit conditional compare
 * floating-point conditional select

bit 31 is M and bit 29 is S (and bit 30 is 0, already checked at
this point in the decode). None of these groups allocate any
encoding for M=1 or S=1. We checked this in disas_fp_compare(),
disas_fp_ccomp() and disas_fp_csel(), but missed it in disas_fp_1src(),
disas_fp_2src(), disas_fp_3src() and disas_fp_imm().

We also missed that in the fp immediate encoding the imm5 field
must be all zeroes.

Correctly UNDEF the unallocated encodings here.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20190125182626.9221-7-peter.maydell@linaro.org
---
 target/arm/translate-a64.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 94907f0ae97..6c4b20daf2c 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -5636,11 +5636,17 @@ static void handle_fp_fcvt(DisasContext *s, int opcode,
  */
 static void disas_fp_1src(DisasContext *s, uint32_t insn)
 {
+    int mos = extract32(insn, 29, 3);
     int type = extract32(insn, 22, 2);
     int opcode = extract32(insn, 15, 6);
     int rn = extract32(insn, 5, 5);
     int rd = extract32(insn, 0, 5);
 
+    if (mos) {
+        unallocated_encoding(s);
+        return;
+    }
+
     switch (opcode) {
     case 0x4: case 0x5: case 0x7:
     {
@@ -5867,13 +5873,14 @@ static void handle_fp_2src_half(DisasContext *s, int opcode,
  */
 static void disas_fp_2src(DisasContext *s, uint32_t insn)
 {
+    int mos = extract32(insn, 29, 3);
     int type = extract32(insn, 22, 2);
     int rd = extract32(insn, 0, 5);
     int rn = extract32(insn, 5, 5);
     int rm = extract32(insn, 16, 5);
     int opcode = extract32(insn, 12, 4);
 
-    if (opcode > 8) {
+    if (opcode > 8 || mos) {
         unallocated_encoding(s);
         return;
     }
@@ -6028,6 +6035,7 @@ static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1,
  */
 static void disas_fp_3src(DisasContext *s, uint32_t insn)
 {
+    int mos = extract32(insn, 29, 3);
     int type = extract32(insn, 22, 2);
     int rd = extract32(insn, 0, 5);
     int rn = extract32(insn, 5, 5);
@@ -6036,6 +6044,11 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
     bool o0 = extract32(insn, 15, 1);
     bool o1 = extract32(insn, 21, 1);
 
+    if (mos) {
+        unallocated_encoding(s);
+        return;
+    }
+
     switch (type) {
     case 0:
         if (!fp_access_check(s)) {
@@ -6105,12 +6118,19 @@ uint64_t vfp_expand_imm(int size, uint8_t imm8)
 static void disas_fp_imm(DisasContext *s, uint32_t insn)
 {
     int rd = extract32(insn, 0, 5);
+    int imm5 = extract32(insn, 5, 5);
     int imm8 = extract32(insn, 13, 8);
     int type = extract32(insn, 22, 2);
+    int mos = extract32(insn, 29, 3);
     uint64_t imm;
     TCGv_i64 tcg_res;
     TCGMemOp sz;
 
+    if (mos || imm5) {
+        unallocated_encoding(s);
+        return;
+    }
+
     switch (type) {
     case 0:
         sz = MO_32;
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 31/47] target/arm/translate-a64: Don't underdecode SDOT and UDOT
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (29 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 30/47] target/arm/translate-a64: Don't underdecode FP insns Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 32/47] exec.c: Don't reallocate IOMMUNotifiers that are in use Peter Maydell
                   ` (17 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

In the AdvSIMD scalar x indexed element and vector x indexed element
encoding group, the SDOT and UDOT instructions are vector only,
and their opcode is unallocated in the scalar group. Correctly
UNDEF this unallocated encoding.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20190125182626.9221-8-peter.maydell@linaro.org
---
 target/arm/translate-a64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 6c4b20daf2c..07fa0523935 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -12641,7 +12641,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
         break;
     case 0x0e: /* SDOT */
     case 0x1e: /* UDOT */
-        if (size != MO_32 || !dc_isar_feature(aa64_dp, s)) {
+        if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_dp, s)) {
             unallocated_encoding(s);
             return;
         }
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 32/47] exec.c: Don't reallocate IOMMUNotifiers that are in use
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (30 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 31/47] target/arm/translate-a64: Don't underdecode SDOT and UDOT Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 33/47] target/arm/translate-a64: Fix FCMLA decoding error Peter Maydell
                   ` (16 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The tcg_register_iommu_notifier() code has a GArray of
TCGIOMMUNotifier structs which it has registered by passing
memory_region_register_iommu_notifier() a pointer to the embedded
IOMMUNotifier field. Unfortunately, if we need to enlarge the
array via g_array_set_size() this can cause a realloc(), which
invalidates the pointer that memory_region_register_iommu_notifier()
put into the MemoryRegion's iommu_notify list. This can result
in segfaults.

Switch the GArray to holding pointers to the TCGIOMMUNotifier
structs, so that we can individually allocate and free them.

Cc: qemu-stable@nongnu.org
Fixes: 1f871c5e6b0f30644a60a ("exec.c: Handle IOMMUs in address_space_translate_for_iotlb()")
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190128174241.5860-1-peter.maydell@linaro.org
---
 exec.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/exec.c b/exec.c
index da3e635f91b..25f3938a271 100644
--- a/exec.c
+++ b/exec.c
@@ -665,7 +665,7 @@ static void tcg_register_iommu_notifier(CPUState *cpu,
     int i;
 
     for (i = 0; i < cpu->iommu_notifiers->len; i++) {
-        notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
+        notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
         if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
             break;
         }
@@ -673,7 +673,8 @@ static void tcg_register_iommu_notifier(CPUState *cpu,
     if (i == cpu->iommu_notifiers->len) {
         /* Not found, add a new entry at the end of the array */
         cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
-        notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
+        notifier = g_new0(TCGIOMMUNotifier, 1);
+        g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i) = notifier;
 
         notifier->mr = mr;
         notifier->iommu_idx = iommu_idx;
@@ -705,8 +706,9 @@ static void tcg_iommu_free_notifier_list(CPUState *cpu)
     TCGIOMMUNotifier *notifier;
 
     for (i = 0; i < cpu->iommu_notifiers->len; i++) {
-        notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
+        notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
         memory_region_unregister_iommu_notifier(notifier->mr, &notifier->n);
+        g_free(notifier);
     }
     g_array_free(cpu->iommu_notifiers, true);
 }
@@ -976,7 +978,7 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
         vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
     }
 
-    cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier));
+    cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier *));
 #endif
 }
 
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 33/47] target/arm/translate-a64: Fix FCMLA decoding error
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (31 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 32/47] exec.c: Don't reallocate IOMMUNotifiers that are in use Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 34/47] target/arm/translate-a64: Fix mishandling of size in FCMLA decode Peter Maydell
                   ` (15 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

The FCMLA (by element) instruction exists in the
"vector x indexed element" encoding group, but not in
the "scalar x indexed element" group. Correctly UNDEF
the unallocated encodings.

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20190129140411.682-2-peter.maydell@linaro.org
---
 target/arm/translate-a64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 07fa0523935..d46ea9f64e7 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -12650,7 +12650,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
     case 0x13: /* FCMLA #90 */
     case 0x15: /* FCMLA #180 */
     case 0x17: /* FCMLA #270 */
-        if (!dc_isar_feature(aa64_fcma, s)) {
+        if (is_scalar || !dc_isar_feature(aa64_fcma, s)) {
             unallocated_encoding(s);
             return;
         }
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 34/47] target/arm/translate-a64: Fix mishandling of size in FCMLA decode
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (32 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 33/47] target/arm/translate-a64: Fix FCMLA decoding error Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 35/47] target/arm: Send interrupts on PMU counter overflow Peter Maydell
                   ` (14 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

In disas_simd_indexed(), for the case of "complex fp", each indexable
element is a complex pair, so the total size is twice that indicated
in the 'size' field in the encoding. We were trying to do this
"double the size" operation with a left shift by 1, but this is
incorrect because the 'size' field is a MO_8/MO_16/MO_32/MO_64
value, and doubling the size should be done by a simple increment.

This meant we were mishandling FCMLA (by element) of values where
the real and imaginary parts are 32-bit floats, and would incorrectly
UNDEF this encoding. (No other insns take this code path, and for
16-bit floats it happens that 1 << 1 and 1 + 1 are both the same).

Reported-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Message-id: 20190129140411.682-3-peter.maydell@linaro.org
---
 target/arm/translate-a64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index d46ea9f64e7..b864ac7a69f 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -12680,7 +12680,7 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
 
     case 2: /* complex fp */
         /* Each indexable element is a complex pair.  */
-        size <<= 1;
+        size += 1;
         switch (size) {
         case MO_32:
             if (h && !is_q) {
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 35/47] target/arm: Send interrupts on PMU counter overflow
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (33 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 34/47] target/arm/translate-a64: Fix mishandling of size in FCMLA decode Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2020-02-25 17:08   ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 36/47] target/arm: Add a timer to predict " Peter Maydell
                   ` (13 subsequent siblings)
  48 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Aaron Lindsay OS <aaron@os.amperecomputing.com>

Whenever we notice that a counter overflow has occurred, send an
interrupt. This is made more reliable with the addition of a timer in a
follow-on commit.

Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190124162401.5111-2-aaron@os.amperecomputing.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/helper.c | 61 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 51 insertions(+), 10 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 66faebea8ec..c27e349dd05 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -977,6 +977,7 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
 /* Definitions for the PMU registers */
 #define PMCRN_MASK  0xf800
 #define PMCRN_SHIFT 11
+#define PMCRLC  0x40
 #define PMCRDP  0x10
 #define PMCRD   0x8
 #define PMCRC   0x4
@@ -1293,6 +1294,13 @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter)
     return enabled && !prohibited && !filtered;
 }
 
+static void pmu_update_irq(CPUARMState *env)
+{
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) &&
+            (env->cp15.c9_pminten & env->cp15.c9_pmovsr));
+}
+
 /*
  * Ensure c15_ccnt is the guest-visible count so that operations such as
  * enabling/disabling the counter or filtering, modifying the count itself,
@@ -1310,7 +1318,16 @@ void pmccntr_op_start(CPUARMState *env)
             eff_cycles /= 64;
         }
 
-        env->cp15.c15_ccnt = eff_cycles - env->cp15.c15_ccnt_delta;
+        uint64_t new_pmccntr = eff_cycles - env->cp15.c15_ccnt_delta;
+
+        uint64_t overflow_mask = env->cp15.c9_pmcr & PMCRLC ? \
+                                 1ull << 63 : 1ull << 31;
+        if (env->cp15.c15_ccnt & ~new_pmccntr & overflow_mask) {
+            env->cp15.c9_pmovsr |= (1 << 31);
+            pmu_update_irq(env);
+        }
+
+        env->cp15.c15_ccnt = new_pmccntr;
     }
     env->cp15.c15_ccnt_delta = cycles;
 }
@@ -1345,8 +1362,13 @@ static void pmevcntr_op_start(CPUARMState *env, uint8_t counter)
     }
 
     if (pmu_counter_enabled(env, counter)) {
-        env->cp15.c14_pmevcntr[counter] =
-            count - env->cp15.c14_pmevcntr_delta[counter];
+        uint32_t new_pmevcntr = count - env->cp15.c14_pmevcntr_delta[counter];
+
+        if (env->cp15.c14_pmevcntr[counter] & ~new_pmevcntr & INT32_MIN) {
+            env->cp15.c9_pmovsr |= (1 << counter);
+            pmu_update_irq(env);
+        }
+        env->cp15.c14_pmevcntr[counter] = new_pmevcntr;
     }
     env->cp15.c14_pmevcntr_delta[counter] = count;
 }
@@ -1423,7 +1445,20 @@ static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri,
                 /* counter is SW_INCR */
                 (env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) == 0x0) {
             pmevcntr_op_start(env, i);
-            env->cp15.c14_pmevcntr[i]++;
+
+            /*
+             * Detect if this write causes an overflow since we can't predict
+             * PMSWINC overflows like we can for other events
+             */
+            uint32_t new_pmswinc = env->cp15.c14_pmevcntr[i] + 1;
+
+            if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & INT32_MIN) {
+                env->cp15.c9_pmovsr |= (1 << i);
+                pmu_update_irq(env);
+            }
+
+            env->cp15.c14_pmevcntr[i] = new_pmswinc;
+
             pmevcntr_op_finish(env, i);
         }
     }
@@ -1508,6 +1543,7 @@ static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     value &= pmu_counter_mask(env);
     env->cp15.c9_pmovsr &= ~value;
+    pmu_update_irq(env);
 }
 
 static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -1515,6 +1551,7 @@ static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     value &= pmu_counter_mask(env);
     env->cp15.c9_pmovsr |= value;
+    pmu_update_irq(env);
 }
 
 static void pmevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -1701,6 +1738,7 @@ static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri,
     /* We have no event counters so only the C bit can be changed */
     value &= pmu_counter_mask(env);
     env->cp15.c9_pminten |= value;
+    pmu_update_irq(env);
 }
 
 static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -1708,6 +1746,7 @@ static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 {
     value &= pmu_counter_mask(env);
     env->cp15.c9_pminten &= ~value;
+    pmu_update_irq(env);
 }
 
 static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -1846,7 +1885,7 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
       .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten),
       .writefn = pmcntenclr_write },
     { .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3,
-      .access = PL0_RW,
+      .access = PL0_RW, .type = ARM_CP_IO,
       .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr),
       .accessfn = pmreg_access,
       .writefn = pmovsr_write,
@@ -1854,16 +1893,18 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
     { .name = "PMOVSCLR_EL0", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 3,
       .access = PL0_RW, .accessfn = pmreg_access,
-      .type = ARM_CP_ALIAS,
+      .type = ARM_CP_ALIAS | ARM_CP_IO,
       .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
       .writefn = pmovsr_write,
       .raw_writefn = raw_write },
     { .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4,
-      .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NO_RAW,
+      .access = PL0_W, .accessfn = pmreg_access_swinc,
+      .type = ARM_CP_NO_RAW | ARM_CP_IO,
       .writefn = pmswinc_write },
     { .name = "PMSWINC_EL0", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 4,
-      .access = PL0_W, .accessfn = pmreg_access_swinc, .type = ARM_CP_NO_RAW,
+      .access = PL0_W, .accessfn = pmreg_access_swinc,
+      .type = ARM_CP_NO_RAW | ARM_CP_IO,
       .writefn = pmswinc_write },
     { .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5,
       .access = PL0_RW, .type = ARM_CP_ALIAS,
@@ -2050,14 +2091,14 @@ static const ARMCPRegInfo pmovsset_cp_reginfo[] = {
     /* PMOVSSET is not implemented in v7 before v7ve */
     { .name = "PMOVSSET", .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 3,
       .access = PL0_RW, .accessfn = pmreg_access,
-      .type = ARM_CP_ALIAS,
+      .type = ARM_CP_ALIAS | ARM_CP_IO,
       .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmovsr),
       .writefn = pmovsset_write,
       .raw_writefn = raw_write },
     { .name = "PMOVSSET_EL0", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 14, .opc2 = 3,
       .access = PL0_RW, .accessfn = pmreg_access,
-      .type = ARM_CP_ALIAS,
+      .type = ARM_CP_ALIAS | ARM_CP_IO,
       .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr),
       .writefn = pmovsset_write,
       .raw_writefn = raw_write },
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 36/47] target/arm: Add a timer to predict PMU counter overflow
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (34 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 35/47] target/arm: Send interrupts on PMU counter overflow Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 37/47] target/arm: Enable API, APK bits in SCR, HCR Peter Maydell
                   ` (12 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Aaron Lindsay OS <aaron@os.amperecomputing.com>

Make PMU overflow interrupts more accurate by using a timer to predict
when they will overflow rather than waiting for an event to occur which
allows us to otherwise check them.

Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190124162401.5111-3-aaron@os.amperecomputing.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.h    | 10 +++++++
 target/arm/cpu.c    | 12 ++++++++
 target/arm/helper.c | 72 +++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index b8161cb6d73..63934a200ad 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -746,6 +746,11 @@ struct ARMCPU {
 
     /* Timers used by the generic (architected) timer */
     QEMUTimer *gt_timer[NUM_GTIMERS];
+    /*
+     * Timer used by the PMU. Its state is restored after migration by
+     * pmu_op_finish() - it does not need other handling during migration
+     */
+    QEMUTimer *pmu_timer;
     /* GPIO outputs for generic timer */
     qemu_irq gt_timer_outputs[NUM_GTIMERS];
     /* GPIO output for GICv3 maintenance interrupt signal */
@@ -1005,6 +1010,11 @@ void pmccntr_op_finish(CPUARMState *env);
 void pmu_op_start(CPUARMState *env);
 void pmu_op_finish(CPUARMState *env);
 
+/*
+ * Called when a PMU counter is due to overflow
+ */
+void arm_pmu_timer_cb(void *opaque);
+
 /**
  * Functions to register as EL change hooks for PMU mode filtering
  */
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index d6da3f4fed3..8a9cd0900d2 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -836,6 +836,13 @@ static void arm_cpu_finalizefn(Object *obj)
         QLIST_REMOVE(hook, node);
         g_free(hook);
     }
+#ifndef CONFIG_USER_ONLY
+    if (cpu->pmu_timer) {
+        timer_del(cpu->pmu_timer);
+        timer_deinit(cpu->pmu_timer);
+        timer_free(cpu->pmu_timer);
+    }
+#endif
 }
 
 static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
@@ -1045,6 +1052,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
             arm_register_pre_el_change_hook(cpu, &pmu_pre_el_change, 0);
             arm_register_el_change_hook(cpu, &pmu_post_el_change, 0);
         }
+
+#ifndef CONFIG_USER_ONLY
+        cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, arm_pmu_timer_cb,
+                cpu);
+#endif
     } else {
         cpu->id_aa64dfr0 &= ~0xf00;
         cpu->pmceid0 = 0;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index c27e349dd05..e6f69180ba0 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1021,6 +1021,13 @@ typedef struct pm_event {
      * counters hold a difference from the return value from this function
      */
     uint64_t (*get_count)(CPUARMState *);
+    /*
+     * Return how many nanoseconds it will take (at a minimum) for count events
+     * to occur. A negative value indicates the counter will never overflow, or
+     * that the counter has otherwise arranged for the overflow bit to be set
+     * and the PMU interrupt to be raised on overflow.
+     */
+    int64_t (*ns_per_count)(uint64_t);
 } pm_event;
 
 static bool event_always_supported(CPUARMState *env)
@@ -1037,6 +1044,11 @@ static uint64_t swinc_get_count(CPUARMState *env)
     return 0;
 }
 
+static int64_t swinc_ns_per(uint64_t ignored)
+{
+    return -1;
+}
+
 /*
  * Return the underlying cycle count for the PMU cycle counters. If we're in
  * usermode, simply return 0.
@@ -1052,6 +1064,11 @@ static uint64_t cycles_get_count(CPUARMState *env)
 }
 
 #ifndef CONFIG_USER_ONLY
+static int64_t cycles_ns_per(uint64_t cycles)
+{
+    return (ARM_CPU_FREQ / NANOSECONDS_PER_SECOND) * cycles;
+}
+
 static bool instructions_supported(CPUARMState *env)
 {
     return use_icount == 1 /* Precise instruction counting */;
@@ -1061,21 +1078,29 @@ static uint64_t instructions_get_count(CPUARMState *env)
 {
     return (uint64_t)cpu_get_icount_raw();
 }
+
+static int64_t instructions_ns_per(uint64_t icount)
+{
+    return cpu_icount_to_ns((int64_t)icount);
+}
 #endif
 
 static const pm_event pm_events[] = {
     { .number = 0x000, /* SW_INCR */
       .supported = event_always_supported,
       .get_count = swinc_get_count,
+      .ns_per_count = swinc_ns_per,
     },
 #ifndef CONFIG_USER_ONLY
     { .number = 0x008, /* INST_RETIRED, Instruction architecturally executed */
       .supported = instructions_supported,
       .get_count = instructions_get_count,
+      .ns_per_count = instructions_ns_per,
     },
     { .number = 0x011, /* CPU_CYCLES, Cycle */
       .supported = event_always_supported,
       .get_count = cycles_get_count,
+      .ns_per_count = cycles_ns_per,
     }
 #endif
 };
@@ -1340,13 +1365,27 @@ void pmccntr_op_start(CPUARMState *env)
 void pmccntr_op_finish(CPUARMState *env)
 {
     if (pmu_counter_enabled(env, 31)) {
-        uint64_t prev_cycles = env->cp15.c15_ccnt_delta;
+#ifndef CONFIG_USER_ONLY
+        /* Calculate when the counter will next overflow */
+        uint64_t remaining_cycles = -env->cp15.c15_ccnt;
+        if (!(env->cp15.c9_pmcr & PMCRLC)) {
+            remaining_cycles = (uint32_t)remaining_cycles;
+        }
+        int64_t overflow_in = cycles_ns_per(remaining_cycles);
 
+        if (overflow_in > 0) {
+            int64_t overflow_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+                overflow_in;
+            ARMCPU *cpu = arm_env_get_cpu(env);
+            timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
+        }
+#endif
+
+        uint64_t prev_cycles = env->cp15.c15_ccnt_delta;
         if (env->cp15.c9_pmcr & PMCRD) {
             /* Increment once every 64 processor clock cycles */
             prev_cycles /= 64;
         }
-
         env->cp15.c15_ccnt_delta = prev_cycles - env->cp15.c15_ccnt;
     }
 }
@@ -1376,6 +1415,21 @@ static void pmevcntr_op_start(CPUARMState *env, uint8_t counter)
 static void pmevcntr_op_finish(CPUARMState *env, uint8_t counter)
 {
     if (pmu_counter_enabled(env, counter)) {
+#ifndef CONFIG_USER_ONLY
+        uint16_t event = env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCOUNT;
+        uint16_t event_idx = supported_event_map[event];
+        uint64_t delta = UINT32_MAX -
+            (uint32_t)env->cp15.c14_pmevcntr[counter] + 1;
+        int64_t overflow_in = pm_events[event_idx].ns_per_count(delta);
+
+        if (overflow_in > 0) {
+            int64_t overflow_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+                overflow_in;
+            ARMCPU *cpu = arm_env_get_cpu(env);
+            timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at);
+        }
+#endif
+
         env->cp15.c14_pmevcntr_delta[counter] -=
             env->cp15.c14_pmevcntr[counter];
     }
@@ -1409,6 +1463,20 @@ void pmu_post_el_change(ARMCPU *cpu, void *ignored)
     pmu_op_finish(&cpu->env);
 }
 
+void arm_pmu_timer_cb(void *opaque)
+{
+    ARMCPU *cpu = opaque;
+
+    /*
+     * Update all the counter values based on the current underlying counts,
+     * triggering interrupts to be raised, if necessary. pmu_op_finish() also
+     * has the effect of setting the cpu->pmu_timer to the next earliest time a
+     * counter may expire.
+     */
+    pmu_op_start(&cpu->env);
+    pmu_op_finish(&cpu->env);
+}
+
 static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
                        uint64_t value)
 {
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 37/47] target/arm: Enable API, APK bits in SCR, HCR
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (35 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 36/47] target/arm: Add a timer to predict " Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 38/47] arm: Clarify the logic of set_pc() Peter Maydell
                   ` (11 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Richard Henderson <richard.henderson@linaro.org>

These bits become writable with the ARMv8.3-PAuth extension.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190129143511.12311-1-richard.henderson@linaro.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/helper.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index e6f69180ba0..d070879894c 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1859,6 +1859,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
     if (cpu_isar_feature(aa64_lor, cpu)) {
         valid_mask |= SCR_TLOR;
     }
+    if (cpu_isar_feature(aa64_pauth, cpu)) {
+        valid_mask |= SCR_API | SCR_APK;
+    }
 
     /* Clear all-context RES0 bits.  */
     value &= valid_mask;
@@ -4558,6 +4561,9 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
     if (cpu_isar_feature(aa64_lor, cpu)) {
         valid_mask |= HCR_TLOR;
     }
+    if (cpu_isar_feature(aa64_pauth, cpu)) {
+        valid_mask |= HCR_API | HCR_APK;
+    }
 
     /* Clear RES0 bits.  */
     value &= valid_mask;
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 38/47] arm: Clarify the logic of set_pc()
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (36 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 37/47] target/arm: Enable API, APK bits in SCR, HCR Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 39/47] target/arm: Always enable pac keys for user-only Peter Maydell
                   ` (10 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Julia Suvorova <jusual@mail.ru>

Until now, the set_pc logic was unclear, which raised questions about
whether it should be used directly, applying a value to PC or adding
additional checks, for example, set the Thumb bit in Arm cpu. Let's set
the set_pc logic for “Configure the PC, as was done in the ELF file”
and implement synchronize_with_tb hook for preserving PC to cpu_tb_exec.

Signed-off-by: Julia Suvorova <jusual@mail.ru>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20190129121817.7109-1-jusual@mail.ru
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/qom/cpu.h         | 16 ++++++++++++++--
 hw/arm/boot.c             |  4 ----
 target/arm/arm-powerctl.c |  3 ---
 target/arm/cpu.c          | 26 +++++++++++++++++++++++++-
 target/arm/cpu64.c        | 15 ---------------
 5 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 4c2feb9c17b..1d6099e5d4b 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -103,9 +103,21 @@ struct TranslationBlock;
  * @get_arch_id: Callback for getting architecture-dependent CPU ID.
  * @get_paging_enabled: Callback for inquiring whether paging is enabled.
  * @get_memory_mapping: Callback for obtaining the memory mappings.
- * @set_pc: Callback for setting the Program Counter register.
+ * @set_pc: Callback for setting the Program Counter register. This
+ *       should have the semantics used by the target architecture when
+ *       setting the PC from a source such as an ELF file entry point;
+ *       for example on Arm it will also set the Thumb mode bit based
+ *       on the least significant bit of the new PC value.
+ *       If the target behaviour here is anything other than "set
+ *       the PC register to the value passed in" then the target must
+ *       also implement the synchronize_from_tb hook.
  * @synchronize_from_tb: Callback for synchronizing state from a TCG
- * #TranslationBlock.
+ *       #TranslationBlock. This is called when we abandon execution
+ *       of a TB before starting it, and must set all parts of the CPU
+ *       state which the previous TB in the chain may not have updated.
+ *       This always includes at least the program counter; some targets
+ *       will need to do more. If this hook is not implemented then the
+ *       default is to call @set_pc(tb->pc).
  * @handle_mmu_fault: Callback for handling an MMU fault.
  * @get_phys_page_debug: Callback for obtaining a physical address.
  * @get_phys_page_attrs_debug: Callback for obtaining a physical address and the
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index c7a67af7a97..05762d0fc1b 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -697,10 +697,6 @@ static void do_cpu_reset(void *opaque)
                 g_assert_not_reached();
             }
 
-            if (!env->aarch64) {
-                env->thumb = info->entry & 1;
-                entry &= 0xfffffffe;
-            }
             cpu_set_pc(cs, entry);
         } else {
             /* If we are booting Linux then we need to check whether we are
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
index 2b856930fb7..f9de5164e55 100644
--- a/target/arm/arm-powerctl.c
+++ b/target/arm/arm-powerctl.c
@@ -120,11 +120,8 @@ static void arm_set_cpu_on_async_work(CPUState *target_cpu_state,
 
     if (info->target_aa64) {
         target_cpu->env.xregs[0] = info->context_id;
-        target_cpu->env.thumb = false;
     } else {
         target_cpu->env.regs[0] = info->context_id;
-        target_cpu->env.thumb = info->entry & 1;
-        info->entry &= 0xfffffffe;
     }
 
     /* Start the new CPU at the requested address */
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 8a9cd0900d2..f00d450d0bd 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -40,8 +40,31 @@
 static void arm_cpu_set_pc(CPUState *cs, vaddr value)
 {
     ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
 
-    cpu->env.regs[15] = value;
+    if (is_a64(env)) {
+        env->pc = value;
+        env->thumb = 0;
+    } else {
+        env->regs[15] = value & ~1;
+        env->thumb = value & 1;
+    }
+}
+
+static void arm_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
+    /*
+     * It's OK to look at env for the current mode here, because it's
+     * never possible for an AArch64 TB to chain to an AArch32 TB.
+     */
+    if (is_a64(env)) {
+        env->pc = tb->pc;
+    } else {
+        env->regs[15] = tb->pc;
+    }
 }
 
 static bool arm_cpu_has_work(CPUState *cs)
@@ -2099,6 +2122,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
     cc->cpu_exec_interrupt = arm_cpu_exec_interrupt;
     cc->dump_state = arm_cpu_dump_state;
     cc->set_pc = arm_cpu_set_pc;
+    cc->synchronize_from_tb = arm_cpu_synchronize_from_tb;
     cc->gdb_read_register = arm_cpu_gdb_read_register;
     cc->gdb_write_register = arm_cpu_gdb_write_register;
 #ifdef CONFIG_USER_ONLY
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index e9bc461c362..8653cecd032 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -480,20 +480,6 @@ static void aarch64_cpu_finalizefn(Object *obj)
 {
 }
 
-static void aarch64_cpu_set_pc(CPUState *cs, vaddr value)
-{
-    ARMCPU *cpu = ARM_CPU(cs);
-    /* It's OK to look at env for the current mode here, because it's
-     * never possible for an AArch64 TB to chain to an AArch32 TB.
-     * (Otherwise we would need to use synchronize_from_tb instead.)
-     */
-    if (is_a64(&cpu->env)) {
-        cpu->env.pc = value;
-    } else {
-        cpu->env.regs[15] = value;
-    }
-}
-
 static gchar *aarch64_gdb_arch_name(CPUState *cs)
 {
     return g_strdup("aarch64");
@@ -504,7 +490,6 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
     CPUClass *cc = CPU_CLASS(oc);
 
     cc->cpu_exec_interrupt = arm_cpu_exec_interrupt;
-    cc->set_pc = aarch64_cpu_set_pc;
     cc->gdb_read_register = aarch64_cpu_gdb_read_register;
     cc->gdb_write_register = aarch64_cpu_gdb_write_register;
     cc->gdb_num_core_regs = 34;
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 39/47] target/arm: Always enable pac keys for user-only
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (37 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 38/47] arm: Clarify the logic of set_pc() Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 40/47] aarch64-linux-user: Update HWCAP bits from linux 5.0-rc1 Peter Maydell
                   ` (9 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Richard Henderson <richard.henderson@linaro.org>

Drop the pac properties.  This approach cannot work as written
because the properties are applied before arm_cpu_reset, which
zeros SCTLR_EL1 (amongst everything else).

We can re-introduce the properties if they turn out to be useful.
But since linux 5.0 enables all of the keys, they may not be.

Fixes: 1ae9cfbd470
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.c   |  3 +++
 target/arm/cpu64.c | 60 ----------------------------------------------
 2 files changed, 3 insertions(+), 60 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index f00d450d0bd..3874dc98754 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -185,6 +185,9 @@ static void arm_cpu_reset(CPUState *s)
         env->pstate = PSTATE_MODE_EL0t;
         /* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */
         env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
+        /* Enable all PAC keys.  */
+        env->cp15.sctlr_el[1] |= (SCTLR_EnIA | SCTLR_EnIB |
+                                  SCTLR_EnDA | SCTLR_EnDB);
         /* Enable all PAC instructions */
         env->cp15.hcr_el2 |= HCR_API;
         env->cp15.scr_el3 |= SCR_API;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 8653cecd032..7107ec8d7eb 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -281,38 +281,6 @@ static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name,
     error_propagate(errp, err);
 }
 
-#ifdef CONFIG_USER_ONLY
-static void cpu_max_get_packey(Object *obj, Visitor *v, const char *name,
-                               void *opaque, Error **errp)
-{
-    ARMCPU *cpu = ARM_CPU(obj);
-    const uint64_t *bit = opaque;
-    bool enabled = (cpu->env.cp15.sctlr_el[1] & *bit) != 0;
-
-    visit_type_bool(v, name, &enabled, errp);
-}
-
-static void cpu_max_set_packey(Object *obj, Visitor *v, const char *name,
-                               void *opaque, Error **errp)
-{
-    ARMCPU *cpu = ARM_CPU(obj);
-    Error *err = NULL;
-    const uint64_t *bit = opaque;
-    bool enabled;
-
-    visit_type_bool(v, name, &enabled, errp);
-
-    if (!err) {
-        if (enabled) {
-            cpu->env.cp15.sctlr_el[1] |= *bit;
-        } else {
-            cpu->env.cp15.sctlr_el[1] &= ~*bit;
-        }
-    }
-    error_propagate(errp, err);
-}
-#endif
-
 /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
  * otherwise, a CPU with as many features enabled as our emulation supports.
  * The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
@@ -388,34 +356,6 @@ static void aarch64_max_initfn(Object *obj)
          */
         cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
         cpu->dcz_blocksize = 7; /*  512 bytes */
-
-        /*
-         * Note that Linux will enable enable all of the keys at once.
-         * But doing it this way will allow experimentation beyond that.
-         */
-        {
-            static const uint64_t apia_bit = SCTLR_EnIA;
-            static const uint64_t apib_bit = SCTLR_EnIB;
-            static const uint64_t apda_bit = SCTLR_EnDA;
-            static const uint64_t apdb_bit = SCTLR_EnDB;
-
-            object_property_add(obj, "apia", "bool", cpu_max_get_packey,
-                                cpu_max_set_packey, NULL,
-                                (void *)&apia_bit, &error_fatal);
-            object_property_add(obj, "apib", "bool", cpu_max_get_packey,
-                                cpu_max_set_packey, NULL,
-                                (void *)&apib_bit, &error_fatal);
-            object_property_add(obj, "apda", "bool", cpu_max_get_packey,
-                                cpu_max_set_packey, NULL,
-                                (void *)&apda_bit, &error_fatal);
-            object_property_add(obj, "apdb", "bool", cpu_max_get_packey,
-                                cpu_max_set_packey, NULL,
-                                (void *)&apdb_bit, &error_fatal);
-
-            /* Enable all PAC keys by default.  */
-            cpu->env.cp15.sctlr_el[1] |= SCTLR_EnIA | SCTLR_EnIB;
-            cpu->env.cp15.sctlr_el[1] |= SCTLR_EnDA | SCTLR_EnDB;
-        }
 #endif
 
         cpu->sve_max_vq = ARM_MAX_VQ;
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 40/47] aarch64-linux-user: Update HWCAP bits from linux 5.0-rc1
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (38 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 39/47] target/arm: Always enable pac keys for user-only Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 41/47] aarch64-linux-user: Enable HWCAP bits for PAuth Peter Maydell
                   ` (8 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Richard Henderson <richard.henderson@linaro.org>

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 linux-user/elfload.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 4cff9e1a313..3c7a7c2836f 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -560,6 +560,15 @@ enum {
     ARM_HWCAP_A64_ASIMDDP       = 1 << 20,
     ARM_HWCAP_A64_SHA512        = 1 << 21,
     ARM_HWCAP_A64_SVE           = 1 << 22,
+    ARM_HWCAP_A64_ASIMDFHM      = 1 << 23,
+    ARM_HWCAP_A64_DIT           = 1 << 24,
+    ARM_HWCAP_A64_USCAT         = 1 << 25,
+    ARM_HWCAP_A64_ILRCPC        = 1 << 26,
+    ARM_HWCAP_A64_FLAGM         = 1 << 27,
+    ARM_HWCAP_A64_SSBS          = 1 << 28,
+    ARM_HWCAP_A64_SB            = 1 << 29,
+    ARM_HWCAP_A64_PACA          = 1 << 30,
+    ARM_HWCAP_A64_PACG          = 1UL << 31,
 };
 
 #define ELF_HWCAP get_elf_hwcap()
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 41/47] aarch64-linux-user: Enable HWCAP bits for PAuth
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (39 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 40/47] aarch64-linux-user: Update HWCAP bits from linux 5.0-rc1 Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 42/47] linux-user: Initialize aarch64 pac keys Peter Maydell
                   ` (7 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Richard Henderson <richard.henderson@linaro.org>

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 linux-user/elfload.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 3c7a7c2836f..775a36ccdda 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -600,6 +600,7 @@ static uint32_t get_elf_hwcap(void)
     GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP);
     GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
     GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
+    GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
 
 #undef GET_FEATURE_ID
 
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 42/47] linux-user: Initialize aarch64 pac keys
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (40 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 41/47] aarch64-linux-user: Enable HWCAP bits for PAuth Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 43/47] target/arm: fix AArch64 virtual address space size Peter Maydell
                   ` (6 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Richard Henderson <richard.henderson@linaro.org>

Initialize the keys to a non-zero value on process start.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 linux-user/aarch64/target_syscall.h |  2 ++
 linux-user/aarch64/cpu_loop.c       | 31 +++++++++++++++++++++++++++--
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h
index 205265e619e..937fd7989e7 100644
--- a/linux-user/aarch64/target_syscall.h
+++ b/linux-user/aarch64/target_syscall.h
@@ -22,4 +22,6 @@ struct target_pt_regs {
 #define TARGET_PR_SVE_SET_VL  50
 #define TARGET_PR_SVE_GET_VL  51
 
+void arm_init_pauth_key(ARMPACKey *key);
+
 #endif /* AARCH64_TARGET_SYSCALL_H */
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index 65d815f0300..d75fd9d3e24 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -147,10 +147,29 @@ void cpu_loop(CPUARMState *env)
     }
 }
 
+static uint64_t arm_rand64(void)
+{
+    int shift = 64 - clz64(RAND_MAX);
+    int i, n = 64 / shift + (64 % shift != 0);
+    uint64_t ret = 0;
+
+    for (i = 0; i < n; i++) {
+        ret = (ret << shift) | rand();
+    }
+    return ret;
+}
+
+void arm_init_pauth_key(ARMPACKey *key)
+{
+    key->lo = arm_rand64();
+    key->hi = arm_rand64();
+}
+
 void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
 {
-    CPUState *cpu = ENV_GET_CPU(env);
-    TaskState *ts = cpu->opaque;
+    ARMCPU *cpu = arm_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
+    TaskState *ts = cs->opaque;
     struct image_info *info = ts->info;
     int i;
 
@@ -172,6 +191,14 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
     }
 #endif
 
+    if (cpu_isar_feature(aa64_pauth, cpu)) {
+        arm_init_pauth_key(&env->apia_key);
+        arm_init_pauth_key(&env->apib_key);
+        arm_init_pauth_key(&env->apda_key);
+        arm_init_pauth_key(&env->apdb_key);
+        arm_init_pauth_key(&env->apga_key);
+    }
+
     ts->stack_base = info->start_stack;
     ts->heap_base = info->brk;
     /* This will be filled in on the first SYS_HEAPINFO call.  */
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 43/47] target/arm: fix AArch64 virtual address space size
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (41 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 42/47] linux-user: Initialize aarch64 pac keys Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-08 14:02   ` Laurent Vivier
  2019-02-01 16:06 ` [Qemu-devel] [PULL 44/47] target/arm: fix decoding of B{, L}RA{A, B} Peter Maydell
                   ` (5 subsequent siblings)
  48 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Remi Denis-Courmont <remi.denis.courmont@huawei.com>

Since QEMU does not support the ARMv8.2-LVA, Large Virtual Address,
extension (yet), the VA address space is 48-bits plus a sign bit. User
mode can only handle the positive half of the address space, so that
makes a limit of 48 bits.

(With LVA, it would be 53 and 52 bits respectively.)

The incorrectly large address space conflicts with PAuth instructions,
which use bits 48-54 and 56-63 for the pointer authentication code. This
also conflicts with (as yet unsupported by QEMU) data tagging and with
the ARMv8.5-MTE extension.

Signed-off-by: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 63934a200ad..a68bcc9fedb 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2512,7 +2512,7 @@ bool write_cpustate_to_list(ARMCPU *cpu);
 
 #if defined(TARGET_AARCH64)
 #  define TARGET_PHYS_ADDR_SPACE_BITS 48
-#  define TARGET_VIRT_ADDR_SPACE_BITS 64
+#  define TARGET_VIRT_ADDR_SPACE_BITS 48
 #else
 #  define TARGET_PHYS_ADDR_SPACE_BITS 40
 #  define TARGET_VIRT_ADDR_SPACE_BITS 32
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 44/47] target/arm: fix decoding of B{, L}RA{A, B}
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (42 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 43/47] target/arm: fix AArch64 virtual address space size Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 45/47] hw/nvram/nrf51_nvm: Add nRF51 non-volatile memories Peter Maydell
                   ` (4 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Remi Denis-Courmont <remi.denis.courmont@huawei.com>

A flawed test lead to the instructions always being treated as
unallocated encodings.

Fixes: https://bugs.launchpad.net/bugs/1813460
Signed-off-by: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/translate-a64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index b864ac7a69f..a1997e3ae28 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -2036,7 +2036,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
         if (!dc_isar_feature(aa64_pauth, s)) {
             goto do_unallocated;
         }
-        if (op3 != 2 || op3 != 3) {
+        if ((op3 & ~1) != 2) {
             goto do_unallocated;
         }
         if (s->pauth_active) {
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 45/47] hw/nvram/nrf51_nvm: Add nRF51 non-volatile memories
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (43 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 44/47] target/arm: fix decoding of B{, L}RA{A, B} Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 46/47] arm: Instantiate NRF51 special NVM's and NVMC Peter Maydell
                   ` (3 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Steffen Görtz <contrib@steffen-goertz.de>

The nRF51 contains three regions of non-volatile memory (NVM):
- CODE (R/W): contains code
- FICR (R): Factory information like code size, chip id etc.
- UICR (R/W): Changeable configuration data. Lock bits, Code
  protection configuration, Bootloader address, Nordic SoftRadio
  configuration, Firmware configuration.

Read and write access to the memories is managed by the
Non-volatile memory controller.

Memory schema:
 [ CPU ] -+- [ NVM, either FICR, UICR or CODE ]
          |      |
          \- [ NVMC ]

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Tested-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20190201023357.22596-2-stefanha@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/nvram/Makefile.objs       |   1 +
 include/hw/nvram/nrf51_nvm.h |  64 ++++++
 hw/nvram/nrf51_nvm.c         | 388 +++++++++++++++++++++++++++++++++++
 3 files changed, 453 insertions(+)
 create mode 100644 include/hw/nvram/nrf51_nvm.h
 create mode 100644 hw/nvram/nrf51_nvm.c

diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs
index b318e53a434..26f7b4ca357 100644
--- a/hw/nvram/Makefile.objs
+++ b/hw/nvram/Makefile.objs
@@ -5,3 +5,4 @@ common-obj-y += fw_cfg.o
 common-obj-y += chrp_nvram.o
 common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
 obj-$(CONFIG_PSERIES) += spapr_nvram.o
+obj-$(CONFIG_NRF51_SOC) += nrf51_nvm.o
diff --git a/include/hw/nvram/nrf51_nvm.h b/include/hw/nvram/nrf51_nvm.h
new file mode 100644
index 00000000000..3792e4a9fec
--- /dev/null
+++ b/include/hw/nvram/nrf51_nvm.h
@@ -0,0 +1,64 @@
+/*
+ * Nordic Semiconductor nRF51 non-volatile memory
+ *
+ * It provides an interface to erase regions in flash memory.
+ * Furthermore it provides the user and factory information registers.
+ *
+ * QEMU interface:
+ * + sysbus MMIO regions 0: NVMC peripheral registers
+ * + sysbus MMIO regions 1: FICR peripheral registers
+ * + sysbus MMIO regions 2: UICR peripheral registers
+ * + flash-size property: flash size in bytes.
+ *
+ * Accuracy of the peripheral model:
+ * + Code regions (MPU configuration) are disregarded.
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#ifndef NRF51_NVM_H
+#define NRF51_NVM_H
+
+#include "hw/sysbus.h"
+#define TYPE_NRF51_NVM "nrf51_soc.nvm"
+#define NRF51_NVM(obj) OBJECT_CHECK(NRF51NVMState, (obj), TYPE_NRF51_NVM)
+
+#define NRF51_UICR_FIXTURE_SIZE 64
+
+#define NRF51_NVMC_SIZE         0x1000
+
+#define NRF51_NVMC_READY        0x400
+#define NRF51_NVMC_READY_READY  0x01
+#define NRF51_NVMC_CONFIG       0x504
+#define NRF51_NVMC_CONFIG_MASK  0x03
+#define NRF51_NVMC_CONFIG_WEN   0x01
+#define NRF51_NVMC_CONFIG_EEN   0x02
+#define NRF51_NVMC_ERASEPCR1    0x508
+#define NRF51_NVMC_ERASEPCR0    0x510
+#define NRF51_NVMC_ERASEALL     0x50C
+#define NRF51_NVMC_ERASEUICR    0x514
+#define NRF51_NVMC_ERASE        0x01
+
+#define NRF51_UICR_SIZE         0x100
+
+typedef struct NRF51NVMState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+    MemoryRegion ficr;
+    MemoryRegion uicr;
+    MemoryRegion flash;
+
+    uint32_t uicr_content[NRF51_UICR_FIXTURE_SIZE];
+    uint32_t flash_size;
+    uint8_t *storage;
+
+    uint32_t config;
+
+} NRF51NVMState;
+
+
+#endif
diff --git a/hw/nvram/nrf51_nvm.c b/hw/nvram/nrf51_nvm.c
new file mode 100644
index 00000000000..7d94cef1db3
--- /dev/null
+++ b/hw/nvram/nrf51_nvm.c
@@ -0,0 +1,388 @@
+/*
+ * Nordic Semiconductor nRF51 non-volatile memory
+ *
+ * It provides an interface to erase regions in flash memory.
+ * Furthermore it provides the user and factory information registers.
+ *
+ * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
+ *
+ * See nRF51 reference manual and product sheet sections:
+ * + Non-Volatile Memory Controller (NVMC)
+ * + Factory Information Configuration Registers (FICR)
+ * + User Information Configuration Registers (UICR)
+ *
+ * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
+ *
+ * This code is licensed under the GPL version 2 or later.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+#include "hw/arm/nrf51.h"
+#include "hw/nvram/nrf51_nvm.h"
+
+/*
+ * FICR Registers Assignments
+ * CODEPAGESIZE      0x010
+ * CODESIZE          0x014
+ * CLENR0            0x028
+ * PPFC              0x02C
+ * NUMRAMBLOCK       0x034
+ * SIZERAMBLOCKS     0x038
+ * SIZERAMBLOCK[0]   0x038
+ * SIZERAMBLOCK[1]   0x03C
+ * SIZERAMBLOCK[2]   0x040
+ * SIZERAMBLOCK[3]   0x044
+ * CONFIGID          0x05C
+ * DEVICEID[0]       0x060
+ * DEVICEID[1]       0x064
+ * ER[0]             0x080
+ * ER[1]             0x084
+ * ER[2]             0x088
+ * ER[3]             0x08C
+ * IR[0]             0x090
+ * IR[1]             0x094
+ * IR[2]             0x098
+ * IR[3]             0x09C
+ * DEVICEADDRTYPE    0x0A0
+ * DEVICEADDR[0]     0x0A4
+ * DEVICEADDR[1]     0x0A8
+ * OVERRIDEEN        0x0AC
+ * NRF_1MBIT[0]      0x0B0
+ * NRF_1MBIT[1]      0x0B4
+ * NRF_1MBIT[2]      0x0B8
+ * NRF_1MBIT[3]      0x0BC
+ * NRF_1MBIT[4]      0x0C0
+ * BLE_1MBIT[0]      0x0EC
+ * BLE_1MBIT[1]      0x0F0
+ * BLE_1MBIT[2]      0x0F4
+ * BLE_1MBIT[3]      0x0F8
+ * BLE_1MBIT[4]      0x0FC
+ */
+static const uint32_t ficr_content[64] = {
+    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000400,
+    0x00000100, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002, 0x00002000,
+    0x00002000, 0x00002000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000003,
+    0x12345678, 0x9ABCDEF1, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+};
+
+static uint64_t ficr_read(void *opaque, hwaddr offset, unsigned int size)
+{
+    assert(offset < sizeof(ficr_content));
+    return ficr_content[offset / 4];
+}
+
+static void ficr_write(void *opaque, hwaddr offset, uint64_t value,
+        unsigned int size)
+{
+    /* Intentionally do nothing */
+}
+
+static const MemoryRegionOps ficr_ops = {
+    .read = ficr_read,
+    .write = ficr_write,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN
+};
+
+/*
+ * UICR Registers Assignments
+ * CLENR0           0x000
+ * RBPCONF          0x004
+ * XTALFREQ         0x008
+ * FWID             0x010
+ * BOOTLOADERADDR   0x014
+ * NRFFW[0]         0x014
+ * NRFFW[1]         0x018
+ * NRFFW[2]         0x01C
+ * NRFFW[3]         0x020
+ * NRFFW[4]         0x024
+ * NRFFW[5]         0x028
+ * NRFFW[6]         0x02C
+ * NRFFW[7]         0x030
+ * NRFFW[8]         0x034
+ * NRFFW[9]         0x038
+ * NRFFW[10]        0x03C
+ * NRFFW[11]        0x040
+ * NRFFW[12]        0x044
+ * NRFFW[13]        0x048
+ * NRFFW[14]        0x04C
+ * NRFHW[0]         0x050
+ * NRFHW[1]         0x054
+ * NRFHW[2]         0x058
+ * NRFHW[3]         0x05C
+ * NRFHW[4]         0x060
+ * NRFHW[5]         0x064
+ * NRFHW[6]         0x068
+ * NRFHW[7]         0x06C
+ * NRFHW[8]         0x070
+ * NRFHW[9]         0x074
+ * NRFHW[10]        0x078
+ * NRFHW[11]        0x07C
+ * CUSTOMER[0]      0x080
+ * CUSTOMER[1]      0x084
+ * CUSTOMER[2]      0x088
+ * CUSTOMER[3]      0x08C
+ * CUSTOMER[4]      0x090
+ * CUSTOMER[5]      0x094
+ * CUSTOMER[6]      0x098
+ * CUSTOMER[7]      0x09C
+ * CUSTOMER[8]      0x0A0
+ * CUSTOMER[9]      0x0A4
+ * CUSTOMER[10]     0x0A8
+ * CUSTOMER[11]     0x0AC
+ * CUSTOMER[12]     0x0B0
+ * CUSTOMER[13]     0x0B4
+ * CUSTOMER[14]     0x0B8
+ * CUSTOMER[15]     0x0BC
+ * CUSTOMER[16]     0x0C0
+ * CUSTOMER[17]     0x0C4
+ * CUSTOMER[18]     0x0C8
+ * CUSTOMER[19]     0x0CC
+ * CUSTOMER[20]     0x0D0
+ * CUSTOMER[21]     0x0D4
+ * CUSTOMER[22]     0x0D8
+ * CUSTOMER[23]     0x0DC
+ * CUSTOMER[24]     0x0E0
+ * CUSTOMER[25]     0x0E4
+ * CUSTOMER[26]     0x0E8
+ * CUSTOMER[27]     0x0EC
+ * CUSTOMER[28]     0x0F0
+ * CUSTOMER[29]     0x0F4
+ * CUSTOMER[30]     0x0F8
+ * CUSTOMER[31]     0x0FC
+ */
+
+static uint64_t uicr_read(void *opaque, hwaddr offset, unsigned int size)
+{
+    NRF51NVMState *s = NRF51_NVM(opaque);
+
+    assert(offset < sizeof(s->uicr_content));
+    return s->uicr_content[offset / 4];
+}
+
+static void uicr_write(void *opaque, hwaddr offset, uint64_t value,
+        unsigned int size)
+{
+    NRF51NVMState *s = NRF51_NVM(opaque);
+
+    assert(offset < sizeof(s->uicr_content));
+    s->uicr_content[offset / 4] = value;
+}
+
+static const MemoryRegionOps uicr_ops = {
+    .read = uicr_read,
+    .write = uicr_write,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN
+};
+
+
+static uint64_t io_read(void *opaque, hwaddr offset, unsigned int size)
+{
+    NRF51NVMState *s = NRF51_NVM(opaque);
+    uint64_t r = 0;
+
+    switch (offset) {
+    case NRF51_NVMC_READY:
+        r = NRF51_NVMC_READY_READY;
+        break;
+    case NRF51_NVMC_CONFIG:
+        r = s->config;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "%s: bad read offset 0x%" HWADDR_PRIx "\n", __func__, offset);
+        break;
+    }
+
+    return r;
+}
+
+static void io_write(void *opaque, hwaddr offset, uint64_t value,
+        unsigned int size)
+{
+    NRF51NVMState *s = NRF51_NVM(opaque);
+
+    switch (offset) {
+    case NRF51_NVMC_CONFIG:
+        s->config = value & NRF51_NVMC_CONFIG_MASK;
+        break;
+    case NRF51_NVMC_ERASEPCR0:
+    case NRF51_NVMC_ERASEPCR1:
+        if (s->config & NRF51_NVMC_CONFIG_EEN) {
+            /* Mask in-page sub address */
+            value &= ~(NRF51_PAGE_SIZE - 1);
+            if (value <= (s->flash_size - NRF51_PAGE_SIZE)) {
+                memset(s->storage + value, 0xFF, NRF51_PAGE_SIZE);
+                memory_region_flush_rom_device(&s->flash, value,
+                                               NRF51_PAGE_SIZE);
+            }
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR,
+            "%s: Flash erase at 0x%" HWADDR_PRIx" while flash not erasable.\n",
+            __func__, offset);
+        }
+        break;
+    case NRF51_NVMC_ERASEALL:
+        if (value == NRF51_NVMC_ERASE) {
+            if (s->config & NRF51_NVMC_CONFIG_EEN) {
+                memset(s->storage, 0xFF, s->flash_size);
+                memory_region_flush_rom_device(&s->flash, 0, s->flash_size);
+                memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
+            } else {
+                qemu_log_mask(LOG_GUEST_ERROR, "%s: Flash not erasable.\n",
+                              __func__);
+            }
+        }
+        break;
+    case NRF51_NVMC_ERASEUICR:
+        if (value == NRF51_NVMC_ERASE) {
+            memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
+        }
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "%s: bad write offset 0x%" HWADDR_PRIx "\n", __func__, offset);
+    }
+}
+
+static const MemoryRegionOps io_ops = {
+        .read = io_read,
+        .write = io_write,
+        .impl.min_access_size = 4,
+        .impl.max_access_size = 4,
+        .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+
+static void flash_write(void *opaque, hwaddr offset, uint64_t value,
+        unsigned int size)
+{
+    NRF51NVMState *s = NRF51_NVM(opaque);
+
+    if (s->config & NRF51_NVMC_CONFIG_WEN) {
+        uint32_t oldval;
+
+        assert(offset + size <= s->flash_size);
+
+        /* NOR Flash only allows bits to be flipped from 1's to 0's on write */
+        oldval = ldl_le_p(s->storage + offset);
+        oldval &= value;
+        stl_le_p(s->storage + offset, oldval);
+
+        memory_region_flush_rom_device(&s->flash, offset, size);
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "%s: Flash write 0x%" HWADDR_PRIx" while flash not writable.\n",
+                __func__, offset);
+    }
+}
+
+
+
+static const MemoryRegionOps flash_ops = {
+    .write = flash_write,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void nrf51_nvm_init(Object *obj)
+{
+    NRF51NVMState *s = NRF51_NVM(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+    memory_region_init_io(&s->mmio, obj, &io_ops, s, "nrf51_soc.nvmc",
+                          NRF51_NVMC_SIZE);
+    sysbus_init_mmio(sbd, &s->mmio);
+
+    memory_region_init_io(&s->ficr, obj, &ficr_ops, s, "nrf51_soc.ficr",
+                          sizeof(ficr_content));
+    sysbus_init_mmio(sbd, &s->ficr);
+
+    memory_region_init_io(&s->uicr, obj, &uicr_ops, s, "nrf51_soc.uicr",
+                          sizeof(s->uicr_content));
+    sysbus_init_mmio(sbd, &s->uicr);
+}
+
+static void nrf51_nvm_realize(DeviceState *dev, Error **errp)
+{
+    NRF51NVMState *s = NRF51_NVM(dev);
+    Error *err = NULL;
+
+    memory_region_init_rom_device(&s->flash, OBJECT(dev), &flash_ops, s,
+        "nrf51_soc.flash", s->flash_size, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    s->storage = memory_region_get_ram_ptr(&s->flash);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->flash);
+}
+
+static void nrf51_nvm_reset(DeviceState *dev)
+{
+    NRF51NVMState *s = NRF51_NVM(dev);
+
+    s->config = 0x00;
+    memset(s->uicr_content, 0xFF, sizeof(s->uicr_content));
+}
+
+static Property nrf51_nvm_properties[] = {
+    DEFINE_PROP_UINT32("flash-size", NRF51NVMState, flash_size, 0x40000),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription vmstate_nvm = {
+    .name = "nrf51_soc.nvm",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(uicr_content, NRF51NVMState,
+                NRF51_UICR_FIXTURE_SIZE),
+        VMSTATE_UINT32(config, NRF51NVMState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void nrf51_nvm_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = nrf51_nvm_properties;
+    dc->vmsd = &vmstate_nvm;
+    dc->realize = nrf51_nvm_realize;
+    dc->reset = nrf51_nvm_reset;
+}
+
+static const TypeInfo nrf51_nvm_info = {
+    .name = TYPE_NRF51_NVM,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(NRF51NVMState),
+    .instance_init = nrf51_nvm_init,
+    .class_init = nrf51_nvm_class_init
+};
+
+static void nrf51_nvm_register_types(void)
+{
+    type_register_static(&nrf51_nvm_info);
+}
+
+type_init(nrf51_nvm_register_types)
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 46/47] arm: Instantiate NRF51 special NVM's and NVMC
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (44 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 45/47] hw/nvram/nrf51_nvm: Add nRF51 non-volatile memories Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 16:06 ` [Qemu-devel] [PULL 47/47] tests/microbit-test: Add tests for nRF51 NVMC Peter Maydell
                   ` (2 subsequent siblings)
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Steffen Görtz <contrib@steffen-goertz.de>

Instantiates UICR, FICR, FLASH and NVMC in nRF51 SOC.

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20190201023357.22596-3-stefanha@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/arm/nrf51_soc.h |  2 ++
 hw/arm/nrf51_soc.c         | 41 +++++++++++++++++++++++++++-----------
 2 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
index fbdefc07e4d..fd7fcc71a56 100644
--- a/include/hw/arm/nrf51_soc.h
+++ b/include/hw/arm/nrf51_soc.h
@@ -15,6 +15,7 @@
 #include "hw/char/nrf51_uart.h"
 #include "hw/misc/nrf51_rng.h"
 #include "hw/gpio/nrf51_gpio.h"
+#include "hw/nvram/nrf51_nvm.h"
 #include "hw/timer/nrf51_timer.h"
 
 #define TYPE_NRF51_SOC "nrf51-soc"
@@ -32,6 +33,7 @@ typedef struct NRF51State {
 
     NRF51UARTState uart;
     NRF51RNGState rng;
+    NRF51NVMState nvm;
     NRF51GPIOState gpio;
     NRF51TimerState timer[NRF51_NUM_TIMERS];
 
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index 3a1c7e200cc..bbaf050103a 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -29,8 +29,10 @@
  * are supported in the future, add a sub-class of NRF51SoC for
  * the specific variants
  */
-#define NRF51822_FLASH_SIZE     (256 * NRF51_PAGE_SIZE)
-#define NRF51822_SRAM_SIZE      (16 * NRF51_PAGE_SIZE)
+#define NRF51822_FLASH_PAGES    256
+#define NRF51822_SRAM_PAGES     16
+#define NRF51822_FLASH_SIZE     (NRF51822_FLASH_PAGES * NRF51_PAGE_SIZE)
+#define NRF51822_SRAM_SIZE      (NRF51822_SRAM_PAGES * NRF51_PAGE_SIZE)
 
 #define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
 
@@ -81,14 +83,6 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
 
     memory_region_add_subregion_overlap(&s->container, 0, s->board_memory, -1);
 
-    memory_region_init_rom(&s->flash, OBJECT(s), "nrf51.flash", s->flash_size,
-            &err);
-    if (err) {
-        error_propagate(errp, err);
-        return;
-    }
-    memory_region_add_subregion(&s->container, NRF51_FLASH_BASE, &s->flash);
-
     memory_region_init_ram(&s->sram, OBJECT(s), "nrf51.sram", s->sram_size,
                            &err);
     if (err) {
@@ -122,6 +116,29 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
                        qdev_get_gpio_in(DEVICE(&s->cpu),
                        BASE_TO_IRQ(NRF51_RNG_BASE)));
 
+    /* UICR, FICR, NVMC, FLASH */
+    object_property_set_uint(OBJECT(&s->nvm), s->flash_size, "flash-size",
+                             &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    object_property_set_bool(OBJECT(&s->nvm), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 0);
+    memory_region_add_subregion_overlap(&s->container, NRF51_NVMC_BASE, mr, 0);
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 1);
+    memory_region_add_subregion_overlap(&s->container, NRF51_FICR_BASE, mr, 0);
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 2);
+    memory_region_add_subregion_overlap(&s->container, NRF51_UICR_BASE, mr, 0);
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->nvm), 3);
+    memory_region_add_subregion_overlap(&s->container, NRF51_FLASH_BASE, mr, 0);
+
     /* GPIO */
     object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
     if (err) {
@@ -159,8 +176,6 @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
 
     create_unimplemented_device("nrf51_soc.io", NRF51_IOMEM_BASE,
                                 NRF51_IOMEM_SIZE);
-    create_unimplemented_device("nrf51_soc.ficr", NRF51_FICR_BASE,
-                                NRF51_FICR_SIZE);
     create_unimplemented_device("nrf51_soc.private",
                                 NRF51_PRIVATE_BASE, NRF51_PRIVATE_SIZE);
 }
@@ -187,6 +202,8 @@ static void nrf51_soc_init(Object *obj)
     sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
                            TYPE_NRF51_RNG);
 
+    sysbus_init_child_obj(obj, "nvm", &s->nvm, sizeof(s->nvm), TYPE_NRF51_NVM);
+
     sysbus_init_child_obj(obj, "gpio", &s->gpio, sizeof(s->gpio),
                           TYPE_NRF51_GPIO);
 
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [Qemu-devel] [PULL 47/47] tests/microbit-test: Add tests for nRF51 NVMC
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (45 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 46/47] arm: Instantiate NRF51 special NVM's and NVMC Peter Maydell
@ 2019-02-01 16:06 ` Peter Maydell
  2019-02-01 17:56 ` [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
  2019-02-03 15:00 ` no-reply
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 16:06 UTC (permalink / raw)
  To: qemu-devel

From: Steffen Görtz <contrib@steffen-goertz.de>

Signed-off-by: Steffen Görtz <contrib@steffen-goertz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20190201023357.22596-4-stefanha@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 tests/microbit-test.c | 108 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/tests/microbit-test.c b/tests/microbit-test.c
index 3bad947b6cd..04e199ec33f 100644
--- a/tests/microbit-test.c
+++ b/tests/microbit-test.c
@@ -21,6 +21,7 @@
 #include "hw/arm/nrf51.h"
 #include "hw/char/nrf51_uart.h"
 #include "hw/gpio/nrf51_gpio.h"
+#include "hw/nvram/nrf51_nvm.h"
 #include "hw/timer/nrf51_timer.h"
 #include "hw/i2c/microbit_i2c.h"
 
@@ -156,6 +157,112 @@ static void test_microbit_i2c(void)
     qtest_quit(qts);
 }
 
+#define FLASH_SIZE          (256 * NRF51_PAGE_SIZE)
+
+static void fill_and_erase(QTestState *qts, hwaddr base, hwaddr size,
+                           uint32_t address_reg)
+{
+    hwaddr i;
+
+    /* Erase Page */
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
+    qtest_writel(qts, NRF51_NVMC_BASE + address_reg, base);
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
+
+    /* Check memory */
+    for (i = 0; i < size / 4; i++) {
+        g_assert_cmpuint(qtest_readl(qts, base + i * 4), ==, 0xFFFFFFFF);
+    }
+
+    /* Fill memory */
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
+    for (i = 0; i < size / 4; i++) {
+        qtest_writel(qts, base + i * 4, i);
+        g_assert_cmpuint(qtest_readl(qts, base + i * 4), ==, i);
+    }
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
+}
+
+static void test_nrf51_nvmc(void)
+{
+    uint32_t value;
+    hwaddr i;
+    QTestState *qts = qtest_init("-M microbit");
+
+    /* Test always ready */
+    value = qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_READY);
+    g_assert_cmpuint(value & 0x01, ==, 0x01);
+
+    /* Test write-read config register */
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x03);
+    g_assert_cmpuint(qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG),
+                     ==, 0x03);
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
+    g_assert_cmpuint(qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG),
+                     ==, 0x00);
+
+    /* Test PCR0 */
+    fill_and_erase(qts, NRF51_FLASH_BASE, NRF51_PAGE_SIZE,
+                   NRF51_NVMC_ERASEPCR0);
+    fill_and_erase(qts, NRF51_FLASH_BASE + NRF51_PAGE_SIZE,
+                   NRF51_PAGE_SIZE, NRF51_NVMC_ERASEPCR0);
+
+    /* Test PCR1 */
+    fill_and_erase(qts, NRF51_FLASH_BASE, NRF51_PAGE_SIZE,
+                   NRF51_NVMC_ERASEPCR1);
+    fill_and_erase(qts, NRF51_FLASH_BASE + NRF51_PAGE_SIZE,
+                   NRF51_PAGE_SIZE, NRF51_NVMC_ERASEPCR1);
+
+    /* Erase all */
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEALL, 0x01);
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
+
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
+    for (i = 0; i < FLASH_SIZE / 4; i++) {
+        qtest_writel(qts, NRF51_FLASH_BASE + i * 4, i);
+        g_assert_cmpuint(qtest_readl(qts, NRF51_FLASH_BASE + i * 4), ==, i);
+    }
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
+
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEALL, 0x01);
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
+
+    for (i = 0; i < FLASH_SIZE / 4; i++) {
+        g_assert_cmpuint(qtest_readl(qts, NRF51_FLASH_BASE + i * 4),
+                         ==, 0xFFFFFFFF);
+    }
+
+    /* Erase UICR */
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEUICR, 0x01);
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
+
+    for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
+        g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4),
+                         ==, 0xFFFFFFFF);
+    }
+
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
+    for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
+        qtest_writel(qts, NRF51_UICR_BASE + i * 4, i);
+        g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4), ==, i);
+    }
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
+
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEUICR, 0x01);
+    qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
+
+    for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
+        g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4),
+                         ==, 0xFFFFFFFF);
+    }
+
+    qtest_quit(qts);
+}
+
 static void test_nrf51_gpio(void)
 {
     size_t i;
@@ -392,6 +499,7 @@ int main(int argc, char **argv)
 
     qtest_add_func("/microbit/nrf51/uart", test_nrf51_uart);
     qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
+    qtest_add_func("/microbit/nrf51/nvmc", test_nrf51_nvmc);
     qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer);
     qtest_add_func("/microbit/microbit/i2c", test_microbit_i2c);
 
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PULL 00/47] target-arm queue
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (46 preceding siblings ...)
  2019-02-01 16:06 ` [Qemu-devel] [PULL 47/47] tests/microbit-test: Add tests for nRF51 NVMC Peter Maydell
@ 2019-02-01 17:56 ` Peter Maydell
  2019-02-03 15:00 ` no-reply
  48 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2019-02-01 17:56 UTC (permalink / raw)
  To: QEMU Developers

On Fri, 1 Feb 2019 at 16:06, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> As promised, more Arm patches. The big thing in here is the
> MPS2-AN521 board model.
>
> thanks
> -- PMM
>
> The following changes since commit cfe6c547690b06fbce54a6d0f7b05dd7f18e36ea:
>
>   Merge remote-tracking branch 'remotes/xanclic/tags/pull-block-2019-01-31' into staging (2019-01-31 19:26:09 +0000)
>
> are available in the Git repository at:
>
>   https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190201
>
> for you to fetch changes up to 7743b70ffe7a8ce168adce2cf50ad156b1fefb8c:
>
>   tests/microbit-test: Add tests for nRF51 NVMC (2019-02-01 15:32:17 +0000)
>
> ----------------------------------------------------------------
> target-arm queue:
>  * New machine mps2-an521 -- this is a model of the AN521 FPGA image for the MPS2 devboard
>  * Fix various places where we failed to UNDEF invalid A64 instructions
>  * Don't UNDEF a valid FCMLA on 32-bit inputs
>  * Fix some bugs in the newly-added PAuth implementation
>  * microbit: Implement NVMC non-volatile memory controller
>

Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/4.0
for any user-visible changes.

-- PMM

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PULL 00/47] target-arm queue
  2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
                   ` (47 preceding siblings ...)
  2019-02-01 17:56 ` [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
@ 2019-02-03 15:00 ` no-reply
  48 siblings, 0 replies; 56+ messages in thread
From: no-reply @ 2019-02-03 15:00 UTC (permalink / raw)
  To: peter.maydell; +Cc: fam, qemu-devel

Patchew URL: https://patchew.org/QEMU/20190201160653.13829-1-peter.maydell@linaro.org/



Hi,

This series failed the docker-mingw@fedora build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
time make docker-test-mingw@fedora SHOW_ENV=1 J=14
=== TEST SCRIPT END ===


Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/tmp/qemu-test/install --python=/usr/bin/python3 --cross-prefix=x86_64-w64-mingw32- --enable-trace-backends=simple --enable-gnutls --enable-nettle --enable-curl --enable-vnc --enable-bzip2 --enable-guest-agent --with-sdlabi=2.0
ERROR: unknown option --with-sdlabi=2.0
Try '/tmp/qemu-test/src/configure --help' for more information
# QEMU configure log Sun Feb  3 15:00:00 UTC 2019
# Configured with: '/tmp/qemu-test/src/configure' '--enable-werror' '--target-list=x86_64-softmmu,aarch64-softmmu' '--prefix=/tmp/qemu-test/install' '--python=/usr/bin/python3' '--cross-prefix=x86_64-w64-mingw32-' '--enable-trace-backends=simple' '--enable-gnutls' '--enable-nettle' '--enable-curl' '--enable-vnc' '--enable-bzip2' '--enable-guest-agent' '--with-sdlabi=2.0'
---
funcs: do_compiler do_cc compile_object check_define main
lines: 92 122 617 634 0
x86_64-w64-mingw32-gcc -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv -std=gnu99 -c -o config-temp/qemu-conf.o config-temp/qemu-conf.c
config-temp/qemu-conf.c:2:2: error: #error __linux__ not defined
 #error __linux__ not defined
  ^~~~~

---
funcs: do_compiler do_cc compile_object check_define main
lines: 92 122 617 686 0
x86_64-w64-mingw32-gcc -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv -std=gnu99 -c -o config-temp/qemu-conf.o config-temp/qemu-conf.c
config-temp/qemu-conf.c:2:2: error: #error __i386__ not defined
 #error __i386__ not defined
  ^~~~~

---
funcs: do_compiler do_cc compile_object check_define main
lines: 92 122 617 689 0
x86_64-w64-mingw32-gcc -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv -std=gnu99 -c -o config-temp/qemu-conf.o config-temp/qemu-conf.c
config-temp/qemu-conf.c:2:2: error: #error __ILP32__ not defined
 #error __ILP32__ not defined
  ^~~~~

---
lines: 92 128 920 0
x86_64-w64-mingw32-gcc -mthreads -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv -std=gnu99 -o config-temp/qemu-conf.exe config-temp/qemu-conf.c -g -liberty
/usr/lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld: cannot find -liberty
collect2: error: ld returned 1 exit status
Failed to run 'configure'
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 563, in <module>


The full log is available at
http://patchew.org/logs/20190201160653.13829-1-peter.maydell@linaro.org/testing.docker-mingw@fedora/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PULL 43/47] target/arm: fix AArch64 virtual address space size
  2019-02-01 16:06 ` [Qemu-devel] [PULL 43/47] target/arm: fix AArch64 virtual address space size Peter Maydell
@ 2019-02-08 14:02   ` Laurent Vivier
  2019-02-08 15:38     ` Remi Denis Courmont
  0 siblings, 1 reply; 56+ messages in thread
From: Laurent Vivier @ 2019-02-08 14:02 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel, Remi Denis-Courmont, Richard Henderson

On 01/02/2019 17:06, Peter Maydell wrote:
> From: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
> 
> Since QEMU does not support the ARMv8.2-LVA, Large Virtual Address,
> extension (yet), the VA address space is 48-bits plus a sign bit. User
> mode can only handle the positive half of the address space, so that
> makes a limit of 48 bits.
> 
> (With LVA, it would be 53 and 52 bits respectively.)
> 
> The incorrectly large address space conflicts with PAuth instructions,
> which use bits 48-54 and 56-63 for the pointer authentication code. This
> also conflicts with (as yet unsupported by QEMU) data tagging and with
> the ARMv8.5-MTE extension.
> 
> Signed-off-by: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/cpu.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 63934a200ad..a68bcc9fedb 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2512,7 +2512,7 @@ bool write_cpustate_to_list(ARMCPU *cpu);
>  
>  #if defined(TARGET_AARCH64)
>  #  define TARGET_PHYS_ADDR_SPACE_BITS 48
> -#  define TARGET_VIRT_ADDR_SPACE_BITS 64
> +#  define TARGET_VIRT_ADDR_SPACE_BITS 48
>  #else
>  #  define TARGET_PHYS_ADDR_SPACE_BITS 40
>  #  define TARGET_VIRT_ADDR_SPACE_BITS 32
> 

This change breaks qemu-aarch64 (using LTP test suite):

# chroot chroot/arm64/bionic /opt/ltp/testcases/bin/access03
tst_test.c:1015: INFO: Timeout per run is 0h 05m 00s
qemu-aarch64: .../qemu/accel/tcg/translate-all.c:2522: page_check_range: Assertion `start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS)' failed.
qemu:handle_cpu_signal received signal outside vCPU context @ pc=0x60001554

Any idea?
Thanks,
Laurent

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PULL 43/47] target/arm: fix AArch64 virtual address space size
  2019-02-08 14:02   ` Laurent Vivier
@ 2019-02-08 15:38     ` Remi Denis Courmont
  2019-02-08 18:26       ` Laurent Vivier
  0 siblings, 1 reply; 56+ messages in thread
From: Remi Denis Courmont @ 2019-02-08 15:38 UTC (permalink / raw)
  To: Laurent Vivier, Peter Maydell, qemu-devel, Richard Henderson

   Hi,

That LTP test case deliberately tries to invoke a system call with an invalid address to make sure that the kernel fails safely. There seems to be an impedance mismatch between access_ok() and page_check_range() here, where the later assumes that the address is in guest range:

    /* This function should never be called with addresses outside the
       guest address space.  If this assert fires, it probably indicates
       a missing call to h2g_valid.  */

It looks to me that there actually two separate bugs here:

1) access_ok() does not fulfill the requirements of page_check_range(), misses a guest_addr_valid() call.
2) The page_check_range() assertion does not account for potential overflow, although the non-debug code does account for it.

________________________________________
De : Laurent Vivier [lvivier@redhat.com]
Envoyé : vendredi 8 février 2019 16:02
À : Peter Maydell; qemu-devel@nongnu.org; Remi Denis Courmont; Richard Henderson
Objet : Re: [Qemu-devel] [PULL 43/47] target/arm: fix AArch64 virtual address space size

On 01/02/2019 17:06, Peter Maydell wrote:
> From: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
>
> Since QEMU does not support the ARMv8.2-LVA, Large Virtual Address,
> extension (yet), the VA address space is 48-bits plus a sign bit. User
> mode can only handle the positive half of the address space, so that
> makes a limit of 48 bits.
>
> (With LVA, it would be 53 and 52 bits respectively.)
>
> The incorrectly large address space conflicts with PAuth instructions,
> which use bits 48-54 and 56-63 for the pointer authentication code. This
> also conflicts with (as yet unsupported by QEMU) data tagging and with
> the ARMv8.5-MTE extension.
>
> Signed-off-by: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target/arm/cpu.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 63934a200ad..a68bcc9fedb 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2512,7 +2512,7 @@ bool write_cpustate_to_list(ARMCPU *cpu);
>
>  #if defined(TARGET_AARCH64)
>  #  define TARGET_PHYS_ADDR_SPACE_BITS 48
> -#  define TARGET_VIRT_ADDR_SPACE_BITS 64
> +#  define TARGET_VIRT_ADDR_SPACE_BITS 48
>  #else
>  #  define TARGET_PHYS_ADDR_SPACE_BITS 40
>  #  define TARGET_VIRT_ADDR_SPACE_BITS 32
>

This change breaks qemu-aarch64 (using LTP test suite):

# chroot chroot/arm64/bionic /opt/ltp/testcases/bin/access03
tst_test.c:1015: INFO: Timeout per run is 0h 05m 00s
qemu-aarch64: .../qemu/accel/tcg/translate-all.c:2522: page_check_range: Assertion `start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS)' failed.
qemu:handle_cpu_signal received signal outside vCPU context @ pc=0x60001554

Any idea?
Thanks,
Laurent

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [Qemu-devel] [PULL 43/47] target/arm: fix AArch64 virtual address space size
  2019-02-08 15:38     ` Remi Denis Courmont
@ 2019-02-08 18:26       ` Laurent Vivier
  0 siblings, 0 replies; 56+ messages in thread
From: Laurent Vivier @ 2019-02-08 18:26 UTC (permalink / raw)
  To: Remi Denis Courmont, Peter Maydell, qemu-devel, Richard Henderson

On 08/02/2019 16:38, Remi Denis Courmont wrote:
>    Hi,
> 
> That LTP test case deliberately tries to invoke a system call with an invalid address to make sure that the kernel fails safely. There seems to be an impedance mismatch between access_ok() and page_check_range() here, where the later assumes that the address is in guest range:
> 
>     /* This function should never be called with addresses outside the
>        guest address space.  If this assert fires, it probably indicates
>        a missing call to h2g_valid.  */
> 
> It looks to me that there actually two separate bugs here:
> 
> 1) access_ok() does not fulfill the requirements of page_check_range(), misses a guest_addr_valid() call.
> 2) The page_check_range() assertion does not account for potential overflow, although the non-debug code does account for it.

You're right, this fixes the problem for me:

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index ef400cb78a..a8dce7f821 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -457,6 +457,9 @@ extern unsigned long guest_stack_size;
 
 static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
 {
+    if (!h2g_valid(addr)) {
+        return 0;
+    }
     return page_check_range((target_ulong)addr, size,
                             (type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0;
 }

> ________________________________________
> De : Laurent Vivier [lvivier@redhat.com]
> Envoyé : vendredi 8 février 2019 16:02
> À : Peter Maydell; qemu-devel@nongnu.org; Remi Denis Courmont; Richard Henderson
> Objet : Re: [Qemu-devel] [PULL 43/47] target/arm: fix AArch64 virtual address space size
> 
> On 01/02/2019 17:06, Peter Maydell wrote:
>> From: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
>>
>> Since QEMU does not support the ARMv8.2-LVA, Large Virtual Address,
>> extension (yet), the VA address space is 48-bits plus a sign bit. User
>> mode can only handle the positive half of the address space, so that
>> makes a limit of 48 bits.
>>
>> (With LVA, it would be 53 and 52 bits respectively.)
>>
>> The incorrectly large address space conflicts with PAuth instructions,
>> which use bits 48-54 and 56-63 for the pointer authentication code. This
>> also conflicts with (as yet unsupported by QEMU) data tagging and with
>> the ARMv8.5-MTE extension.
>>
>> Signed-off-by: Remi Denis-Courmont <remi.denis.courmont@huawei.com>
>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
>> ---
>>  target/arm/cpu.h | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
>> index 63934a200ad..a68bcc9fedb 100644
>> --- a/target/arm/cpu.h
>> +++ b/target/arm/cpu.h
>> @@ -2512,7 +2512,7 @@ bool write_cpustate_to_list(ARMCPU *cpu);
>>
>>  #if defined(TARGET_AARCH64)
>>  #  define TARGET_PHYS_ADDR_SPACE_BITS 48
>> -#  define TARGET_VIRT_ADDR_SPACE_BITS 64
>> +#  define TARGET_VIRT_ADDR_SPACE_BITS 48
>>  #else
>>  #  define TARGET_PHYS_ADDR_SPACE_BITS 40
>>  #  define TARGET_VIRT_ADDR_SPACE_BITS 32
>>
> 
> This change breaks qemu-aarch64 (using LTP test suite):
> 
> # chroot chroot/arm64/bionic /opt/ltp/testcases/bin/access03
> tst_test.c:1015: INFO: Timeout per run is 0h 05m 00s
> qemu-aarch64: .../qemu/accel/tcg/translate-all.c:2522: page_check_range: Assertion `start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS)' failed.
> qemu:handle_cpu_signal received signal outside vCPU context @ pc=0x60001554
> 
> Any idea?
> Thanks,
> Laurent
> 

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PULL 35/47] target/arm: Send interrupts on PMU counter overflow
  2019-02-01 16:06 ` [Qemu-devel] [PULL 35/47] target/arm: Send interrupts on PMU counter overflow Peter Maydell
@ 2020-02-25 17:08   ` Peter Maydell
  2020-07-01 15:11     ` Aaron Lindsay
  0 siblings, 1 reply; 56+ messages in thread
From: Peter Maydell @ 2020-02-25 17:08 UTC (permalink / raw)
  To: QEMU Developers, Aaron Lindsay

On Fri, 1 Feb 2019 at 16:07, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> From: Aaron Lindsay OS <aaron@os.amperecomputing.com>
>
> Whenever we notice that a counter overflow has occurred, send an
> interrupt. This is made more reliable with the addition of a timer in a
> follow-on commit.
>
> Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Message-id: 20190124162401.5111-2-aaron@os.amperecomputing.com
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Hi Aaron -- I've just noticed a problem with this patch that
went into QEMU recently. The problem is that we can end up
calling pmu_update_irq(), which injects an interrupt, from
a raw-write function for some of the PMU registers. This is
bad because when we're using KVM the raw-write functions are
called as part of syncing state to and from the kernel. In
particular, if using '-cpu host,pmu=off' we don't set up the
PMU interrupt because we don't want to provide the guest a
PMU but then we can still find ourselves in this function,
and then we assert because we try to set a bogus interrupt.
Here's the backtrace:

#1  0x0000fffff6be68b4 in __GI_abort () at abort.c:79
#2  0x0000aaaaaae20820 in kvm_set_irq (s=0xaaaaabf8a020, irq=33554455, level=0)
    at /home/pm/qemu-bisect/accel/kvm/kvm-all.c:1277
#3  0x0000aaaaaafb7890 in kvm_arm_set_irq (cpu=0, irqtype=2, irq=23, level=0)
    at /home/pm/qemu-bisect/target/arm/kvm.c:897
#4  0x0000aaaaaae729dc in kvm_arm_gic_set_irq (num_irq=288, irq=23, level=0)
    at /home/pm/qemu-bisect/hw/intc/arm_gic_kvm.c:75
#5  0x0000aaaaaae72a1c in kvm_arm_gicv2_set_irq
(opaque=0xaaaaac169ff0, irq=279, level=0)
    at /home/pm/qemu-bisect/hw/intc/arm_gic_kvm.c:82
#6  0x0000aaaaab1ba15c in qemu_set_irq (irq=0xaaaaac186090, level=0)
    at /home/pm/qemu-bisect/hw/core/irq.c:44
#7  0x0000aaaaaaf86050 in pmu_update_irq (env=0xaaaaac0fa470)
    at /home/pm/qemu-bisect/target/arm/helper.c:1412
#8  0x0000aaaaaaf8747c in pmintenclr_write (env=0xaaaaac0fa470,
ri=0xaaaaac12c3e0, value=2154950974777589790) at
/home/pm/qemu-bisect/target/arm/helper.c:1903
#9  0x0000aaaaaaf83e68 in write_raw_cp_reg (env=0xaaaaac0fa470,
ri=0xaaaaac12c3e0, v=2154950976315703518) at
/home/pm/qemu-bisect/target/arm/helper.c:206
#10 0x0000aaaaaaf840d4 in write_cpustate_to_list (cpu=0xaaaaac0f0b90,
kvm_sync=true)
    at /home/pm/qemu-bisect/target/arm/helper.c:290
#11 0x0000aaaaaafbb1ac in kvm_arch_put_registers (cs=0xaaaaac0f0b90, level=3)
    at /home/pm/qemu-bisect/target/arm/kvm64.c:1108
#12 0x0000aaaaaae22ea0 in do_kvm_cpu_synchronize_post_init
(cpu=0xaaaaac0f0b90, arg=...)
    at /home/pm/qemu-bisect/accel/kvm/kvm-all.c:2223
#13 0x0000aaaaab107fa0 in process_queued_cpu_work (cpu=0xaaaaac0f0b90)
    at /home/pm/qemu-bisect/cpus-common.c:338
#14 0x0000aaaaaadf4ff4 in qemu_wait_io_event_common (cpu=0xaaaaac0f0b90)
    at /home/pm/qemu-bisect/cpus.c:1175
#15 0x0000aaaaaadf51a8 in qemu_wait_io_event (cpu=0xaaaaac0f0b90)
    at /home/pm/qemu-bisect/cpus.c:1215
#16 0x0000aaaaaadf52cc in qemu_kvm_cpu_thread_fn (arg=0xaaaaac0f0b90)
    at /home/pm/qemu-bisect/cpus.c:1251
#17 0x0000aaaaab690268 in qemu_thread_start (args=0xaaaaac14b1d0)
    at /home/pm/qemu-bisect/util/qemu-thread-posix.c:519


The point of the 'raw_read/write' accessors is that they're supposed
to not have side effects but just to be usable to read and write
any underlying register state. If the regdef doesn't define them
we fall back to the usual readfn/writefn on the assumption that
they're side-effect-free. So I think the fix here would be to
provide a raw_writefn everywhere where we've made
the normal writefn have a "sets an interrupt" side effect.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PULL 35/47] target/arm: Send interrupts on PMU counter overflow
  2020-02-25 17:08   ` Peter Maydell
@ 2020-07-01 15:11     ` Aaron Lindsay
  2020-07-03 15:14       ` Peter Maydell
  0 siblings, 1 reply; 56+ messages in thread
From: Aaron Lindsay @ 2020-07-01 15:11 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers

On Feb 25 17:08, Peter Maydell wrote:
> On Fri, 1 Feb 2019 at 16:07, Peter Maydell <peter.maydell@linaro.org> wrote:
> >
> > From: Aaron Lindsay OS <aaron@os.amperecomputing.com>
> >
> > Whenever we notice that a counter overflow has occurred, send an
> > interrupt. This is made more reliable with the addition of a timer in a
> > follow-on commit.
> >
> > Signed-off-by: Aaron Lindsay <aaron@os.amperecomputing.com>
> > Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> > Message-id: 20190124162401.5111-2-aaron@os.amperecomputing.com
> > Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> 
> Hi Aaron -- I've just noticed a problem with this patch that
> went into QEMU recently. The problem is that we can end up
> calling pmu_update_irq(), which injects an interrupt, from
> a raw-write function for some of the PMU registers. This is
> bad because when we're using KVM the raw-write functions are
> called as part of syncing state to and from the kernel. In
> particular, if using '-cpu host,pmu=off' we don't set up the
> PMU interrupt because we don't want to provide the guest a
> PMU but then we can still find ourselves in this function,
> and then we assert because we try to set a bogus interrupt.
> Here's the backtrace:
> 
> #1  0x0000fffff6be68b4 in __GI_abort () at abort.c:79
> #2  0x0000aaaaaae20820 in kvm_set_irq (s=0xaaaaabf8a020, irq=33554455, level=0)
>     at /home/pm/qemu-bisect/accel/kvm/kvm-all.c:1277
> #3  0x0000aaaaaafb7890 in kvm_arm_set_irq (cpu=0, irqtype=2, irq=23, level=0)
>     at /home/pm/qemu-bisect/target/arm/kvm.c:897
> #4  0x0000aaaaaae729dc in kvm_arm_gic_set_irq (num_irq=288, irq=23, level=0)
>     at /home/pm/qemu-bisect/hw/intc/arm_gic_kvm.c:75
> #5  0x0000aaaaaae72a1c in kvm_arm_gicv2_set_irq
> (opaque=0xaaaaac169ff0, irq=279, level=0)
>     at /home/pm/qemu-bisect/hw/intc/arm_gic_kvm.c:82
> #6  0x0000aaaaab1ba15c in qemu_set_irq (irq=0xaaaaac186090, level=0)
>     at /home/pm/qemu-bisect/hw/core/irq.c:44
> #7  0x0000aaaaaaf86050 in pmu_update_irq (env=0xaaaaac0fa470)
>     at /home/pm/qemu-bisect/target/arm/helper.c:1412
> #8  0x0000aaaaaaf8747c in pmintenclr_write (env=0xaaaaac0fa470,
> ri=0xaaaaac12c3e0, value=2154950974777589790) at
> /home/pm/qemu-bisect/target/arm/helper.c:1903
> #9  0x0000aaaaaaf83e68 in write_raw_cp_reg (env=0xaaaaac0fa470,
> ri=0xaaaaac12c3e0, v=2154950976315703518) at
> /home/pm/qemu-bisect/target/arm/helper.c:206
> #10 0x0000aaaaaaf840d4 in write_cpustate_to_list (cpu=0xaaaaac0f0b90,
> kvm_sync=true)
>     at /home/pm/qemu-bisect/target/arm/helper.c:290
> #11 0x0000aaaaaafbb1ac in kvm_arch_put_registers (cs=0xaaaaac0f0b90, level=3)
>     at /home/pm/qemu-bisect/target/arm/kvm64.c:1108
> #12 0x0000aaaaaae22ea0 in do_kvm_cpu_synchronize_post_init
> (cpu=0xaaaaac0f0b90, arg=...)
>     at /home/pm/qemu-bisect/accel/kvm/kvm-all.c:2223
> #13 0x0000aaaaab107fa0 in process_queued_cpu_work (cpu=0xaaaaac0f0b90)
>     at /home/pm/qemu-bisect/cpus-common.c:338
> #14 0x0000aaaaaadf4ff4 in qemu_wait_io_event_common (cpu=0xaaaaac0f0b90)
>     at /home/pm/qemu-bisect/cpus.c:1175
> #15 0x0000aaaaaadf51a8 in qemu_wait_io_event (cpu=0xaaaaac0f0b90)
>     at /home/pm/qemu-bisect/cpus.c:1215
> #16 0x0000aaaaaadf52cc in qemu_kvm_cpu_thread_fn (arg=0xaaaaac0f0b90)
>     at /home/pm/qemu-bisect/cpus.c:1251
> #17 0x0000aaaaab690268 in qemu_thread_start (args=0xaaaaac14b1d0)
>     at /home/pm/qemu-bisect/util/qemu-thread-posix.c:519
> 
> 
> The point of the 'raw_read/write' accessors is that they're supposed
> to not have side effects but just to be usable to read and write
> any underlying register state. If the regdef doesn't define them
> we fall back to the usual readfn/writefn on the assumption that
> they're side-effect-free. So I think the fix here would be to
> provide a raw_writefn everywhere where we've made
> the normal writefn have a "sets an interrupt" side effect.

Ouch - I'm sorry this slipped through the cracks in my inbox for so
long.

I assume you mean something like:

diff --git a/target/arm/helper.c b/target/arm/helper.c
index dc9c29f998..9b917f9425 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2271,13 +2271,13 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
       .access = PL1_RW, .accessfn = access_tpm,
       .type = ARM_CP_ALIAS | ARM_CP_IO,
       .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
-      .writefn = pmintenclr_write, },
+      .writefn = pmintenclr_write, .raw_writefn = raw_write },
     { .name = "PMINTENCLR_EL1", .state = ARM_CP_STATE_AA64,
       .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 2,
       .access = PL1_RW, .accessfn = access_tpm,
       .type = ARM_CP_ALIAS | ARM_CP_IO,
       .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
-      .writefn = pmintenclr_write },
+      .writefn = pmintenclr_write, .raw_writefn = raw_write },
     { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
       .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
       .access = PL1_R,

One thing I'm trying to figure out (talking non-KVM here) is whether
skipping calling pmu_update_irq() can mean an interrupt would not be set
when it should have been. It looks like the ARMCPRegInfo's for
PMINTENSET already do `.raw_writefn = raw_write`, so I suppose at least
we would be consistent with this change. But I can never remember - is
it guaranteed that the raw functions are only ever called when the
interrupt state would already be taken care of separately (i.e. when
restoring a checkpoint)?

-Aaron


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PULL 35/47] target/arm: Send interrupts on PMU counter overflow
  2020-07-01 15:11     ` Aaron Lindsay
@ 2020-07-03 15:14       ` Peter Maydell
  0 siblings, 0 replies; 56+ messages in thread
From: Peter Maydell @ 2020-07-03 15:14 UTC (permalink / raw)
  To: Aaron Lindsay; +Cc: QEMU Developers

On Wed, 1 Jul 2020 at 16:11, Aaron Lindsay <aaron@os.amperecomputing.com> wrote:
> Ouch - I'm sorry this slipped through the cracks in my inbox for so
> long.
>
> I assume you mean something like:
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index dc9c29f998..9b917f9425 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -2271,13 +2271,13 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
>        .access = PL1_RW, .accessfn = access_tpm,
>        .type = ARM_CP_ALIAS | ARM_CP_IO,
>        .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
> -      .writefn = pmintenclr_write, },
> +      .writefn = pmintenclr_write, .raw_writefn = raw_write },
>      { .name = "PMINTENCLR_EL1", .state = ARM_CP_STATE_AA64,
>        .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 2,
>        .access = PL1_RW, .accessfn = access_tpm,
>        .type = ARM_CP_ALIAS | ARM_CP_IO,
>        .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
> -      .writefn = pmintenclr_write },
> +      .writefn = pmintenclr_write, .raw_writefn = raw_write },
>      { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
>        .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
>        .access = PL1_R,

For cases like this where you have a 'set' and a 'clr' register
that really are accessing the same state under the hood, the
way to do it is:
 * the 'set' register provides the raw_readfn/raw_writefn
   as raw_read/raw_write
 * the 'clr' register adds ARM_CP_NO_RAW to its .type flags,
   which means "don't do any raw accesses to this, it doesn't
   have any underlying state that's not already synced or
   migrated via some other mechanism".

> One thing I'm trying to figure out (talking non-KVM here) is whether
> skipping calling pmu_update_irq() can mean an interrupt would not be set
> when it should have been. It looks like the ARMCPRegInfo's for
> PMINTENSET already do `.raw_writefn = raw_write`, so I suppose at least
> we would be consistent with this change. But I can never remember - is
> it guaranteed that the raw functions are only ever called when the
> interrupt state would already be taken care of separately (i.e. when
> restoring a checkpoint)?

Yes, the raw writes only happen for migration or for when
we're syncing state from a KVM kernel, so the state of
the device at the other end of the irq line should already
be correct.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2020-07-03 15:15 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-01 16:06 [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 01/47] hw/arm/nrf51_soc: set object owner in memory_region_init_ram Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 02/47] armv7m: Don't assume the NVIC's CPU is CPU 0 Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 03/47] armv7m: Make cpu object a child of the armv7m container Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 04/47] armv7m: Pass through start-powered-off CPU property Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 05/47] hw/arm/iotkit: Rename IoTKit to ARMSSE Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 06/47] hw/arm/iotkit: Refactor into abstract base class and subclass Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 07/47] hw/arm/iotkit: Rename 'iotkit' local variables and functions Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 08/47] hw/arm/iotkit: Rename files to hw/arm/armsse.[ch] Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 09/47] hw/misc/iotkit-secctl: Support 4 internal MPCs Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 10/47] hw/arm/armsse: Make number of SRAM banks parameterised Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 11/47] hw/arm/armsse: Make SRAM bank size configurable Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 12/47] hw/arm/armsse: Support dual-CPU configuration Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 13/47] hw/arm/armsse: Give each CPU its own view of memory Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 14/47] hw/arm/armsse: Put each CPU in its own cluster object Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 15/47] iotkit-sysinfo: Make SYS_VERSION and SYS_CONFIG configurable Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 16/47] hw/arm/armsse: Add unimplemented-device stubs for MHUs Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 17/47] hw/arm/armsse: Add unimplemented-device stubs for PPUs Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 18/47] hw/arm/armsse: Add unimplemented-device stub for cache control registers Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 19/47] hw/arm/armsse: Add unimplemented-device stub for CPU local " Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 20/47] hw/misc/armsse-cpuid: Implement SSE-200 CPU_IDENTITY register block Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 21/47] hw/arm/armsse: Add CPU_IDENTITY block to SSE-200 Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 22/47] hw/arm/armsse: Add SSE-200 model Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 23/47] hw/arm/mps2-tz: Add IRQ infrastructure to support SSE-200 Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 24/47] hw/arm/mps2-tz: Add mps2-an521 model Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 25/47] target/arm/translate-a64: Don't underdecode system instructions Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 26/47] target/arm/translate-a64: Don't underdecode PRFM Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 27/47] target/arm/translate-a64: Don't underdecode SIMD ld/st multiple Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 28/47] target/arm/translate-a64: Don't underdecode SIMD ld/st single Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 29/47] target/arm/translate-a64: Don't underdecode add/sub extended register Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 30/47] target/arm/translate-a64: Don't underdecode FP insns Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 31/47] target/arm/translate-a64: Don't underdecode SDOT and UDOT Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 32/47] exec.c: Don't reallocate IOMMUNotifiers that are in use Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 33/47] target/arm/translate-a64: Fix FCMLA decoding error Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 34/47] target/arm/translate-a64: Fix mishandling of size in FCMLA decode Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 35/47] target/arm: Send interrupts on PMU counter overflow Peter Maydell
2020-02-25 17:08   ` Peter Maydell
2020-07-01 15:11     ` Aaron Lindsay
2020-07-03 15:14       ` Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 36/47] target/arm: Add a timer to predict " Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 37/47] target/arm: Enable API, APK bits in SCR, HCR Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 38/47] arm: Clarify the logic of set_pc() Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 39/47] target/arm: Always enable pac keys for user-only Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 40/47] aarch64-linux-user: Update HWCAP bits from linux 5.0-rc1 Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 41/47] aarch64-linux-user: Enable HWCAP bits for PAuth Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 42/47] linux-user: Initialize aarch64 pac keys Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 43/47] target/arm: fix AArch64 virtual address space size Peter Maydell
2019-02-08 14:02   ` Laurent Vivier
2019-02-08 15:38     ` Remi Denis Courmont
2019-02-08 18:26       ` Laurent Vivier
2019-02-01 16:06 ` [Qemu-devel] [PULL 44/47] target/arm: fix decoding of B{, L}RA{A, B} Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 45/47] hw/nvram/nrf51_nvm: Add nRF51 non-volatile memories Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 46/47] arm: Instantiate NRF51 special NVM's and NVMC Peter Maydell
2019-02-01 16:06 ` [Qemu-devel] [PULL 47/47] tests/microbit-test: Add tests for nRF51 NVMC Peter Maydell
2019-02-01 17:56 ` [Qemu-devel] [PULL 00/47] target-arm queue Peter Maydell
2019-02-03 15:00 ` no-reply

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).