All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 00/54] target-arm queue
@ 2021-03-08 17:31 Peter Maydell
  2021-03-08 17:31 ` [PULL 01/54] clock: Add ClockEvent parameter to callbacks Peter Maydell
                   ` (54 more replies)
  0 siblings, 55 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:31 UTC (permalink / raw)
  To: qemu-devel

This is almost all the mps3-an547 series, but there are a few
other bits in there too.

thanks
-- PMM


The following changes since commit 0436c55edf6b357ff56e2a5bf688df8636f83456:

  Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2021-03-08 13:51:41 +0000)

are available in the Git repository at:

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

for you to fetch changes up to da2140183ac3a04b1ccb861aeac1f2c048c71b66:

  hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() (2021-03-08 17:20:04 +0000)

----------------------------------------------------------------
 * Add new mps3-an547 board
 * target/arm: Restrict v7A TCG cpus to TCG accel
 * Implement a Xilinx CSU DMA model
 * hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt()

----------------------------------------------------------------
Peter Maydell (48):
      clock: Add ClockEvent parameter to callbacks
      clock: Add ClockPreUpdate callback event type
      clock: Add clock_ns_to_ticks() function
      hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks()
      hw/arm/armsse: Introduce SSE subsystem version property
      hw/misc/iotkit-sysctl: Remove is_sse200 flag
      hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values
      hw/misc/iotkit-sysinfo.c: Implement SSE-300 PID register values
      hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300
      hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR
      hw/timer/sse-counter: Model the SSE Subsystem System Counter
      hw/timer/sse-timer: Model the SSE Subsystem System Timer
      hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour
      hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300
      hw/misc/iotkit-sysctl: Handle INITSVTOR* for SSE-300
      hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register
      hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers
      hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values
      hw/arm/Kconfig: Move ARMSSE_CPUID and ARMSSE_MHU stanzas to hw/misc
      hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block
      hw/arm/armsse: Use an array for apb_ppc fields in the state structure
      hw/arm/armsse: Add a define for number of IRQs used by the SSE itself
      hw/arm/armsse: Add framework for data-driven device placement
      hw/arm/armsse: Move dual-timer device into data-driven framework
      hw/arm/armsse: Move watchdogs into data-driven framework
      hw/arm/armsse: Move s32ktimer into data-driven framework
      hw/arm/armsse: Move sysinfo register block into data-driven framework
      hw/arm/armsse: Move sysctl register block into data-driven framework
      hw/arm/armsse: Move PPUs into data-driven framework
      hw/arm/armsse: Add missing SSE-200 SYS_PPU
      hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo
      hw/arm/armsse: Add support for SSE variants with a system counter
      hw/arm/armsse: Add support for TYPE_SSE_TIMER in ARMSSEDeviceInfo
      hw/arm/armsse: Support variants with ARMSSE_CPU_PWRCTRL block
      hw/arm/armsse: Add SSE-300 support
      hw/arm/mps2-tz: Make UART overflow IRQ board-specific
      hw/misc/mps2-fpgaio: Fold counters subsection into main vmstate
      hw/misc/mps2-fpgaio: Support AN547 DBGCTRL register
      hw/misc/mps2-scc: Implement changes for AN547
      hw/arm/mps2-tz: Support running APB peripherals on different clock
      hw/arm/mps2-tz: Make initsvtor0 setting board-specific
      hw/arm/mps2-tz: Add new mps3-an547 board
      docs/system/arm/mps2.rst: Document the new mps3-an547 board
      tests/qtest/sse-timer-test: Add simple test of the SSE counter
      tests/qtest/sse-timer-test: Test the system timer
      tests/qtest/sse-timer-test: Test counter scaling changes
      hw/timer/renesas_tmr: Prefix constants for CSS values with CSS_
      hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt()

Philippe Mathieu-Daudé (1):
      target/arm: Restrict v7A TCG cpus to TCG accel

Xuzhou Cheng (5):
      hw/dma: Implement a Xilinx CSU DMA model
      hw/arm: xlnx-zynqmp: Clean up coding convention issues
      hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI
      hw/ssi: xilinx_spips: Clean up coding convention issues
      hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips

 docs/devel/clocks.rst                |   71 ++-
 docs/system/arm/mps2.rst             |    6 +-
 include/hw/arm/armsse-version.h      |   42 ++
 include/hw/arm/armsse.h              |   40 +-
 include/hw/arm/xlnx-zynqmp.h         |    5 +-
 include/hw/clock.h                   |   63 ++-
 include/hw/dma/xlnx_csu_dma.h        |   52 ++
 include/hw/misc/armsse-cpu-pwrctrl.h |   40 ++
 include/hw/misc/iotkit-secctl.h      |    2 +
 include/hw/misc/iotkit-sysctl.h      |   13 +-
 include/hw/misc/iotkit-sysinfo.h     |    2 +
 include/hw/misc/mps2-fpgaio.h        |    2 +
 include/hw/qdev-clock.h              |   17 +-
 include/hw/ssi/xilinx_spips.h        |    2 +-
 include/hw/timer/sse-counter.h       |  105 ++++
 include/hw/timer/sse-timer.h         |   53 ++
 hw/adc/npcm7xx_adc.c                 |    2 +-
 hw/arm/armsse.c                      | 1008 +++++++++++++++++++++++++---------
 hw/arm/mps2-tz.c                     |  168 +++++-
 hw/arm/xlnx-zynqmp.c                 |   21 +-
 hw/char/cadence_uart.c               |    4 +-
 hw/char/ibex_uart.c                  |    4 +-
 hw/char/pl011.c                      |    5 +-
 hw/core/clock.c                      |   24 +-
 hw/core/qdev-clock.c                 |    8 +-
 hw/dma/xlnx_csu_dma.c                |  745 +++++++++++++++++++++++++
 hw/mips/cps.c                        |    2 +-
 hw/misc/armsse-cpu-pwrctrl.c         |  149 +++++
 hw/misc/bcm2835_cprman.c             |   23 +-
 hw/misc/iotkit-secctl.c              |   50 +-
 hw/misc/iotkit-sysctl.c              |  522 +++++++++++++++---
 hw/misc/iotkit-sysinfo.c             |   51 +-
 hw/misc/mps2-fpgaio.c                |   52 +-
 hw/misc/mps2-scc.c                   |   15 +-
 hw/misc/npcm7xx_clk.c                |   26 +-
 hw/misc/npcm7xx_pwm.c                |    2 +-
 hw/misc/zynq_slcr.c                  |    5 +-
 hw/ssi/xilinx_spips.c                |   33 +-
 hw/timer/cmsdk-apb-dualtimer.c       |    5 +-
 hw/timer/cmsdk-apb-timer.c           |    4 +-
 hw/timer/npcm7xx_timer.c             |    6 +-
 hw/timer/renesas_tmr.c               |   33 +-
 hw/timer/sse-counter.c               |  474 ++++++++++++++++
 hw/timer/sse-timer.c                 |  470 ++++++++++++++++
 hw/watchdog/cmsdk-apb-watchdog.c     |    5 +-
 target/arm/cpu.c                     |  335 -----------
 target/arm/cpu_tcg.c                 |  318 +++++++++++
 target/mips/cpu.c                    |    2 +-
 tests/qtest/sse-timer-test.c         |  240 ++++++++
 MAINTAINERS                          |    7 +
 hw/arm/Kconfig                       |   10 +-
 hw/dma/Kconfig                       |    4 +
 hw/dma/meson.build                   |    1 +
 hw/misc/Kconfig                      |    9 +
 hw/misc/meson.build                  |    1 +
 hw/misc/trace-events                 |    4 +
 hw/timer/Kconfig                     |    6 +
 hw/timer/meson.build                 |    2 +
 hw/timer/trace-events                |   12 +
 tests/qtest/meson.build              |    1 +
 60 files changed, 4537 insertions(+), 846 deletions(-)
 create mode 100644 include/hw/arm/armsse-version.h
 create mode 100644 include/hw/dma/xlnx_csu_dma.h
 create mode 100644 include/hw/misc/armsse-cpu-pwrctrl.h
 create mode 100644 include/hw/timer/sse-counter.h
 create mode 100644 include/hw/timer/sse-timer.h
 create mode 100644 hw/dma/xlnx_csu_dma.c
 create mode 100644 hw/misc/armsse-cpu-pwrctrl.c
 create mode 100644 hw/timer/sse-counter.c
 create mode 100644 hw/timer/sse-timer.c
 create mode 100644 tests/qtest/sse-timer-test.c


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

* [PULL 01/54] clock: Add ClockEvent parameter to callbacks
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
@ 2021-03-08 17:31 ` Peter Maydell
  2021-03-08 17:31 ` [PULL 02/54] clock: Add ClockPreUpdate callback event type Peter Maydell
                   ` (53 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:31 UTC (permalink / raw)
  To: qemu-devel

The Clock framework allows users to specify a callback which is
called after the clock's period has been updated.  Some users need to
also have a callback which is called before the clock period is
updated.

As the first step in adding support for notifying Clock users on
pre-update events, add an argument to the ClockCallback to specify
what event is being notified, and add an argument to the various
functions for registering a callback to specify which events are
of interest to that callback.

Note that the documentation update renders correct the previously
incorrect claim in 'Adding a new clock' that callbacks "will be
explained in a following section".

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Luc Michel <luc@lmichel.fr>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-2-peter.maydell@linaro.org
---
 docs/devel/clocks.rst            | 52 +++++++++++++++++++++++++++-----
 include/hw/clock.h               | 21 +++++++++++--
 include/hw/qdev-clock.h          | 17 ++++++++---
 hw/adc/npcm7xx_adc.c             |  2 +-
 hw/arm/armsse.c                  |  9 +++---
 hw/char/cadence_uart.c           |  4 +--
 hw/char/ibex_uart.c              |  4 +--
 hw/char/pl011.c                  |  5 +--
 hw/core/clock.c                  | 21 ++++++++++---
 hw/core/qdev-clock.c             |  8 +++--
 hw/mips/cps.c                    |  2 +-
 hw/misc/bcm2835_cprman.c         | 23 ++++++++------
 hw/misc/npcm7xx_clk.c            | 26 +++++++++++++---
 hw/misc/npcm7xx_pwm.c            |  2 +-
 hw/misc/zynq_slcr.c              |  5 +--
 hw/timer/cmsdk-apb-dualtimer.c   |  5 +--
 hw/timer/cmsdk-apb-timer.c       |  4 +--
 hw/timer/npcm7xx_timer.c         |  2 +-
 hw/watchdog/cmsdk-apb-watchdog.c |  5 +--
 target/mips/cpu.c                |  2 +-
 20 files changed, 161 insertions(+), 58 deletions(-)

diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
index c54bbb82409..cd344e3fe5d 100644
--- a/docs/devel/clocks.rst
+++ b/docs/devel/clocks.rst
@@ -80,11 +80,12 @@ Adding clocks to a device must be done during the init method of the Device
 instance.
 
 To add an input clock to a device, the function ``qdev_init_clock_in()``
-must be used.  It takes the name, a callback and an opaque parameter
-for the callback (this will be explained in a following section).
+must be used.  It takes the name, a callback, an opaque parameter
+for the callback and a mask of events when the callback should be
+called (this will be explained in a following section).
 Output is simpler; only the name is required. Typically::
 
-    qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev);
+    qdev_init_clock_in(DEVICE(dev), "clk_in", clk_in_callback, dev, ClockUpdate);
     qdev_init_clock_out(DEVICE(dev), "clk_out");
 
 Both functions return the created Clock pointer, which should be saved in the
@@ -113,7 +114,7 @@ output.
      * callback for the input clock (see "Callback on input clock
      * change" section below for more information).
      */
-    static void clk_in_callback(void *opaque);
+    static void clk_in_callback(void *opaque, ClockEvent event);
 
     /*
      * static array describing clocks:
@@ -124,7 +125,7 @@ output.
      *   the clk_out field of a MyDeviceState structure.
      */
     static const ClockPortInitArray mydev_clocks = {
-        QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback),
+        QDEV_CLOCK_IN(MyDeviceState, clk_in, clk_in_callback, ClockUpdate),
         QDEV_CLOCK_OUT(MyDeviceState, clk_out),
         QDEV_CLOCK_END
     };
@@ -153,6 +154,40 @@ nothing else to do. This value will be propagated to other clocks when
 connecting the clocks together and devices will fetch the right value during
 the first reset.
 
+Clock callbacks
+---------------
+
+You can give a clock a callback function in several ways:
+
+ * by passing it as an argument to ``qdev_init_clock_in()``
+ * as an argument to the ``QDEV_CLOCK_IN()`` macro initializing an
+   array to be passed to ``qdev_init_clocks()``
+ * by directly calling the ``clock_set_callback()`` function
+
+The callback function must be of this type:
+
+.. code-block:: c
+
+   typedef void ClockCallback(void *opaque, ClockEvent event);
+
+The ``opaque`` argument is the pointer passed to ``qdev_init_clock_in()``
+or ``clock_set_callback()``; for ``qdev_init_clocks()`` it is the
+``dev`` device pointer.
+
+The ``event`` argument specifies why the callback has been called.
+When you register the callback you specify a mask of ClockEvent values
+that you are interested in. The callback will only be called for those
+events.
+
+The events currently supported are:
+
+ * ``ClockUpdate`` : called after the input clock's period has changed
+
+Note that a clock only has one callback: it is not possible to register
+different functions for different events. You must register a single
+callback which listens for all of the events you are interested in,
+and use the ``event`` argument to identify which event has happened.
+
 Retrieving clocks from a device
 -------------------------------
 
@@ -231,7 +266,7 @@ object during device instance init. For example:
 .. code-block:: c
 
     clk = qdev_init_clock_in(DEVICE(dev), "clk-in", clk_in_callback,
-                             dev);
+                             dev, ClockUpdate);
     /* set initial value to 10ns / 100MHz */
     clock_set_ns(clk, 10);
 
@@ -267,11 +302,12 @@ next lowest integer. This implies some inaccuracy due to the rounding,
 so be cautious about using it in calculations.
 
 It is also possible to register a callback on clock frequency changes.
-Here is an example:
+Here is an example, which assumes that ``clock_callback`` has been
+specified as the callback for the ``ClockUpdate`` event:
 
 .. code-block:: c
 
-    void clock_callback(void *opaque) {
+    void clock_callback(void *opaque, ClockEvent event) {
         MyDeviceState *s = (MyDeviceState *) opaque;
         /*
          * 'opaque' is the argument passed to qdev_init_clock_in();
diff --git a/include/hw/clock.h b/include/hw/clock.h
index e5f45e2626d..282a37f7c5a 100644
--- a/include/hw/clock.h
+++ b/include/hw/clock.h
@@ -22,7 +22,17 @@
 #define TYPE_CLOCK "clock"
 OBJECT_DECLARE_SIMPLE_TYPE(Clock, CLOCK)
 
-typedef void ClockCallback(void *opaque);
+/*
+ * Argument to ClockCallback functions indicating why the callback
+ * has been called. A mask of these values logically ORed together
+ * is used to specify which events are interesting when the callback
+ * is registered, so these values must all be different bit values.
+ */
+typedef enum ClockEvent {
+    ClockUpdate = 1, /* Clock period has just updated */
+} ClockEvent;
+
+typedef void ClockCallback(void *opaque, ClockEvent event);
 
 /*
  * clock store a value representing the clock's period in 2^-32ns unit.
@@ -50,6 +60,7 @@ typedef void ClockCallback(void *opaque);
  * @canonical_path: clock path string cache (used for trace purpose)
  * @callback: called when clock changes
  * @callback_opaque: argument for @callback
+ * @callback_events: mask of events when callback should be called
  * @source: source (or parent in clock tree) of the clock
  * @children: list of clocks connected to this one (it is their source)
  * @sibling: structure used to form a clock list
@@ -67,6 +78,7 @@ struct Clock {
     char *canonical_path;
     ClockCallback *callback;
     void *callback_opaque;
+    unsigned int callback_events;
 
     /* Clocks are organized in a clock tree */
     Clock *source;
@@ -114,10 +126,15 @@ Clock *clock_new(Object *parent, const char *name);
  * @clk: the clock to register the callback into
  * @cb: the callback function
  * @opaque: the argument to the callback
+ * @events: the events the callback should be called for
+ *          (logical OR of ClockEvent enum values)
  *
  * Register a callback called on every clock update.
+ * Note that a clock has only one callback: you cannot register
+ * different callback functions for different events.
  */
-void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque);
+void clock_set_callback(Clock *clk, ClockCallback *cb,
+                        void *opaque, unsigned int events);
 
 /**
  * clock_clear_callback:
diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h
index 64ca4d266f2..ffa0f7ba09e 100644
--- a/include/hw/qdev-clock.h
+++ b/include/hw/qdev-clock.h
@@ -22,6 +22,8 @@
  * @name: the name of the clock (can't be NULL).
  * @callback: optional callback to be called on update or NULL.
  * @opaque: argument for the callback
+ * @events: the events the callback should be called for
+ *          (logical OR of ClockEvent enum values)
  * @returns: a pointer to the newly added clock
  *
  * Add an input clock to device @dev as a clock named @name.
@@ -29,7 +31,8 @@
  * The callback will be called with @opaque as opaque parameter.
  */
 Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
-                          ClockCallback *callback, void *opaque);
+                          ClockCallback *callback, void *opaque,
+                          unsigned int events);
 
 /**
  * qdev_init_clock_out:
@@ -105,6 +108,7 @@ void qdev_finalize_clocklist(DeviceState *dev);
  * @output: indicates whether the clock is input or output
  * @callback: for inputs, optional callback to be called on clock's update
  * with device as opaque
+ * @callback_events: mask of ClockEvent values for when callback is called
  * @offset: optional offset to store the ClockIn or ClockOut pointer in device
  * state structure (0 means unused)
  */
@@ -112,6 +116,7 @@ struct ClockPortInitElem {
     const char *name;
     bool is_output;
     ClockCallback *callback;
+    unsigned int callback_events;
     size_t offset;
 };
 
@@ -119,10 +124,11 @@ struct ClockPortInitElem {
     (offsetof(devstate, field) + \
      type_check(Clock *, typeof_field(devstate, field)))
 
-#define QDEV_CLOCK(out_not_in, devstate, field, cb) { \
+#define QDEV_CLOCK(out_not_in, devstate, field, cb, cbevents) {  \
     .name = (stringify(field)), \
     .is_output = out_not_in, \
     .callback = cb, \
+    .callback_events = cbevents, \
     .offset = clock_offset_value(devstate, field), \
 }
 
@@ -133,14 +139,15 @@ struct ClockPortInitElem {
  * @field: a field in @_devstate (must be Clock*)
  * @callback: (for input only) callback (or NULL) to be called with the device
  * state as argument
+ * @cbevents: (for input only) ClockEvent mask for when callback is called
  *
  * The name of the clock will be derived from @field
  */
-#define QDEV_CLOCK_IN(devstate, field, callback) \
-    QDEV_CLOCK(false, devstate, field, callback)
+#define QDEV_CLOCK_IN(devstate, field, callback, cbevents)       \
+    QDEV_CLOCK(false, devstate, field, callback, cbevents)
 
 #define QDEV_CLOCK_OUT(devstate, field) \
-    QDEV_CLOCK(true, devstate, field, NULL)
+    QDEV_CLOCK(true, devstate, field, NULL, 0)
 
 #define QDEV_CLOCK_END { .name = NULL }
 
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
index 870a6d50c27..0f0a9f63e20 100644
--- a/hw/adc/npcm7xx_adc.c
+++ b/hw/adc/npcm7xx_adc.c
@@ -238,7 +238,7 @@ static void npcm7xx_adc_init(Object *obj)
     memory_region_init_io(&s->iomem, obj, &npcm7xx_adc_ops, s,
                           TYPE_NPCM7XX_ADC, 4 * KiB);
     sysbus_init_mmio(sbd, &s->iomem);
-    s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
+    s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL, 0);
 
     for (i = 0; i < NPCM7XX_ADC_NUM_INPUTS; ++i) {
         object_property_add_uint32_ptr(obj, "adci[*]",
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 26e1a8c95b6..fa155b72022 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -230,9 +230,10 @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
     qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
 }
 
-static void armsse_mainclk_update(void *opaque)
+static void armsse_mainclk_update(void *opaque, ClockEvent event)
 {
     ARMSSE *s = ARM_SSE(opaque);
+
     /*
      * Set system_clock_scale from our Clock input; this is what
      * controls the tick rate of the CPU SysTick timer.
@@ -251,8 +252,8 @@ static void armsse_init(Object *obj)
     assert(info->num_cpus <= SSE_MAX_CPUS);
 
     s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
-                                    armsse_mainclk_update, s);
-    s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL);
+                                    armsse_mainclk_update, s, ClockUpdate);
+    s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL, 0);
 
     memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
 
@@ -1120,7 +1121,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
 
     /* Set initial system_clock_scale from MAINCLK */
-    armsse_mainclk_update(s);
+    armsse_mainclk_update(s, ClockUpdate);
 }
 
 static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index c603e14012a..ceb677bc5a8 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -519,7 +519,7 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
                              uart_event, NULL, s, NULL, true);
 }
 
-static void cadence_uart_refclk_update(void *opaque)
+static void cadence_uart_refclk_update(void *opaque, ClockEvent event)
 {
     CadenceUARTState *s = opaque;
 
@@ -537,7 +537,7 @@ static void cadence_uart_init(Object *obj)
     sysbus_init_irq(sbd, &s->irq);
 
     s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk",
-            cadence_uart_refclk_update, s);
+                                   cadence_uart_refclk_update, s, ClockUpdate);
     /* initialize the frequency in case the clock remains unconnected */
     clock_set_hz(s->refclk, UART_DEFAULT_REF_CLK);
 
diff --git a/hw/char/ibex_uart.c b/hw/char/ibex_uart.c
index 89f1182c9bf..edcaa30aded 100644
--- a/hw/char/ibex_uart.c
+++ b/hw/char/ibex_uart.c
@@ -396,7 +396,7 @@ static void ibex_uart_write(void *opaque, hwaddr addr,
     }
 }
 
-static void ibex_uart_clk_update(void *opaque)
+static void ibex_uart_clk_update(void *opaque, ClockEvent event)
 {
     IbexUartState *s = opaque;
 
@@ -466,7 +466,7 @@ static void ibex_uart_init(Object *obj)
     IbexUartState *s = IBEX_UART(obj);
 
     s->f_clk = qdev_init_clock_in(DEVICE(obj), "f_clock",
-                                  ibex_uart_clk_update, s);
+                                  ibex_uart_clk_update, s, ClockUpdate);
     clock_set_hz(s->f_clk, IBEX_UART_CLOCK);
 
     sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->tx_watermark);
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index ea4a4e52356..c5621a195ff 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -309,7 +309,7 @@ static void pl011_event(void *opaque, QEMUChrEvent event)
         pl011_put_fifo(opaque, 0x400);
 }
 
-static void pl011_clock_update(void *opaque)
+static void pl011_clock_update(void *opaque, ClockEvent event)
 {
     PL011State *s = PL011(opaque);
 
@@ -378,7 +378,8 @@ static void pl011_init(Object *obj)
         sysbus_init_irq(sbd, &s->irq[i]);
     }
 
-    s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s);
+    s->clk = qdev_init_clock_in(DEVICE(obj), "clk", pl011_clock_update, s,
+                                ClockUpdate);
 
     s->read_trigger = 1;
     s->ifl = 0x12;
diff --git a/hw/core/clock.c b/hw/core/clock.c
index 76b5f468b6e..4479eff145b 100644
--- a/hw/core/clock.c
+++ b/hw/core/clock.c
@@ -39,15 +39,17 @@ Clock *clock_new(Object *parent, const char *name)
     return clk;
 }
 
-void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque)
+void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque,
+                        unsigned int events)
 {
     clk->callback = cb;
     clk->callback_opaque = opaque;
+    clk->callback_events = events;
 }
 
 void clock_clear_callback(Clock *clk)
 {
-    clock_set_callback(clk, NULL, NULL);
+    clock_set_callback(clk, NULL, NULL, 0);
 }
 
 bool clock_set(Clock *clk, uint64_t period)
@@ -62,6 +64,17 @@ bool clock_set(Clock *clk, uint64_t period)
     return true;
 }
 
+static void clock_call_callback(Clock *clk, ClockEvent event)
+{
+    /*
+     * Call the Clock's callback for this event, if it has one and
+     * is interested in this event.
+     */
+    if (clk->callback && (clk->callback_events & event)) {
+        clk->callback(clk->callback_opaque, event);
+    }
+}
+
 static void clock_propagate_period(Clock *clk, bool call_callbacks)
 {
     Clock *child;
@@ -72,8 +85,8 @@ static void clock_propagate_period(Clock *clk, bool call_callbacks)
             trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
                                CLOCK_PERIOD_TO_HZ(clk->period),
                                call_callbacks);
-            if (call_callbacks && child->callback) {
-                child->callback(child->callback_opaque);
+            if (call_callbacks) {
+                clock_call_callback(child, ClockUpdate);
             }
             clock_propagate_period(child, call_callbacks);
         }
diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c
index eb05f2a13ca..117f4c6ea4a 100644
--- a/hw/core/qdev-clock.c
+++ b/hw/core/qdev-clock.c
@@ -111,7 +111,8 @@ Clock *qdev_init_clock_out(DeviceState *dev, const char *name)
 }
 
 Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
-                            ClockCallback *callback, void *opaque)
+                          ClockCallback *callback, void *opaque,
+                          unsigned int events)
 {
     NamedClockList *ncl;
 
@@ -120,7 +121,7 @@ Clock *qdev_init_clock_in(DeviceState *dev, const char *name,
     ncl = qdev_init_clocklist(dev, name, false, NULL);
 
     if (callback) {
-        clock_set_callback(ncl->clock, callback, opaque);
+        clock_set_callback(ncl->clock, callback, opaque, events);
     }
     return ncl->clock;
 }
@@ -137,7 +138,8 @@ void qdev_init_clocks(DeviceState *dev, const ClockPortInitArray clocks)
         if (elem->is_output) {
             *clkp = qdev_init_clock_out(dev, elem->name);
         } else {
-            *clkp = qdev_init_clock_in(dev, elem->name, elem->callback, dev);
+            *clkp = qdev_init_clock_in(dev, elem->name, elem->callback, dev,
+                                       elem->callback_events);
         }
     }
 }
diff --git a/hw/mips/cps.c b/hw/mips/cps.c
index 7a0d289efaf..2b436700ce6 100644
--- a/hw/mips/cps.c
+++ b/hw/mips/cps.c
@@ -39,7 +39,7 @@ static void mips_cps_init(Object *obj)
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
     MIPSCPSState *s = MIPS_CPS(obj);
 
-    s->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, NULL);
+    s->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, NULL, 0);
     /*
      * Cover entire address space as there do not seem to be any
      * constraints for the base address of CPC and GIC.
diff --git a/hw/misc/bcm2835_cprman.c b/hw/misc/bcm2835_cprman.c
index 7e415a017c9..75e6c574d46 100644
--- a/hw/misc/bcm2835_cprman.c
+++ b/hw/misc/bcm2835_cprman.c
@@ -107,7 +107,7 @@ static void pll_update(CprmanPllState *pll)
     clock_update_hz(pll->out, freq);
 }
 
-static void pll_xosc_update(void *opaque)
+static void pll_xosc_update(void *opaque, ClockEvent event)
 {
     pll_update(CPRMAN_PLL(opaque));
 }
@@ -116,7 +116,8 @@ static void pll_init(Object *obj)
 {
     CprmanPllState *s = CPRMAN_PLL(obj);
 
-    s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update, s);
+    s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update,
+                                    s, ClockUpdate);
     s->out = qdev_init_clock_out(DEVICE(s), "out");
 }
 
@@ -209,7 +210,7 @@ static void pll_update_all_channels(BCM2835CprmanState *s,
     }
 }
 
-static void pll_channel_pll_in_update(void *opaque)
+static void pll_channel_pll_in_update(void *opaque, ClockEvent event)
 {
     pll_channel_update(CPRMAN_PLL_CHANNEL(opaque));
 }
@@ -219,7 +220,8 @@ static void pll_channel_init(Object *obj)
     CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(obj);
 
     s->pll_in = qdev_init_clock_in(DEVICE(s), "pll-in",
-                                   pll_channel_pll_in_update, s);
+                                   pll_channel_pll_in_update, s,
+                                   ClockUpdate);
     s->out = qdev_init_clock_out(DEVICE(s), "out");
 }
 
@@ -303,7 +305,7 @@ static void clock_mux_update(CprmanClockMuxState *mux)
     clock_update_hz(mux->out, freq);
 }
 
-static void clock_mux_src_update(void *opaque)
+static void clock_mux_src_update(void *opaque, ClockEvent event)
 {
     CprmanClockMuxState **backref = opaque;
     CprmanClockMuxState *s = *backref;
@@ -335,7 +337,8 @@ static void clock_mux_init(Object *obj)
         s->backref[i] = s;
         s->srcs[i] = qdev_init_clock_in(DEVICE(s), name,
                                         clock_mux_src_update,
-                                        &s->backref[i]);
+                                        &s->backref[i],
+                                        ClockUpdate);
         g_free(name);
     }
 
@@ -380,7 +383,7 @@ static void dsi0hsck_mux_update(CprmanDsi0HsckMuxState *s)
     clock_update(s->out, clock_get(src));
 }
 
-static void dsi0hsck_mux_in_update(void *opaque)
+static void dsi0hsck_mux_in_update(void *opaque, ClockEvent event)
 {
     dsi0hsck_mux_update(CPRMAN_DSI0HSCK_MUX(opaque));
 }
@@ -390,8 +393,10 @@ static void dsi0hsck_mux_init(Object *obj)
     CprmanDsi0HsckMuxState *s = CPRMAN_DSI0HSCK_MUX(obj);
     DeviceState *dev = DEVICE(obj);
 
-    s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update, s);
-    s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update, s);
+    s->plla_in = qdev_init_clock_in(dev, "plla-in", dsi0hsck_mux_in_update,
+                                    s, ClockUpdate);
+    s->plld_in = qdev_init_clock_in(dev, "plld-in", dsi0hsck_mux_in_update,
+                                    s, ClockUpdate);
     s->out = qdev_init_clock_out(DEVICE(s), "out");
 }
 
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
index 0bcae9ce957..a1ee67dc9a1 100644
--- a/hw/misc/npcm7xx_clk.c
+++ b/hw/misc/npcm7xx_clk.c
@@ -586,15 +586,26 @@ static const DividerInitInfo divider_init_info_list[] = {
     },
 };
 
+static void npcm7xx_clk_update_pll_cb(void *opaque, ClockEvent event)
+{
+    npcm7xx_clk_update_pll(opaque);
+}
+
 static void npcm7xx_clk_pll_init(Object *obj)
 {
     NPCM7xxClockPLLState *pll = NPCM7XX_CLOCK_PLL(obj);
 
     pll->clock_in = qdev_init_clock_in(DEVICE(pll), "clock-in",
-            npcm7xx_clk_update_pll, pll);
+                                       npcm7xx_clk_update_pll_cb, pll,
+                                       ClockUpdate);
     pll->clock_out = qdev_init_clock_out(DEVICE(pll), "clock-out");
 }
 
+static void npcm7xx_clk_update_sel_cb(void *opaque, ClockEvent event)
+{
+    npcm7xx_clk_update_sel(opaque);
+}
+
 static void npcm7xx_clk_sel_init(Object *obj)
 {
     int i;
@@ -603,16 +614,23 @@ static void npcm7xx_clk_sel_init(Object *obj)
     for (i = 0; i < NPCM7XX_CLK_SEL_MAX_INPUT; ++i) {
         sel->clock_in[i] = qdev_init_clock_in(DEVICE(sel),
                 g_strdup_printf("clock-in[%d]", i),
-                npcm7xx_clk_update_sel, sel);
+                npcm7xx_clk_update_sel_cb, sel, ClockUpdate);
     }
     sel->clock_out = qdev_init_clock_out(DEVICE(sel), "clock-out");
 }
+
+static void npcm7xx_clk_update_divider_cb(void *opaque, ClockEvent event)
+{
+    npcm7xx_clk_update_divider(opaque);
+}
+
 static void npcm7xx_clk_divider_init(Object *obj)
 {
     NPCM7xxClockDividerState *div = NPCM7XX_CLOCK_DIVIDER(obj);
 
     div->clock_in = qdev_init_clock_in(DEVICE(div), "clock-in",
-            npcm7xx_clk_update_divider, div);
+                                       npcm7xx_clk_update_divider_cb,
+                                       div, ClockUpdate);
     div->clock_out = qdev_init_clock_out(DEVICE(div), "clock-out");
 }
 
@@ -875,7 +893,7 @@ static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
 {
     int i;
 
-    s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL);
+    s->clkref = qdev_init_clock_in(DEVICE(s), "clkref", NULL, NULL, 0);
 
     /* First pass: init all converter modules */
     QEMU_BUILD_BUG_ON(ARRAY_SIZE(pll_init_info_list) != NPCM7XX_CLOCK_NR_PLLS);
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
index dabcb6c0f95..ce192bb2741 100644
--- a/hw/misc/npcm7xx_pwm.c
+++ b/hw/misc/npcm7xx_pwm.c
@@ -493,7 +493,7 @@ static void npcm7xx_pwm_init(Object *obj)
     memory_region_init_io(&s->iomem, obj, &npcm7xx_pwm_ops, s,
                           TYPE_NPCM7XX_PWM, 4 * KiB);
     sysbus_init_mmio(sbd, &s->iomem);
-    s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL);
+    s->clock = qdev_init_clock_in(DEVICE(s), "clock", NULL, NULL, 0);
 
     for (i = 0; i < NPCM7XX_PWM_PER_MODULE; ++i) {
         object_property_add_uint32_ptr(obj, "freq[*]",
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index 66504a9d3ab..c66d7db177d 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -307,9 +307,10 @@ static void zynq_slcr_propagate_clocks(ZynqSLCRState *s)
     clock_propagate(s->uart1_ref_clk);
 }
 
-static void zynq_slcr_ps_clk_callback(void *opaque)
+static void zynq_slcr_ps_clk_callback(void *opaque, ClockEvent event)
 {
     ZynqSLCRState *s = (ZynqSLCRState *) opaque;
+
     zynq_slcr_compute_clocks(s);
     zynq_slcr_propagate_clocks(s);
 }
@@ -576,7 +577,7 @@ static const MemoryRegionOps slcr_ops = {
 };
 
 static const ClockPortInitArray zynq_slcr_clocks = {
-    QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback),
+    QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback, ClockUpdate),
     QDEV_CLOCK_OUT(ZynqSLCRState, uart0_ref_clk),
     QDEV_CLOCK_OUT(ZynqSLCRState, uart1_ref_clk),
     QDEV_CLOCK_END
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
index ef49f5852d3..d4a509c798e 100644
--- a/hw/timer/cmsdk-apb-dualtimer.c
+++ b/hw/timer/cmsdk-apb-dualtimer.c
@@ -449,7 +449,7 @@ static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
     s->timeritop = 0;
 }
 
-static void cmsdk_apb_dualtimer_clk_update(void *opaque)
+static void cmsdk_apb_dualtimer_clk_update(void *opaque, ClockEvent event)
 {
     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
     int i;
@@ -478,7 +478,8 @@ static void cmsdk_apb_dualtimer_init(Object *obj)
         sysbus_init_irq(sbd, &s->timermod[i].timerint);
     }
     s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK",
-                                   cmsdk_apb_dualtimer_clk_update, s);
+                                   cmsdk_apb_dualtimer_clk_update, s,
+                                   ClockUpdate);
 }
 
 static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
index ee51ce3369c..68aa1a76360 100644
--- a/hw/timer/cmsdk-apb-timer.c
+++ b/hw/timer/cmsdk-apb-timer.c
@@ -204,7 +204,7 @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
     ptimer_transaction_commit(s->timer);
 }
 
-static void cmsdk_apb_timer_clk_update(void *opaque)
+static void cmsdk_apb_timer_clk_update(void *opaque, ClockEvent event)
 {
     CMSDKAPBTimer *s = CMSDK_APB_TIMER(opaque);
 
@@ -223,7 +223,7 @@ static void cmsdk_apb_timer_init(Object *obj)
     sysbus_init_mmio(sbd, &s->iomem);
     sysbus_init_irq(sbd, &s->timerint);
     s->pclk = qdev_init_clock_in(DEVICE(s), "pclk",
-                                 cmsdk_apb_timer_clk_update, s);
+                                 cmsdk_apb_timer_clk_update, s, ClockUpdate);
 }
 
 static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
index 36e2c07db26..4efdf135b82 100644
--- a/hw/timer/npcm7xx_timer.c
+++ b/hw/timer/npcm7xx_timer.c
@@ -627,7 +627,7 @@ static void npcm7xx_timer_init(Object *obj)
     sysbus_init_mmio(sbd, &s->iomem);
     qdev_init_gpio_out_named(dev, &w->reset_signal,
             NPCM7XX_WATCHDOG_RESET_GPIO_OUT, 1);
-    s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL);
+    s->clock = qdev_init_clock_in(dev, "clock", NULL, NULL, 0);
 }
 
 static const VMStateDescription vmstate_npcm7xx_base_timer = {
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
index 302f1711738..5a2cd46eb76 100644
--- a/hw/watchdog/cmsdk-apb-watchdog.c
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
@@ -310,7 +310,7 @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
     ptimer_transaction_commit(s->timer);
 }
 
-static void cmsdk_apb_watchdog_clk_update(void *opaque)
+static void cmsdk_apb_watchdog_clk_update(void *opaque, ClockEvent event)
 {
     CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(opaque);
 
@@ -329,7 +329,8 @@ static void cmsdk_apb_watchdog_init(Object *obj)
     sysbus_init_mmio(sbd, &s->iomem);
     sysbus_init_irq(sbd, &s->wdogint);
     s->wdogclk = qdev_init_clock_in(DEVICE(s), "WDOGCLK",
-                                    cmsdk_apb_watchdog_clk_update, s);
+                                    cmsdk_apb_watchdog_clk_update, s,
+                                    ClockUpdate);
 
     s->is_luminary = false;
     s->id = cmsdk_apb_watchdog_id;
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index bf70c77295f..f6ef09c9e2d 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -653,7 +653,7 @@ static void mips_cpu_initfn(Object *obj)
     MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj);
 
     cpu_set_cpustate_pointers(cpu);
-    cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu);
+    cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu, 0);
     env->cpu_model = mcc->cpu_def;
 }
 
-- 
2.20.1



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

* [PULL 02/54] clock: Add ClockPreUpdate callback event type
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
  2021-03-08 17:31 ` [PULL 01/54] clock: Add ClockEvent parameter to callbacks Peter Maydell
@ 2021-03-08 17:31 ` Peter Maydell
  2021-03-08 17:31 ` [PULL 03/54] clock: Add clock_ns_to_ticks() function Peter Maydell
                   ` (52 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:31 UTC (permalink / raw)
  To: qemu-devel

Add a new callback event type ClockPreUpdate, which is called on
period changes before the period is updated.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Luc Michel <luc@lmichel.fr>
Reviewed-by: Hao Wu <wuhaotsh@google.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210219144617.4782-3-peter.maydell@linaro.org
---
 docs/devel/clocks.rst | 9 ++++++++-
 include/hw/clock.h    | 1 +
 hw/core/clock.c       | 3 +++
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
index cd344e3fe5d..f0391e76b4f 100644
--- a/docs/devel/clocks.rst
+++ b/docs/devel/clocks.rst
@@ -181,7 +181,14 @@ events.
 
 The events currently supported are:
 
- * ``ClockUpdate`` : called after the input clock's period has changed
+ * ``ClockPreUpdate`` : called when the input clock's period is about to
+   update. This is useful if the device needs to do some action for
+   which it needs to know the old value of the clock period. During
+   this callback, Clock API functions like ``clock_get()`` or
+   ``clock_ticks_to_ns()`` will use the old period.
+ * ``ClockUpdate`` : called after the input clock's period has changed.
+   During this callback, Clock API functions like ``clock_ticks_to_ns()``
+   will use the new period.
 
 Note that a clock only has one callback: it is not possible to register
 different functions for different events. You must register a single
diff --git a/include/hw/clock.h b/include/hw/clock.h
index 282a37f7c5a..2ba44e14424 100644
--- a/include/hw/clock.h
+++ b/include/hw/clock.h
@@ -30,6 +30,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(Clock, CLOCK)
  */
 typedef enum ClockEvent {
     ClockUpdate = 1, /* Clock period has just updated */
+    ClockPreUpdate = 2, /* Clock period is about to update */
 } ClockEvent;
 
 typedef void ClockCallback(void *opaque, ClockEvent event);
diff --git a/hw/core/clock.c b/hw/core/clock.c
index 4479eff145b..fc5a99683f8 100644
--- a/hw/core/clock.c
+++ b/hw/core/clock.c
@@ -81,6 +81,9 @@ static void clock_propagate_period(Clock *clk, bool call_callbacks)
 
     QLIST_FOREACH(child, &clk->children, sibling) {
         if (child->period != clk->period) {
+            if (call_callbacks) {
+                clock_call_callback(child, ClockPreUpdate);
+            }
             child->period = clk->period;
             trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
                                CLOCK_PERIOD_TO_HZ(clk->period),
-- 
2.20.1



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

* [PULL 03/54] clock: Add clock_ns_to_ticks() function
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
  2021-03-08 17:31 ` [PULL 01/54] clock: Add ClockEvent parameter to callbacks Peter Maydell
  2021-03-08 17:31 ` [PULL 02/54] clock: Add ClockPreUpdate callback event type Peter Maydell
@ 2021-03-08 17:31 ` Peter Maydell
  2021-03-08 17:31 ` [PULL 04/54] hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks() Peter Maydell
                   ` (51 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:31 UTC (permalink / raw)
  To: qemu-devel

Add a clock_ns_to_ticks() function which does the opposite of
clock_ticks_to_ns(): given a duration in nanoseconds, it returns the
number of clock ticks that would happen in that time.  This is useful
for devices that have a free running counter register whose value can
be calculated when it is read.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Luc Michel <luc@lmichel.fr>
Reviewed-by: Hao Wu <wuhaotsh@google.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210219144617.4782-4-peter.maydell@linaro.org
---
 docs/devel/clocks.rst | 12 ++++++++++++
 include/hw/clock.h    | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
index f0391e76b4f..956bd147ea0 100644
--- a/docs/devel/clocks.rst
+++ b/docs/devel/clocks.rst
@@ -360,6 +360,18 @@ rather than simply passing it to a QEMUTimer function like
 ``timer_mod_ns()`` then you should be careful to avoid overflow
 in those calculations, of course.)
 
+Obtaining tick counts
+---------------------
+
+For calculations where you need to know the number of ticks in
+a given duration, use ``clock_ns_to_ticks()``. This function handles
+possible non-whole-number-of-nanoseconds periods and avoids
+potential rounding errors. It will return '0' if the clock is stopped
+(i.e. it has period zero). If the inputs imply a tick count that
+overflows a 64-bit value (a very long duration for a clock with a
+very short period) the output value is truncated, so effectively
+the 64-bit output wraps around.
+
 Changing a clock period
 -----------------------
 
diff --git a/include/hw/clock.h b/include/hw/clock.h
index 2ba44e14424..a7187eab95e 100644
--- a/include/hw/clock.h
+++ b/include/hw/clock.h
@@ -286,6 +286,47 @@ static inline uint64_t clock_ticks_to_ns(const Clock *clk, uint64_t ticks)
     return ns_low >> 32 | ns_high << 32;
 }
 
+/**
+ * clock_ns_to_ticks:
+ * @clk: the clock to query
+ * @ns: duration in nanoseconds
+ *
+ * Returns the number of ticks this clock would make in the given
+ * number of nanoseconds. Because a clock can have a period which
+ * is not a whole number of nanoseconds, it is important to use this
+ * function rather than attempting to obtain a "period in nanoseconds"
+ * value and then dividing the duration by that value.
+ *
+ * If the clock is stopped (ie it has period zero), returns 0.
+ *
+ * For some inputs the result could overflow a 64-bit value (because
+ * the clock's period is short and the duration is long). In these
+ * cases we truncate the result to a 64-bit value. This is on the
+ * assumption that generally the result is going to be used to report
+ * a 32-bit or 64-bit guest register value, so wrapping either cannot
+ * happen or is the desired behaviour.
+ */
+static inline uint64_t clock_ns_to_ticks(const Clock *clk, uint64_t ns)
+{
+    /*
+     * ticks = duration_in_ns / period_in_ns
+     *       = ns / (period / 2^32)
+     *       = (ns * 2^32) / period
+     * The hi, lo inputs to divu128() are (ns << 32) as a 128 bit value.
+     */
+    uint64_t lo = ns << 32;
+    uint64_t hi = ns >> 32;
+    if (clk->period == 0) {
+        return 0;
+    }
+    /*
+     * Ignore divu128() return value as we've caught div-by-zero and don't
+     * need different behaviour for overflow.
+     */
+    divu128(&lo, &hi, clk->period);
+    return lo;
+}
+
 /**
  * clock_is_enabled:
  * @clk: a clock
-- 
2.20.1



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

* [PULL 04/54] hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks()
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (2 preceding siblings ...)
  2021-03-08 17:31 ` [PULL 03/54] clock: Add clock_ns_to_ticks() function Peter Maydell
@ 2021-03-08 17:31 ` Peter Maydell
  2021-03-08 17:31 ` [PULL 05/54] hw/arm/armsse: Introduce SSE subsystem version property Peter Maydell
                   ` (50 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:31 UTC (permalink / raw)
  To: qemu-devel

Use the new clock_ns_to_ticks() function in npcm7xx_timer where
appropriate.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Luc Michel <luc@lmichel.fr>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Hao Wu <wuhaotsh@google.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210219144617.4782-5-peter.maydell@linaro.org
---
 hw/timer/npcm7xx_timer.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
index 4efdf135b82..32f5e021f85 100644
--- a/hw/timer/npcm7xx_timer.c
+++ b/hw/timer/npcm7xx_timer.c
@@ -138,8 +138,8 @@ static int64_t npcm7xx_timer_count_to_ns(NPCM7xxTimer *t, uint32_t count)
 /* Convert a time interval in nanoseconds to a timer cycle count. */
 static uint32_t npcm7xx_timer_ns_to_count(NPCM7xxTimer *t, int64_t ns)
 {
-    return ns / clock_ticks_to_ns(t->ctrl->clock,
-                                  npcm7xx_tcsr_prescaler(t->tcsr));
+    return clock_ns_to_ticks(t->ctrl->clock, ns) /
+        npcm7xx_tcsr_prescaler(t->tcsr);
 }
 
 static uint32_t npcm7xx_watchdog_timer_prescaler(const NPCM7xxWatchdogTimer *t)
-- 
2.20.1



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

* [PULL 05/54] hw/arm/armsse: Introduce SSE subsystem version property
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (3 preceding siblings ...)
  2021-03-08 17:31 ` [PULL 04/54] hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks() Peter Maydell
@ 2021-03-08 17:31 ` Peter Maydell
  2021-03-08 17:31 ` [PULL 06/54] hw/misc/iotkit-sysctl: Remove is_sse200 flag Peter Maydell
                   ` (49 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:31 UTC (permalink / raw)
  To: qemu-devel

We model Arm "Subsystems for Embedded" SoC subsystems using generic
code which is split into various sub-devices which are configurable
by QOM properties to handle the behaviour differences between the SSE
subsystems we implement.  Currently the only sub-device which needs
to change is the IOTKIT_SYSCTL device, and we do this with a mix of
properties that directly specify divergent behaviours (eg
CPUWAIT_RST) and passing it the SYS_VERSION register value as a way
for it to distinguish IoTKit from SSE-200.

The "pass SYS_VERSION" approach is already a bit hacky, since the
IOTKIT_SYSCTL device has to know that the different part of the
register value happens to be bits [31:28].  For SSE-300 this register
is renamed SOC_IDENTITY and has a different format entirely, all of
whose fields can be configured by the SoC integrator when they
integrate the SSE into their SoC, and so "pass SYS_VERSION" breaks
down completely.

Switch to using a simple integer property representing an
internal-to-QEMU enumeration of the SSE flavour.  For the moment we
only need this in IOTKIT_SYSCTL, but as we add SSE-300 support a few
of the other devices will also need to know.

We define and permit a value for the SSE-300 so we can start using
it in subsequent commits which add SSE-300 support.

The now-redundant is_sse200 flag in IoTKitSysCtl will be removed
in the following commit.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-6-peter.maydell@linaro.org
---
 include/hw/arm/armsse-version.h | 42 +++++++++++++++++++++++++++++++++
 include/hw/misc/iotkit-sysctl.h |  7 +++---
 hw/arm/armsse.c                 |  8 +++++--
 hw/misc/iotkit-sysctl.c         | 11 +++++----
 4 files changed, 58 insertions(+), 10 deletions(-)
 create mode 100644 include/hw/arm/armsse-version.h

diff --git a/include/hw/arm/armsse-version.h b/include/hw/arm/armsse-version.h
new file mode 100644
index 00000000000..60780fa9843
--- /dev/null
+++ b/include/hw/arm/armsse-version.h
@@ -0,0 +1,42 @@
+/*
+ * ARM SSE (Subsystems for Embedded): IoTKit, SSE-200
+ *
+ * Copyright (c) 2020 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.
+ */
+
+#ifndef ARMSSE_VERSION_H
+#define ARMSSE_VERSION_H
+
+
+/*
+ * Define an enumeration of the possible values of the sse-version
+ * property implemented by various sub-devices of the SSE, and
+ * a validation function that checks that a valid value has been passed.
+ * These are arbitrary QEMU-internal values (nobody should be creating
+ * the sub-devices of the SSE except for the SSE object itself), but
+ * we pick obvious numbers for the benefit of people debugging with gdb.
+ */
+enum {
+    ARMSSE_IOTKIT = 0,
+    ARMSSE_SSE200 = 200,
+    ARMSSE_SSE300 = 300,
+};
+
+static inline bool armsse_version_valid(uint32_t sse_version)
+{
+    switch (sse_version) {
+    case ARMSSE_IOTKIT:
+    case ARMSSE_SSE200:
+    case ARMSSE_SSE300:
+        return true;
+    default:
+        return false;
+    }
+}
+
+#endif
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
index 2bc391138db..7cdafea3e25 100644
--- a/include/hw/misc/iotkit-sysctl.h
+++ b/include/hw/misc/iotkit-sysctl.h
@@ -17,9 +17,8 @@
  * "system control register" blocks.
  *
  * QEMU interface:
- *  + QOM property "SYS_VERSION": value of the SYS_VERSION register of the
- *    system information block of the SSE
- *    (used to identify whether to provide SSE-200-only registers)
+ *  + QOM property "sse-version": indicates which SSE version this is part of
+ *    (used to identify whether to provide SSE-200-only registers, etc)
  *  + sysbus MMIO region 0: the system information register bank
  *  + sysbus MMIO region 1: the system control register bank
  */
@@ -61,7 +60,7 @@ struct IoTKitSysCtl {
     uint32_t pdcm_pd_sram3_sense;
 
     /* Properties */
-    uint32_t sys_version;
+    uint32_t sse_version;
     uint32_t cpuwait_rst;
     uint32_t initsvtor0_rst;
     uint32_t initsvtor1_rst;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index fa155b72022..f509f59d4a8 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -19,6 +19,7 @@
 #include "migration/vmstate.h"
 #include "hw/registerfields.h"
 #include "hw/arm/armsse.h"
+#include "hw/arm/armsse-version.h"
 #include "hw/arm/boot.h"
 #include "hw/irq.h"
 #include "hw/qdev-clock.h"
@@ -31,6 +32,7 @@ typedef enum SysConfigFormat {
 
 struct ARMSSEInfo {
     const char *name;
+    uint32_t sse_version;
     int sram_banks;
     int num_cpus;
     uint32_t sys_version;
@@ -71,6 +73,7 @@ static Property armsse_properties[] = {
 static const ARMSSEInfo armsse_variants[] = {
     {
         .name = TYPE_IOTKIT,
+        .sse_version = ARMSSE_IOTKIT,
         .sram_banks = 1,
         .num_cpus = 1,
         .sys_version = 0x41743,
@@ -85,6 +88,7 @@ static const ARMSSEInfo armsse_variants[] = {
     },
     {
         .name = TYPE_SSE200,
+        .sse_version = ARMSSE_SSE200,
         .sram_banks = 4,
         .num_cpus = 2,
         .sys_version = 0x22041743,
@@ -951,8 +955,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     /* System information registers */
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
     /* System control registers */
-    object_property_set_int(OBJECT(&s->sysctl), "SYS_VERSION",
-                            info->sys_version, &error_abort);
+    object_property_set_int(OBJECT(&s->sysctl), "sse-version",
+                            info->sse_version, &error_abort);
     object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
                             info->cpuwait_rst, &error_abort);
     object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index 222511c4b04..34b37fe8824 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -28,6 +28,7 @@
 #include "hw/registerfields.h"
 #include "hw/misc/iotkit-sysctl.h"
 #include "hw/qdev-properties.h"
+#include "hw/arm/armsse-version.h"
 #include "target/arm/arm-powerctl.h"
 #include "target/arm/cpu.h"
 
@@ -438,10 +439,12 @@ static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
 {
     IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
 
-    /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */
-    if (extract32(s->sys_version, 28, 4) == 2) {
-        s->is_sse200 = true;
+    if (!armsse_version_valid(s->sse_version)) {
+        error_setg(errp, "invalid sse-version value %d", s->sse_version);
+        return;
     }
+
+    s->is_sse200 = s->sse_version == ARMSSE_SSE200;
 }
 
 static bool sse200_needed(void *opaque)
@@ -493,7 +496,7 @@ static const VMStateDescription iotkit_sysctl_vmstate = {
 };
 
 static Property iotkit_sysctl_props[] = {
-    DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0),
+    DEFINE_PROP_UINT32("sse-version", IoTKitSysCtl, sse_version, 0),
     DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
     DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
                        0x10000000),
-- 
2.20.1



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

* [PULL 06/54] hw/misc/iotkit-sysctl: Remove is_sse200 flag
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (4 preceding siblings ...)
  2021-03-08 17:31 ` [PULL 05/54] hw/arm/armsse: Introduce SSE subsystem version property Peter Maydell
@ 2021-03-08 17:31 ` Peter Maydell
  2021-03-08 17:31 ` [PULL 07/54] hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values Peter Maydell
                   ` (48 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:31 UTC (permalink / raw)
  To: qemu-devel

Remove the is_sse200 flag in favour of just directly testing the new
sse_version field.

Since some of these registers exist in the SSE-300 but some do not or
have different behaviour, we expand out the if() statements in the
read and write functions into switch()es, so we have an easy place to
put SSE-300 specific behaviour.

(Until we do add the SSE-300 behaviour, the thing preventing us
reaching the "unreachable" default cases is that armsse.c doesn't
yet pass us an ARMSSE_SSE300 version.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-7-peter.maydell@linaro.org
---
 include/hw/misc/iotkit-sysctl.h |   2 -
 hw/misc/iotkit-sysctl.c         | 256 +++++++++++++++++++++++---------
 2 files changed, 187 insertions(+), 71 deletions(-)

diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
index 7cdafea3e25..980c2ddfd3c 100644
--- a/include/hw/misc/iotkit-sysctl.h
+++ b/include/hw/misc/iotkit-sysctl.h
@@ -64,8 +64,6 @@ struct IoTKitSysCtl {
     uint32_t cpuwait_rst;
     uint32_t initsvtor0_rst;
     uint32_t initsvtor1_rst;
-
-    bool is_sse200;
 };
 
 #endif
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index 34b37fe8824..c67f5b320ab 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -101,28 +101,48 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         r = s->secure_debug;
         break;
     case A_SCSECCTRL:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->scsecctrl;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->scsecctrl;
         break;
     case A_FCLK_DIV:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->fclk_div;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->fclk_div;
         break;
     case A_SYSCLK_DIV:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->sysclk_div;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->sysclk_div;
         break;
     case A_CLOCK_FORCE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->clock_force;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->clock_force;
         break;
     case A_RESET_SYNDROME:
         r = s->reset_syndrome;
@@ -137,60 +157,100 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         r = s->initsvtor0;
         break;
     case A_INITSVTOR1:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->initsvtor1;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->initsvtor1;
         break;
     case A_CPUWAIT:
         r = s->cpuwait;
         break;
     case A_NMI_ENABLE:
-        /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
+            /* In IoTKit this is named BUSWAIT but marked reserved, R/O, zero */
             r = 0;
             break;
+        case ARMSSE_SSE200:
+            r = s->nmi_enable;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->nmi_enable;
         break;
     case A_WICCTRL:
         r = s->wicctrl;
         break;
     case A_EWCTRL:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->ewctrl;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->ewctrl;
         break;
     case A_PDCM_PD_SYS_SENSE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->pdcm_pd_sys_sense;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->pdcm_pd_sys_sense;
         break;
     case A_PDCM_PD_SRAM0_SENSE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->pdcm_pd_sram0_sense;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->pdcm_pd_sram0_sense;
         break;
     case A_PDCM_PD_SRAM1_SENSE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->pdcm_pd_sram1_sense;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->pdcm_pd_sram1_sense;
         break;
     case A_PDCM_PD_SRAM2_SENSE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->pdcm_pd_sram2_sense;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->pdcm_pd_sram2_sense;
         break;
     case A_PDCM_PD_SRAM3_SENSE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            r = s->pdcm_pd_sram3_sense;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        r = s->pdcm_pd_sram3_sense;
         break;
     case A_PID4 ... A_CID3:
         r = sysctl_id[(offset - A_PID4) / 4];
@@ -284,94 +344,154 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
         }
         break;
     case A_SCSECCTRL:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
+            s->scsecctrl = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
-        s->scsecctrl = value;
         break;
     case A_FCLK_DIV:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
+            s->fclk_div = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
-        s->fclk_div = value;
         break;
     case A_SYSCLK_DIV:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
+            s->sysclk_div = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
-        s->sysclk_div = value;
         break;
     case A_CLOCK_FORCE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
+            s->clock_force = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
-        s->clock_force = value;
         break;
     case A_INITSVTOR1:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            s->initsvtor1 = value;
+            set_init_vtor(1, s->initsvtor1);
+            break;
+        default:
+            g_assert_not_reached();
         }
-        s->initsvtor1 = value;
-        set_init_vtor(1, s->initsvtor1);
         break;
     case A_EWCTRL:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
+            s->ewctrl = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
-        s->ewctrl = value;
         break;
     case A_PDCM_PD_SYS_SENSE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP,
+                          "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
+            s->pdcm_pd_sys_sense = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP,
-                      "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
-        s->pdcm_pd_sys_sense = value;
         break;
     case A_PDCM_PD_SRAM0_SENSE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP,
+                          "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
+            s->pdcm_pd_sram0_sense = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP,
-                      "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
-        s->pdcm_pd_sram0_sense = value;
         break;
     case A_PDCM_PD_SRAM1_SENSE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP,
+                          "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
+            s->pdcm_pd_sram1_sense = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP,
-                      "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
-        s->pdcm_pd_sram1_sense = value;
         break;
     case A_PDCM_PD_SRAM2_SENSE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP,
+                          "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
+            s->pdcm_pd_sram2_sense = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP,
-                      "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
-        s->pdcm_pd_sram2_sense = value;
         break;
     case A_PDCM_PD_SRAM3_SENSE:
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto bad_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP,
+                          "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
+            s->pdcm_pd_sram3_sense = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP,
-                      "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
-        s->pdcm_pd_sram3_sense = value;
         break;
     case A_NMI_ENABLE:
         /* In IoTKit this is BUSWAIT: reserved, R/O, zero */
-        if (!s->is_sse200) {
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
             goto ro_offset;
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
+            s->nmi_enable = value;
+            break;
+        default:
+            g_assert_not_reached();
         }
-        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
-        s->nmi_enable = value;
         break;
     case A_SECDBGSTAT:
     case A_PID4 ... A_CID3:
@@ -443,15 +563,13 @@ static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
         error_setg(errp, "invalid sse-version value %d", s->sse_version);
         return;
     }
-
-    s->is_sse200 = s->sse_version == ARMSSE_SSE200;
 }
 
 static bool sse200_needed(void *opaque)
 {
     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
 
-    return s->is_sse200;
+    return s->sse_version == ARMSSE_SSE200;
 }
 
 static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
-- 
2.20.1



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

* [PULL 07/54] hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (5 preceding siblings ...)
  2021-03-08 17:31 ` [PULL 06/54] hw/misc/iotkit-sysctl: Remove is_sse200 flag Peter Maydell
@ 2021-03-08 17:31 ` Peter Maydell
  2021-03-08 17:31 ` [PULL 08/54] hw/misc/iotkit-sysinfo.c: " Peter Maydell
                   ` (47 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:31 UTC (permalink / raw)
  To: qemu-devel

The versions of the Secure Access Configuration Register Block
and Non-secure Access Configuration Register Block in the SSE-300
are the same as those in the SSE-200, but the CIDR/PIDR ID
register values are different.

Plumb through the sse-version property and use it to select
the correct ID register values.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-8-peter.maydell@linaro.org
---
 include/hw/misc/iotkit-secctl.h |  2 ++
 hw/arm/armsse.c                 |  2 ++
 hw/misc/iotkit-secctl.c         | 50 +++++++++++++++++++++++++++++++--
 3 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
index 227d44abe49..79a36283201 100644
--- a/include/hw/misc/iotkit-secctl.h
+++ b/include/hw/misc/iotkit-secctl.h
@@ -120,6 +120,8 @@ struct IoTKitSecCtl {
     IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
     IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
     IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC];
+
+    uint32_t sse_version;
 };
 
 #endif
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index f509f59d4a8..9632c287351 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -654,6 +654,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     }
 
     /* Security controller */
+    object_property_set_int(OBJECT(&s->secctl), "sse-version",
+                            info->sse_version, &error_abort);
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->secctl), errp)) {
         return;
     }
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
index 9fdb82056a8..7b41cfa8fc5 100644
--- a/hw/misc/iotkit-secctl.c
+++ b/hw/misc/iotkit-secctl.c
@@ -19,6 +19,8 @@
 #include "hw/registerfields.h"
 #include "hw/irq.h"
 #include "hw/misc/iotkit-secctl.h"
+#include "hw/arm/armsse-version.h"
+#include "hw/qdev-properties.h"
 
 /* Registers in the secure privilege control block */
 REG32(SECRESPCFG, 0x10)
@@ -95,6 +97,19 @@ static const uint8_t iotkit_secctl_ns_idregs[] = {
     0x0d, 0xf0, 0x05, 0xb1,
 };
 
+static const uint8_t iotkit_secctl_s_sse300_idregs[] = {
+    0x04, 0x00, 0x00, 0x00,
+    0x52, 0xb8, 0x2b, 0x00,
+    0x0d, 0xf0, 0x05, 0xb1,
+};
+
+static const uint8_t iotkit_secctl_ns_sse300_idregs[] = {
+    0x04, 0x00, 0x00, 0x00,
+    0x53, 0xb8, 0x2b, 0x00,
+    0x0d, 0xf0, 0x05, 0xb1,
+};
+
+
 /* The register sets for the various PPCs (AHB internal, APB internal,
  * AHB expansion, APB expansion) are all set up so that they are
  * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
@@ -213,7 +228,14 @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
     case A_CID1:
     case A_CID2:
     case A_CID3:
-        r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
+        switch (s->sse_version) {
+        case ARMSSE_SSE300:
+            r = iotkit_secctl_s_sse300_idregs[(offset - A_PID4) / 4];
+            break;
+        default:
+            r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
+            break;
+        }
         break;
     case A_SECPPCINTCLR:
     case A_SECMSCINTCLR:
@@ -473,7 +495,14 @@ static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
     case A_CID1:
     case A_CID2:
     case A_CID3:
-        r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
+        switch (s->sse_version) {
+        case ARMSSE_SSE300:
+            r = iotkit_secctl_ns_sse300_idregs[(offset - A_PID4) / 4];
+            break;
+        default:
+            r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
+            break;
+        }
         break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR,
@@ -710,6 +739,16 @@ static void iotkit_secctl_init(Object *obj)
     sysbus_init_mmio(sbd, &s->ns_regs);
 }
 
+static void iotkit_secctl_realize(DeviceState *dev, Error **errp)
+{
+    IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
+
+    if (!armsse_version_valid(s->sse_version)) {
+        error_setg(errp, "invalid sse-version value %d", s->sse_version);
+        return;
+    }
+}
+
 static const VMStateDescription iotkit_secctl_ppc_vmstate = {
     .name = "iotkit-secctl-ppc",
     .version_id = 1,
@@ -775,12 +814,19 @@ static const VMStateDescription iotkit_secctl_vmstate = {
     },
 };
 
+static Property iotkit_secctl_props[] = {
+    DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
 static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd = &iotkit_secctl_vmstate;
     dc->reset = iotkit_secctl_reset;
+    dc->realize = iotkit_secctl_realize;
+    device_class_set_props(dc, iotkit_secctl_props);
 }
 
 static const TypeInfo iotkit_secctl_info = {
-- 
2.20.1



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

* [PULL 08/54] hw/misc/iotkit-sysinfo.c: Implement SSE-300 PID register values
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (6 preceding siblings ...)
  2021-03-08 17:31 ` [PULL 07/54] hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values Peter Maydell
@ 2021-03-08 17:31 ` Peter Maydell
  2021-03-08 17:31 ` [PULL 09/54] hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300 Peter Maydell
                   ` (46 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:31 UTC (permalink / raw)
  To: qemu-devel

The version of the SYSINFO Register Block in the SSE-300 has
different CIDR/PIDR register values to the SSE-200; pass in
the sse-version property and use it to select the correct
ID register values.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-9-peter.maydell@linaro.org
---
 include/hw/misc/iotkit-sysinfo.h |  1 +
 hw/arm/armsse.c                  |  2 ++
 hw/misc/iotkit-sysinfo.c         | 29 +++++++++++++++++++++++++++--
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
index 055771d2098..91bd14bdbff 100644
--- a/include/hw/misc/iotkit-sysinfo.h
+++ b/include/hw/misc/iotkit-sysinfo.h
@@ -38,6 +38,7 @@ struct IoTKitSysInfo {
     /* Properties */
     uint32_t sys_version;
     uint32_t sys_config;
+    uint32_t sse_version;
 };
 
 #endif
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 9632c287351..67fa4ffe34a 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -951,6 +951,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                                  armsse_sys_config_value(s, info), errp)) {
         return;
     }
+    object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
+                            info->sse_version, &error_abort);
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) {
         return;
     }
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
index 52e70053df7..4bd3fd4c8f3 100644
--- a/hw/misc/iotkit-sysinfo.c
+++ b/hw/misc/iotkit-sysinfo.c
@@ -26,6 +26,7 @@
 #include "hw/registerfields.h"
 #include "hw/misc/iotkit-sysinfo.h"
 #include "hw/qdev-properties.h"
+#include "hw/arm/armsse-version.h"
 
 REG32(SYS_VERSION, 0x0)
 REG32(SYS_CONFIG, 0x4)
@@ -49,6 +50,12 @@ static const int sysinfo_id[] = {
     0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
 };
 
+static const int sysinfo_sse300_id[] = {
+    0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+    0x58, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
+    0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
 static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
                                     unsigned size)
 {
@@ -64,7 +71,14 @@ static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
         r = s->sys_config;
         break;
     case A_PID4 ... A_CID3:
-        r = sysinfo_id[(offset - A_PID4) / 4];
+        switch (s->sse_version) {
+        case ARMSSE_SSE300:
+            r = sysinfo_sse300_id[(offset - A_PID4) / 4];
+            break;
+        default:
+            r = sysinfo_id[(offset - A_PID4) / 4];
+            break;
+        }
         break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR,
@@ -99,6 +113,7 @@ static const MemoryRegionOps iotkit_sysinfo_ops = {
 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_UINT32("sse-version", IoTKitSysInfo, sse_version, 0),
     DEFINE_PROP_END_OF_LIST()
 };
 
@@ -112,6 +127,16 @@ static void iotkit_sysinfo_init(Object *obj)
     sysbus_init_mmio(sbd, &s->iomem);
 }
 
+static void iotkit_sysinfo_realize(DeviceState *dev, Error **errp)
+{
+    IoTKitSysInfo *s = IOTKIT_SYSINFO(dev);
+
+    if (!armsse_version_valid(s->sse_version)) {
+        error_setg(errp, "invalid sse-version value %d", s->sse_version);
+        return;
+    }
+}
+
 static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -120,7 +145,7 @@ static void iotkit_sysinfo_class_init(ObjectClass *klass, void *data)
      * This device has no guest-modifiable state and so it
      * does not need a reset function or VMState.
      */
-
+    dc->realize = iotkit_sysinfo_realize;
     device_class_set_props(dc, iotkit_sysinfo_props);
 }
 
-- 
2.20.1



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

* [PULL 09/54] hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (7 preceding siblings ...)
  2021-03-08 17:31 ` [PULL 08/54] hw/misc/iotkit-sysinfo.c: " Peter Maydell
@ 2021-03-08 17:31 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 10/54] hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR Peter Maydell
                   ` (45 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:31 UTC (permalink / raw)
  To: qemu-devel

In the SSE-300, the format of the SYS_CONFIG0 register has changed again;
pass through the correct value to the SYSINFO register block device.

We drop the old SysConfigFormat enum, which was implemented in the
hope that different flavours of SSE would share the same format;
since they all seem to be different and we now have an sse_version
enum to key off, just use that.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-10-peter.maydell@linaro.org
---
 hw/arm/armsse.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 67fa4ffe34a..113a783a46a 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -24,12 +24,6 @@
 #include "hw/irq.h"
 #include "hw/qdev-clock.h"
 
-/* Format of the System Information block SYS_CONFIG register */
-typedef enum SysConfigFormat {
-    IoTKitFormat,
-    SSE200Format,
-} SysConfigFormat;
-
 struct ARMSSEInfo {
     const char *name;
     uint32_t sse_version;
@@ -37,7 +31,6 @@ struct ARMSSEInfo {
     int num_cpus;
     uint32_t sys_version;
     uint32_t cpuwait_rst;
-    SysConfigFormat sys_config_format;
     bool has_mhus;
     bool has_ppus;
     bool has_cachectrl;
@@ -78,7 +71,6 @@ static const ARMSSEInfo armsse_variants[] = {
         .num_cpus = 1,
         .sys_version = 0x41743,
         .cpuwait_rst = 0,
-        .sys_config_format = IoTKitFormat,
         .has_mhus = false,
         .has_ppus = false,
         .has_cachectrl = false,
@@ -93,7 +85,6 @@ static const ARMSSEInfo armsse_variants[] = {
         .num_cpus = 2,
         .sys_version = 0x22041743,
         .cpuwait_rst = 2,
-        .sys_config_format = SSE200Format,
         .has_mhus = true,
         .has_ppus = true,
         .has_cachectrl = true,
@@ -108,13 +99,13 @@ 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:
+    switch (info->sse_version) {
+    case ARMSSE_IOTKIT:
         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:
+    case ARMSSE_SSE200:
         sys_config = 0;
         sys_config = deposit32(sys_config, 0, 4, info->sram_banks);
         sys_config = deposit32(sys_config, 4, 5, s->sram_addr_width);
@@ -125,6 +116,12 @@ static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
             sys_config = deposit32(sys_config, 28, 4, 2);
         }
         break;
+    case ARMSSE_SSE300:
+        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, 16, 3, 3); /* CPU0 = Cortex-M55 */
+        break;
     default:
         g_assert_not_reached();
     }
-- 
2.20.1



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

* [PULL 10/54] hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (8 preceding siblings ...)
  2021-03-08 17:31 ` [PULL 09/54] hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300 Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 11/54] hw/timer/sse-counter: Model the SSE Subsystem System Counter Peter Maydell
                   ` (44 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

For SSE-300, the SYSINFO register block has two new registers:

 * SYS_CONFIG1 indicates the config for a potential CPU2 and CPU3;
   since the SSE-300 can only be configured with a single CPU it
   is always zero

 * IIDR is the subsystem implementation identity register;
   its value is set by the SoC integrator, so we plumb this in from
   the armsse.c code as we do with SYS_VERSION and SYS_CONFIG

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-11-peter.maydell@linaro.org
---
 include/hw/misc/iotkit-sysinfo.h |  1 +
 hw/arm/armsse.c                  |  5 +++++
 hw/misc/iotkit-sysinfo.c         | 22 ++++++++++++++++++++++
 3 files changed, 28 insertions(+)

diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
index 91bd14bdbff..91c23f90d23 100644
--- a/include/hw/misc/iotkit-sysinfo.h
+++ b/include/hw/misc/iotkit-sysinfo.h
@@ -39,6 +39,7 @@ struct IoTKitSysInfo {
     uint32_t sys_version;
     uint32_t sys_config;
     uint32_t sse_version;
+    uint32_t iidr;
 };
 
 #endif
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 113a783a46a..326e161c8d4 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -30,6 +30,7 @@ struct ARMSSEInfo {
     int sram_banks;
     int num_cpus;
     uint32_t sys_version;
+    uint32_t iidr;
     uint32_t cpuwait_rst;
     bool has_mhus;
     bool has_ppus;
@@ -70,6 +71,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .sram_banks = 1,
         .num_cpus = 1,
         .sys_version = 0x41743,
+        .iidr = 0,
         .cpuwait_rst = 0,
         .has_mhus = false,
         .has_ppus = false,
@@ -84,6 +86,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .sram_banks = 4,
         .num_cpus = 2,
         .sys_version = 0x22041743,
+        .iidr = 0,
         .cpuwait_rst = 2,
         .has_mhus = true,
         .has_ppus = true,
@@ -950,6 +953,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     }
     object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
                             info->sse_version, &error_abort);
+    object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
+                            info->iidr, &error_abort);
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) {
         return;
     }
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
index 4bd3fd4c8f3..aaa9305b2ea 100644
--- a/hw/misc/iotkit-sysinfo.c
+++ b/hw/misc/iotkit-sysinfo.c
@@ -30,6 +30,8 @@
 
 REG32(SYS_VERSION, 0x0)
 REG32(SYS_CONFIG, 0x4)
+REG32(SYS_CONFIG1, 0x8)
+REG32(IIDR, 0xfc8)
 REG32(PID4, 0xfd0)
 REG32(PID5, 0xfd4)
 REG32(PID6, 0xfd8)
@@ -70,6 +72,24 @@ static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
     case A_SYS_CONFIG:
         r = s->sys_config;
         break;
+    case A_SYS_CONFIG1:
+        switch (s->sse_version) {
+        case ARMSSE_SSE300:
+            return 0;
+            break;
+        default:
+            goto bad_read;
+        }
+        break;
+    case A_IIDR:
+        switch (s->sse_version) {
+        case ARMSSE_SSE300:
+            return s->iidr;
+            break;
+        default:
+            goto bad_read;
+        }
+        break;
     case A_PID4 ... A_CID3:
         switch (s->sse_version) {
         case ARMSSE_SSE300:
@@ -81,6 +101,7 @@ static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset,
         }
         break;
     default:
+    bad_read:
         qemu_log_mask(LOG_GUEST_ERROR,
                       "IoTKit SysInfo read: bad offset %x\n", (int)offset);
         r = 0;
@@ -114,6 +135,7 @@ 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_UINT32("sse-version", IoTKitSysInfo, sse_version, 0),
+    DEFINE_PROP_UINT32("IIDR", IoTKitSysInfo, iidr, 0),
     DEFINE_PROP_END_OF_LIST()
 };
 
-- 
2.20.1



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

* [PULL 11/54] hw/timer/sse-counter: Model the SSE Subsystem System Counter
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (9 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 10/54] hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 12/54] hw/timer/sse-timer: Model the SSE Subsystem System Timer Peter Maydell
                   ` (43 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-300 includes a counter module; implement a model of it.

This counter is documented in the SSE-123 Example Subsystem
Technical Reference Manual:
 https://developer.arm.com/documentation/101370/latest/

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-12-peter.maydell@linaro.org
---
 include/hw/timer/sse-counter.h | 105 ++++++++
 hw/timer/sse-counter.c         | 474 +++++++++++++++++++++++++++++++++
 MAINTAINERS                    |   2 +
 hw/arm/Kconfig                 |   1 +
 hw/timer/Kconfig               |   3 +
 hw/timer/meson.build           |   1 +
 hw/timer/trace-events          |   7 +
 7 files changed, 593 insertions(+)
 create mode 100644 include/hw/timer/sse-counter.h
 create mode 100644 hw/timer/sse-counter.c

diff --git a/include/hw/timer/sse-counter.h b/include/hw/timer/sse-counter.h
new file mode 100644
index 00000000000..b433e58d370
--- /dev/null
+++ b/include/hw/timer/sse-counter.h
@@ -0,0 +1,105 @@
+/*
+ * Arm SSE Subsystem System Counter
+ *
+ * Copyright (c) 2020 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 "System counter" which is documented in
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
+ * https://developer.arm.com/documentation/101370/latest/
+ *
+ * QEMU interface:
+ *  + Clock input "CLK": clock
+ *  + sysbus MMIO region 0: the control register frame
+ *  + sysbus MMIO region 1: the status register frame
+ *
+ * Consumers of the system counter's timestamp, such as the SSE
+ * System Timer device, can also use the APIs sse_counter_for_timestamp(),
+ * sse_counter_tick_to_time() and sse_counter_register_consumer() to
+ * interact with an instance of the System Counter. Generally the
+ * consumer device should have a QOM link property which the board
+ * code can set to the appropriate instance of the system counter.
+ */
+
+#ifndef SSE_COUNTER_H
+#define SSE_COUNTER_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+#include "qemu/notify.h"
+
+#define TYPE_SSE_COUNTER "sse-counter"
+OBJECT_DECLARE_SIMPLE_TYPE(SSECounter, SSE_COUNTER)
+
+struct SSECounter {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    MemoryRegion control_mr;
+    MemoryRegion status_mr;
+    Clock *clk;
+    NotifierList notifier_list;
+
+    uint32_t cntcr;
+    uint32_t cntscr0;
+
+    /*
+     * These are used for handling clock frequency changes: they are a
+     * tuple of (QEMU_CLOCK_VIRTUAL timestamp, CNTCV at that time),
+     * taken when the clock frequency changes. sse_cntcv() needs them
+     * to calculate the current CNTCV.
+     */
+    uint64_t ns_then;
+    uint64_t ticks_then;
+};
+
+/*
+ * These functions are the interface by which a consumer of
+ * the system timestamp (such as the SSE system timer device)
+ * can communicate with the SSECounter.
+ */
+
+/**
+ * sse_counter_for_timestamp:
+ * @counter: SSECounter
+ * @ns: timestamp of QEMU_CLOCK_VIRTUAL in nanoseconds
+ *
+ * Returns the value of the timestamp counter at the specified
+ * point in time (assuming that no changes to scale factor, enable, etc
+ * happen in the meantime).
+ */
+uint64_t sse_counter_for_timestamp(SSECounter *counter, uint64_t ns);
+
+/**
+ * sse_counter_tick_to_time:
+ * @counter: SSECounter
+ * @tick: tick value
+ *
+ * Returns the time (a QEMU_CLOCK_VIRTUAL timestamp in nanoseconds)
+ * when the timestamp counter will reach the specified tick count.
+ * If the counter is not currently running, returns UINT64_MAX.
+ */
+uint64_t sse_counter_tick_to_time(SSECounter *counter, uint64_t tick);
+
+/**
+ * sse_counter_register_consumer:
+ * @counter: SSECounter
+ * @notifier: Notifier which is notified on counter changes
+ *
+ * Registers @notifier with the SSECounter. When the counter's
+ * configuration changes in a way that might invalidate information
+ * previously returned via sse_counter_for_timestamp() or
+ * sse_counter_tick_to_time(), the notifier will be called.
+ * Devices which consume the timestamp counter can use this as
+ * a cue to recalculate timer events.
+ */
+void sse_counter_register_consumer(SSECounter *counter, Notifier *notifier);
+
+#endif
diff --git a/hw/timer/sse-counter.c b/hw/timer/sse-counter.c
new file mode 100644
index 00000000000..0384051f151
--- /dev/null
+++ b/hw/timer/sse-counter.c
@@ -0,0 +1,474 @@
+/*
+ * Arm SSE Subsystem System Counter
+ *
+ * Copyright (c) 2020 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 "System counter" which is documented in
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
+ * https://developer.arm.com/documentation/101370/latest/
+ *
+ * The system counter is a non-stop 64-bit up-counter. It provides
+ * this count value to other devices like the SSE system timer,
+ * which are driven by this system timestamp rather than directly
+ * from a clock. Internally to the counter the count is actually
+ * 88-bit precision (64.24 fixed point), with a programmable scale factor.
+ *
+ * The hardware has the optional feature that it supports dynamic
+ * clock switching, where two clock inputs are connected, and which
+ * one is used is selected via a CLKSEL input signal. Since the
+ * users of this device in QEMU don't use this feature, we only model
+ * the HWCLKSW=0 configuration.
+ */
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+#include "qapi/error.h"
+#include "trace.h"
+#include "hw/timer/sse-counter.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/registerfields.h"
+#include "hw/clock.h"
+#include "hw/qdev-clock.h"
+#include "migration/vmstate.h"
+
+/* Registers in the control frame */
+REG32(CNTCR, 0x0)
+    FIELD(CNTCR, EN, 0, 1)
+    FIELD(CNTCR, HDBG, 1, 1)
+    FIELD(CNTCR, SCEN, 2, 1)
+    FIELD(CNTCR, INTRMASK, 3, 1)
+    FIELD(CNTCR, PSLVERRDIS, 4, 1)
+    FIELD(CNTCR, INTRCLR, 5, 1)
+/*
+ * Although CNTCR defines interrupt-related bits, the counter doesn't
+ * appear to actually have an interrupt output. So INTRCLR is
+ * effectively a RAZ/WI bit, as are the reserved bits [31:6].
+ */
+#define CNTCR_VALID_MASK (R_CNTCR_EN_MASK | R_CNTCR_HDBG_MASK | \
+                          R_CNTCR_SCEN_MASK | R_CNTCR_INTRMASK_MASK | \
+                          R_CNTCR_PSLVERRDIS_MASK)
+REG32(CNTSR, 0x4)
+REG32(CNTCV_LO, 0x8)
+REG32(CNTCV_HI, 0xc)
+REG32(CNTSCR, 0x10) /* Aliased with CNTSCR0 */
+REG32(CNTID, 0x1c)
+    FIELD(CNTID, CNTSC, 0, 4)
+    FIELD(CNTID, CNTCS, 16, 1)
+    FIELD(CNTID, CNTSELCLK, 17, 2)
+    FIELD(CNTID, CNTSCR_OVR, 19, 1)
+REG32(CNTSCR0, 0xd0)
+REG32(CNTSCR1, 0xd4)
+
+/* Registers in the status frame */
+REG32(STATUS_CNTCV_LO, 0x0)
+REG32(STATUS_CNTCV_HI, 0x4)
+
+/* Standard ID registers, present in both frames */
+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 control_id[] = {
+    0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+    0xba, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
+    0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
+static const int status_id[] = {
+    0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+    0xbb, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
+    0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
+static void sse_counter_notify_users(SSECounter *s)
+{
+    /*
+     * Notify users of the count timestamp that they may
+     * need to recalculate.
+     */
+    notifier_list_notify(&s->notifier_list, NULL);
+}
+
+static bool sse_counter_enabled(SSECounter *s)
+{
+    return (s->cntcr & R_CNTCR_EN_MASK) != 0;
+}
+
+uint64_t sse_counter_tick_to_time(SSECounter *s, uint64_t tick)
+{
+    if (!sse_counter_enabled(s)) {
+        return UINT64_MAX;
+    }
+
+    tick -= s->ticks_then;
+
+    if (s->cntcr & R_CNTCR_SCEN_MASK) {
+        /* Adjust the tick count to account for the scale factor */
+        tick = muldiv64(tick, 0x01000000, s->cntscr0);
+    }
+
+    return s->ns_then + clock_ticks_to_ns(s->clk, tick);
+}
+
+void sse_counter_register_consumer(SSECounter *s, Notifier *notifier)
+{
+    /*
+     * For the moment we assume that both we and the devices
+     * which consume us last for the life of the simulation,
+     * and so there is no mechanism for removing a notifier.
+     */
+    notifier_list_add(&s->notifier_list, notifier);
+}
+
+uint64_t sse_counter_for_timestamp(SSECounter *s, uint64_t now)
+{
+    /* Return the CNTCV value for a particular timestamp (clock ns value). */
+    uint64_t ticks;
+
+    if (!sse_counter_enabled(s)) {
+        /* Counter is disabled and does not increment */
+        return s->ticks_then;
+    }
+
+    ticks = clock_ns_to_ticks(s->clk, now - s->ns_then);
+    if (s->cntcr & R_CNTCR_SCEN_MASK) {
+        /*
+         * Scaling is enabled. The CNTSCR value is the amount added to
+         * the underlying 88-bit counter for every tick of the
+         * underlying clock; CNTCV is the top 64 bits of that full
+         * 88-bit value. Multiplying the tick count by CNTSCR tells us
+         * how much the full 88-bit counter has moved on; we then
+         * divide that by 0x01000000 to find out how much the 64-bit
+         * visible portion has advanced. muldiv64() gives us the
+         * necessary at-least-88-bit precision for the intermediate
+         * result.
+         */
+        ticks = muldiv64(ticks, s->cntscr0, 0x01000000);
+    }
+    return s->ticks_then + ticks;
+}
+
+static uint64_t sse_cntcv(SSECounter *s)
+{
+    /* Return the CNTCV value for the current time */
+    return sse_counter_for_timestamp(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+}
+
+static void sse_write_cntcv(SSECounter *s, uint32_t value, unsigned startbit)
+{
+    /*
+     * Write one 32-bit half of the counter value; startbit is the
+     * bit position of this half in the 64-bit word, either 0 or 32.
+     */
+    uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    uint64_t cntcv = sse_counter_for_timestamp(s, now);
+
+    cntcv = deposit64(cntcv, startbit, 32, value);
+    s->ticks_then = cntcv;
+    s->ns_then = now;
+    sse_counter_notify_users(s);
+}
+
+static uint64_t sse_counter_control_read(void *opaque, hwaddr offset,
+                                         unsigned size)
+{
+    SSECounter *s = SSE_COUNTER(opaque);
+    uint64_t r;
+
+    switch (offset) {
+    case A_CNTCR:
+        r = s->cntcr;
+        break;
+    case A_CNTSR:
+        /*
+         * The only bit here is DBGH, indicating that the counter has been
+         * halted via the Halt-on-Debug signal. We don't implement halting
+         * debug, so the whole register always reads as zero.
+         */
+        r = 0;
+        break;
+    case A_CNTCV_LO:
+        r = extract64(sse_cntcv(s), 0, 32);
+        break;
+    case A_CNTCV_HI:
+        r = extract64(sse_cntcv(s), 32, 32);
+        break;
+    case A_CNTID:
+        /*
+         * For our implementation:
+         *  - CNTSCR can only be written when CNTCR.EN == 0
+         *  - HWCLKSW=0, so selected clock is always CLK0
+         *  - counter scaling is implemented
+         */
+        r = (1 << R_CNTID_CNTSELCLK_SHIFT) | (1 << R_CNTID_CNTSC_SHIFT);
+        break;
+    case A_CNTSCR:
+    case A_CNTSCR0:
+        r = s->cntscr0;
+        break;
+    case A_CNTSCR1:
+        /* If HWCLKSW == 0, CNTSCR1 is RAZ/WI */
+        r = 0;
+        break;
+    case A_PID4 ... A_CID3:
+        r = control_id[(offset - A_PID4) / 4];
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE System Counter control frame read: bad offset 0x%x",
+                      (unsigned)offset);
+        r = 0;
+        break;
+    }
+
+    trace_sse_counter_control_read(offset, r, size);
+    return r;
+}
+
+static void sse_counter_control_write(void *opaque, hwaddr offset,
+                                      uint64_t value, unsigned size)
+{
+    SSECounter *s = SSE_COUNTER(opaque);
+
+    trace_sse_counter_control_write(offset, value, size);
+
+    switch (offset) {
+    case A_CNTCR:
+        /*
+         * Although CNTCR defines interrupt-related bits, the counter doesn't
+         * appear to actually have an interrupt output. So INTRCLR is
+         * effectively a RAZ/WI bit, as are the reserved bits [31:6].
+         * The documentation does not explicitly say so, but we assume
+         * that changing the scale factor while the counter is enabled
+         * by toggling CNTCR.SCEN has the same behaviour (making the counter
+         * value UNKNOWN) as changing it by writing to CNTSCR, and so we
+         * don't need to try to recalculate for that case.
+         */
+        value &= CNTCR_VALID_MASK;
+        if ((value ^ s->cntcr) & R_CNTCR_EN_MASK) {
+            /*
+             * Whether the counter is being enabled or disabled, the
+             * required action is the same: sync the (ns_then, ticks_then)
+             * tuple.
+             */
+            uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+            s->ticks_then = sse_counter_for_timestamp(s, now);
+            s->ns_then = now;
+            sse_counter_notify_users(s);
+        }
+        s->cntcr = value;
+        break;
+    case A_CNTCV_LO:
+        sse_write_cntcv(s, value, 0);
+        break;
+    case A_CNTCV_HI:
+        sse_write_cntcv(s, value, 32);
+        break;
+    case A_CNTSCR:
+    case A_CNTSCR0:
+        /*
+         * If the scale registers are changed when the counter is enabled,
+         * the count value becomes UNKNOWN. So we don't try to recalculate
+         * anything here but only do it on a write to CNTCR.EN.
+         */
+        s->cntscr0 = value;
+        break;
+    case A_CNTSCR1:
+        /* If HWCLKSW == 0, CNTSCR1 is RAZ/WI */
+        break;
+    case A_CNTSR:
+    case A_CNTID:
+    case A_PID4 ... A_CID3:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE System Counter control frame: write to RO offset 0x%x\n",
+                      (unsigned)offset);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE System Counter control frame: write to bad offset 0x%x\n",
+                      (unsigned)offset);
+        break;
+    }
+}
+
+static uint64_t sse_counter_status_read(void *opaque, hwaddr offset,
+                                        unsigned size)
+{
+    SSECounter *s = SSE_COUNTER(opaque);
+    uint64_t r;
+
+    switch (offset) {
+    case A_STATUS_CNTCV_LO:
+        r = extract64(sse_cntcv(s), 0, 32);
+        break;
+    case A_STATUS_CNTCV_HI:
+        r = extract64(sse_cntcv(s), 32, 32);
+        break;
+    case A_PID4 ... A_CID3:
+        r = status_id[(offset - A_PID4) / 4];
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE System Counter status frame read: bad offset 0x%x",
+                      (unsigned)offset);
+        r = 0;
+        break;
+    }
+
+    trace_sse_counter_status_read(offset, r, size);
+    return r;
+}
+
+static void sse_counter_status_write(void *opaque, hwaddr offset,
+                                     uint64_t value, unsigned size)
+{
+    trace_sse_counter_status_write(offset, value, size);
+
+    switch (offset) {
+    case A_STATUS_CNTCV_LO:
+    case A_STATUS_CNTCV_HI:
+    case A_PID4 ... A_CID3:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE System Counter status frame: write to RO offset 0x%x\n",
+                      (unsigned)offset);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE System Counter status frame: write to bad offset 0x%x\n",
+                      (unsigned)offset);
+        break;
+    }
+}
+
+static const MemoryRegionOps sse_counter_control_ops = {
+    .read = sse_counter_control_read,
+    .write = sse_counter_control_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+};
+
+static const MemoryRegionOps sse_counter_status_ops = {
+    .read = sse_counter_status_read,
+    .write = sse_counter_status_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+};
+
+static void sse_counter_reset(DeviceState *dev)
+{
+    SSECounter *s = SSE_COUNTER(dev);
+
+    trace_sse_counter_reset();
+
+    s->cntcr = 0;
+    s->cntscr0 = 0x01000000;
+    s->ns_then = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    s->ticks_then = 0;
+}
+
+static void sse_clk_callback(void *opaque, ClockEvent event)
+{
+    SSECounter *s = SSE_COUNTER(opaque);
+    uint64_t now;
+
+    switch (event) {
+    case ClockPreUpdate:
+        /*
+         * Before the clock period updates, set (ticks_then, ns_then)
+         * to the current time and tick count (as calculated with
+         * the old clock period).
+         */
+        if (sse_counter_enabled(s)) {
+            now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+            s->ticks_then = sse_counter_for_timestamp(s, now);
+            s->ns_then = now;
+        }
+        break;
+    case ClockUpdate:
+        sse_counter_notify_users(s);
+        break;
+    default:
+        break;
+    }
+}
+
+static void sse_counter_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    SSECounter *s = SSE_COUNTER(obj);
+
+    notifier_list_init(&s->notifier_list);
+
+    s->clk = qdev_init_clock_in(DEVICE(obj), "CLK", sse_clk_callback, s,
+                                ClockPreUpdate | ClockUpdate);
+    memory_region_init_io(&s->control_mr, obj, &sse_counter_control_ops,
+                          s, "sse-counter-control", 0x1000);
+    memory_region_init_io(&s->status_mr, obj, &sse_counter_status_ops,
+                          s, "sse-counter-status", 0x1000);
+    sysbus_init_mmio(sbd, &s->control_mr);
+    sysbus_init_mmio(sbd, &s->status_mr);
+}
+
+static void sse_counter_realize(DeviceState *dev, Error **errp)
+{
+    SSECounter *s = SSE_COUNTER(dev);
+
+    if (!clock_has_source(s->clk)) {
+        error_setg(errp, "SSE system counter: CLK must be connected");
+        return;
+    }
+}
+
+static const VMStateDescription sse_counter_vmstate = {
+    .name = "sse-counter",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_CLOCK(clk, SSECounter),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void sse_counter_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = sse_counter_realize;
+    dc->vmsd = &sse_counter_vmstate;
+    dc->reset = sse_counter_reset;
+}
+
+static const TypeInfo sse_counter_info = {
+    .name = TYPE_SSE_COUNTER,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SSECounter),
+    .instance_init = sse_counter_init,
+    .class_init = sse_counter_class_init,
+};
+
+static void sse_counter_register_types(void)
+{
+    type_register_static(&sse_counter_info);
+}
+
+type_init(sse_counter_register_types);
diff --git a/MAINTAINERS b/MAINTAINERS
index 26c9454823a..68c37957cfe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -751,6 +751,8 @@ F: hw/misc/armsse-cpuid.c
 F: include/hw/misc/armsse-cpuid.h
 F: hw/misc/armsse-mhu.c
 F: include/hw/misc/armsse-mhu.h
+F: hw/timer/sse-counter.c
+F: include/hw/timer/sse-counter.h
 F: docs/system/arm/mps2.rst
 
 Musca
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 4e6f4ffe90c..a23992a47c8 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -520,6 +520,7 @@ config ARMSSE
     select TZ_MSC
     select TZ_PPC
     select UNIMP
+    select SSE_COUNTER
 
 config ARMSSE_CPUID
     bool
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
index 8749edfb6a5..e103c8872ab 100644
--- a/hw/timer/Kconfig
+++ b/hw/timer/Kconfig
@@ -42,5 +42,8 @@ config RENESAS_TMR
 config RENESAS_CMT
     bool
 
+config SSE_COUNTER
+    bool
+
 config AVR_TIMER16
     bool
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
index be343f68fed..79a3012349d 100644
--- a/hw/timer/meson.build
+++ b/hw/timer/meson.build
@@ -32,6 +32,7 @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_timer.c'))
 softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_systmr.c'))
 softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('sh_timer.c'))
 softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_timer.c'))
+softmmu_ss.add(when: 'CONFIG_SSE_COUNTER', if_true: files('sse-counter.c'))
 softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c'))
 softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
 
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index 7a4326d9566..bb9c1000878 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -93,3 +93,10 @@ avr_timer16_interrupt_count(uint8_t cnt) "count: %u"
 avr_timer16_interrupt_overflow(const char *reason) "overflow: %s"
 avr_timer16_next_alarm(uint64_t delay_ns) "next alarm: %" PRIu64 " ns from now"
 avr_timer16_clksrc_update(uint64_t freq_hz, uint64_t period_ns, uint64_t delay_s) "timer frequency: %" PRIu64 " Hz, period: %" PRIu64 " ns (%" PRId64 " us)"
+
+# sse_counter.c
+sse_counter_control_read(uint64_t offset, uint64_t data, unsigned size) "SSE system counter control frame read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+sse_counter_control_write(uint64_t offset, uint64_t data, unsigned size) "SSE system counter control framen write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+sse_counter_status_read(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+sse_counter_status_write(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+sse_counter_reset(void) "SSE system counter: reset"
-- 
2.20.1



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

* [PULL 12/54] hw/timer/sse-timer: Model the SSE Subsystem System Timer
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (10 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 11/54] hw/timer/sse-counter: Model the SSE Subsystem System Counter Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 13/54] hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour Peter Maydell
                   ` (42 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-300 includes some timers which are a different kind to
those in the SSE-200. Model them.

These timers are documented in the SSE-123 Example Subsystem
Technical Reference Manual:
 https://developer.arm.com/documentation/101370/latest/

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-13-peter.maydell@linaro.org
---
 include/hw/timer/sse-timer.h |  53 ++++
 hw/timer/sse-timer.c         | 470 +++++++++++++++++++++++++++++++++++
 MAINTAINERS                  |   2 +
 hw/arm/Kconfig               |   1 +
 hw/timer/Kconfig             |   3 +
 hw/timer/meson.build         |   1 +
 hw/timer/trace-events        |   5 +
 7 files changed, 535 insertions(+)
 create mode 100644 include/hw/timer/sse-timer.h
 create mode 100644 hw/timer/sse-timer.c

diff --git a/include/hw/timer/sse-timer.h b/include/hw/timer/sse-timer.h
new file mode 100644
index 00000000000..b4ee8e7f6c4
--- /dev/null
+++ b/include/hw/timer/sse-timer.h
@@ -0,0 +1,53 @@
+/*
+ * Arm SSE Subsystem System Timer
+ *
+ * Copyright (c) 2020 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 "System timer" which is documented in
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
+ * https://developer.arm.com/documentation/101370/latest/
+ *
+ * QEMU interface:
+ *  + QOM property "counter": link property to be set to the
+ *    TYPE_SSE_COUNTER timestamp counter device this timer runs off
+ *  + sysbus MMIO region 0: the register bank
+ *  + sysbus IRQ 0: timer interrupt
+ */
+
+#ifndef SSE_TIMER_H
+#define SSE_TIMER_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+#include "hw/timer/sse-counter.h"
+
+#define TYPE_SSE_TIMER "sse-timer"
+OBJECT_DECLARE_SIMPLE_TYPE(SSETimer, SSE_TIMER)
+
+struct SSETimer {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    MemoryRegion iomem;
+    qemu_irq irq;
+    SSECounter *counter;
+    QEMUTimer timer;
+    Notifier counter_notifier;
+
+    uint32_t cntfrq;
+    uint32_t cntp_ctl;
+    uint64_t cntp_cval;
+    uint64_t cntp_aival;
+    uint32_t cntp_aival_ctl;
+    uint32_t cntp_aival_reload;
+};
+
+#endif
diff --git a/hw/timer/sse-timer.c b/hw/timer/sse-timer.c
new file mode 100644
index 00000000000..8dbe6ac651e
--- /dev/null
+++ b/hw/timer/sse-timer.c
@@ -0,0 +1,470 @@
+/*
+ * Arm SSE Subsystem System Timer
+ *
+ * Copyright (c) 2020 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 "System timer" which is documented in
+ * the Arm SSE-123 Example Subsystem Technical Reference Manual:
+ * https://developer.arm.com/documentation/101370/latest/
+ *
+ * The timer is based around a simple 64-bit incrementing counter
+ * (readable from CNTPCT_HI/LO). The timer fires when
+ *  Counter - CompareValue >= 0.
+ * The CompareValue is guest-writable, via CNTP_CVAL_HI/LO.
+ * CNTP_TVAL is an alternative view of the CompareValue defined by
+ *  TimerValue = CompareValue[31:0] - Counter[31:0]
+ * which can be both read and written.
+ * This part is similar to the generic timer in an Arm A-class CPU.
+ *
+ * The timer also has a separate auto-increment timer. When this
+ * timer is enabled, then the AutoIncrValue is set to:
+ *  AutoIncrValue = Reload + Counter
+ * and this timer fires when
+ *  Counter - AutoIncrValue >= 0
+ * at which point, an interrupt is generated and the new AutoIncrValue
+ * is calculated.
+ * When the auto-increment timer is enabled, interrupt generation
+ * via the compare/timervalue registers is disabled.
+ */
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+#include "qapi/error.h"
+#include "trace.h"
+#include "hw/timer/sse-timer.h"
+#include "hw/timer/sse-counter.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/registerfields.h"
+#include "hw/clock.h"
+#include "hw/qdev-clock.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+
+REG32(CNTPCT_LO, 0x0)
+REG32(CNTPCT_HI, 0x4)
+REG32(CNTFRQ, 0x10)
+REG32(CNTP_CVAL_LO, 0x20)
+REG32(CNTP_CVAL_HI, 0x24)
+REG32(CNTP_TVAL, 0x28)
+REG32(CNTP_CTL, 0x2c)
+    FIELD(CNTP_CTL, ENABLE, 0, 1)
+    FIELD(CNTP_CTL, IMASK, 1, 1)
+    FIELD(CNTP_CTL, ISTATUS, 2, 1)
+REG32(CNTP_AIVAL_LO, 0x40)
+REG32(CNTP_AIVAL_HI, 0x44)
+REG32(CNTP_AIVAL_RELOAD, 0x48)
+REG32(CNTP_AIVAL_CTL, 0x4c)
+    FIELD(CNTP_AIVAL_CTL, EN, 0, 1)
+    FIELD(CNTP_AIVAL_CTL, CLR, 1, 1)
+REG32(CNTP_CFG, 0x50)
+    FIELD(CNTP_CFG, AIVAL, 0, 4)
+#define R_CNTP_CFG_AIVAL_IMPLEMENTED 1
+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 timer_id[] = {
+    0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+    0xb7, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
+    0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
+static bool sse_is_autoinc(SSETimer *s)
+{
+    return (s->cntp_aival_ctl & R_CNTP_AIVAL_CTL_EN_MASK) != 0;
+}
+
+static bool sse_enabled(SSETimer *s)
+{
+    return (s->cntp_ctl & R_CNTP_CTL_ENABLE_MASK) != 0;
+}
+
+static uint64_t sse_cntpct(SSETimer *s)
+{
+    /* Return the CNTPCT value for the current time */
+    return sse_counter_for_timestamp(s->counter,
+                                     qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+}
+
+static bool sse_timer_status(SSETimer *s)
+{
+    /*
+     * Return true if timer condition is met. This is used for both
+     * the CNTP_CTL.ISTATUS bit and for whether (unless masked) we
+     * assert our IRQ.
+     * The documentation is unclear about the behaviour of ISTATUS when
+     * in autoincrement mode; we assume that it follows CNTP_AIVAL_CTL.CLR
+     * (ie whether the autoincrement timer is asserting the interrupt).
+     */
+    if (!sse_enabled(s)) {
+        return false;
+    }
+
+    if (sse_is_autoinc(s)) {
+        return s->cntp_aival_ctl & R_CNTP_AIVAL_CTL_CLR_MASK;
+    } else {
+        return sse_cntpct(s) >= s->cntp_cval;
+    }
+}
+
+static void sse_update_irq(SSETimer *s)
+{
+    bool irqstate = (!(s->cntp_ctl & R_CNTP_CTL_IMASK_MASK) &&
+                     sse_timer_status(s));
+
+    qemu_set_irq(s->irq, irqstate);
+}
+
+static void sse_set_timer(SSETimer *s, uint64_t nexttick)
+{
+    /* Set the timer to expire at nexttick */
+    uint64_t expiry = sse_counter_tick_to_time(s->counter, nexttick);
+
+    if (expiry <= INT64_MAX) {
+        timer_mod_ns(&s->timer, expiry);
+    } else {
+        /*
+         * nexttick is so far in the future that it would overflow the
+         * signed 64-bit range of a QEMUTimer. Since timer_mod_ns()
+         * expiry times are absolute, not relative, we are never going
+         * to be able to set the timer to this value, so we must just
+         * assume that guest execution can never run so long that it
+         * reaches the theoretical point when the timer fires.
+         * This is also the code path for "counter is not running",
+         * which is signalled by expiry == UINT64_MAX.
+         */
+        timer_del(&s->timer);
+    }
+}
+
+static void sse_recalc_timer(SSETimer *s)
+{
+    /* Recalculate the normal timer */
+    uint64_t count, nexttick;
+
+    if (sse_is_autoinc(s)) {
+        return;
+    }
+
+    if (!sse_enabled(s)) {
+        timer_del(&s->timer);
+        return;
+    }
+
+    count = sse_cntpct(s);
+
+    if (count >= s->cntp_cval) {
+        /*
+         * Timer condition already met. In theory we have a transition when
+         * the count rolls back over to 0, but that is so far in the future
+         * that it is not representable as a timer_mod() expiry, so in
+         * fact sse_set_timer() will always just delete the timer.
+         */
+        nexttick = UINT64_MAX;
+    } else {
+        /* Next transition is when count hits cval */
+        nexttick = s->cntp_cval;
+    }
+    sse_set_timer(s, nexttick);
+    sse_update_irq(s);
+}
+
+static void sse_autoinc(SSETimer *s)
+{
+    /* Auto-increment the AIVAL, and set the timer accordingly */
+    s->cntp_aival = sse_cntpct(s) + s->cntp_aival_reload;
+    sse_set_timer(s, s->cntp_aival);
+}
+
+static void sse_timer_cb(void *opaque)
+{
+    SSETimer *s = SSE_TIMER(opaque);
+
+    if (sse_is_autoinc(s)) {
+        uint64_t count = sse_cntpct(s);
+
+        if (count >= s->cntp_aival) {
+            /* Timer condition met, set CLR and do another autoinc */
+            s->cntp_aival_ctl |= R_CNTP_AIVAL_CTL_CLR_MASK;
+            s->cntp_aival = count + s->cntp_aival_reload;
+        }
+        sse_set_timer(s, s->cntp_aival);
+        sse_update_irq(s);
+    } else {
+        sse_recalc_timer(s);
+    }
+}
+
+static uint64_t sse_timer_read(void *opaque, hwaddr offset, unsigned size)
+{
+    SSETimer *s = SSE_TIMER(opaque);
+    uint64_t r;
+
+    switch (offset) {
+    case A_CNTPCT_LO:
+        r = extract64(sse_cntpct(s), 0, 32);
+        break;
+    case A_CNTPCT_HI:
+        r = extract64(sse_cntpct(s), 32, 32);
+        break;
+    case A_CNTFRQ:
+        r = s->cntfrq;
+        break;
+    case A_CNTP_CVAL_LO:
+        r = extract64(s->cntp_cval, 0, 32);
+        break;
+    case A_CNTP_CVAL_HI:
+        r = extract64(s->cntp_cval, 32, 32);
+        break;
+    case A_CNTP_TVAL:
+        r = extract64(s->cntp_cval - sse_cntpct(s), 0, 32);
+        break;
+    case A_CNTP_CTL:
+        r = s->cntp_ctl;
+        if (sse_timer_status(s)) {
+            r |= R_CNTP_CTL_ISTATUS_MASK;
+        }
+        break;
+    case A_CNTP_AIVAL_LO:
+        r = extract64(s->cntp_aival, 0, 32);
+        break;
+    case A_CNTP_AIVAL_HI:
+        r = extract64(s->cntp_aival, 32, 32);
+        break;
+    case A_CNTP_AIVAL_RELOAD:
+        r = s->cntp_aival_reload;
+        break;
+    case A_CNTP_AIVAL_CTL:
+        /*
+         * All the bits of AIVAL_CTL are documented as WO, but this is probably
+         * a documentation error. We implement them as readable.
+         */
+        r = s->cntp_aival_ctl;
+        break;
+    case A_CNTP_CFG:
+        r = R_CNTP_CFG_AIVAL_IMPLEMENTED << R_CNTP_CFG_AIVAL_SHIFT;
+        break;
+    case A_PID4 ... A_CID3:
+        r = timer_id[(offset - A_PID4) / 4];
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE System Timer read: bad offset 0x%x",
+                      (unsigned) offset);
+        r = 0;
+        break;
+    }
+
+    trace_sse_timer_read(offset, r, size);
+    return r;
+}
+
+static void sse_timer_write(void *opaque, hwaddr offset, uint64_t value,
+                            unsigned size)
+{
+    SSETimer *s = SSE_TIMER(opaque);
+
+    trace_sse_timer_write(offset, value, size);
+
+    switch (offset) {
+    case A_CNTFRQ:
+        s->cntfrq = value;
+        break;
+    case A_CNTP_CVAL_LO:
+        s->cntp_cval = deposit64(s->cntp_cval, 0, 32, value);
+        sse_recalc_timer(s);
+        break;
+    case A_CNTP_CVAL_HI:
+        s->cntp_cval = deposit64(s->cntp_cval, 32, 32, value);
+        sse_recalc_timer(s);
+        break;
+    case A_CNTP_TVAL:
+        s->cntp_cval = sse_cntpct(s) + sextract64(value, 0, 32);
+        sse_recalc_timer(s);
+        break;
+    case A_CNTP_CTL:
+    {
+        uint32_t old_ctl = s->cntp_ctl;
+        value &= R_CNTP_CTL_ENABLE_MASK | R_CNTP_CTL_IMASK_MASK;
+        s->cntp_ctl = value;
+        if ((old_ctl ^ s->cntp_ctl) & R_CNTP_CTL_ENABLE_MASK) {
+            if (sse_enabled(s)) {
+                if (sse_is_autoinc(s)) {
+                    sse_autoinc(s);
+                } else {
+                    sse_recalc_timer(s);
+                }
+            }
+        }
+        sse_update_irq(s);
+        break;
+    }
+    case A_CNTP_AIVAL_RELOAD:
+        s->cntp_aival_reload = value;
+        break;
+    case A_CNTP_AIVAL_CTL:
+    {
+        uint32_t old_ctl = s->cntp_aival_ctl;
+
+        /* EN bit is writeable; CLR bit is write-0-to-clear, write-1-ignored */
+        s->cntp_aival_ctl &= ~R_CNTP_AIVAL_CTL_EN_MASK;
+        s->cntp_aival_ctl |= value & R_CNTP_AIVAL_CTL_EN_MASK;
+        if (!(value & R_CNTP_AIVAL_CTL_CLR_MASK)) {
+            s->cntp_aival_ctl &= ~R_CNTP_AIVAL_CTL_CLR_MASK;
+        }
+        if ((old_ctl ^ s->cntp_aival_ctl) & R_CNTP_AIVAL_CTL_EN_MASK) {
+            /* Auto-increment toggled on/off */
+            if (sse_enabled(s)) {
+                if (sse_is_autoinc(s)) {
+                    sse_autoinc(s);
+                } else {
+                    sse_recalc_timer(s);
+                }
+            }
+        }
+        sse_update_irq(s);
+        break;
+    }
+    case A_CNTPCT_LO:
+    case A_CNTPCT_HI:
+    case A_CNTP_CFG:
+    case A_CNTP_AIVAL_LO:
+    case A_CNTP_AIVAL_HI:
+    case A_PID4 ... A_CID3:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE System Timer write: write to RO offset 0x%x\n",
+                      (unsigned)offset);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE System Timer write: bad offset 0x%x\n",
+                      (unsigned)offset);
+        break;
+    }
+}
+
+static const MemoryRegionOps sse_timer_ops = {
+    .read = sse_timer_read,
+    .write = sse_timer_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+};
+
+static void sse_timer_reset(DeviceState *dev)
+{
+    SSETimer *s = SSE_TIMER(dev);
+
+    trace_sse_timer_reset();
+
+    timer_del(&s->timer);
+    s->cntfrq = 0;
+    s->cntp_ctl = 0;
+    s->cntp_cval = 0;
+    s->cntp_aival = 0;
+    s->cntp_aival_ctl = 0;
+    s->cntp_aival_reload = 0;
+}
+
+static void sse_timer_counter_callback(Notifier *notifier, void *data)
+{
+    SSETimer *s = container_of(notifier, SSETimer, counter_notifier);
+
+    /* System counter told us we need to recalculate */
+    if (sse_enabled(s)) {
+        if (sse_is_autoinc(s)) {
+            sse_set_timer(s, s->cntp_aival);
+        } else {
+            sse_recalc_timer(s);
+        }
+    }
+}
+
+static void sse_timer_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    SSETimer *s = SSE_TIMER(obj);
+
+    memory_region_init_io(&s->iomem, obj, &sse_timer_ops,
+                          s, "sse-timer", 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq);
+}
+
+static void sse_timer_realize(DeviceState *dev, Error **errp)
+{
+    SSETimer *s = SSE_TIMER(dev);
+
+    if (!s->counter) {
+        error_setg(errp, "counter property was not set");
+    }
+
+    s->counter_notifier.notify = sse_timer_counter_callback;
+    sse_counter_register_consumer(s->counter, &s->counter_notifier);
+
+    timer_init_ns(&s->timer, QEMU_CLOCK_VIRTUAL, sse_timer_cb, s);
+}
+
+static const VMStateDescription sse_timer_vmstate = {
+    .name = "sse-timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_TIMER(timer, SSETimer),
+        VMSTATE_UINT32(cntfrq, SSETimer),
+        VMSTATE_UINT32(cntp_ctl, SSETimer),
+        VMSTATE_UINT64(cntp_cval, SSETimer),
+        VMSTATE_UINT64(cntp_aival, SSETimer),
+        VMSTATE_UINT32(cntp_aival_ctl, SSETimer),
+        VMSTATE_UINT32(cntp_aival_reload, SSETimer),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property sse_timer_properties[] = {
+    DEFINE_PROP_LINK("counter", SSETimer, counter, TYPE_SSE_COUNTER, SSECounter *),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sse_timer_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = sse_timer_realize;
+    dc->vmsd = &sse_timer_vmstate;
+    dc->reset = sse_timer_reset;
+    device_class_set_props(dc, sse_timer_properties);
+}
+
+static const TypeInfo sse_timer_info = {
+    .name = TYPE_SSE_TIMER,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(SSETimer),
+    .instance_init = sse_timer_init,
+    .class_init = sse_timer_class_init,
+};
+
+static void sse_timer_register_types(void)
+{
+    type_register_static(&sse_timer_info);
+}
+
+type_init(sse_timer_register_types);
diff --git a/MAINTAINERS b/MAINTAINERS
index 68c37957cfe..ea206fc900e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -753,6 +753,8 @@ F: hw/misc/armsse-mhu.c
 F: include/hw/misc/armsse-mhu.h
 F: hw/timer/sse-counter.c
 F: include/hw/timer/sse-counter.h
+F: hw/timer/sse-timer.c
+F: include/hw/timer/sse-timer.h
 F: docs/system/arm/mps2.rst
 
 Musca
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index a23992a47c8..5b3bd1e866b 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -521,6 +521,7 @@ config ARMSSE
     select TZ_PPC
     select UNIMP
     select SSE_COUNTER
+    select SSE_TIMER
 
 config ARMSSE_CPUID
     bool
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
index e103c8872ab..726be4f82ca 100644
--- a/hw/timer/Kconfig
+++ b/hw/timer/Kconfig
@@ -45,5 +45,8 @@ config RENESAS_CMT
 config SSE_COUNTER
     bool
 
+config SSE_TIMER
+    bool
+
 config AVR_TIMER16
     bool
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
index 79a3012349d..91ab2aa803f 100644
--- a/hw/timer/meson.build
+++ b/hw/timer/meson.build
@@ -33,6 +33,7 @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_systmr.c'))
 softmmu_ss.add(when: 'CONFIG_SH4', if_true: files('sh_timer.c'))
 softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_timer.c'))
 softmmu_ss.add(when: 'CONFIG_SSE_COUNTER', if_true: files('sse-counter.c'))
+softmmu_ss.add(when: 'CONFIG_SSE_TIMER', if_true: files('sse-timer.c'))
 softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c'))
 softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
 
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index bb9c1000878..f8b9db25c27 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -100,3 +100,8 @@ sse_counter_control_write(uint64_t offset, uint64_t data, unsigned size) "SSE sy
 sse_counter_status_read(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
 sse_counter_status_write(uint64_t offset, uint64_t data, unsigned size) "SSE system counter status frame write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
 sse_counter_reset(void) "SSE system counter: reset"
+
+# sse_timer.c
+sse_timer_read(uint64_t offset, uint64_t data, unsigned size) "SSE system timer read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+sse_timer_write(uint64_t offset, uint64_t data, unsigned size) "SSE system timer write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+sse_timer_reset(void) "SSE system timer: reset"
-- 
2.20.1



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

* [PULL 13/54] hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (11 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 12/54] hw/timer/sse-timer: Model the SSE Subsystem System Timer Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 14/54] hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300 Peter Maydell
                   ` (41 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-300's iokit-sysctl device is similar to the SSE-200, but
some registers have moved address or have different behaviours.
In this commit we add case statements for the registers where
the SSE-300 and SSE-200 have the same behaviour. Some registers
are the same on all SSE versions and so need no code change at all.
Putting both of these categories together covers:

0x0 SECDBGSTAT
0x4 SECDBGSET
0x8 SECDBGCLR
0xc SCSECCTRL
0x10 CLK_CFG0 -- this is like SSE-200 FCLK_DIV but with a
   different set of clocks being controlled; our implementation
   is a dummy reads-as-written anyway
0x14 CLK_CFG1 -- similar to SSE-200 SYSCLK_DIV; our implementation
   is a dummy
0x18 CLK_FORCE -- similar to SSE-200 but different bit allocations;
   we have a dummy implementation
0x100 RESET_SYNDROME -- bit allocation differs from SSE-200 but our
   implementation is a dummy
0x104 RESET_MASK -- bit allocation differs from SSE-200 but our
   implementation is a dummy
0x108 SWRESET
0x10c GRETREG
0x200 PDCM_PD_SYS_SENSE -- some bit allocations differ, but our
   implementation is a dummy

We also need to migrate the state of these registers which are shared
between the SSE-200 and SSE-300, so update the vmstate 'needed'
function to do this.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-14-peter.maydell@linaro.org
---
 hw/misc/iotkit-sysctl.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index c67f5b320ab..7f8608c814c 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -105,6 +105,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_IOTKIT:
             goto bad_offset;
         case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
             r = s->scsecctrl;
             break;
         default:
@@ -116,6 +117,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_IOTKIT:
             goto bad_offset;
         case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
             r = s->fclk_div;
             break;
         default:
@@ -127,6 +129,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_IOTKIT:
             goto bad_offset;
         case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
             r = s->sysclk_div;
             break;
         default:
@@ -138,6 +141,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_IOTKIT:
             goto bad_offset;
         case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
             r = s->clock_force;
             break;
         default:
@@ -202,6 +206,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_IOTKIT:
             goto bad_offset;
         case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
             r = s->pdcm_pd_sys_sense;
             break;
         default:
@@ -348,6 +353,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
         case ARMSSE_IOTKIT:
             goto bad_offset;
         case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
             s->scsecctrl = value;
             break;
@@ -360,6 +366,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
         case ARMSSE_IOTKIT:
             goto bad_offset;
         case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
             s->fclk_div = value;
             break;
@@ -372,6 +379,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
         case ARMSSE_IOTKIT:
             goto bad_offset;
         case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
             s->sysclk_div = value;
             break;
@@ -384,6 +392,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
         case ARMSSE_IOTKIT:
             goto bad_offset;
         case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
             s->clock_force = value;
             break;
@@ -420,6 +429,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
         case ARMSSE_IOTKIT:
             goto bad_offset;
         case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
             qemu_log_mask(LOG_UNIMP,
                           "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
             s->pdcm_pd_sys_sense = value;
@@ -569,7 +579,7 @@ static bool sse200_needed(void *opaque)
 {
     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
 
-    return s->sse_version == ARMSSE_SSE200;
+    return s->sse_version != ARMSSE_IOTKIT;
 }
 
 static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
-- 
2.20.1



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

* [PULL 14/54] hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (12 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 13/54] hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 15/54] hw/misc/iotkit-sysctl: Handle INITSVTOR* " Peter Maydell
                   ` (40 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

In the SSE-300 the CPU_WAIT and NMI_ENABLE registers have
moved offsets, so they are now where the SSE-200's WICCTRL
and EWCTRL were. The SSE-300 does not have WICCTLR or EWCTRL
at all, and the old offsets are reserved:

 Offset    SSE-200      SSE-300
-----------------------------------
 0x118     CPUWAIT      reserved
 0x118     NMI_ENABLE   reserved
 0x120     WICCTRL      CPUWAIT
 0x124     EWCTRL       NMI_ENABLE

Handle this reshuffle, and the fact that SSE-300 has only
one CPU and so only one active bit in CPUWAIT.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-15-peter.maydell@linaro.org
---
 hw/misc/iotkit-sysctl.c | 88 +++++++++++++++++++++++++++++++++++------
 1 file changed, 76 insertions(+), 12 deletions(-)

diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index 7f8608c814c..54004bebcbf 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -172,7 +172,17 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         }
         break;
     case A_CPUWAIT:
-        r = s->cpuwait;
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
+        case ARMSSE_SSE200:
+            r = s->cpuwait;
+            break;
+        case ARMSSE_SSE300:
+            /* In SSE300 this is reserved (for INITSVTOR2) */
+            goto bad_offset;
+        default:
+            g_assert_not_reached();
+        }
         break;
     case A_NMI_ENABLE:
         switch (s->sse_version) {
@@ -183,12 +193,26 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_SSE200:
             r = s->nmi_enable;
             break;
+        case ARMSSE_SSE300:
+            /* In SSE300 this is reserved (for INITSVTOR3) */
+            goto bad_offset;
         default:
             g_assert_not_reached();
         }
         break;
     case A_WICCTRL:
-        r = s->wicctrl;
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
+        case ARMSSE_SSE200:
+            r = s->wicctrl;
+            break;
+        case ARMSSE_SSE300:
+            /* In SSE300 this offset is CPUWAIT */
+            r = s->cpuwait;
+            break;
+        default:
+            g_assert_not_reached();
+        }
         break;
     case A_EWCTRL:
         switch (s->sse_version) {
@@ -197,6 +221,10 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_SSE200:
             r = s->ewctrl;
             break;
+        case ARMSSE_SSE300:
+            /* In SSE300 this offset is is NMI_ENABLE */
+            r = s->nmi_enable;
+            break;
         default:
             g_assert_not_reached();
         }
@@ -279,6 +307,21 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
     return r;
 }
 
+static void cpuwait_write(IoTKitSysCtl *s, uint32_t value)
+{
+    int num_cpus = (s->sse_version == ARMSSE_SSE300) ? 1 : 2;
+    int i;
+
+    for (i = 0; i < num_cpus; i++) {
+        uint32_t mask = 1 << i;
+        if ((s->cpuwait & mask) && !(value & mask)) {
+            /* Powering up CPU 0 */
+            arm_set_cpu_on_and_reset(i);
+        }
+    }
+    s->cpuwait = value;
+}
+
 static void iotkit_sysctl_write(void *opaque, hwaddr offset,
                                  uint64_t value, unsigned size)
 {
@@ -319,19 +362,32 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
         set_init_vtor(0, s->initsvtor0);
         break;
     case A_CPUWAIT:
-        if ((s->cpuwait & 1) && !(value & 1)) {
-            /* Powering up CPU 0 */
-            arm_set_cpu_on_and_reset(0);
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
+        case ARMSSE_SSE200:
+            cpuwait_write(s, value);
+            break;
+        case ARMSSE_SSE300:
+            /* In SSE300 this is reserved (for INITSVTOR2) */
+            goto bad_offset;
+        default:
+            g_assert_not_reached();
         }
-        if ((s->cpuwait & 2) && !(value & 2)) {
-            /* Powering up CPU 1 */
-            arm_set_cpu_on_and_reset(1);
-        }
-        s->cpuwait = value;
         break;
     case A_WICCTRL:
-        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
-        s->wicctrl = value;
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
+        case ARMSSE_SSE200:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
+            s->wicctrl = value;
+            break;
+        case ARMSSE_SSE300:
+            /* In SSE300 this offset is CPUWAIT */
+            cpuwait_write(s, value);
+            break;
+        default:
+            g_assert_not_reached();
+        }
         break;
     case A_SECDBGSET:
         /* write-1-to-set */
@@ -420,6 +476,11 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
             s->ewctrl = value;
             break;
+        case ARMSSE_SSE300:
+            /* In SSE300 this offset is is NMI_ENABLE */
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
+            s->nmi_enable = value;
+            break;
         default:
             g_assert_not_reached();
         }
@@ -499,6 +560,9 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
             qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
             s->nmi_enable = value;
             break;
+        case ARMSSE_SSE300:
+            /* In SSE300 this is reserved (for INITSVTOR3) */
+            goto bad_offset;
         default:
             g_assert_not_reached();
         }
-- 
2.20.1



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

* [PULL 15/54] hw/misc/iotkit-sysctl: Handle INITSVTOR* for SSE-300
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (13 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 14/54] hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300 Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 16/54] hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register Peter Maydell
                   ` (39 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-300 has only one CPU and so no INITSVTOR1. It does
have INITSVTOR0, but unlike the SSE-200 this register now
has a LOCK bit which can be set to 1 to prevent any further
writes to the register. Implement these differences.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-16-peter.maydell@linaro.org
---
 hw/misc/iotkit-sysctl.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index 54004bebcbf..511ede089c2 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -45,6 +45,8 @@ REG32(SWRESET, 0x108)
     FIELD(SWRESET, SWRESETREQ, 9, 1)
 REG32(GRETREG, 0x10c)
 REG32(INITSVTOR0, 0x110)
+    FIELD(INITSVTOR0, LOCK, 0, 1)
+    FIELD(INITSVTOR0, VTOR, 7, 25)
 REG32(INITSVTOR1, 0x114)
 REG32(CPUWAIT, 0x118)
 REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
@@ -167,6 +169,8 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_SSE200:
             r = s->initsvtor1;
             break;
+        case ARMSSE_SSE300:
+            goto bad_offset;
         default:
             g_assert_not_reached();
         }
@@ -358,8 +362,25 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
         s->gretreg = value;
         break;
     case A_INITSVTOR0:
-        s->initsvtor0 = value;
-        set_init_vtor(0, s->initsvtor0);
+        switch (s->sse_version) {
+        case ARMSSE_SSE300:
+            /* SSE300 has a LOCK bit which prevents further writes when set */
+            if (s->initsvtor0 & R_INITSVTOR0_LOCK_MASK) {
+                qemu_log_mask(LOG_GUEST_ERROR,
+                              "IoTKit INITSVTOR0 write when register locked\n");
+                break;
+            }
+            s->initsvtor0 = value;
+            set_init_vtor(0, s->initsvtor0 & R_INITSVTOR0_VTOR_MASK);
+            break;
+        case ARMSSE_IOTKIT:
+        case ARMSSE_SSE200:
+            s->initsvtor0 = value;
+            set_init_vtor(0, s->initsvtor0);
+            break;
+        default:
+            g_assert_not_reached();
+        }
         break;
     case A_CPUWAIT:
         switch (s->sse_version) {
@@ -464,6 +485,8 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
             s->initsvtor1 = value;
             set_init_vtor(1, s->initsvtor1);
             break;
+        case ARMSSE_SSE300:
+            goto bad_offset;
         default:
             g_assert_not_reached();
         }
-- 
2.20.1



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

* [PULL 16/54] hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (14 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 15/54] hw/misc/iotkit-sysctl: Handle INITSVTOR* " Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 17/54] hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers Peter Maydell
                   ` (38 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-300 has a new PWRCTRL register at offset 0x1fc (previously
reserved). This register controls accessibility of some registers
in the Power Policy Units (PPUs). Since QEMU doesn't implement
the PPUs, we don't need to implement any real behaviour for this
register, so we just handle the UNLOCK bit which controls whether
writes to the register itself are permitted and otherwise make it
be reads-as-written.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-17-peter.maydell@linaro.org
---
 include/hw/misc/iotkit-sysctl.h |  1 +
 hw/misc/iotkit-sysctl.c         | 52 +++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
index 980c2ddfd3c..8859b15d73b 100644
--- a/include/hw/misc/iotkit-sysctl.h
+++ b/include/hw/misc/iotkit-sysctl.h
@@ -53,6 +53,7 @@ struct IoTKitSysCtl {
     uint32_t initsvtor1;
     uint32_t nmi_enable;
     uint32_t ewctrl;
+    uint32_t pwrctrl;
     uint32_t pdcm_pd_sys_sense;
     uint32_t pdcm_pd_sram0_sense;
     uint32_t pdcm_pd_sram1_sense;
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index 511ede089c2..9ec02c3e942 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -52,6 +52,9 @@ REG32(CPUWAIT, 0x118)
 REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
 REG32(WICCTRL, 0x120)
 REG32(EWCTRL, 0x124)
+REG32(PWRCTRL, 0x1fc)
+    FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
+    FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
 REG32(PDCM_PD_SYS_SENSE, 0x200)
 REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
 REG32(PDCM_PD_SRAM1_SENSE, 0x210)
@@ -233,6 +236,18 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
             g_assert_not_reached();
         }
         break;
+    case A_PWRCTRL:
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
+        case ARMSSE_SSE200:
+            goto bad_offset;
+        case ARMSSE_SSE300:
+            r = s->pwrctrl;
+            break;
+        default:
+            g_assert_not_reached();
+        }
+        break;
     case A_PDCM_PD_SYS_SENSE:
         switch (s->sse_version) {
         case ARMSSE_IOTKIT:
@@ -508,6 +523,23 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
             g_assert_not_reached();
         }
         break;
+    case A_PWRCTRL:
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
+        case ARMSSE_SSE200:
+            goto bad_offset;
+        case ARMSSE_SSE300:
+            if (!(s->pwrctrl & R_PWRCTRL_PPU_ACCESS_UNLOCK_MASK)) {
+                qemu_log_mask(LOG_GUEST_ERROR,
+                              "IoTKit PWRCTRL write when register locked\n");
+                break;
+            }
+            s->pwrctrl = value;
+            break;
+        default:
+            g_assert_not_reached();
+        }
+        break;
     case A_PDCM_PD_SYS_SENSE:
         switch (s->sse_version) {
         case ARMSSE_IOTKIT:
@@ -635,6 +667,7 @@ static void iotkit_sysctl_reset(DeviceState *dev)
     s->clock_force = 0;
     s->nmi_enable = 0;
     s->ewctrl = 0;
+    s->pwrctrl = 0x3;
     s->pdcm_pd_sys_sense = 0x7f;
     s->pdcm_pd_sram0_sense = 0;
     s->pdcm_pd_sram1_sense = 0;
@@ -662,6 +695,24 @@ static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
     }
 }
 
+static bool sse300_needed(void *opaque)
+{
+    IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
+
+    return s->sse_version == ARMSSE_SSE300;
+}
+
+static const VMStateDescription iotkit_sysctl_sse300_vmstate = {
+    .name = "iotkit-sysctl/sse-300",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = sse300_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(pwrctrl, IoTKitSysCtl),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static bool sse200_needed(void *opaque)
 {
     IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
@@ -706,6 +757,7 @@ static const VMStateDescription iotkit_sysctl_vmstate = {
     },
     .subsections = (const VMStateDescription*[]) {
         &iotkit_sysctl_sse200_vmstate,
+        &iotkit_sysctl_sse300_vmstate,
         NULL
     }
 };
-- 
2.20.1



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

* [PULL 17/54] hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (15 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 16/54] hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 18/54] hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values Peter Maydell
                   ` (37 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The sysctl PDCM_PD_*_SENSE registers control various power domains in
the system and allow the guest to configure which conditions keep a
power domain awake and what power state to use when the domain is in
a low power state.  QEMU doesn't model power domains, so for us these
registers are dummy reads-as-written implementations.

The SSE-300 has a different power domain setup, so the set of
registers is slightly different:

 Offset   SSE-200               SSE-300
---------------------------------------------------
 0x200    PDCM_PD_SYS_SENSE     PDCM_PD_SYS_SENSE
 0x204    reserved              PDCM_PD_CPU0_SENSE
 0x208    reserved              reserved
 0x20c    PDCM_PD_SRAM0_SENSE   reserved
 0x210    PDCM_PD_SRAM1_SENSE   reserved
 0x214    PDCM_PD_SRAM2_SENSE   PDCM_PD_VMR0_SENSE
 0x218    PDCM_PD_SRAM3_SENSE   PDCM_PD_VMR1_SENSE

Offsets 0x200 and 0x208 are the same for both, so handled in a
previous commit; here we deal with 0x204, 0x20c, 0x210, 0x214, 0x218.

(We can safely add new lines to the SSE300 vmstate because no board
uses this device in an SSE300 yet.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-18-peter.maydell@linaro.org
---
 include/hw/misc/iotkit-sysctl.h |  3 ++
 hw/misc/iotkit-sysctl.c         | 61 +++++++++++++++++++++++++++++++--
 2 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
index 8859b15d73b..481e27f4db1 100644
--- a/include/hw/misc/iotkit-sysctl.h
+++ b/include/hw/misc/iotkit-sysctl.h
@@ -59,6 +59,9 @@ struct IoTKitSysCtl {
     uint32_t pdcm_pd_sram1_sense;
     uint32_t pdcm_pd_sram2_sense;
     uint32_t pdcm_pd_sram3_sense;
+    uint32_t pdcm_pd_cpu0_sense;
+    uint32_t pdcm_pd_vmr0_sense;
+    uint32_t pdcm_pd_vmr1_sense;
 
     /* Properties */
     uint32_t sse_version;
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index 9ec02c3e942..aa8c49d9b6b 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -56,10 +56,11 @@ REG32(PWRCTRL, 0x1fc)
     FIELD(PWRCTRL, PPU_ACCESS_UNLOCK, 0, 1)
     FIELD(PWRCTRL, PPU_ACCESS_FILTER, 1, 1)
 REG32(PDCM_PD_SYS_SENSE, 0x200)
+REG32(PDCM_PD_CPU0_SENSE, 0x204)
 REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
 REG32(PDCM_PD_SRAM1_SENSE, 0x210)
-REG32(PDCM_PD_SRAM2_SENSE, 0x214)
-REG32(PDCM_PD_SRAM3_SENSE, 0x218)
+REG32(PDCM_PD_SRAM2_SENSE, 0x214) /* PDCM_PD_VMR0_SENSE on SSE300 */
+REG32(PDCM_PD_SRAM3_SENSE, 0x218) /* PDCM_PD_VMR1_SENSE on SSE300 */
 REG32(PID4, 0xfd0)
 REG32(PID5, 0xfd4)
 REG32(PID6, 0xfd8)
@@ -260,6 +261,18 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
             g_assert_not_reached();
         }
         break;
+    case A_PDCM_PD_CPU0_SENSE:
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
+        case ARMSSE_SSE200:
+            goto bad_offset;
+        case ARMSSE_SSE300:
+            r = s->pdcm_pd_cpu0_sense;
+            break;
+        default:
+            g_assert_not_reached();
+        }
+        break;
     case A_PDCM_PD_SRAM0_SENSE:
         switch (s->sse_version) {
         case ARMSSE_IOTKIT:
@@ -267,6 +280,8 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_SSE200:
             r = s->pdcm_pd_sram0_sense;
             break;
+        case ARMSSE_SSE300:
+            goto bad_offset;
         default:
             g_assert_not_reached();
         }
@@ -278,6 +293,8 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_SSE200:
             r = s->pdcm_pd_sram1_sense;
             break;
+        case ARMSSE_SSE300:
+            goto bad_offset;
         default:
             g_assert_not_reached();
         }
@@ -289,6 +306,9 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_SSE200:
             r = s->pdcm_pd_sram2_sense;
             break;
+        case ARMSSE_SSE300:
+            r = s->pdcm_pd_vmr0_sense;
+            break;
         default:
             g_assert_not_reached();
         }
@@ -300,6 +320,9 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         case ARMSSE_SSE200:
             r = s->pdcm_pd_sram3_sense;
             break;
+        case ARMSSE_SSE300:
+            r = s->pdcm_pd_vmr1_sense;
+            break;
         default:
             g_assert_not_reached();
         }
@@ -554,6 +577,20 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
             g_assert_not_reached();
         }
         break;
+    case A_PDCM_PD_CPU0_SENSE:
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
+        case ARMSSE_SSE200:
+            goto bad_offset;
+        case ARMSSE_SSE300:
+            qemu_log_mask(LOG_UNIMP,
+                          "IoTKit SysCtl PDCM_PD_CPU0_SENSE unimplemented\n");
+            s->pdcm_pd_cpu0_sense = value;
+            break;
+        default:
+            g_assert_not_reached();
+        }
+        break;
     case A_PDCM_PD_SRAM0_SENSE:
         switch (s->sse_version) {
         case ARMSSE_IOTKIT:
@@ -563,6 +600,8 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
                           "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
             s->pdcm_pd_sram0_sense = value;
             break;
+        case ARMSSE_SSE300:
+            goto bad_offset;
         default:
             g_assert_not_reached();
         }
@@ -576,6 +615,8 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
                           "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
             s->pdcm_pd_sram1_sense = value;
             break;
+        case ARMSSE_SSE300:
+            goto bad_offset;
         default:
             g_assert_not_reached();
         }
@@ -589,6 +630,11 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
                           "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
             s->pdcm_pd_sram2_sense = value;
             break;
+        case ARMSSE_SSE300:
+            qemu_log_mask(LOG_UNIMP,
+                          "IoTKit SysCtl PDCM_PD_VMR0_SENSE unimplemented\n");
+            s->pdcm_pd_vmr0_sense = value;
+            break;
         default:
             g_assert_not_reached();
         }
@@ -602,6 +648,11 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset,
                           "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
             s->pdcm_pd_sram3_sense = value;
             break;
+        case ARMSSE_SSE300:
+            qemu_log_mask(LOG_UNIMP,
+                          "IoTKit SysCtl PDCM_PD_VMR1_SENSE unimplemented\n");
+            s->pdcm_pd_vmr1_sense = value;
+            break;
         default:
             g_assert_not_reached();
         }
@@ -673,6 +724,9 @@ static void iotkit_sysctl_reset(DeviceState *dev)
     s->pdcm_pd_sram1_sense = 0;
     s->pdcm_pd_sram2_sense = 0;
     s->pdcm_pd_sram3_sense = 0;
+    s->pdcm_pd_cpu0_sense = 0;
+    s->pdcm_pd_vmr0_sense = 0;
+    s->pdcm_pd_vmr1_sense = 0;
 }
 
 static void iotkit_sysctl_init(Object *obj)
@@ -709,6 +763,9 @@ static const VMStateDescription iotkit_sysctl_sse300_vmstate = {
     .needed = sse300_needed,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(pwrctrl, IoTKitSysCtl),
+        VMSTATE_UINT32(pdcm_pd_cpu0_sense, IoTKitSysCtl),
+        VMSTATE_UINT32(pdcm_pd_vmr0_sense, IoTKitSysCtl),
+        VMSTATE_UINT32(pdcm_pd_vmr1_sense, IoTKitSysCtl),
         VMSTATE_END_OF_LIST()
     }
 };
-- 
2.20.1



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

* [PULL 18/54] hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (16 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 17/54] hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 19/54] hw/arm/Kconfig: Move ARMSSE_CPUID and ARMSSE_MHU stanzas to hw/misc Peter Maydell
                   ` (36 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-200 and SSE-300 have different PID register values from the
IoTKit for the sysctl register block.  We incorrectly implemented the
SSE-200 with the same PID values as IoTKit.  Fix the SSE-200 bug and
report these register values for SSE-300.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-19-peter.maydell@linaro.org
---
 hw/misc/iotkit-sysctl.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
index aa8c49d9b6b..9ee8fe8495c 100644
--- a/hw/misc/iotkit-sysctl.c
+++ b/hw/misc/iotkit-sysctl.c
@@ -75,12 +75,19 @@ REG32(CID2, 0xff8)
 REG32(CID3, 0xffc)
 
 /* PID/CID values */
-static const int sysctl_id[] = {
+static const int iotkit_sysctl_id[] = {
     0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
     0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
     0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
 };
 
+/* Also used by the SSE300 */
+static const int sse200_sysctl_id[] = {
+    0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+    0x54, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
+    0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
 /*
  * Set the initial secure vector table offset address for the core.
  * This will take effect when the CPU next resets.
@@ -328,7 +335,17 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
         }
         break;
     case A_PID4 ... A_CID3:
-        r = sysctl_id[(offset - A_PID4) / 4];
+        switch (s->sse_version) {
+        case ARMSSE_IOTKIT:
+            r = iotkit_sysctl_id[(offset - A_PID4) / 4];
+            break;
+        case ARMSSE_SSE200:
+        case ARMSSE_SSE300:
+            r = sse200_sysctl_id[(offset - A_PID4) / 4];
+            break;
+        default:
+            g_assert_not_reached();
+        }
         break;
     case A_SECDBGSET:
     case A_SECDBGCLR:
-- 
2.20.1



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

* [PULL 19/54] hw/arm/Kconfig: Move ARMSSE_CPUID and ARMSSE_MHU stanzas to hw/misc
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (17 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 18/54] hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 20/54] hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block Peter Maydell
                   ` (35 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The ARMSSE_CPUID and ARMSSE_MHU Kconfig stanzas are for the devices
implemented by hw/misc/cpuid.c and hw/misc/armsse-mhu.c.  Move them
to hw/misc/Kconfig where they belong.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-20-peter.maydell@linaro.org
---
 hw/arm/Kconfig  | 6 ------
 hw/misc/Kconfig | 6 ++++++
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 5b3bd1e866b..69a550a0fcd 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -522,9 +522,3 @@ config ARMSSE
     select UNIMP
     select SSE_COUNTER
     select SSE_TIMER
-
-config ARMSSE_CPUID
-    bool
-
-config ARMSSE_MHU
-    bool
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 19c216f3efb..16b96e4dafb 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -2,6 +2,12 @@ config APPLESMC
     bool
     depends on ISA_BUS
 
+config ARMSSE_CPUID
+    bool
+
+config ARMSSE_MHU
+    bool
+
 config MAX111X
     bool
 
-- 
2.20.1



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

* [PULL 20/54] hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (18 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 19/54] hw/arm/Kconfig: Move ARMSSE_CPUID and ARMSSE_MHU stanzas to hw/misc Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 21/54] hw/arm/armsse: Use an array for apb_ppc fields in the state structure Peter Maydell
                   ` (34 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-300 has a new register block CPU<N>_PWRCTRL.  There is one
instance of this per CPU in the system (so just one for the SSE-300),
and as well as the usual CIDR/PIDR ID registers it has just one
register, CPUPWRCFG.  This register allows the guest to configure
behaviour of the system in power-down and deep-sleep states.  Since
QEMU does not model those, we make the register a dummy
reads-as-written implementation.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-21-peter.maydell@linaro.org
---
 include/hw/misc/armsse-cpu-pwrctrl.h |  40 +++++++
 hw/misc/armsse-cpu-pwrctrl.c         | 149 +++++++++++++++++++++++++++
 MAINTAINERS                          |   2 +
 hw/arm/Kconfig                       |   1 +
 hw/misc/Kconfig                      |   3 +
 hw/misc/meson.build                  |   1 +
 hw/misc/trace-events                 |   4 +
 7 files changed, 200 insertions(+)
 create mode 100644 include/hw/misc/armsse-cpu-pwrctrl.h
 create mode 100644 hw/misc/armsse-cpu-pwrctrl.c

diff --git a/include/hw/misc/armsse-cpu-pwrctrl.h b/include/hw/misc/armsse-cpu-pwrctrl.h
new file mode 100644
index 00000000000..51d45ede7db
--- /dev/null
+++ b/include/hw/misc/armsse-cpu-pwrctrl.h
@@ -0,0 +1,40 @@
+/*
+ * ARM SSE CPU PWRCTRL register block
+ *
+ * Copyright (c) 2021 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<N>_PWRCTRL block" which is part of the
+ * Arm Corstone SSE-300 Example Subsystem and documented in
+ * https://developer.arm.com/documentation/101773/0000
+ *
+ * QEMU interface:
+ *  + sysbus MMIO region 0: the register bank
+ */
+
+#ifndef HW_MISC_ARMSSE_CPU_PWRCTRL_H
+#define HW_MISC_ARMSSE_CPU_PWRCTRL_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_ARMSSE_CPU_PWRCTRL "armsse-cpu-pwrctrl"
+OBJECT_DECLARE_SIMPLE_TYPE(ARMSSECPUPwrCtrl, ARMSSE_CPU_PWRCTRL)
+
+struct ARMSSECPUPwrCtrl {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    MemoryRegion iomem;
+
+    uint32_t cpupwrcfg;
+};
+
+#endif
diff --git a/hw/misc/armsse-cpu-pwrctrl.c b/hw/misc/armsse-cpu-pwrctrl.c
new file mode 100644
index 00000000000..42fc38879f2
--- /dev/null
+++ b/hw/misc/armsse-cpu-pwrctrl.c
@@ -0,0 +1,149 @@
+/*
+ * Arm SSE CPU PWRCTRL register block
+ *
+ * Copyright (c) 2021 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<N>_PWRCTRL block" which is part of the
+ * Arm Corstone SSE-300 Example Subsystem and documented in
+ * https://developer.arm.com/documentation/101773/0000
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+#include "qapi/error.h"
+#include "migration/vmstate.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/misc/armsse-cpu-pwrctrl.h"
+
+REG32(CPUPWRCFG, 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 cpu_pwrctrl_id[] = {
+    0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
+    0x5a, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
+    0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
+};
+
+static uint64_t pwrctrl_read(void *opaque, hwaddr offset, unsigned size)
+{
+    ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(opaque);
+    uint64_t r;
+
+    switch (offset) {
+    case A_CPUPWRCFG:
+        r = s->cpupwrcfg;
+        break;
+    case A_PID4 ... A_CID3:
+        r = cpu_pwrctrl_id[(offset - A_PID4) / 4];
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE CPU_PWRCTRL read: bad offset %x\n", (int)offset);
+        r = 0;
+        break;
+    }
+    trace_armsse_cpu_pwrctrl_read(offset, r, size);
+    return r;
+}
+
+static void pwrctrl_write(void *opaque, hwaddr offset,
+                          uint64_t value, unsigned size)
+{
+    ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(opaque);
+
+    trace_armsse_cpu_pwrctrl_write(offset, value, size);
+
+    switch (offset) {
+    case A_CPUPWRCFG:
+        qemu_log_mask(LOG_UNIMP,
+                      "SSE CPU_PWRCTRL: CPUPWRCFG unimplemented\n");
+        s->cpupwrcfg = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "SSE CPU_PWRCTRL write: bad offset 0x%x\n", (int)offset);
+        break;
+    }
+}
+
+static const MemoryRegionOps pwrctrl_ops = {
+    .read = pwrctrl_read,
+    .write = pwrctrl_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+};
+
+static void pwrctrl_reset(DeviceState *dev)
+{
+    ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(dev);
+
+    s->cpupwrcfg = 0;
+}
+
+static const VMStateDescription pwrctrl_vmstate = {
+    .name = "armsse-cpu-pwrctrl",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(cpupwrcfg, ARMSSECPUPwrCtrl),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static void pwrctrl_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    ARMSSECPUPwrCtrl *s = ARMSSE_CPU_PWRCTRL(obj);
+
+    memory_region_init_io(&s->iomem, obj, &pwrctrl_ops,
+                          s, "armsse-cpu-pwrctrl", 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void pwrctrl_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = pwrctrl_reset;
+    dc->vmsd = &pwrctrl_vmstate;
+}
+
+static const TypeInfo pwrctrl_info = {
+    .name = TYPE_ARMSSE_CPU_PWRCTRL,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(ARMSSECPUPwrCtrl),
+    .instance_init = pwrctrl_init,
+    .class_init = pwrctrl_class_init,
+};
+
+static void pwrctrl_register_types(void)
+{
+    type_register_static(&pwrctrl_info);
+}
+
+type_init(pwrctrl_register_types);
diff --git a/MAINTAINERS b/MAINTAINERS
index ea206fc900e..bd863cfeca4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -747,6 +747,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-cpu-pwrctrl.c
+F: include/hw/misc/armsse-cpu-pwrctrl.h
 F: hw/misc/armsse-cpuid.c
 F: include/hw/misc/armsse-cpuid.h
 F: hw/misc/armsse-mhu.c
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 69a550a0fcd..f2b7a8fc0b0 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -505,6 +505,7 @@ config ARM11MPCORE
 config ARMSSE
     bool
     select ARM_V7M
+    select ARMSSE_CPU_PWRCTRL
     select ARMSSE_CPUID
     select ARMSSE_MHU
     select CMSDK_APB_TIMER
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 16b96e4dafb..5426b9b1a1a 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -8,6 +8,9 @@ config ARMSSE_CPUID
 config ARMSSE_MHU
     bool
 
+config ARMSSE_CPU_PWRCTRL
+    bool
+
 config MAX111X
     bool
 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 629283957fc..e30a555db5c 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -96,6 +96,7 @@ softmmu_ss.add(when: 'CONFIG_TZ_MSC', if_true: files('tz-msc.c'))
 softmmu_ss.add(when: 'CONFIG_TZ_PPC', if_true: files('tz-ppc.c'))
 softmmu_ss.add(when: 'CONFIG_IOTKIT_SECCTL', if_true: files('iotkit-secctl.c'))
 softmmu_ss.add(when: 'CONFIG_IOTKIT_SYSINFO', if_true: files('iotkit-sysinfo.c'))
+softmmu_ss.add(when: 'CONFIG_ARMSSE_CPU_PWRCTRL', if_true: files('armsse-cpu-pwrctrl.c'))
 softmmu_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
 softmmu_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
 
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index d626b9d7a7c..4b15db8ca48 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -186,6 +186,10 @@ iotkit_sysctl_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit SysCtl
 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"
 
+# armsse-cpu-pwrctrl.c
+armsse_cpu_pwrctrl_read(uint64_t offset, uint64_t data, unsigned size) "SSE-300 CPU_PWRCTRL read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+armsse_cpu_pwrctrl_write(uint64_t offset, uint64_t data, unsigned size) "SSE-300 CPU_PWRCTRL write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+
 # 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] 58+ messages in thread

* [PULL 21/54] hw/arm/armsse: Use an array for apb_ppc fields in the state structure
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (19 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 20/54] hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 22/54] hw/arm/armsse: Add a define for number of IRQs used by the SSE itself Peter Maydell
                   ` (33 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Convert the apb_ppc0 and apb_ppc1 fields in the ARMSSE state struct
to use an array instead of two separate fields.  We already had one
place in the code that wanted to be able to refer to the PPC by
index, and we're about to add more code like that.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-22-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  6 +++---
 hw/arm/armsse.c         | 32 ++++++++++++++++++--------------
 2 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 09284ca75cf..771150b0a94 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -124,8 +124,9 @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
 /* We have an IRQ splitter and an OR gate input for each external PPC
  * and the 2 internal PPCs
  */
+#define NUM_INTERNAL_PPCS 2
 #define NUM_EXTERNAL_PPCS (IOTS_NUM_AHB_EXP_PPC + IOTS_NUM_APB_EXP_PPC)
-#define NUM_PPCS (NUM_EXTERNAL_PPCS + 2)
+#define NUM_PPCS (NUM_EXTERNAL_PPCS + NUM_INTERNAL_PPCS)
 
 #define MAX_SRAM_BANKS 4
 #if MAX_SRAM_BANKS > IOTS_NUM_MPC
@@ -152,8 +153,7 @@ struct ARMSSE {
     ARMv7MState armv7m[SSE_MAX_CPUS];
     CPUClusterState cluster[SSE_MAX_CPUS];
     IoTKitSecCtl secctl;
-    TZPPC apb_ppc0;
-    TZPPC apb_ppc1;
+    TZPPC apb_ppc[NUM_INTERNAL_PPCS];
     TZMPC mpc[IOTS_NUM_MPC];
     CMSDKAPBTimer timer0;
     CMSDKAPBTimer timer1;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 326e161c8d4..2b25fca1ca2 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -291,8 +291,12 @@ static void armsse_init(Object *obj)
     }
 
     object_initialize_child(obj, "secctl", &s->secctl, TYPE_IOTKIT_SECCTL);
-    object_initialize_child(obj, "apb-ppc0", &s->apb_ppc0, TYPE_TZ_PPC);
-    object_initialize_child(obj, "apb-ppc1", &s->apb_ppc1, TYPE_TZ_PPC);
+
+    for (i = 0; i < ARRAY_SIZE(s->apb_ppc); i++) {
+        g_autofree char *name = g_strdup_printf("apb-ppc%d", i);
+        object_initialize_child(obj, name, &s->apb_ppc[i], TYPE_TZ_PPC);
+    }
+
     for (i = 0; i < info->sram_banks; i++) {
         char *name = g_strdup_printf("mpc%d", i);
         object_initialize_child(obj, name, &s->mpc[i], TYPE_TZ_MPC);
@@ -739,7 +743,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
                        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), "port[0]", OBJECT(mr),
+    object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[0]", OBJECT(mr),
                              &error_abort);
 
     qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
@@ -749,7 +753,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
                        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), "port[1]", OBJECT(mr),
+    object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[1]", OBJECT(mr),
                              &error_abort);
 
     qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
@@ -759,7 +763,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
                        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), "port[2]", OBJECT(mr),
+    object_property_set_link(OBJECT(&s->apb_ppc[0]), "port[2]", OBJECT(mr),
                              &error_abort);
 
     if (info->has_mhus) {
@@ -782,7 +786,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
             }
             port = g_strdup_printf("port[%d]", i + 3);
             mr = sysbus_mmio_get_region(mhu_sbd, 0);
-            object_property_set_link(OBJECT(&s->apb_ppc0), port, OBJECT(mr),
+            object_property_set_link(OBJECT(&s->apb_ppc[0]), port, OBJECT(mr),
                                      &error_abort);
             g_free(port);
 
@@ -802,12 +806,12 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         }
     }
 
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc0), errp)) {
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[0]), errp)) {
         return;
     }
 
-    sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc0);
-    dev_apb_ppc0 = DEVICE(&s->apb_ppc0);
+    sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
+    dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
 
     mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
     memory_region_add_subregion(&s->container, 0x40000000, mr);
@@ -917,16 +921,16 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
                        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), "port[0]", OBJECT(mr),
+    object_property_set_link(OBJECT(&s->apb_ppc[1]), "port[0]", OBJECT(mr),
                              &error_abort);
 
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc1), errp)) {
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
         return;
     }
-    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc1), 0);
+    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc[1]), 0);
     memory_region_add_subregion(&s->container, 0x4002f000, mr);
 
-    dev_apb_ppc1 = DEVICE(&s->apb_ppc1);
+    dev_apb_ppc1 = DEVICE(&s->apb_ppc[1]);
     qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
                                 qdev_get_gpio_in_named(dev_apb_ppc1,
                                                        "cfg_nonsec", 0));
@@ -1063,7 +1067,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         DeviceState *devs = DEVICE(&s->ppc_irq_splitter[i]);
         char *gpioname = g_strdup_printf("apb_ppc%d_irq_status",
                                          i - NUM_EXTERNAL_PPCS);
-        TZPPC *ppc = (i == NUM_EXTERNAL_PPCS) ? &s->apb_ppc0 : &s->apb_ppc1;
+        TZPPC *ppc = &s->apb_ppc[i - NUM_EXTERNAL_PPCS];
 
         qdev_connect_gpio_out(devs, 0,
                               qdev_get_gpio_in_named(dev_secctl, gpioname, 0));
-- 
2.20.1



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

* [PULL 22/54] hw/arm/armsse: Add a define for number of IRQs used by the SSE itself
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (20 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 21/54] hw/arm/armsse: Use an array for apb_ppc fields in the state structure Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 23/54] hw/arm/armsse: Add framework for data-driven device placement Peter Maydell
                   ` (32 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE uses 32 interrupts for its own devices, and then passes through
its expansion IRQ inputs to the CPU's interrupts 33 and upward.
Add a define for the number of IRQs the SSE uses for itself, instead
of hardcoding 32.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-23-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h | 5 ++++-
 hw/arm/armsse.c         | 4 ++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 771150b0a94..e34263fed8b 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -145,6 +145,9 @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
 #define RAM3_PPU 6
 #define NUM_PPUS 7
 
+/* Number of CPU IRQs used by the SSE itself */
+#define NUM_SSE_IRQS 32
+
 struct ARMSSE {
     /*< private >*/
     SysBusDevice parent_obj;
@@ -165,7 +168,7 @@ struct ARMSSE {
     qemu_or_irq mpc_irq_orgate;
     qemu_or_irq nmi_orgate;
 
-    SplitIRQ cpu_irq_splitter[32];
+    SplitIRQ cpu_irq_splitter[NUM_SSE_IRQS];
 
     CMSDKAPBDualTimer dualtimer;
 
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 2b25fca1ca2..5ae6ce344ee 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -531,7 +531,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         int j;
         char *gpioname;
 
-        qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + 32);
+        qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + NUM_SSE_IRQS);
         /*
          * In real hardware the initial Secure VTOR is set from the INITSVTOR*
          * registers in the IoT Kit System Control Register block. In QEMU
@@ -602,7 +602,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         /* 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, j + 32);
+            s->exp_irqs[i][j] = qdev_get_gpio_in(cpudev, j + NUM_SSE_IRQS);
         }
         if (i == 0) {
             gpioname = g_strdup("EXP_IRQ");
-- 
2.20.1



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

* [PULL 23/54] hw/arm/armsse: Add framework for data-driven device placement
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (21 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 22/54] hw/arm/armsse: Add a define for number of IRQs used by the SSE itself Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 24/54] hw/arm/armsse: Move dual-timer device into data-driven framework Peter Maydell
                   ` (31 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-300 is mostly the same as the SSE-200, but it has moved some
of the devices in the memory map and uses different device types in
some cases.  To accommodate this, add a framework where the placement
and wiring of some devices can be specified in a data table.

This commit adds the framework for this data-driven device placement,
and makes the CMSDK APB timer devices use it.  Subsequent commits
will convert the other devices which differ between SSE-200 and
SSE-300.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-24-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |   3 +-
 hw/arm/armsse.c         | 147 +++++++++++++++++++++++++++++++++-------
 2 files changed, 125 insertions(+), 25 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index e34263fed8b..c1f4df295a4 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -158,8 +158,7 @@ struct ARMSSE {
     IoTKitSecCtl secctl;
     TZPPC apb_ppc[NUM_INTERNAL_PPCS];
     TZMPC mpc[IOTS_NUM_MPC];
-    CMSDKAPBTimer timer0;
-    CMSDKAPBTimer timer1;
+    CMSDKAPBTimer timer[2];
     CMSDKAPBTimer s32ktimer;
     qemu_or_irq ppc_irq_orgate;
     SplitIRQ sec_resp_splitter;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 5ae6ce344ee..22dd437a4ba 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -24,6 +24,27 @@
 #include "hw/irq.h"
 #include "hw/qdev-clock.h"
 
+/*
+ * The SSE-300 puts some devices in different places to the
+ * SSE-200 (and original IoTKit). We use an array of these structs
+ * to define how each variant lays out these devices. (Parts of the
+ * SoC that are the same for all variants aren't handled via these
+ * data structures.)
+ */
+
+#define NO_IRQ -1
+#define NO_PPC -1
+
+typedef struct ARMSSEDeviceInfo {
+    const char *name; /* name to use for the QOM object; NULL terminates list */
+    const char *type; /* QOM type name */
+    unsigned int index; /* Which of the N devices of this type is this ? */
+    hwaddr addr;
+    int ppc; /* Index of APB PPC this device is wired up to, or NO_PPC */
+    int ppc_port; /* Port number of this device on the PPC */
+    int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1 */
+} ARMSSEDeviceInfo;
+
 struct ARMSSEInfo {
     const char *name;
     uint32_t sse_version;
@@ -38,6 +59,7 @@ struct ARMSSEInfo {
     bool has_cpusecctrl;
     bool has_cpuid;
     Property *props;
+    const ARMSSEDeviceInfo *devinfo;
 };
 
 static Property iotkit_properties[] = {
@@ -64,6 +86,30 @@ static Property armsse_properties[] = {
     DEFINE_PROP_END_OF_LIST()
 };
 
+static const ARMSSEDeviceInfo sse200_devices[] = {
+    {
+        .name = "timer0",
+        .type = TYPE_CMSDK_APB_TIMER,
+        .index = 0,
+        .addr = 0x40000000,
+        .ppc = 0,
+        .ppc_port = 0,
+        .irq = 3,
+    },
+    {
+        .name = "timer1",
+        .type = TYPE_CMSDK_APB_TIMER,
+        .index = 1,
+        .addr = 0x40001000,
+        .ppc = 0,
+        .ppc_port = 1,
+        .irq = 4,
+    },
+    {
+        .name = NULL,
+    }
+};
+
 static const ARMSSEInfo armsse_variants[] = {
     {
         .name = TYPE_IOTKIT,
@@ -79,6 +125,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_cpusecctrl = false,
         .has_cpuid = false,
         .props = iotkit_properties,
+        .devinfo = sse200_devices,
     },
     {
         .name = TYPE_SSE200,
@@ -94,6 +141,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_cpusecctrl = true,
         .has_cpuid = true,
         .props = armsse_properties,
+        .devinfo = sse200_devices,
     },
 };
 
@@ -250,6 +298,7 @@ static void armsse_init(Object *obj)
     ARMSSE *s = ARM_SSE(obj);
     ARMSSEClass *asc = ARM_SSE_GET_CLASS(obj);
     const ARMSSEInfo *info = asc->info;
+    const ARMSSEDeviceInfo *devinfo;
     int i;
 
     assert(info->sram_banks <= MAX_SRAM_BANKS);
@@ -290,6 +339,18 @@ static void armsse_init(Object *obj)
         }
     }
 
+    for (devinfo = info->devinfo; devinfo->name; devinfo++) {
+        assert(devinfo->ppc == NO_PPC || devinfo->ppc < ARRAY_SIZE(s->apb_ppc));
+        if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
+            assert(devinfo->index < ARRAY_SIZE(s->timer));
+            object_initialize_child(obj, devinfo->name,
+                                    &s->timer[devinfo->index],
+                                    TYPE_CMSDK_APB_TIMER);
+        } else {
+            g_assert_not_reached();
+        }
+    }
+
     object_initialize_child(obj, "secctl", &s->secctl, TYPE_IOTKIT_SECCTL);
 
     for (i = 0; i < ARRAY_SIZE(s->apb_ppc); i++) {
@@ -312,8 +373,6 @@ static void armsse_init(Object *obj)
         object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
         g_free(name);
     }
-    object_initialize_child(obj, "timer0", &s->timer0, TYPE_CMSDK_APB_TIMER);
-    object_initialize_child(obj, "timer1", &s->timer1, TYPE_CMSDK_APB_TIMER);
     object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
                             TYPE_CMSDK_APB_TIMER);
     object_initialize_child(obj, "dualtimer", &s->dualtimer,
@@ -453,6 +512,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     ARMSSE *s = ARM_SSE(dev);
     ARMSSEClass *asc = ARM_SSE_GET_CLASS(dev);
     const ARMSSEInfo *info = asc->info;
+    const ARMSSEDeviceInfo *devinfo;
     int i;
     MemoryRegion *mr;
     Error *err = NULL;
@@ -736,25 +796,53 @@ static void armsse_realize(DeviceState *dev, Error **errp)
      * it to the appropriate PPC port; then we can realize the PPC and
      * map its upstream ends to the right place in the container.
      */
-    qdev_connect_clock_in(DEVICE(&s->timer0), "pclk", s->mainclk);
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer0), errp)) {
-        return;
-    }
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer0), 0,
-                       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_ppc[0]), "port[0]", OBJECT(mr),
-                             &error_abort);
+    for (devinfo = info->devinfo; devinfo->name; devinfo++) {
+        SysBusDevice *sbd;
+        qemu_irq irq;
 
-    qdev_connect_clock_in(DEVICE(&s->timer1), "pclk", s->mainclk);
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer1), errp)) {
-        return;
+        if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
+            sbd = SYS_BUS_DEVICE(&s->timer[devinfo->index]);
+
+            qdev_connect_clock_in(DEVICE(sbd), "pclk", s->mainclk);
+            if (!sysbus_realize(sbd, errp)) {
+                return;
+            }
+            mr = sysbus_mmio_get_region(sbd, 0);
+        } else {
+            g_assert_not_reached();
+        }
+
+        switch (devinfo->irq) {
+        case NO_IRQ:
+            irq = NULL;
+            break;
+        case 0 ... NUM_SSE_IRQS - 1:
+            irq = armsse_get_common_irq_in(s, devinfo->irq);
+            break;
+        default:
+            g_assert_not_reached();
+        }
+
+        if (irq) {
+            sysbus_connect_irq(sbd, 0, irq);
+        }
+
+        /*
+         * Devices connected to a PPC are connected to the port here;
+         * we will map the upstream end of that port to the right address
+         * in the container later after the PPC has been realized.
+         * Devices not connected to a PPC can be mapped immediately.
+         */
+        if (devinfo->ppc != NO_PPC) {
+            TZPPC *ppc = &s->apb_ppc[devinfo->ppc];
+            g_autofree char *portname = g_strdup_printf("port[%d]",
+                                                        devinfo->ppc_port);
+            object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
+                                     &error_abort);
+        } else {
+            memory_region_add_subregion(&s->container, devinfo->addr, mr);
+        }
     }
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer1), 0,
-                       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_ppc[0]), "port[1]", OBJECT(mr),
-                             &error_abort);
 
     qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
@@ -813,10 +901,6 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
     dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
 
-    mr = sysbus_mmio_get_region(sbd_apb_ppc0, 0);
-    memory_region_add_subregion(&s->container, 0x40000000, mr);
-    mr = sysbus_mmio_get_region(sbd_apb_ppc0, 1);
-    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) {
@@ -947,6 +1031,23 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                           qdev_get_gpio_in_named(dev_apb_ppc1,
                                                  "cfg_sec_resp", 0));
 
+    /*
+     * Now both PPCs are realized we can map the upstream ends of
+     * ports which correspond to entries in the devinfo array.
+     * The ports which are connected to non-devinfo devices have
+     * already been mapped.
+     */
+    for (devinfo = info->devinfo; devinfo->name; devinfo++) {
+        SysBusDevice *ppc_sbd;
+
+        if (devinfo->ppc == NO_PPC) {
+            continue;
+        }
+        ppc_sbd = SYS_BUS_DEVICE(&s->apb_ppc[devinfo->ppc]);
+        mr = sysbus_mmio_get_region(ppc_sbd, devinfo->ppc_port);
+        memory_region_add_subregion(&s->container, devinfo->addr, mr);
+    }
+
     if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
                                  info->sys_version, errp)) {
         return;
-- 
2.20.1



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

* [PULL 24/54] hw/arm/armsse: Move dual-timer device into data-driven framework
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (22 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 23/54] hw/arm/armsse: Add framework for data-driven device placement Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 25/54] hw/arm/armsse: Move watchdogs " Peter Maydell
                   ` (30 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Move the CMSDK dualtimer device handling into the data-driven
device placement framework.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-25-peter.maydell@linaro.org
---
 hw/arm/armsse.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 22dd437a4ba..f8da7fb00f9 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -105,6 +105,15 @@ static const ARMSSEDeviceInfo sse200_devices[] = {
         .ppc_port = 1,
         .irq = 4,
     },
+    {
+        .name = "dualtimer",
+        .type = TYPE_CMSDK_APB_DUALTIMER,
+        .index = 0,
+        .addr = 0x40002000,
+        .ppc = 0,
+        .ppc_port = 2,
+        .irq = 5,
+    },
     {
         .name = NULL,
     }
@@ -346,6 +355,10 @@ static void armsse_init(Object *obj)
             object_initialize_child(obj, devinfo->name,
                                     &s->timer[devinfo->index],
                                     TYPE_CMSDK_APB_TIMER);
+        } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
+            assert(devinfo->index == 0);
+            object_initialize_child(obj, devinfo->name, &s->dualtimer,
+                                    TYPE_CMSDK_APB_DUALTIMER);
         } else {
             g_assert_not_reached();
         }
@@ -375,8 +388,6 @@ static void armsse_init(Object *obj)
     }
     object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
                             TYPE_CMSDK_APB_TIMER);
-    object_initialize_child(obj, "dualtimer", &s->dualtimer,
-                            TYPE_CMSDK_APB_DUALTIMER);
     object_initialize_child(obj, "s32kwatchdog", &s->s32kwatchdog,
                             TYPE_CMSDK_APB_WATCHDOG);
     object_initialize_child(obj, "nswatchdog", &s->nswatchdog,
@@ -808,6 +819,14 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                 return;
             }
             mr = sysbus_mmio_get_region(sbd, 0);
+        } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_DUALTIMER)) {
+            sbd = SYS_BUS_DEVICE(&s->dualtimer);
+
+            qdev_connect_clock_in(DEVICE(sbd), "TIMCLK", s->mainclk);
+            if (!sysbus_realize(sbd, errp)) {
+                return;
+            }
+            mr = sysbus_mmio_get_region(sbd, 0);
         } else {
             g_assert_not_reached();
         }
@@ -844,16 +863,6 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         }
     }
 
-    qdev_connect_clock_in(DEVICE(&s->dualtimer), "TIMCLK", s->mainclk);
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->dualtimer), errp)) {
-        return;
-    }
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->dualtimer), 0,
-                       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_ppc[0]), "port[2]", OBJECT(mr),
-                             &error_abort);
-
     if (info->has_mhus) {
         /*
          * An SSE-200 with only one CPU should have only one MHU created,
@@ -901,8 +910,6 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     sbd_apb_ppc0 = SYS_BUS_DEVICE(&s->apb_ppc[0]);
     dev_apb_ppc0 = DEVICE(&s->apb_ppc[0]);
 
-    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);
-- 
2.20.1



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

* [PULL 25/54] hw/arm/armsse: Move watchdogs into data-driven framework
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (23 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 24/54] hw/arm/armsse: Move dual-timer device into data-driven framework Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 26/54] hw/arm/armsse: Move s32ktimer " Peter Maydell
                   ` (29 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Move the CMSDK watchdog device handling into the data-driven device
placement framework.  This is slightly more complicated because these
devices might wire their IRQs up to the NMI line, and because one of
them uses the slow 32KHz clock rather than the main clock.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-26-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |   4 +-
 hw/arm/armsse.c         | 109 ++++++++++++++++++++++++----------------
 2 files changed, 66 insertions(+), 47 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index c1f4df295a4..3f8f3750577 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -171,9 +171,7 @@ struct ARMSSE {
 
     CMSDKAPBDualTimer dualtimer;
 
-    CMSDKAPBWatchdog s32kwatchdog;
-    CMSDKAPBWatchdog nswatchdog;
-    CMSDKAPBWatchdog swatchdog;
+    CMSDKAPBWatchdog cmsdk_watchdog[3];
 
     IoTKitSysCtl sysctl;
     IoTKitSysCtl sysinfo;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index f8da7fb00f9..6540ffb919b 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -34,6 +34,13 @@
 
 #define NO_IRQ -1
 #define NO_PPC -1
+/*
+ * Special values for ARMSSEDeviceInfo::irq to indicate that this
+ * device uses one of the inputs to the OR gate that feeds into the
+ * CPU NMI input.
+ */
+#define NMI_0 10000
+#define NMI_1 10001
 
 typedef struct ARMSSEDeviceInfo {
     const char *name; /* name to use for the QOM object; NULL terminates list */
@@ -42,7 +49,8 @@ typedef struct ARMSSEDeviceInfo {
     hwaddr addr;
     int ppc; /* Index of APB PPC this device is wired up to, or NO_PPC */
     int ppc_port; /* Port number of this device on the PPC */
-    int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1 */
+    int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1, or NMI_0 or NMI_1 */
+    bool slowclk; /* true if device uses the slow 32KHz clock */
 } ARMSSEDeviceInfo;
 
 struct ARMSSEInfo {
@@ -114,6 +122,31 @@ static const ARMSSEDeviceInfo sse200_devices[] = {
         .ppc_port = 2,
         .irq = 5,
     },
+    {
+        .name = "s32kwatchdog",
+        .type = TYPE_CMSDK_APB_WATCHDOG,
+        .index = 0,
+        .addr = 0x5002e000,
+        .ppc = NO_PPC,
+        .irq = NMI_0,
+        .slowclk = true,
+    },
+    {
+        .name = "nswatchdog",
+        .type = TYPE_CMSDK_APB_WATCHDOG,
+        .index = 1,
+        .addr = 0x40081000,
+        .ppc = NO_PPC,
+        .irq = 1,
+    },
+    {
+        .name = "swatchdog",
+        .type = TYPE_CMSDK_APB_WATCHDOG,
+        .index = 2,
+        .addr = 0x50081000,
+        .ppc = NO_PPC,
+        .irq = NMI_1,
+    },
     {
         .name = NULL,
     }
@@ -359,6 +392,11 @@ static void armsse_init(Object *obj)
             assert(devinfo->index == 0);
             object_initialize_child(obj, devinfo->name, &s->dualtimer,
                                     TYPE_CMSDK_APB_DUALTIMER);
+        } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
+            assert(devinfo->index < ARRAY_SIZE(s->cmsdk_watchdog));
+            object_initialize_child(obj, devinfo->name,
+                                    &s->cmsdk_watchdog[devinfo->index],
+                                    TYPE_CMSDK_APB_WATCHDOG);
         } else {
             g_assert_not_reached();
         }
@@ -386,14 +424,9 @@ static void armsse_init(Object *obj)
         object_initialize_child(obj, name, splitter, TYPE_SPLIT_IRQ);
         g_free(name);
     }
+
     object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
                             TYPE_CMSDK_APB_TIMER);
-    object_initialize_child(obj, "s32kwatchdog", &s->s32kwatchdog,
-                            TYPE_CMSDK_APB_WATCHDOG);
-    object_initialize_child(obj, "nswatchdog", &s->nswatchdog,
-                            TYPE_CMSDK_APB_WATCHDOG);
-    object_initialize_child(obj, "swatchdog", &s->swatchdog,
-                            TYPE_CMSDK_APB_WATCHDOG);
     object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
                             TYPE_IOTKIT_SYSCTL);
     object_initialize_child(obj, "armsse-sysinfo", &s->sysinfo,
@@ -797,6 +830,17 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
                           armsse_get_common_irq_in(s, 9));
 
+    /* This OR gate wires together outputs from the secure watchdogs to NMI */
+    if (!object_property_set_int(OBJECT(&s->nmi_orgate), "num-lines", 2,
+                                 errp)) {
+        return;
+    }
+    if (!qdev_realize(DEVICE(&s->nmi_orgate), NULL, errp)) {
+        return;
+    }
+    qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
+                          qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
+
     /* Devices behind APB PPC0:
      *   0x40000000: timer0
      *   0x40001000: timer1
@@ -827,6 +871,15 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                 return;
             }
             mr = sysbus_mmio_get_region(sbd, 0);
+        } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
+            sbd = SYS_BUS_DEVICE(&s->cmsdk_watchdog[devinfo->index]);
+
+            qdev_connect_clock_in(DEVICE(sbd), "WDOGCLK",
+                                  devinfo->slowclk ? s->s32kclk : s->mainclk);
+            if (!sysbus_realize(sbd, errp)) {
+                return;
+            }
+            mr = sysbus_mmio_get_region(sbd, 0);
         } else {
             g_assert_not_reached();
         }
@@ -838,6 +891,11 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         case 0 ... NUM_SSE_IRQS - 1:
             irq = armsse_get_common_irq_in(s, devinfo->irq);
             break;
+        case NMI_0:
+        case NMI_1:
+            irq = qdev_get_gpio_in(DEVICE(&s->nmi_orgate),
+                                   devinfo->irq - NMI_0);
+            break;
         default:
             g_assert_not_reached();
         }
@@ -1108,43 +1166,6 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         }
     }
 
-    /* This OR gate wires together outputs from the secure watchdogs to NMI */
-    if (!object_property_set_int(OBJECT(&s->nmi_orgate), "num-lines", 2,
-                                 errp)) {
-        return;
-    }
-    if (!qdev_realize(DEVICE(&s->nmi_orgate), NULL, errp)) {
-        return;
-    }
-    qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
-                          qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
-
-    qdev_connect_clock_in(DEVICE(&s->s32kwatchdog), "WDOGCLK", s->s32kclk);
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32kwatchdog), errp)) {
-        return;
-    }
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0,
-                       qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0));
-    sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000);
-
-    /* 0x40080000 .. 0x4008ffff : ARMSSE second Base peripheral region */
-
-    qdev_connect_clock_in(DEVICE(&s->nswatchdog), "WDOGCLK", s->mainclk);
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->nswatchdog), errp)) {
-        return;
-    }
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0,
-                       armsse_get_common_irq_in(s, 1));
-    sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000);
-
-    qdev_connect_clock_in(DEVICE(&s->swatchdog), "WDOGCLK", s->mainclk);
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->swatchdog), errp)) {
-        return;
-    }
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0,
-                       qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1));
-    sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000);
-
     for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
         Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
 
-- 
2.20.1



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

* [PULL 26/54] hw/arm/armsse: Move s32ktimer into data-driven framework
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (24 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 25/54] hw/arm/armsse: Move watchdogs " Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 27/54] hw/arm/armsse: Move sysinfo register block " Peter Maydell
                   ` (28 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Move the CMSDK timer that uses the S32K slow clock into the data-driven
device placement framework.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-27-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  3 +--
 hw/arm/armsse.c         | 31 ++++++++++++-------------------
 2 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 3f8f3750577..7416c08a802 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -158,8 +158,7 @@ struct ARMSSE {
     IoTKitSecCtl secctl;
     TZPPC apb_ppc[NUM_INTERNAL_PPCS];
     TZMPC mpc[IOTS_NUM_MPC];
-    CMSDKAPBTimer timer[2];
-    CMSDKAPBTimer s32ktimer;
+    CMSDKAPBTimer timer[3];
     qemu_or_irq ppc_irq_orgate;
     SplitIRQ sec_resp_splitter;
     SplitIRQ ppc_irq_splitter[NUM_PPCS];
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 6540ffb919b..3270362d599 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -113,6 +113,16 @@ static const ARMSSEDeviceInfo sse200_devices[] = {
         .ppc_port = 1,
         .irq = 4,
     },
+    {
+        .name = "s32ktimer",
+        .type = TYPE_CMSDK_APB_TIMER,
+        .index = 2,
+        .addr = 0x4002f000,
+        .ppc = 1,
+        .ppc_port = 0,
+        .irq = 2,
+        .slowclk = true,
+    },
     {
         .name = "dualtimer",
         .type = TYPE_CMSDK_APB_DUALTIMER,
@@ -425,8 +435,6 @@ static void armsse_init(Object *obj)
         g_free(name);
     }
 
-    object_initialize_child(obj, "s32ktimer", &s->s32ktimer,
-                            TYPE_CMSDK_APB_TIMER);
     object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
                             TYPE_IOTKIT_SYSCTL);
     object_initialize_child(obj, "armsse-sysinfo", &s->sysinfo,
@@ -858,7 +866,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         if (!strcmp(devinfo->type, TYPE_CMSDK_APB_TIMER)) {
             sbd = SYS_BUS_DEVICE(&s->timer[devinfo->index]);
 
-            qdev_connect_clock_in(DEVICE(sbd), "pclk", s->mainclk);
+            qdev_connect_clock_in(DEVICE(sbd), "pclk",
+                                  devinfo->slowclk ? s->s32kclk : s->mainclk);
             if (!sysbus_realize(sbd, errp)) {
                 return;
             }
@@ -1059,25 +1068,9 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         }
     }
 
-    /* 0x40020000 .. 0x4002ffff : ARMSSE system control peripheral region */
-    /* Devices behind APB PPC1:
-     *   0x4002f000: S32K timer
-     */
-    qdev_connect_clock_in(DEVICE(&s->s32ktimer), "pclk", s->s32kclk);
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->s32ktimer), errp)) {
-        return;
-    }
-    sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0,
-                       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_ppc[1]), "port[0]", OBJECT(mr),
-                             &error_abort);
-
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
         return;
     }
-    mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->apb_ppc[1]), 0);
-    memory_region_add_subregion(&s->container, 0x4002f000, mr);
 
     dev_apb_ppc1 = DEVICE(&s->apb_ppc[1]);
     qdev_connect_gpio_out_named(dev_secctl, "apb_ppc1_nonsec", 0,
-- 
2.20.1



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

* [PULL 27/54] hw/arm/armsse: Move sysinfo register block into data-driven framework
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (25 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 26/54] hw/arm/armsse: Move s32ktimer " Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 28/54] hw/arm/armsse: Move sysctl " Peter Maydell
                   ` (27 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Move the sysinfo register block into the data-driven framework.

While we are moving the code for configuring this device around,
regularize on using &error_abortw when setting the integer
properties: they are all simple DEFINE_PROP_UINT32 properties so the
setting can never fail.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-28-peter.maydell@linaro.org
---
 hw/arm/armsse.c | 47 ++++++++++++++++++++++++++++-------------------
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 3270362d599..91f30b1fdc4 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -157,6 +157,14 @@ static const ARMSSEDeviceInfo sse200_devices[] = {
         .ppc = NO_PPC,
         .irq = NMI_1,
     },
+    {
+        .name = "armsse-sysinfo",
+        .type = TYPE_IOTKIT_SYSINFO,
+        .index = 0,
+        .addr = 0x40020000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
     {
         .name = NULL,
     }
@@ -407,6 +415,10 @@ static void armsse_init(Object *obj)
             object_initialize_child(obj, devinfo->name,
                                     &s->cmsdk_watchdog[devinfo->index],
                                     TYPE_CMSDK_APB_WATCHDOG);
+        } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
+            assert(devinfo->index == 0);
+            object_initialize_child(obj, devinfo->name, &s->sysinfo,
+                                    TYPE_IOTKIT_SYSINFO);
         } else {
             g_assert_not_reached();
         }
@@ -437,8 +449,6 @@ static void armsse_init(Object *obj)
 
     object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
                             TYPE_IOTKIT_SYSCTL);
-    object_initialize_child(obj, "armsse-sysinfo", &s->sysinfo,
-                            TYPE_IOTKIT_SYSINFO);
     if (info->has_mhus) {
         object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
         object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
@@ -889,6 +899,22 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                 return;
             }
             mr = sysbus_mmio_get_region(sbd, 0);
+        } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSINFO)) {
+            sbd = SYS_BUS_DEVICE(&s->sysinfo);
+
+            object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
+                                    info->sys_version, &error_abort);
+            object_property_set_int(OBJECT(&s->sysinfo), "SYS_CONFIG",
+                                    armsse_sys_config_value(s, info),
+                                    &error_abort);
+            object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
+                                    info->sse_version, &error_abort);
+            object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
+                                    info->iidr, &error_abort);
+            if (!sysbus_realize(sbd, errp)) {
+                return;
+            }
+            mr = sysbus_mmio_get_region(sbd, 0);
         } else {
             g_assert_not_reached();
         }
@@ -1106,23 +1132,6 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         memory_region_add_subregion(&s->container, devinfo->addr, mr);
     }
 
-    if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_VERSION",
-                                 info->sys_version, errp)) {
-        return;
-    }
-    if (!object_property_set_int(OBJECT(&s->sysinfo), "SYS_CONFIG",
-                                 armsse_sys_config_value(s, info), errp)) {
-        return;
-    }
-    object_property_set_int(OBJECT(&s->sysinfo), "sse-version",
-                            info->sse_version, &error_abort);
-    object_property_set_int(OBJECT(&s->sysinfo), "IIDR",
-                            info->iidr, &error_abort);
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysinfo), errp)) {
-        return;
-    }
-    /* System information registers */
-    sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysinfo), 0, 0x40020000);
     /* System control registers */
     object_property_set_int(OBJECT(&s->sysctl), "sse-version",
                             info->sse_version, &error_abort);
-- 
2.20.1



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

* [PULL 28/54] hw/arm/armsse: Move sysctl register block into data-driven framework
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (26 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 27/54] hw/arm/armsse: Move sysinfo register block " Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 29/54] hw/arm/armsse: Move PPUs " Peter Maydell
                   ` (26 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Move the sysctl register block into the data-driven device placement
framework.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-29-peter.maydell@linaro.org
---
 hw/arm/armsse.c | 44 ++++++++++++++++++++++++++++----------------
 1 file changed, 28 insertions(+), 16 deletions(-)

diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 91f30b1fdc4..961b2d44137 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -165,6 +165,14 @@ static const ARMSSEDeviceInfo sse200_devices[] = {
         .ppc = NO_PPC,
         .irq = NO_IRQ,
     },
+    {
+        .name = "armsse-sysctl",
+        .type = TYPE_IOTKIT_SYSCTL,
+        .index = 0,
+        .addr = 0x50021000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
     {
         .name = NULL,
     }
@@ -419,6 +427,10 @@ static void armsse_init(Object *obj)
             assert(devinfo->index == 0);
             object_initialize_child(obj, devinfo->name, &s->sysinfo,
                                     TYPE_IOTKIT_SYSINFO);
+        } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
+            assert(devinfo->index == 0);
+            object_initialize_child(obj, devinfo->name, &s->sysctl,
+                                    TYPE_IOTKIT_SYSCTL);
         } else {
             g_assert_not_reached();
         }
@@ -447,8 +459,6 @@ static void armsse_init(Object *obj)
         g_free(name);
     }
 
-    object_initialize_child(obj, "armsse-sysctl", &s->sysctl,
-                            TYPE_IOTKIT_SYSCTL);
     if (info->has_mhus) {
         object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
         object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
@@ -915,6 +925,22 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                 return;
             }
             mr = sysbus_mmio_get_region(sbd, 0);
+        } else if (!strcmp(devinfo->type, TYPE_IOTKIT_SYSCTL)) {
+            /* System control registers */
+            sbd = SYS_BUS_DEVICE(&s->sysctl);
+
+            object_property_set_int(OBJECT(&s->sysctl), "sse-version",
+                                    info->sse_version, &error_abort);
+            object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
+                                    info->cpuwait_rst, &error_abort);
+            object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
+                                    s->init_svtor, &error_abort);
+            object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR1_RST",
+                                    s->init_svtor, &error_abort);
+            if (!sysbus_realize(sbd, errp)) {
+                return;
+            }
+            mr = sysbus_mmio_get_region(sbd, 0);
         } else {
             g_assert_not_reached();
         }
@@ -1132,20 +1158,6 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         memory_region_add_subregion(&s->container, devinfo->addr, mr);
     }
 
-    /* System control registers */
-    object_property_set_int(OBJECT(&s->sysctl), "sse-version",
-                            info->sse_version, &error_abort);
-    object_property_set_int(OBJECT(&s->sysctl), "CPUWAIT_RST",
-                            info->cpuwait_rst, &error_abort);
-    object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR0_RST",
-                            s->init_svtor, &error_abort);
-    object_property_set_int(OBJECT(&s->sysctl), "INITSVTOR1_RST",
-                            s->init_svtor, &error_abort);
-    if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysctl), errp)) {
-        return;
-    }
-    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++) {
-- 
2.20.1



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

* [PULL 29/54] hw/arm/armsse: Move PPUs into data-driven framework
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (27 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 28/54] hw/arm/armsse: Move sysctl " Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 30/54] hw/arm/armsse: Add missing SSE-200 SYS_PPU Peter Maydell
                   ` (25 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Move the PPUs into the data-driven device placement framework.
We don't implement them, so they are just TYPE_UNIMPLEMENTED stubs.

Because the SSE-200 and the IotKit diverge here (the IoTKit does
not have the PPUs) we need to separate out the ARMSSEDeviceInfo
for the two variants, and only add the PPUs to the SSE-200.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-30-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  10 +-
 hw/arm/armsse.c         | 222 +++++++++++++++++++++++++++++-----------
 2 files changed, 165 insertions(+), 67 deletions(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 7416c08a802..eb4e937173f 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -135,14 +135,6 @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
 
 #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
 
 /* Number of CPU IRQs used by the SSE itself */
@@ -176,7 +168,7 @@ struct ARMSSE {
     IoTKitSysCtl sysinfo;
 
     ARMSSEMHU mhu[2];
-    UnimplementedDeviceState ppu[NUM_PPUS];
+    UnimplementedDeviceState unimp[NUM_PPUS];
     UnimplementedDeviceState cachectrl[SSE_MAX_CPUS];
     UnimplementedDeviceState cpusecctrl[SSE_MAX_CPUS];
 
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 961b2d44137..f72d1adafea 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -47,6 +47,7 @@ typedef struct ARMSSEDeviceInfo {
     const char *type; /* QOM type name */
     unsigned int index; /* Which of the N devices of this type is this ? */
     hwaddr addr;
+    hwaddr size; /* only needed for TYPE_UNIMPLEMENTED_DEVICE */
     int ppc; /* Index of APB PPC this device is wired up to, or NO_PPC */
     int ppc_port; /* Port number of this device on the PPC */
     int irq; /* NO_IRQ, or 0..NUM_SSE_IRQS-1, or NMI_0 or NMI_1 */
@@ -62,7 +63,6 @@ struct ARMSSEInfo {
     uint32_t iidr;
     uint32_t cpuwait_rst;
     bool has_mhus;
-    bool has_ppus;
     bool has_cachectrl;
     bool has_cpusecctrl;
     bool has_cpuid;
@@ -94,7 +94,7 @@ static Property armsse_properties[] = {
     DEFINE_PROP_END_OF_LIST()
 };
 
-static const ARMSSEDeviceInfo sse200_devices[] = {
+static const ARMSSEDeviceInfo iotkit_devices[] = {
     {
         .name = "timer0",
         .type = TYPE_CMSDK_APB_TIMER,
@@ -178,6 +178,153 @@ static const ARMSSEDeviceInfo sse200_devices[] = {
     }
 };
 
+static const ARMSSEDeviceInfo sse200_devices[] = {
+    {
+        .name = "timer0",
+        .type = TYPE_CMSDK_APB_TIMER,
+        .index = 0,
+        .addr = 0x40000000,
+        .ppc = 0,
+        .ppc_port = 0,
+        .irq = 3,
+    },
+    {
+        .name = "timer1",
+        .type = TYPE_CMSDK_APB_TIMER,
+        .index = 1,
+        .addr = 0x40001000,
+        .ppc = 0,
+        .ppc_port = 1,
+        .irq = 4,
+    },
+    {
+        .name = "s32ktimer",
+        .type = TYPE_CMSDK_APB_TIMER,
+        .index = 2,
+        .addr = 0x4002f000,
+        .ppc = 1,
+        .ppc_port = 0,
+        .irq = 2,
+        .slowclk = true,
+    },
+    {
+        .name = "dualtimer",
+        .type = TYPE_CMSDK_APB_DUALTIMER,
+        .index = 0,
+        .addr = 0x40002000,
+        .ppc = 0,
+        .ppc_port = 2,
+        .irq = 5,
+    },
+    {
+        .name = "s32kwatchdog",
+        .type = TYPE_CMSDK_APB_WATCHDOG,
+        .index = 0,
+        .addr = 0x5002e000,
+        .ppc = NO_PPC,
+        .irq = NMI_0,
+        .slowclk = true,
+    },
+    {
+        .name = "nswatchdog",
+        .type = TYPE_CMSDK_APB_WATCHDOG,
+        .index = 1,
+        .addr = 0x40081000,
+        .ppc = NO_PPC,
+        .irq = 1,
+    },
+    {
+        .name = "swatchdog",
+        .type = TYPE_CMSDK_APB_WATCHDOG,
+        .index = 2,
+        .addr = 0x50081000,
+        .ppc = NO_PPC,
+        .irq = NMI_1,
+    },
+    {
+        .name = "armsse-sysinfo",
+        .type = TYPE_IOTKIT_SYSINFO,
+        .index = 0,
+        .addr = 0x40020000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "armsse-sysctl",
+        .type = TYPE_IOTKIT_SYSCTL,
+        .index = 0,
+        .addr = 0x50021000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "CPU0CORE_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 0,
+        .addr = 0x50023000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "CPU1CORE_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 1,
+        .addr = 0x50025000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "DBG_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 2,
+        .addr = 0x50029000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "RAM0_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 3,
+        .addr = 0x5002a000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "RAM1_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 4,
+        .addr = 0x5002b000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "RAM2_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 5,
+        .addr = 0x5002c000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "RAM3_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 6,
+        .addr = 0x5002d000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = NULL,
+    }
+};
+
 static const ARMSSEInfo armsse_variants[] = {
     {
         .name = TYPE_IOTKIT,
@@ -188,12 +335,11 @@ static const ARMSSEInfo armsse_variants[] = {
         .iidr = 0,
         .cpuwait_rst = 0,
         .has_mhus = false,
-        .has_ppus = false,
         .has_cachectrl = false,
         .has_cpusecctrl = false,
         .has_cpuid = false,
         .props = iotkit_properties,
-        .devinfo = sse200_devices,
+        .devinfo = iotkit_devices,
     },
     {
         .name = TYPE_SSE200,
@@ -204,7 +350,6 @@ static const ARMSSEInfo armsse_variants[] = {
         .iidr = 0,
         .cpuwait_rst = 2,
         .has_mhus = true,
-        .has_ppus = true,
         .has_cachectrl = true,
         .has_cpusecctrl = true,
         .has_cpuid = true,
@@ -431,6 +576,11 @@ static void armsse_init(Object *obj)
             assert(devinfo->index == 0);
             object_initialize_child(obj, devinfo->name, &s->sysctl,
                                     TYPE_IOTKIT_SYSCTL);
+        } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
+            assert(devinfo->index < ARRAY_SIZE(s->unimp));
+            object_initialize_child(obj, devinfo->name,
+                                    &s->unimp[devinfo->index],
+                                    TYPE_UNIMPLEMENTED_DEVICE);
         } else {
             g_assert_not_reached();
         }
@@ -463,26 +613,6 @@ static void armsse_init(Object *obj)
         object_initialize_child(obj, "mhu0", &s->mhu[0], TYPE_ARMSSE_MHU);
         object_initialize_child(obj, "mhu1", &s->mhu[1], TYPE_ARMSSE_MHU);
     }
-    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;
-
-            object_initialize_child(obj, name, &s->ppu[ppuidx],
-                                    TYPE_UNIMPLEMENTED_DEVICE);
-            g_free(name);
-        }
-        object_initialize_child(obj, "DBG_PPU", &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;
-
-            object_initialize_child(obj, name, &s->ppu[ppuidx],
-                                    TYPE_UNIMPLEMENTED_DEVICE);
-            g_free(name);
-        }
-    }
     if (info->has_cachectrl) {
         for (i = 0; i < info->num_cpus; i++) {
             char *name = g_strdup_printf("cachectrl%d", i);
@@ -568,17 +698,6 @@ 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);
-    sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
-    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ppu[ppuidx]), 0, addr);
-}
-
 static void armsse_realize(DeviceState *dev, Error **errp)
 {
     ARMSSE *s = ARM_SSE(dev);
@@ -941,6 +1060,15 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                 return;
             }
             mr = sysbus_mmio_get_region(sbd, 0);
+        } else if (!strcmp(devinfo->type, TYPE_UNIMPLEMENTED_DEVICE)) {
+            sbd = SYS_BUS_DEVICE(&s->unimp[devinfo->index]);
+
+            qdev_prop_set_string(DEVICE(sbd), "name", devinfo->name);
+            qdev_prop_set_uint64(DEVICE(sbd), "size", devinfo->size);
+            if (!sysbus_realize(sbd, errp)) {
+                return;
+            }
+            mr = sysbus_mmio_get_region(sbd, 0);
         } else {
             g_assert_not_reached();
         }
@@ -1158,28 +1286,6 @@ static void armsse_realize(DeviceState *dev, Error **errp)
         memory_region_add_subregion(&s->container, devinfo->addr, mr);
     }
 
-    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);
-        }
-    }
-
     for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
         Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
 
-- 
2.20.1



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

* [PULL 30/54] hw/arm/armsse: Add missing SSE-200 SYS_PPU
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (28 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 29/54] hw/arm/armsse: Move PPUs " Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 31/54] hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo Peter Maydell
                   ` (24 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

We forgot to implement a TYPE_UNIMPLEMENTED_DEVICE stub
for the SYS_PPU in the SSE-200, which is at 0x50022000.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-31-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h | 2 +-
 hw/arm/armsse.c         | 9 +++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index eb4e937173f..104ba8d26ec 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -135,7 +135,7 @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
 
 #define SSE_MAX_CPUS 2
 
-#define NUM_PPUS 7
+#define NUM_PPUS 8
 
 /* Number of CPU IRQs used by the SSE itself */
 #define NUM_SSE_IRQS 32
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index f72d1adafea..f43f0524e28 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -320,6 +320,15 @@ static const ARMSSEDeviceInfo sse200_devices[] = {
         .ppc = NO_PPC,
         .irq = NO_IRQ,
     },
+    {
+        .name = "SYS_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 7,
+        .addr = 0x50022000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
     {
         .name = NULL,
     }
-- 
2.20.1



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

* [PULL 31/54] hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (29 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 30/54] hw/arm/armsse: Add missing SSE-200 SYS_PPU Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 32/54] hw/arm/armsse: Add support for SSE variants with a system counter Peter Maydell
                   ` (23 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-300 has a slightly different set of shared-per-CPU interrupts,
allow the irq_is_common[] array to be different per SSE variant.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-32-peter.maydell@linaro.org
---
 hw/arm/armsse.c | 39 +++++++++++++++++++++------------------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index f43f0524e28..b316fe69571 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -68,6 +68,7 @@ struct ARMSSEInfo {
     bool has_cpuid;
     Property *props;
     const ARMSSEDeviceInfo *devinfo;
+    const bool *irq_is_common;
 };
 
 static Property iotkit_properties[] = {
@@ -334,6 +335,21 @@ static const ARMSSEDeviceInfo sse200_devices[] = {
     }
 };
 
+/* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
+static const bool sse200_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 */
+};
+
 static const ARMSSEInfo armsse_variants[] = {
     {
         .name = TYPE_IOTKIT,
@@ -349,6 +365,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_cpuid = false,
         .props = iotkit_properties,
         .devinfo = iotkit_devices,
+        .irq_is_common = sse200_irq_is_common,
     },
     {
         .name = TYPE_SSE200,
@@ -364,6 +381,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_cpuid = true,
         .props = armsse_properties,
         .devinfo = sse200_devices,
+        .irq_is_common = sse200_irq_is_common,
     },
 };
 
@@ -404,21 +422,6 @@ static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
 /* 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 in @container of @size bytes starting at @base
  * which mirrors the memory starting at @orig.
@@ -663,7 +666,7 @@ static void armsse_init(Object *obj)
     }
     if (info->num_cpus > 1) {
         for (i = 0; i < ARRAY_SIZE(s->cpu_irq_splitter); i++) {
-            if (irq_is_common[i]) {
+            if (info->irq_is_common[i]) {
                 char *name = g_strdup_printf("cpu-irq-splitter%d", i);
                 SplitIRQ *splitter = &s->cpu_irq_splitter[i];
 
@@ -696,7 +699,7 @@ static qemu_irq armsse_get_common_irq_in(ARMSSE *s, int irqno)
     ARMSSEClass *asc = ARM_SSE_GET_CLASS(s);
     const ARMSSEInfo *info = asc->info;
 
-    assert(irq_is_common[irqno]);
+    assert(info->irq_is_common[irqno]);
 
     if (info->num_cpus == 1) {
         /* Only one CPU -- just connect directly to it */
@@ -878,7 +881,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     /* 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]) {
+            if (info->irq_is_common[i]) {
                 Object *splitter = OBJECT(&s->cpu_irq_splitter[i]);
                 DeviceState *devs = DEVICE(splitter);
                 int cpunum;
-- 
2.20.1



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

* [PULL 32/54] hw/arm/armsse: Add support for SSE variants with a system counter
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (30 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 31/54] hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 33/54] hw/arm/armsse: Add support for TYPE_SSE_TIMER in ARMSSEDeviceInfo Peter Maydell
                   ` (22 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-300 has a system counter device; add support for SSE
variants having this device.

As with the existing devices like the cache control block, CPUID
block, etc, we don't try to make the MMIO addresses configurable.  We
can do that if and when we need to model a future SSE variant which
has the counter in a different location.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-33-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  3 +++
 hw/arm/armsse.c         | 27 +++++++++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 104ba8d26ec..149f17dfc88 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -97,6 +97,7 @@
 #include "hw/misc/tz-mpc.h"
 #include "hw/timer/cmsdk-apb-timer.h"
 #include "hw/timer/cmsdk-apb-dualtimer.h"
+#include "hw/timer/sse-counter.h"
 #include "hw/watchdog/cmsdk-apb-watchdog.h"
 #include "hw/misc/iotkit-sysctl.h"
 #include "hw/misc/iotkit-sysinfo.h"
@@ -164,6 +165,8 @@ struct ARMSSE {
 
     CMSDKAPBWatchdog cmsdk_watchdog[3];
 
+    SSECounter sse_counter;
+
     IoTKitSysCtl sysctl;
     IoTKitSysCtl sysinfo;
 
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index b316fe69571..4387e98376c 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -66,6 +66,7 @@ struct ARMSSEInfo {
     bool has_cachectrl;
     bool has_cpusecctrl;
     bool has_cpuid;
+    bool has_sse_counter;
     Property *props;
     const ARMSSEDeviceInfo *devinfo;
     const bool *irq_is_common;
@@ -363,6 +364,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_cachectrl = false,
         .has_cpusecctrl = false,
         .has_cpuid = false,
+        .has_sse_counter = false,
         .props = iotkit_properties,
         .devinfo = iotkit_devices,
         .irq_is_common = sse200_irq_is_common,
@@ -379,6 +381,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_cachectrl = true,
         .has_cpusecctrl = true,
         .has_cpuid = true,
+        .has_sse_counter = false,
         .props = armsse_properties,
         .devinfo = sse200_devices,
         .irq_is_common = sse200_irq_is_common,
@@ -652,6 +655,11 @@ static void armsse_init(Object *obj)
             g_free(name);
         }
     }
+    if (info->has_sse_counter) {
+        object_initialize_child(obj, "sse-counter", &s->sse_counter,
+                                TYPE_SSE_COUNTER);
+    }
+
     object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, TYPE_OR_IRQ);
     object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate,
                             TYPE_OR_IRQ);
@@ -1000,6 +1008,25 @@ static void armsse_realize(DeviceState *dev, Error **errp)
     qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0,
                           qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI", 0));
 
+    /* The SSE-300 has a System Counter / System Timestamp Generator */
+    if (info->has_sse_counter) {
+        SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sse_counter);
+
+        qdev_connect_clock_in(DEVICE(sbd), "CLK", s->mainclk);
+        if (!sysbus_realize(sbd, errp)) {
+            return;
+        }
+        /*
+         * The control frame is only in the Secure region;
+         * the status frame is in the NS region (and visible in the
+         * S region via the alias mapping).
+         */
+        memory_region_add_subregion(&s->container, 0x58100000,
+                                    sysbus_mmio_get_region(sbd, 0));
+        memory_region_add_subregion(&s->container, 0x48101000,
+                                    sysbus_mmio_get_region(sbd, 1));
+    }
+
     /* Devices behind APB PPC0:
      *   0x40000000: timer0
      *   0x40001000: timer1
-- 
2.20.1



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

* [PULL 33/54] hw/arm/armsse: Add support for TYPE_SSE_TIMER in ARMSSEDeviceInfo
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (31 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 32/54] hw/arm/armsse: Add support for SSE variants with a system counter Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 34/54] hw/arm/armsse: Support variants with ARMSSE_CPU_PWRCTRL block Peter Maydell
                   ` (21 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The SSE-300 has four timers of type TYPE_SSE_TIMER; add support in
the code for having these in an ARMSSEDeviceInfo array.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-34-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  2 ++
 hw/arm/armsse.c         | 15 +++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 149f17dfc88..f4e2b680479 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -98,6 +98,7 @@
 #include "hw/timer/cmsdk-apb-timer.h"
 #include "hw/timer/cmsdk-apb-dualtimer.h"
 #include "hw/timer/sse-counter.h"
+#include "hw/timer/sse-timer.h"
 #include "hw/watchdog/cmsdk-apb-watchdog.h"
 #include "hw/misc/iotkit-sysctl.h"
 #include "hw/misc/iotkit-sysinfo.h"
@@ -166,6 +167,7 @@ struct ARMSSE {
     CMSDKAPBWatchdog cmsdk_watchdog[3];
 
     SSECounter sse_counter;
+    SSETimer sse_timer[4];
 
     IoTKitSysCtl sysctl;
     IoTKitSysCtl sysinfo;
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 4387e98376c..ec9c30e0996 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -578,6 +578,11 @@ static void armsse_init(Object *obj)
             assert(devinfo->index == 0);
             object_initialize_child(obj, devinfo->name, &s->dualtimer,
                                     TYPE_CMSDK_APB_DUALTIMER);
+        } else if (!strcmp(devinfo->type, TYPE_SSE_TIMER)) {
+            assert(devinfo->index < ARRAY_SIZE(s->sse_timer));
+            object_initialize_child(obj, devinfo->name,
+                                    &s->sse_timer[devinfo->index],
+                                    TYPE_SSE_TIMER);
         } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
             assert(devinfo->index < ARRAY_SIZE(s->cmsdk_watchdog));
             object_initialize_child(obj, devinfo->name,
@@ -1058,6 +1063,16 @@ static void armsse_realize(DeviceState *dev, Error **errp)
                 return;
             }
             mr = sysbus_mmio_get_region(sbd, 0);
+        } else if (!strcmp(devinfo->type, TYPE_SSE_TIMER)) {
+            sbd = SYS_BUS_DEVICE(&s->sse_timer[devinfo->index]);
+
+            assert(info->has_sse_counter);
+            object_property_set_link(OBJECT(sbd), "counter",
+                                     OBJECT(&s->sse_counter), &error_abort);
+            if (!sysbus_realize(sbd, errp)) {
+                return;
+            }
+            mr = sysbus_mmio_get_region(sbd, 0);
         } else if (!strcmp(devinfo->type, TYPE_CMSDK_APB_WATCHDOG)) {
             sbd = SYS_BUS_DEVICE(&s->cmsdk_watchdog[devinfo->index]);
 
-- 
2.20.1



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

* [PULL 34/54] hw/arm/armsse: Support variants with ARMSSE_CPU_PWRCTRL block
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (32 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 33/54] hw/arm/armsse: Add support for TYPE_SSE_TIMER in ARMSSEDeviceInfo Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 35/54] hw/arm/armsse: Add SSE-300 support Peter Maydell
                   ` (20 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Support SSE variants like the SSE-300 with an ARMSSE_CPU_PWRCTRL register
block. Because this block is per-CPU and does not clash with any of the
SSE-200 devices, we handle it with a has_cpu_pwrctrl flag like the
existing has_cachectrl, has_cpusectrl and has_cpuid, rather than
trying to add per-CPU-device support to the devinfo array handling code.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-35-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |  3 +++
 hw/arm/armsse.c         | 26 ++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index f4e2b680479..21d239c381c 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -104,6 +104,7 @@
 #include "hw/misc/iotkit-sysinfo.h"
 #include "hw/misc/armsse-cpuid.h"
 #include "hw/misc/armsse-mhu.h"
+#include "hw/misc/armsse-cpu-pwrctrl.h"
 #include "hw/misc/unimp.h"
 #include "hw/or-irq.h"
 #include "hw/clock.h"
@@ -179,6 +180,8 @@ struct ARMSSE {
 
     ARMSSECPUID cpuid[SSE_MAX_CPUS];
 
+    ARMSSECPUPwrCtrl cpu_pwrctrl[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 ec9c30e0996..2366c49376d 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -66,6 +66,7 @@ struct ARMSSEInfo {
     bool has_cachectrl;
     bool has_cpusecctrl;
     bool has_cpuid;
+    bool has_cpu_pwrctrl;
     bool has_sse_counter;
     Property *props;
     const ARMSSEDeviceInfo *devinfo;
@@ -364,6 +365,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_cachectrl = false,
         .has_cpusecctrl = false,
         .has_cpuid = false,
+        .has_cpu_pwrctrl = false,
         .has_sse_counter = false,
         .props = iotkit_properties,
         .devinfo = iotkit_devices,
@@ -381,6 +383,7 @@ static const ARMSSEInfo armsse_variants[] = {
         .has_cachectrl = true,
         .has_cpusecctrl = true,
         .has_cpuid = true,
+        .has_cpu_pwrctrl = false,
         .has_sse_counter = false,
         .props = armsse_properties,
         .devinfo = sse200_devices,
@@ -660,6 +663,15 @@ static void armsse_init(Object *obj)
             g_free(name);
         }
     }
+    if (info->has_cpu_pwrctrl) {
+        for (i = 0; i < info->num_cpus; i++) {
+            char *name = g_strdup_printf("cpu_pwrctrl%d", i);
+
+            object_initialize_child(obj, name, &s->cpu_pwrctrl[i],
+                                    TYPE_ARMSSE_CPU_PWRCTRL);
+            g_free(name);
+        }
+    }
     if (info->has_sse_counter) {
         object_initialize_child(obj, "sse-counter", &s->sse_counter,
                                 TYPE_SSE_COUNTER);
@@ -1255,6 +1267,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
      *  0x50010000: L1 icache control registers
      *  0x50011000: CPUSECCTRL (CPU local security control registers)
      *  0x4001f000 and 0x5001f000: CPU_IDENTITY register block
+     * The SSE-300 has an extra:
+     *  0x40012000 and 0x50012000: CPU_PWRCTRL register block
      */
     if (info->has_cachectrl) {
         for (i = 0; i < info->num_cpus; i++) {
@@ -1301,6 +1315,18 @@ static void armsse_realize(DeviceState *dev, Error **errp)
             memory_region_add_subregion(&s->cpu_container[i], 0x4001F000, mr);
         }
     }
+    if (info->has_cpu_pwrctrl) {
+        for (i = 0; i < info->num_cpus; i++) {
+            MemoryRegion *mr;
+
+            if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), errp)) {
+                return;
+            }
+
+            mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpu_pwrctrl[i]), 0);
+            memory_region_add_subregion(&s->cpu_container[i], 0x40012000, mr);
+        }
+    }
 
     if (!sysbus_realize(SYS_BUS_DEVICE(&s->apb_ppc[1]), errp)) {
         return;
-- 
2.20.1



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

* [PULL 35/54] hw/arm/armsse: Add SSE-300 support
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (33 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 34/54] hw/arm/armsse: Support variants with ARMSSE_CPU_PWRCTRL block Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 36/54] hw/arm/mps2-tz: Make UART overflow IRQ board-specific Peter Maydell
                   ` (19 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Now we have sufficiently parameterised the code, we can add SSE-300
support by adding a new entry to the armsse_variants[] array.

Note that the main watchdog (unlike the s32k watchdog) in the SSE-300
is a different device from the CMSDK watchdog; we don't have a model
of it so we leave it as a TYPE_UNIMPLEMENTED_DEVICE stub.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-36-peter.maydell@linaro.org
---
 include/hw/arm/armsse.h |   1 +
 hw/arm/armsse.c         | 152 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 153 insertions(+)

diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
index 21d239c381c..36592be62c5 100644
--- a/include/hw/arm/armsse.h
+++ b/include/hw/arm/armsse.h
@@ -123,6 +123,7 @@ OBJECT_DECLARE_TYPE(ARMSSE, ARMSSEClass,
  */
 #define TYPE_IOTKIT "iotkit"
 #define TYPE_SSE200 "sse-200"
+#define TYPE_SSE300 "sse-300"
 
 /* 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 2366c49376d..e5aeb9e485f 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -337,6 +337,128 @@ static const ARMSSEDeviceInfo sse200_devices[] = {
     }
 };
 
+static const ARMSSEDeviceInfo sse300_devices[] = {
+    {
+        .name = "timer0",
+        .type = TYPE_SSE_TIMER,
+        .index = 0,
+        .addr = 0x48000000,
+        .ppc = 0,
+        .ppc_port = 0,
+        .irq = 3,
+    },
+    {
+        .name = "timer1",
+        .type = TYPE_SSE_TIMER,
+        .index = 1,
+        .addr = 0x48001000,
+        .ppc = 0,
+        .ppc_port = 1,
+        .irq = 4,
+    },
+    {
+        .name = "timer2",
+        .type = TYPE_SSE_TIMER,
+        .index = 2,
+        .addr = 0x48002000,
+        .ppc = 0,
+        .ppc_port = 2,
+        .irq = 5,
+    },
+    {
+        .name = "timer3",
+        .type = TYPE_SSE_TIMER,
+        .index = 3,
+        .addr = 0x48003000,
+        .ppc = 0,
+        .ppc_port = 5,
+        .irq = 27,
+    },
+    {
+        .name = "s32ktimer",
+        .type = TYPE_CMSDK_APB_TIMER,
+        .index = 0,
+        .addr = 0x4802f000,
+        .ppc = 1,
+        .ppc_port = 0,
+        .irq = 2,
+        .slowclk = true,
+    },
+    {
+        .name = "s32kwatchdog",
+        .type = TYPE_CMSDK_APB_WATCHDOG,
+        .index = 0,
+        .addr = 0x4802e000,
+        .ppc = NO_PPC,
+        .irq = NMI_0,
+        .slowclk = true,
+    },
+    {
+        .name = "watchdog",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 0,
+        .addr = 0x48040000,
+        .size = 0x2000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "armsse-sysinfo",
+        .type = TYPE_IOTKIT_SYSINFO,
+        .index = 0,
+        .addr = 0x48020000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "armsse-sysctl",
+        .type = TYPE_IOTKIT_SYSCTL,
+        .index = 0,
+        .addr = 0x58021000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "SYS_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 1,
+        .addr = 0x58022000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "CPU0CORE_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 2,
+        .addr = 0x50023000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "MGMT_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 3,
+        .addr = 0x50028000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = "DEBUG_PPU",
+        .type = TYPE_UNIMPLEMENTED_DEVICE,
+        .index = 4,
+        .addr = 0x50029000,
+        .size = 0x1000,
+        .ppc = NO_PPC,
+        .irq = NO_IRQ,
+    },
+    {
+        .name = NULL,
+    }
+};
+
 /* Is internal IRQ n shared between CPUs in a multi-core SSE ? */
 static const bool sse200_irq_is_common[32] = {
     [0 ... 5] = true,
@@ -352,6 +474,18 @@ static const bool sse200_irq_is_common[32] = {
     /* 30, 31: reserved */
 };
 
+static const bool sse300_irq_is_common[32] = {
+    [0 ... 5] = true,
+    /* 6, 7: per-CPU MHU interrupts */
+    [8 ... 12] = true,
+    /* 13: reserved */
+    [14 ... 16] = true,
+    /* 17-25: reserved */
+    [26 ... 27] = true,
+    /* 28, 29: per-CPU CTI interrupts */
+    /* 30, 31: reserved */
+};
+
 static const ARMSSEInfo armsse_variants[] = {
     {
         .name = TYPE_IOTKIT,
@@ -389,6 +523,24 @@ static const ARMSSEInfo armsse_variants[] = {
         .devinfo = sse200_devices,
         .irq_is_common = sse200_irq_is_common,
     },
+    {
+        .name = TYPE_SSE300,
+        .sse_version = ARMSSE_SSE300,
+        .sram_banks = 2,
+        .num_cpus = 1,
+        .sys_version = 0x7e00043b,
+        .iidr = 0x74a0043b,
+        .cpuwait_rst = 0,
+        .has_mhus = false,
+        .has_cachectrl = false,
+        .has_cpusecctrl = true,
+        .has_cpuid = true,
+        .has_cpu_pwrctrl = true,
+        .has_sse_counter = true,
+        .props = armsse_properties,
+        .devinfo = sse300_devices,
+        .irq_is_common = sse300_irq_is_common,
+    },
 };
 
 static uint32_t armsse_sys_config_value(ARMSSE *s, const ARMSSEInfo *info)
-- 
2.20.1



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

* [PULL 36/54] hw/arm/mps2-tz: Make UART overflow IRQ board-specific
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (34 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 35/54] hw/arm/armsse: Add SSE-300 support Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 37/54] hw/misc/mps2-fpgaio: Fold counters subsection into main vmstate Peter Maydell
                   ` (18 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The AN547 puts the combined UART overflow IRQ at 48, not 47 like the
other images. Make this setting board-specific.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-37-peter.maydell@linaro.org
---
 hw/arm/mps2-tz.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 72da8cb1a16..85e80c4d726 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -111,6 +111,7 @@ struct MPS2TZMachineClass {
     uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
     bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
     int numirq; /* Number of external interrupts */
+    int uart_overflow_irq; /* number of the combined UART overflow IRQ */
     const RAMInfo *raminfo;
     const char *armsse_type;
 };
@@ -770,7 +771,7 @@ static void mps2tz_common_init(MachineState *machine)
                             &error_fatal);
     qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
     qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
-                          get_sse_irq_in(mms, 47));
+                          get_sse_irq_in(mms, mmc->uart_overflow_irq));
 
     /* Most of the devices in the FPGA are behind Peripheral Protection
      * Controllers. The required order for initializing things is:
@@ -1046,6 +1047,7 @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
     mmc->fpgaio_num_leds = 2;
     mmc->fpgaio_has_switches = false;
     mmc->numirq = 92;
+    mmc->uart_overflow_irq = 47;
     mmc->raminfo = an505_raminfo;
     mmc->armsse_type = TYPE_IOTKIT;
     mps2tz_set_default_ram_info(mmc);
@@ -1069,6 +1071,7 @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
     mmc->fpgaio_num_leds = 2;
     mmc->fpgaio_has_switches = false;
     mmc->numirq = 92;
+    mmc->uart_overflow_irq = 47;
     mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
     mmc->armsse_type = TYPE_SSE200;
     mps2tz_set_default_ram_info(mmc);
@@ -1092,6 +1095,7 @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
     mmc->fpgaio_num_leds = 10;
     mmc->fpgaio_has_switches = true;
     mmc->numirq = 95;
+    mmc->uart_overflow_irq = 47;
     mmc->raminfo = an524_raminfo;
     mmc->armsse_type = TYPE_SSE200;
     mps2tz_set_default_ram_info(mmc);
-- 
2.20.1



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

* [PULL 37/54] hw/misc/mps2-fpgaio: Fold counters subsection into main vmstate
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (35 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 36/54] hw/arm/mps2-tz: Make UART overflow IRQ board-specific Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 38/54] hw/misc/mps2-fpgaio: Support AN547 DBGCTRL register Peter Maydell
                   ` (17 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

We've already broken migration compatibility for all the MPS
boards, so we might as well take advantage of this to simplify
the vmstate for the FPGAIO device by folding the counters
subsection into the main vmstate description.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-38-peter.maydell@linaro.org
---
 hw/misc/mps2-fpgaio.c | 30 +++++-------------------------
 1 file changed, 5 insertions(+), 25 deletions(-)

diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
index f3db88ddcc8..72598c8a3d2 100644
--- a/hw/misc/mps2-fpgaio.c
+++ b/hw/misc/mps2-fpgaio.c
@@ -285,41 +285,21 @@ static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
     }
 }
 
-static bool mps2_fpgaio_counters_needed(void *opaque)
-{
-    /* Currently vmstate.c insists all subsections have a 'needed' function */
-    return true;
-}
-
-static const VMStateDescription mps2_fpgaio_counters_vmstate = {
-    .name = "mps2-fpgaio/counters",
+static const VMStateDescription mps2_fpgaio_vmstate = {
+    .name = "mps2-fpgaio",
     .version_id = 2,
     .minimum_version_id = 2,
-    .needed = mps2_fpgaio_counters_needed,
     .fields = (VMStateField[]) {
+        VMSTATE_UINT32(led0, MPS2FPGAIO),
+        VMSTATE_UINT32(prescale, MPS2FPGAIO),
+        VMSTATE_UINT32(misc, MPS2FPGAIO),
         VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
         VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
         VMSTATE_UINT32(counter, MPS2FPGAIO),
         VMSTATE_UINT32(pscntr, MPS2FPGAIO),
         VMSTATE_INT64(pscntr_sync_ticks, MPS2FPGAIO),
         VMSTATE_END_OF_LIST()
-    }
-};
-
-static const VMStateDescription mps2_fpgaio_vmstate = {
-    .name = "mps2-fpgaio",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(led0, MPS2FPGAIO),
-        VMSTATE_UINT32(prescale, MPS2FPGAIO),
-        VMSTATE_UINT32(misc, MPS2FPGAIO),
-        VMSTATE_END_OF_LIST()
     },
-    .subsections = (const VMStateDescription*[]) {
-        &mps2_fpgaio_counters_vmstate,
-        NULL
-    }
 };
 
 static Property mps2_fpgaio_properties[] = {
-- 
2.20.1



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

* [PULL 38/54] hw/misc/mps2-fpgaio: Support AN547 DBGCTRL register
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (36 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 37/54] hw/misc/mps2-fpgaio: Fold counters subsection into main vmstate Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 39/54] hw/misc/mps2-scc: Implement changes for AN547 Peter Maydell
                   ` (16 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

For the AN547 image, the FPGAIO block has an extra DBGCTRL register,
which is used to control the SPNIDEN, SPIDEN, NPIDEN and DBGEN inputs
to the CPU.  These signals control when the CPU permits use of the
external debug interface.  Our CPU models don't implement the
external debug interface, so we model the register as
reads-as-written.

Implement the register, with a property defining whether it is
present, and allow mps2-tz boards to specify that it is present.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-39-peter.maydell@linaro.org
---
 include/hw/misc/mps2-fpgaio.h |  2 ++
 hw/arm/mps2-tz.c              |  5 +++++
 hw/misc/mps2-fpgaio.c         | 22 ++++++++++++++++++++--
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
index e04fd590b63..7b8bd604de0 100644
--- a/include/hw/misc/mps2-fpgaio.h
+++ b/include/hw/misc/mps2-fpgaio.h
@@ -39,10 +39,12 @@ struct MPS2FPGAIO {
     LEDState *led[MPS2FPGAIO_MAX_LEDS];
     uint32_t num_leds;
     bool has_switches;
+    bool has_dbgctrl;
 
     uint32_t led0;
     uint32_t prescale;
     uint32_t misc;
+    uint32_t dbgctrl;
 
     /* QEMU_CLOCK_VIRTUAL time at which counter and pscntr were last synced */
     int64_t pscntr_sync_ticks;
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 85e80c4d726..79a076ce693 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -110,6 +110,7 @@ struct MPS2TZMachineClass {
     const uint32_t *oscclk;
     uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
     bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
+    bool fpgaio_has_dbgctrl; /* Does FPGAIO have DBGCTRL register? */
     int numirq; /* Number of external interrupts */
     int uart_overflow_irq; /* number of the combined UART overflow IRQ */
     const RAMInfo *raminfo;
@@ -422,6 +423,7 @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
     object_initialize_child(OBJECT(mms), "fpgaio", fpgaio, TYPE_MPS2_FPGAIO);
     qdev_prop_set_uint32(DEVICE(fpgaio), "num-leds", mmc->fpgaio_num_leds);
     qdev_prop_set_bit(DEVICE(fpgaio), "has-switches", mmc->fpgaio_has_switches);
+    qdev_prop_set_bit(DEVICE(fpgaio), "has-dbgctrl", mmc->fpgaio_has_dbgctrl);
     sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal);
     return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
 }
@@ -1046,6 +1048,7 @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
     mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
     mmc->fpgaio_num_leds = 2;
     mmc->fpgaio_has_switches = false;
+    mmc->fpgaio_has_dbgctrl = false;
     mmc->numirq = 92;
     mmc->uart_overflow_irq = 47;
     mmc->raminfo = an505_raminfo;
@@ -1070,6 +1073,7 @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
     mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
     mmc->fpgaio_num_leds = 2;
     mmc->fpgaio_has_switches = false;
+    mmc->fpgaio_has_dbgctrl = false;
     mmc->numirq = 92;
     mmc->uart_overflow_irq = 47;
     mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
@@ -1094,6 +1098,7 @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
     mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
     mmc->fpgaio_num_leds = 10;
     mmc->fpgaio_has_switches = true;
+    mmc->fpgaio_has_dbgctrl = false;
     mmc->numirq = 95;
     mmc->uart_overflow_irq = 47;
     mmc->raminfo = an524_raminfo;
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
index 72598c8a3d2..07b8cbdad28 100644
--- a/hw/misc/mps2-fpgaio.c
+++ b/hw/misc/mps2-fpgaio.c
@@ -29,6 +29,7 @@
 #include "qemu/timer.h"
 
 REG32(LED0, 0)
+REG32(DBGCTRL, 4)
 REG32(BUTTON, 8)
 REG32(CLK1HZ, 0x10)
 REG32(CLK100HZ, 0x14)
@@ -129,6 +130,12 @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
     case A_LED0:
         r = s->led0;
         break;
+    case A_DBGCTRL:
+        if (!s->has_dbgctrl) {
+            goto bad_offset;
+        }
+        r = s->dbgctrl;
+        break;
     case A_BUTTON:
         /* User-pressable board buttons. We don't model that, so just return
          * zeroes.
@@ -195,6 +202,14 @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
             }
         }
         break;
+    case A_DBGCTRL:
+        if (!s->has_dbgctrl) {
+            goto bad_offset;
+        }
+        qemu_log_mask(LOG_UNIMP,
+                      "MPS2 FPGAIO: DBGCTRL unimplemented\n");
+        s->dbgctrl = value;
+        break;
     case A_PRESCALE:
         resync_counter(s);
         s->prescale = value;
@@ -225,6 +240,7 @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
         s->pscntr = value;
         break;
     default:
+    bad_offset:
         qemu_log_mask(LOG_GUEST_ERROR,
                       "MPS2 FPGAIO write: bad offset 0x%x\n", (int) offset);
         break;
@@ -287,12 +303,13 @@ static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
 
 static const VMStateDescription mps2_fpgaio_vmstate = {
     .name = "mps2-fpgaio",
-    .version_id = 2,
-    .minimum_version_id = 2,
+    .version_id = 3,
+    .minimum_version_id = 3,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(led0, MPS2FPGAIO),
         VMSTATE_UINT32(prescale, MPS2FPGAIO),
         VMSTATE_UINT32(misc, MPS2FPGAIO),
+        VMSTATE_UINT32(dbgctrl, MPS2FPGAIO),
         VMSTATE_INT64(clk1hz_tick_offset, MPS2FPGAIO),
         VMSTATE_INT64(clk100hz_tick_offset, MPS2FPGAIO),
         VMSTATE_UINT32(counter, MPS2FPGAIO),
@@ -308,6 +325,7 @@ static Property mps2_fpgaio_properties[] = {
     /* Number of LEDs controlled by LED0 register */
     DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
     DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false),
+    DEFINE_PROP_BOOL("has-dbgctrl", MPS2FPGAIO, has_dbgctrl, false),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.20.1



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

* [PULL 39/54] hw/misc/mps2-scc: Implement changes for AN547
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (37 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 38/54] hw/misc/mps2-fpgaio: Support AN547 DBGCTRL register Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 40/54] hw/arm/mps2-tz: Support running APB peripherals on different clock Peter Maydell
                   ` (15 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Implement the minor changes required to the SCC block for AN547 images:
 * CFG2 and CFG5 exist (like AN524)
 * CFG3 is reserved (like AN524)
 * CFG0 bit 1 is CPU_WAIT; we don't implement it, but note this
   in the TODO comment

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-40-peter.maydell@linaro.org
---
 hw/misc/mps2-scc.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
index 140a4b9ceba..c56aca86ad5 100644
--- a/hw/misc/mps2-scc.c
+++ b/hw/misc/mps2-scc.c
@@ -110,14 +110,14 @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
         r = s->cfg1;
         break;
     case A_CFG2:
-        if (scc_partno(s) != 0x524) {
+        if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
             /* CFG2 reserved on other boards */
             goto bad_offset;
         }
         r = s->cfg2;
         break;
     case A_CFG3:
-        if (scc_partno(s) == 0x524) {
+        if (scc_partno(s) == 0x524 && scc_partno(s) == 0x547) {
             /* CFG3 reserved on AN524 */
             goto bad_offset;
         }
@@ -130,7 +130,7 @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
         r = s->cfg4;
         break;
     case A_CFG5:
-        if (scc_partno(s) != 0x524) {
+        if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
             /* CFG5 reserved on other boards */
             goto bad_offset;
         }
@@ -185,7 +185,10 @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
 
     switch (offset) {
     case A_CFG0:
-        /* TODO on some boards bit 0 controls RAM remapping */
+        /*
+         * TODO on some boards bit 0 controls RAM remapping;
+         * on others bit 1 is CPU_WAIT.
+         */
         s->cfg0 = value;
         break;
     case A_CFG1:
@@ -195,7 +198,7 @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
         }
         break;
     case A_CFG2:
-        if (scc_partno(s) != 0x524) {
+        if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
             /* CFG2 reserved on other boards */
             goto bad_offset;
         }
@@ -203,7 +206,7 @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
         s->cfg2 = value;
         break;
     case A_CFG5:
-        if (scc_partno(s) != 0x524) {
+        if (scc_partno(s) != 0x524 && scc_partno(s) != 0x547) {
             /* CFG5 reserved on other boards */
             goto bad_offset;
         }
-- 
2.20.1



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

* [PULL 40/54] hw/arm/mps2-tz: Support running APB peripherals on different clock
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (38 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 39/54] hw/misc/mps2-scc: Implement changes for AN547 Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 41/54] hw/arm/mps2-tz: Make initsvtor0 setting board-specific Peter Maydell
                   ` (14 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The AN547 runs the APB peripherals outside the SSE-300 on a different
and slightly slower clock than it runs the SSE-300 with.  Support
making the APB peripheral clock frequency board-specific.  (For our
implementation only the UARTs actually take a clock.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-41-peter.maydell@linaro.org
---
 hw/arm/mps2-tz.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 79a076ce693..f25a4ac0929 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -106,6 +106,7 @@ struct MPS2TZMachineClass {
     MPS2TZFPGAType fpga_type;
     uint32_t scc_id;
     uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
+    uint32_t apb_periph_frq; /* APB peripheral frequency in Hz */
     uint32_t len_oscclk;
     const uint32_t *oscclk;
     uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
@@ -379,7 +380,7 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
 
     object_initialize_child(OBJECT(mms), name, uart, TYPE_CMSDK_APB_UART);
     qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
-    qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
+    qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->apb_periph_frq);
     sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
     s = SYS_BUS_DEVICE(uart);
     sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
@@ -1044,6 +1045,7 @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
     mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
     mmc->scc_id = 0x41045050;
     mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
+    mmc->apb_periph_frq = mmc->sysclk_frq;
     mmc->oscclk = an505_oscclk;
     mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
     mmc->fpgaio_num_leds = 2;
@@ -1069,6 +1071,7 @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
     mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
     mmc->scc_id = 0x41045210;
     mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
+    mmc->apb_periph_frq = mmc->sysclk_frq;
     mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
     mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
     mmc->fpgaio_num_leds = 2;
@@ -1094,6 +1097,7 @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
     mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
     mmc->scc_id = 0x41045240;
     mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
+    mmc->apb_periph_frq = mmc->sysclk_frq;
     mmc->oscclk = an524_oscclk;
     mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
     mmc->fpgaio_num_leds = 10;
-- 
2.20.1



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

* [PULL 41/54] hw/arm/mps2-tz: Make initsvtor0 setting board-specific
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (39 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 40/54] hw/arm/mps2-tz: Support running APB peripherals on different clock Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 42/54] hw/arm/mps2-tz: Add new mps3-an547 board Peter Maydell
                   ` (13 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The AN547 configures the SSE-300 with a different initsvtor0
setting from its default; make this a board-specific setting.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-42-peter.maydell@linaro.org
---
 hw/arm/mps2-tz.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index f25a4ac0929..0a1e6c20c21 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -114,6 +114,7 @@ struct MPS2TZMachineClass {
     bool fpgaio_has_dbgctrl; /* Does FPGAIO have DBGCTRL register? */
     int numirq; /* Number of external interrupts */
     int uart_overflow_irq; /* number of the combined UART overflow IRQ */
+    uint32_t init_svtor; /* init-svtor setting for SSE */
     const RAMInfo *raminfo;
     const char *armsse_type;
 };
@@ -700,6 +701,7 @@ static void mps2tz_common_init(MachineState *machine)
     object_property_set_link(OBJECT(&mms->iotkit), "memory",
                              OBJECT(system_memory), &error_abort);
     qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
+    qdev_prop_set_uint32(iotkitdev, "init-svtor", mmc->init_svtor);
     qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
     qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
     sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
@@ -1053,6 +1055,7 @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
     mmc->fpgaio_has_dbgctrl = false;
     mmc->numirq = 92;
     mmc->uart_overflow_irq = 47;
+    mmc->init_svtor = 0x10000000;
     mmc->raminfo = an505_raminfo;
     mmc->armsse_type = TYPE_IOTKIT;
     mps2tz_set_default_ram_info(mmc);
@@ -1079,6 +1082,7 @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
     mmc->fpgaio_has_dbgctrl = false;
     mmc->numirq = 92;
     mmc->uart_overflow_irq = 47;
+    mmc->init_svtor = 0x10000000;
     mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
     mmc->armsse_type = TYPE_SSE200;
     mps2tz_set_default_ram_info(mmc);
@@ -1105,6 +1109,7 @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
     mmc->fpgaio_has_dbgctrl = false;
     mmc->numirq = 95;
     mmc->uart_overflow_irq = 47;
+    mmc->init_svtor = 0x10000000;
     mmc->raminfo = an524_raminfo;
     mmc->armsse_type = TYPE_SSE200;
     mps2tz_set_default_ram_info(mmc);
-- 
2.20.1



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

* [PULL 42/54] hw/arm/mps2-tz: Add new mps3-an547 board
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (40 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 41/54] hw/arm/mps2-tz: Make initsvtor0 setting board-specific Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 43/54] docs/system/arm/mps2.rst: Document the " Peter Maydell
                   ` (12 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Add support for the mps3-an547 board; this is an SSE-300 based
FPGA image that runs on the MPS3.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210219144617.4782-43-peter.maydell@linaro.org
---
 hw/arm/mps2-tz.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 144 insertions(+), 2 deletions(-)

diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 0a1e6c20c21..3fbe3d29f95 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -17,6 +17,7 @@
  *  "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
  *  "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
  *  "mps2-an524" -- Dual Cortex-M33 as documented in Application Note AN524
+ *  "mps2-an547" -- Single Cortex-M55 as documented in Application Note AN547
  *
  * Links to the TRM for the board itself and to the various Application
  * Notes which document the FPGA images can be found here:
@@ -30,6 +31,8 @@
  * https://developer.arm.com/documentation/dai0521/latest/
  * Application Note AN524:
  * https://developer.arm.com/documentation/dai0524/latest/
+ * Application Note AN547:
+ * https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/DAI0547B_SSE300_PLUS_U55_FPGA_for_mps3.pdf
  *
  * 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:
@@ -37,6 +40,8 @@
  * Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
  * most of the device layout:
  *  https://developer.arm.com/documentation/101104/latest/
+ * and the AN547 uses the SSE-300, whose layout is in the SSE-300 TRM:
+ *  https://developer.arm.com/documentation/101773/latest/
  */
 
 #include "qemu/osdep.h"
@@ -68,13 +73,14 @@
 #include "hw/qdev-clock.h"
 #include "qom/object.h"
 
-#define MPS2TZ_NUMIRQ_MAX 95
-#define MPS2TZ_RAM_MAX 4
+#define MPS2TZ_NUMIRQ_MAX 96
+#define MPS2TZ_RAM_MAX 5
 
 typedef enum MPS2TZFPGAType {
     FPGA_AN505,
     FPGA_AN521,
     FPGA_AN524,
+    FPGA_AN547,
 } MPS2TZFPGAType;
 
 /*
@@ -153,6 +159,7 @@ struct MPS2TZMachineState {
 #define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
 #define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
 #define TYPE_MPS3TZ_AN524_MACHINE MACHINE_TYPE_NAME("mps3-an524")
+#define TYPE_MPS3TZ_AN547_MACHINE MACHINE_TYPE_NAME("mps3-an547")
 
 OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
 
@@ -252,6 +259,49 @@ static const RAMInfo an524_raminfo[] = { {
     },
 };
 
+static const RAMInfo an547_raminfo[] = { {
+        .name = "itcm",
+        .base = 0x00000000,
+        .size = 512 * KiB,
+        .mpc = -1,
+        .mrindex = 0,
+    }, {
+        .name = "sram",
+        .base = 0x01000000,
+        .size = 2 * MiB,
+        .mpc = 0,
+        .mrindex = 1,
+    }, {
+        .name = "dtcm",
+        .base = 0x20000000,
+        .size = 4 * 128 * KiB,
+        .mpc = -1,
+        .mrindex = 2,
+    }, {
+        .name = "sram 2",
+        .base = 0x21000000,
+        .size = 4 * MiB,
+        .mpc = -1,
+        .mrindex = 3,
+    }, {
+        /* We don't model QSPI flash yet; for now expose it as simple ROM */
+        .name = "QSPI",
+        .base = 0x28000000,
+        .size = 8 * MiB,
+        .mpc = 1,
+        .mrindex = 4,
+        .flags = IS_ROM,
+    }, {
+        .name = "DDR",
+        .base = 0x60000000,
+        .size = MPS3_DDR_SIZE,
+        .mpc = 2,
+        .mrindex = -1,
+    }, {
+        .name = NULL,
+    },
+};
+
 static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
 {
     MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
@@ -893,6 +943,55 @@ static void mps2tz_common_init(MachineState *machine)
         },
     };
 
+    const PPCInfo an547_ppcs[] = { {
+            .name = "apb_ppcexp0",
+            .ports = {
+                { "ssram-mpc", make_mpc, &mms->mpc[0], 0x57000000, 0x1000 },
+                { "qspi-mpc", make_mpc, &mms->mpc[1], 0x57001000, 0x1000 },
+                { "ddr-mpc", make_mpc, &mms->mpc[2], 0x57002000, 0x1000 },
+            },
+        }, {
+            .name = "apb_ppcexp1",
+            .ports = {
+                { "i2c0", make_i2c, &mms->i2c[0], 0x49200000, 0x1000 },
+                { "i2c1", make_i2c, &mms->i2c[1], 0x49201000, 0x1000 },
+                { "spi0", make_spi, &mms->spi[0], 0x49202000, 0x1000, { 53 } },
+                { "spi1", make_spi, &mms->spi[1], 0x49203000, 0x1000, { 54 } },
+                { "spi2", make_spi, &mms->spi[2], 0x49204000, 0x1000, { 55 } },
+                { "i2c2", make_i2c, &mms->i2c[2], 0x49205000, 0x1000 },
+                { "i2c3", make_i2c, &mms->i2c[3], 0x49206000, 0x1000 },
+                { /* port 7 reserved */ },
+                { "i2c4", make_i2c, &mms->i2c[4], 0x49208000, 0x1000 },
+            },
+        }, {
+            .name = "apb_ppcexp2",
+            .ports = {
+                { "scc", make_scc, &mms->scc, 0x49300000, 0x1000 },
+                { "i2s-audio", make_unimp_dev, &mms->i2s_audio, 0x49301000, 0x1000 },
+                { "fpgaio", make_fpgaio, &mms->fpgaio, 0x49302000, 0x1000 },
+                { "uart0", make_uart, &mms->uart[0], 0x49303000, 0x1000, { 33, 34, 43 } },
+                { "uart1", make_uart, &mms->uart[1], 0x49304000, 0x1000, { 35, 36, 44 } },
+                { "uart2", make_uart, &mms->uart[2], 0x49305000, 0x1000, { 37, 38, 45 } },
+                { "uart3", make_uart, &mms->uart[3], 0x49306000, 0x1000, { 39, 40, 46 } },
+                { "uart4", make_uart, &mms->uart[4], 0x49307000, 0x1000, { 41, 42, 47 } },
+                { "uart5", make_uart, &mms->uart[5], 0x49308000, 0x1000, { 125, 126, 127 } },
+
+                { /* port 9 reserved */ },
+                { "clcd", make_unimp_dev, &mms->cldc, 0x4930a000, 0x1000 },
+                { "rtc", make_rtc, &mms->rtc, 0x4930b000, 0x1000 },
+            },
+        }, {
+            .name = "ahb_ppcexp0",
+            .ports = {
+                { "gpio0", make_unimp_dev, &mms->gpio[0], 0x41100000, 0x1000 },
+                { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
+                { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
+                { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
+                { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 49 } },
+            },
+        },
+    };
+
     switch (mmc->fpga_type) {
     case FPGA_AN505:
     case FPGA_AN521:
@@ -903,6 +1002,10 @@ static void mps2tz_common_init(MachineState *machine)
         ppcs = an524_ppcs;
         num_ppcs = ARRAY_SIZE(an524_ppcs);
         break;
+    case FPGA_AN547:
+        ppcs = an547_ppcs;
+        num_ppcs = ARRAY_SIZE(an547_ppcs);
+        break;
     default:
         g_assert_not_reached();
     }
@@ -981,6 +1084,11 @@ static void mps2tz_common_init(MachineState *machine)
 
     create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
 
+    if (mmc->fpga_type == FPGA_AN547) {
+        create_unimplemented_device("U55 timing adapter 0", 0x48102000, 0x1000);
+        create_unimplemented_device("U55 timing adapter 1", 0x48103000, 0x1000);
+    }
+
     create_non_mpc_ram(mms);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
@@ -1115,6 +1223,33 @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
     mps2tz_set_default_ram_info(mmc);
 }
 
+static void mps3tz_an547_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+    MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
+
+    mc->desc = "ARM MPS3 with AN547 FPGA image for Cortex-M55";
+    mc->default_cpus = 1;
+    mc->min_cpus = mc->default_cpus;
+    mc->max_cpus = mc->default_cpus;
+    mmc->fpga_type = FPGA_AN547;
+    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m55");
+    mmc->scc_id = 0x41055470;
+    mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
+    mmc->apb_periph_frq = 25 * 1000 * 1000; /* 25MHz */
+    mmc->oscclk = an524_oscclk; /* same as AN524 */
+    mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
+    mmc->fpgaio_num_leds = 10;
+    mmc->fpgaio_has_switches = true;
+    mmc->fpgaio_has_dbgctrl = true;
+    mmc->numirq = 96;
+    mmc->uart_overflow_irq = 48;
+    mmc->init_svtor = 0x00000000;
+    mmc->raminfo = an547_raminfo;
+    mmc->armsse_type = TYPE_SSE300;
+    mps2tz_set_default_ram_info(mmc);
+}
+
 static const TypeInfo mps2tz_info = {
     .name = TYPE_MPS2TZ_MACHINE,
     .parent = TYPE_MACHINE,
@@ -1146,12 +1281,19 @@ static const TypeInfo mps3tz_an524_info = {
     .class_init = mps3tz_an524_class_init,
 };
 
+static const TypeInfo mps3tz_an547_info = {
+    .name = TYPE_MPS3TZ_AN547_MACHINE,
+    .parent = TYPE_MPS2TZ_MACHINE,
+    .class_init = mps3tz_an547_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_register_static(&mps3tz_an524_info);
+    type_register_static(&mps3tz_an547_info);
 }
 
 type_init(mps2tz_machine_init);
-- 
2.20.1



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

* [PULL 43/54] docs/system/arm/mps2.rst: Document the new mps3-an547 board
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (41 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 42/54] hw/arm/mps2-tz: Add new mps3-an547 board Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 44/54] tests/qtest/sse-timer-test: Add simple test of the SSE counter Peter Maydell
                   ` (11 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Add brief documentation of the new mps3-an547 board.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210219144617.4782-44-peter.maydell@linaro.org
---
 docs/system/arm/mps2.rst | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
index 601ccea15cb..f83b1517871 100644
--- a/docs/system/arm/mps2.rst
+++ b/docs/system/arm/mps2.rst
@@ -1,5 +1,5 @@
-Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``)
-=========================================================================================================================================
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``, ``mps3-an547``)
+=========================================================================================================================================================
 
 These board models all use Arm M-profile CPUs.
 
@@ -27,6 +27,8 @@ QEMU models the following FPGA images:
   Dual Cortex-M33 as documented in Arm Application Note AN521
 ``mps3-an524``
   Dual Cortex-M33 on an MPS3, as documented in Arm Application Note AN524
+``mps3-an547``
+  Cortex-M55 on an MPS3, as documented in Arm Application Note AN547
 
 Differences between QEMU and real hardware:
 
-- 
2.20.1



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

* [PULL 44/54] tests/qtest/sse-timer-test: Add simple test of the SSE counter
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (42 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 43/54] docs/system/arm/mps2.rst: Document the " Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 45/54] tests/qtest/sse-timer-test: Test the system timer Peter Maydell
                   ` (10 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Add a simple qtest to exercise the new system counter device in the
SSE-300.

We'll add tests of the system timer device here too, so this includes
scaffolding (register definitions, etc) for those.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210219144617.4782-45-peter.maydell@linaro.org
---
 tests/qtest/sse-timer-test.c | 117 +++++++++++++++++++++++++++++++++++
 MAINTAINERS                  |   1 +
 tests/qtest/meson.build      |   1 +
 3 files changed, 119 insertions(+)
 create mode 100644 tests/qtest/sse-timer-test.c

diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
new file mode 100644
index 00000000000..5b86ef6dbbf
--- /dev/null
+++ b/tests/qtest/sse-timer-test.c
@@ -0,0 +1,117 @@
+/*
+ * QTest testcase for the SSE timer device
+ *
+ * Copyright (c) 2021 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest-single.h"
+
+/*
+ * SSE-123/SSE-300 timer in the mps3-an547 board, where it is driven
+ * at 32MHz, so 31.25ns per tick.
+ */
+#define TIMER_BASE 0x48000000
+
+/* PERIPHNSPPC0 register in the SSE-300 Secure Access Configuration block */
+#define PERIPHNSPPC0 (0x50080000 + 0x70)
+
+/* Base of the System Counter control frame */
+#define COUNTER_BASE 0x58100000
+
+/* SSE counter register offsets in the control frame */
+#define CNTCR 0
+#define CNTSR 0x4
+#define CNTCV_LO 0x8
+#define CNTCV_HI 0xc
+#define CNTSCR 0x10
+
+/* SSE timer register offsets */
+#define CNTPCT_LO 0
+#define CNTPCT_HI 4
+#define CNTFRQ 0x10
+#define CNTP_CVAL_LO 0x20
+#define CNTP_CVAL_HI 0x24
+#define CNTP_TVAL 0x28
+#define CNTP_CTL 0x2c
+#define CNTP_AIVAL_LO 0x40
+#define CNTP_AIVAL_HI 0x44
+#define CNTP_AIVAL_RELOAD 0x48
+#define CNTP_AIVAL_CTL 0x4c
+
+/* 4 ticks in nanoseconds (so we can work in integers) */
+#define FOUR_TICKS 125
+
+static void clock_step_ticks(uint64_t ticks)
+{
+    /*
+     * Advance the qtest clock by however many nanoseconds we
+     * need to move the timer forward the specified number of ticks.
+     * ticks must be a multiple of 4, so we get a whole number of ns.
+     */
+    assert(!(ticks & 3));
+    clock_step(FOUR_TICKS * (ticks >> 2));
+}
+
+static void reset_counter_and_timer(void)
+{
+    /*
+     * Reset the system counter and the timer between tests. This
+     * isn't a full reset, but it's sufficient for what the tests check.
+     */
+    writel(COUNTER_BASE + CNTCR, 0);
+    writel(TIMER_BASE + CNTP_CTL, 0);
+    writel(TIMER_BASE + CNTP_AIVAL_CTL, 0);
+    writel(COUNTER_BASE + CNTCV_LO, 0);
+    writel(COUNTER_BASE + CNTCV_HI, 0);
+}
+
+static void test_counter(void)
+{
+    /* Basic counter functionality test */
+
+    reset_counter_and_timer();
+    /* The counter should start disabled: check that it doesn't move */
+    clock_step_ticks(100);
+    g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_LO), ==, 0);
+    g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
+    /* Now enable it and check that it does count */
+    writel(COUNTER_BASE + CNTCR, 1);
+    clock_step_ticks(100);
+    g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_LO), ==, 100);
+    g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
+    /* Check the counter scaling functionality */
+    writel(COUNTER_BASE + CNTCR, 0);
+    writel(COUNTER_BASE + CNTSCR, 0x00100000); /* 1/16th normal speed */
+    writel(COUNTER_BASE + CNTCR, 5); /* EN, SCEN */
+    clock_step_ticks(160);
+    g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_LO), ==, 110);
+    g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
+}
+
+int main(int argc, char **argv)
+{
+    int r;
+
+    g_test_init(&argc, &argv, NULL);
+
+    qtest_start("-machine mps3-an547");
+
+    qtest_add_func("/sse-timer/counter", test_counter);
+
+    r = g_test_run();
+
+    qtest_end();
+
+    return r;
+}
diff --git a/MAINTAINERS b/MAINTAINERS
index bd863cfeca4..be8385255d0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -757,6 +757,7 @@ F: hw/timer/sse-counter.c
 F: include/hw/timer/sse-counter.h
 F: hw/timer/sse-timer.c
 F: include/hw/timer/sse-timer.h
+F: tests/qtest/sse-timer-test.c
 F: docs/system/arm/mps2.rst
 
 Musca
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 58efc46144e..2688e1bfad7 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -157,6 +157,7 @@ qtests_npcm7xx = \
    'npcm7xx_watchdog_timer-test'] + \
    (slirp.found() ? ['npcm7xx_emc-test'] : [])
 qtests_arm = \
+  (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
   (config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
   (config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
   (config_all_devices.has_key('CONFIG_CMSDK_APB_WATCHDOG') ? ['cmsdk-apb-watchdog-test'] : []) + \
-- 
2.20.1



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

* [PULL 45/54] tests/qtest/sse-timer-test: Test the system timer
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (43 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 44/54] tests/qtest/sse-timer-test: Add simple test of the SSE counter Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 46/54] tests/qtest/sse-timer-test: Test counter scaling changes Peter Maydell
                   ` (9 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Add a test which tests various parts of the functionality of the
SSE system timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 tests/qtest/sse-timer-test.c | 91 ++++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
index 5b86ef6dbbf..f4f6704b308 100644
--- a/tests/qtest/sse-timer-test.c
+++ b/tests/qtest/sse-timer-test.c
@@ -99,6 +99,96 @@ static void test_counter(void)
     g_assert_cmpuint(readl(COUNTER_BASE + CNTCV_HI), ==, 0);
 }
 
+static void test_timer(void)
+{
+    /* Basic timer functionality test */
+
+    reset_counter_and_timer();
+    /*
+     * The timer is behind a Peripheral Protection Controller, and
+     * qtest accesses are always non-secure (no memory attributes),
+     * so we must program the PPC to accept NS transactions.  TIMER0
+     * is on port 0 of PPC0, controlled by bit 0 of this register.
+     */
+    writel(PERIPHNSPPC0, 1);
+    /* We must enable the System Counter or the timer won't run. */
+    writel(COUNTER_BASE + CNTCR, 1);
+
+    /* Timer starts disabled and with a counter of 0 */
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 0);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 0);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0);
+
+    /* Turn it on */
+    writel(TIMER_BASE + CNTP_CTL, 1);
+
+    /* Is the timer ticking? */
+    clock_step_ticks(100);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 100);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0);
+
+    /* Set the CompareValue to 4000 ticks */
+    writel(TIMER_BASE + CNTP_CVAL_LO, 4000);
+    writel(TIMER_BASE + CNTP_CVAL_HI, 0);
+
+    /* Check TVAL view of the counter */
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_TVAL), ==, 3900);
+
+    /* Advance to the CompareValue mark and check ISTATUS is set */
+    clock_step_ticks(3900);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_TVAL), ==, 0);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
+
+    /* Now exercise the auto-reload part of the timer */
+    writel(TIMER_BASE + CNTP_AIVAL_RELOAD, 200);
+    writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
+
+    /* Check AIVAL was reloaded and that ISTATUS is now clear */
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4200);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
+
+    /*
+     * Check that when we advance forward to the reload time the interrupt
+     * fires and the value reloads
+     */
+    clock_step_ticks(100);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
+    clock_step_ticks(100);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4400);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0);
+
+    clock_step_ticks(100);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
+    /* Check that writing 0 to CLR clears the interrupt */
+    writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
+    /* Check that when we move forward to the reload time it fires again */
+    clock_step_ticks(100);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4600);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0);
+
+    /*
+     * Step the clock far enough that we overflow the low half of the
+     * CNTPCT and AIVAL registers, and check that their high halves
+     * give the right values. We do the forward movement in
+     * non-autoinc mode because otherwise it takes forever as the
+     * timer has to emulate all the 'reload at t + N, t + 2N, etc'
+     * steps.
+     */
+    writel(TIMER_BASE + CNTP_AIVAL_CTL, 0);
+    clock_step_ticks(0x42ULL << 32);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 4400);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0x42);
+
+    /* Turn on the autoinc again to check AIVAL_HI */
+    writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4600);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0x42);
+}
+
 int main(int argc, char **argv)
 {
     int r;
@@ -108,6 +198,7 @@ int main(int argc, char **argv)
     qtest_start("-machine mps3-an547");
 
     qtest_add_func("/sse-timer/counter", test_counter);
+    qtest_add_func("/sse-timer/timer", test_timer);
 
     r = g_test_run();
 
-- 
2.20.1



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

* [PULL 46/54] tests/qtest/sse-timer-test: Test counter scaling changes
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (44 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 45/54] tests/qtest/sse-timer-test: Test the system timer Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 47/54] target/arm: Restrict v7A TCG cpus to TCG accel Peter Maydell
                   ` (8 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

Test that when we change the scaling of the system counter that the
system timer responds appropriately.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
 tests/qtest/sse-timer-test.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
index f4f6704b308..a65d7542d51 100644
--- a/tests/qtest/sse-timer-test.c
+++ b/tests/qtest/sse-timer-test.c
@@ -189,6 +189,37 @@ static void test_timer(void)
     g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0x42);
 }
 
+static void test_timer_scale_change(void)
+{
+    /*
+     * Test that the timer responds correctly to counter
+     * scaling changes while it has an active timer.
+     */
+    reset_counter_and_timer();
+    /* Give ourselves access to the timer, and enable the counter and timer */
+    writel(PERIPHNSPPC0, 1);
+    writel(COUNTER_BASE + CNTCR, 1);
+    writel(TIMER_BASE + CNTP_CTL, 1);
+    /* Set the CompareValue to 4000 ticks */
+    writel(TIMER_BASE + CNTP_CVAL_LO, 4000);
+    writel(TIMER_BASE + CNTP_CVAL_HI, 0);
+    /* Advance halfway and check ISTATUS is not set */
+    clock_step_ticks(2000);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
+    /* Reprogram the counter to run at 1/16th speed */
+    writel(COUNTER_BASE + CNTCR, 0);
+    writel(COUNTER_BASE + CNTSCR, 0x00100000); /* 1/16th normal speed */
+    writel(COUNTER_BASE + CNTCR, 5); /* EN, SCEN */
+    /* Advance to where the timer would have fired and check it has not */
+    clock_step_ticks(2000);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
+    /* Advance to where the timer must fire at the new clock rate */
+    clock_step_ticks(29996);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 1);
+    clock_step_ticks(4);
+    g_assert_cmpuint(readl(TIMER_BASE + CNTP_CTL), ==, 5);
+}
+
 int main(int argc, char **argv)
 {
     int r;
@@ -199,6 +230,7 @@ int main(int argc, char **argv)
 
     qtest_add_func("/sse-timer/counter", test_counter);
     qtest_add_func("/sse-timer/timer", test_timer);
+    qtest_add_func("/sse-timer/timer-scale-change", test_timer_scale_change);
 
     r = g_test_run();
 
-- 
2.20.1



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

* [PULL 47/54] target/arm: Restrict v7A TCG cpus to TCG accel
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (45 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 46/54] tests/qtest/sse-timer-test: Test counter scaling changes Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 48/54] hw/dma: Implement a Xilinx CSU DMA model Peter Maydell
                   ` (7 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

From: Philippe Mathieu-Daudé <f4bug@amsat.org>

KVM requires the target cpu to be at least ARMv8 architecture
(support on ARMv7 has been dropped in commit 82bf7ae84ce:
"target/arm: Remove KVM support for 32-bit Arm hosts").

A KVM-only build won't be able to run TCG cpus, move the
v7A CPU definitions to cpu_tcg.c.

Reported-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210306151801.2388182-1-f4bug@amsat.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/cpu.c     | 335 -------------------------------------------
 target/arm/cpu_tcg.c | 318 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 318 insertions(+), 335 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 6facb66f4d2..ae04884408c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1922,331 +1922,6 @@ static ObjectClass *arm_cpu_class_by_name(const char *cpu_model)
     return oc;
 }
 
-/* CPU models. These are not needed for the AArch64 linux-user build. */
-#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
-
-static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
-    { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    { .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    REGINFO_SENTINEL
-};
-
-static void cortex_a8_initfn(Object *obj)
-{
-    ARMCPU *cpu = ARM_CPU(obj);
-
-    cpu->dtb_compatible = "arm,cortex-a8";
-    set_feature(&cpu->env, ARM_FEATURE_V7);
-    set_feature(&cpu->env, ARM_FEATURE_NEON);
-    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
-    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
-    set_feature(&cpu->env, ARM_FEATURE_EL3);
-    cpu->midr = 0x410fc080;
-    cpu->reset_fpsid = 0x410330c0;
-    cpu->isar.mvfr0 = 0x11110222;
-    cpu->isar.mvfr1 = 0x00011111;
-    cpu->ctr = 0x82048004;
-    cpu->reset_sctlr = 0x00c50078;
-    cpu->isar.id_pfr0 = 0x1031;
-    cpu->isar.id_pfr1 = 0x11;
-    cpu->isar.id_dfr0 = 0x400;
-    cpu->id_afr0 = 0;
-    cpu->isar.id_mmfr0 = 0x31100003;
-    cpu->isar.id_mmfr1 = 0x20000000;
-    cpu->isar.id_mmfr2 = 0x01202000;
-    cpu->isar.id_mmfr3 = 0x11;
-    cpu->isar.id_isar0 = 0x00101111;
-    cpu->isar.id_isar1 = 0x12112111;
-    cpu->isar.id_isar2 = 0x21232031;
-    cpu->isar.id_isar3 = 0x11112131;
-    cpu->isar.id_isar4 = 0x00111142;
-    cpu->isar.dbgdidr = 0x15141000;
-    cpu->clidr = (1 << 27) | (2 << 24) | 3;
-    cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
-    cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
-    cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
-    cpu->reset_auxcr = 2;
-    define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
-}
-
-static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
-    /*
-     * power_control should be set to maximum latency. Again,
-     * default to 0 and set by private hook
-     */
-    { .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .resetvalue = 0,
-      .fieldoffset = offsetof(CPUARMState, cp15.c15_power_control) },
-    { .name = "A9_DIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 1,
-      .access = PL1_RW, .resetvalue = 0,
-      .fieldoffset = offsetof(CPUARMState, cp15.c15_diagnostic) },
-    { .name = "A9_PWRDIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 2,
-      .access = PL1_RW, .resetvalue = 0,
-      .fieldoffset = offsetof(CPUARMState, cp15.c15_power_diagnostic) },
-    { .name = "NEONBUSY", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
-      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
-    /* TLB lockdown control */
-    { .name = "TLB_LOCKR", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 2,
-      .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
-    { .name = "TLB_LOCKW", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 4,
-      .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
-    { .name = "TLB_VA", .cp = 15, .crn = 15, .crm = 5, .opc1 = 5, .opc2 = 2,
-      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
-    { .name = "TLB_PA", .cp = 15, .crn = 15, .crm = 6, .opc1 = 5, .opc2 = 2,
-      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
-    { .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
-      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
-    REGINFO_SENTINEL
-};
-
-static void cortex_a9_initfn(Object *obj)
-{
-    ARMCPU *cpu = ARM_CPU(obj);
-
-    cpu->dtb_compatible = "arm,cortex-a9";
-    set_feature(&cpu->env, ARM_FEATURE_V7);
-    set_feature(&cpu->env, ARM_FEATURE_NEON);
-    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
-    set_feature(&cpu->env, ARM_FEATURE_EL3);
-    /*
-     * Note that A9 supports the MP extensions even for
-     * A9UP and single-core A9MP (which are both different
-     * and valid configurations; we don't model A9UP).
-     */
-    set_feature(&cpu->env, ARM_FEATURE_V7MP);
-    set_feature(&cpu->env, ARM_FEATURE_CBAR);
-    cpu->midr = 0x410fc090;
-    cpu->reset_fpsid = 0x41033090;
-    cpu->isar.mvfr0 = 0x11110222;
-    cpu->isar.mvfr1 = 0x01111111;
-    cpu->ctr = 0x80038003;
-    cpu->reset_sctlr = 0x00c50078;
-    cpu->isar.id_pfr0 = 0x1031;
-    cpu->isar.id_pfr1 = 0x11;
-    cpu->isar.id_dfr0 = 0x000;
-    cpu->id_afr0 = 0;
-    cpu->isar.id_mmfr0 = 0x00100103;
-    cpu->isar.id_mmfr1 = 0x20000000;
-    cpu->isar.id_mmfr2 = 0x01230000;
-    cpu->isar.id_mmfr3 = 0x00002111;
-    cpu->isar.id_isar0 = 0x00101111;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232041;
-    cpu->isar.id_isar3 = 0x11112131;
-    cpu->isar.id_isar4 = 0x00111142;
-    cpu->isar.dbgdidr = 0x35141000;
-    cpu->clidr = (1 << 27) | (1 << 24) | 3;
-    cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
-    cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
-    define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
-}
-
-#ifndef CONFIG_USER_ONLY
-static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
-    MachineState *ms = MACHINE(qdev_get_machine());
-
-    /*
-     * Linux wants the number of processors from here.
-     * Might as well set the interrupt-controller bit too.
-     */
-    return ((ms->smp.cpus - 1) << 24) | (1 << 23);
-}
-#endif
-
-static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
-#ifndef CONFIG_USER_ONLY
-    { .name = "L2CTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
-      .access = PL1_RW, .resetvalue = 0, .readfn = a15_l2ctlr_read,
-      .writefn = arm_cp_write_ignore, },
-#endif
-    { .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
-      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
-    REGINFO_SENTINEL
-};
-
-static void cortex_a7_initfn(Object *obj)
-{
-    ARMCPU *cpu = ARM_CPU(obj);
-
-    cpu->dtb_compatible = "arm,cortex-a7";
-    set_feature(&cpu->env, ARM_FEATURE_V7VE);
-    set_feature(&cpu->env, ARM_FEATURE_NEON);
-    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
-    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
-    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
-    set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
-    set_feature(&cpu->env, ARM_FEATURE_EL2);
-    set_feature(&cpu->env, ARM_FEATURE_EL3);
-    set_feature(&cpu->env, ARM_FEATURE_PMU);
-    cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
-    cpu->midr = 0x410fc075;
-    cpu->reset_fpsid = 0x41023075;
-    cpu->isar.mvfr0 = 0x10110222;
-    cpu->isar.mvfr1 = 0x11111111;
-    cpu->ctr = 0x84448003;
-    cpu->reset_sctlr = 0x00c50078;
-    cpu->isar.id_pfr0 = 0x00001131;
-    cpu->isar.id_pfr1 = 0x00011011;
-    cpu->isar.id_dfr0 = 0x02010555;
-    cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x10101105;
-    cpu->isar.id_mmfr1 = 0x40000000;
-    cpu->isar.id_mmfr2 = 0x01240000;
-    cpu->isar.id_mmfr3 = 0x02102211;
-    /*
-     * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
-     * table 4-41 gives 0x02101110, which includes the arm div insns.
-     */
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232041;
-    cpu->isar.id_isar3 = 0x11112131;
-    cpu->isar.id_isar4 = 0x10011142;
-    cpu->isar.dbgdidr = 0x3515f005;
-    cpu->clidr = 0x0a200023;
-    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
-    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
-    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
-    define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
-}
-
-static void cortex_a15_initfn(Object *obj)
-{
-    ARMCPU *cpu = ARM_CPU(obj);
-
-    cpu->dtb_compatible = "arm,cortex-a15";
-    set_feature(&cpu->env, ARM_FEATURE_V7VE);
-    set_feature(&cpu->env, ARM_FEATURE_NEON);
-    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
-    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
-    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
-    set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
-    set_feature(&cpu->env, ARM_FEATURE_EL2);
-    set_feature(&cpu->env, ARM_FEATURE_EL3);
-    set_feature(&cpu->env, ARM_FEATURE_PMU);
-    cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
-    cpu->midr = 0x412fc0f1;
-    cpu->reset_fpsid = 0x410430f0;
-    cpu->isar.mvfr0 = 0x10110222;
-    cpu->isar.mvfr1 = 0x11111111;
-    cpu->ctr = 0x8444c004;
-    cpu->reset_sctlr = 0x00c50078;
-    cpu->isar.id_pfr0 = 0x00001131;
-    cpu->isar.id_pfr1 = 0x00011011;
-    cpu->isar.id_dfr0 = 0x02010555;
-    cpu->id_afr0 = 0x00000000;
-    cpu->isar.id_mmfr0 = 0x10201105;
-    cpu->isar.id_mmfr1 = 0x20000000;
-    cpu->isar.id_mmfr2 = 0x01240000;
-    cpu->isar.id_mmfr3 = 0x02102211;
-    cpu->isar.id_isar0 = 0x02101110;
-    cpu->isar.id_isar1 = 0x13112111;
-    cpu->isar.id_isar2 = 0x21232041;
-    cpu->isar.id_isar3 = 0x11112131;
-    cpu->isar.id_isar4 = 0x10011142;
-    cpu->isar.dbgdidr = 0x3515f021;
-    cpu->clidr = 0x0a200023;
-    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
-    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
-    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
-    define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
-}
-
-#ifndef TARGET_AARCH64
-/*
- * -cpu max: a CPU with as many features enabled as our emulation supports.
- * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
- * this only needs to handle 32 bits, and need not care about KVM.
- */
-static void arm_max_initfn(Object *obj)
-{
-    ARMCPU *cpu = ARM_CPU(obj);
-
-    cortex_a15_initfn(obj);
-
-    /* old-style VFP short-vector support */
-    cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
-
-#ifdef CONFIG_USER_ONLY
-    /*
-     * We don't set these in system emulation mode for the moment,
-     * since we don't correctly set (all of) the ID registers to
-     * advertise them.
-     */
-    set_feature(&cpu->env, ARM_FEATURE_V8);
-    {
-        uint32_t t;
-
-        t = cpu->isar.id_isar5;
-        t = FIELD_DP32(t, ID_ISAR5, AES, 2);
-        t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
-        t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
-        t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
-        t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
-        t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
-        cpu->isar.id_isar5 = t;
-
-        t = cpu->isar.id_isar6;
-        t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
-        t = FIELD_DP32(t, ID_ISAR6, DP, 1);
-        t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
-        t = FIELD_DP32(t, ID_ISAR6, SB, 1);
-        t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
-        cpu->isar.id_isar6 = t;
-
-        t = cpu->isar.mvfr1;
-        t = FIELD_DP32(t, MVFR1, FPHP, 3);     /* v8.2-FP16 */
-        t = FIELD_DP32(t, MVFR1, SIMDHP, 2);   /* v8.2-FP16 */
-        cpu->isar.mvfr1 = t;
-
-        t = cpu->isar.mvfr2;
-        t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
-        t = FIELD_DP32(t, MVFR2, FPMISC, 4);   /* FP MaxNum */
-        cpu->isar.mvfr2 = t;
-
-        t = cpu->isar.id_mmfr3;
-        t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
-        cpu->isar.id_mmfr3 = t;
-
-        t = cpu->isar.id_mmfr4;
-        t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
-        t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
-        t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
-        t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
-        cpu->isar.id_mmfr4 = t;
-
-        t = cpu->isar.id_pfr0;
-        t = FIELD_DP32(t, ID_PFR0, DIT, 1);
-        cpu->isar.id_pfr0 = t;
-
-        t = cpu->isar.id_pfr2;
-        t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
-        cpu->isar.id_pfr2 = t;
-    }
-#endif
-}
-#endif
-
-#endif /* !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64) */
-
-static const ARMCPUInfo arm_cpus[] = {
-#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
-    { .name = "cortex-a7",   .initfn = cortex_a7_initfn },
-    { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
-    { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
-    { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
-#ifndef TARGET_AARCH64
-    { .name = "max",         .initfn = arm_max_initfn },
-#endif
-#ifdef CONFIG_USER_ONLY
-    { .name = "any",         .initfn = arm_max_initfn },
-#endif
-#endif
-};
-
 static Property arm_cpu_properties[] = {
     DEFINE_PROP_UINT32("psci-conduit", ARMCPU, psci_conduit, 0),
     DEFINE_PROP_UINT64("midr", ARMCPU, midr, 0),
@@ -2390,21 +2065,11 @@ static const TypeInfo arm_cpu_type_info = {
 
 static void arm_cpu_register_types(void)
 {
-    const size_t cpu_count = ARRAY_SIZE(arm_cpus);
-
     type_register_static(&arm_cpu_type_info);
 
 #ifdef CONFIG_KVM
     type_register_static(&host_arm_cpu_type_info);
 #endif
-
-    if (cpu_count) {
-        size_t i;
-
-        for (i = 0; i < cpu_count; ++i) {
-            arm_cpu_register(&arm_cpus[i]);
-        }
-    }
 }
 
 type_init(arm_cpu_register_types)
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
index fb07a336939..046e476f65f 100644
--- a/target/arm/cpu_tcg.c
+++ b/target/arm/cpu_tcg.c
@@ -15,6 +15,9 @@
 #endif /* CONFIG_TCG */
 #include "internals.h"
 #include "target/arm/idau.h"
+#if !defined(CONFIG_USER_ONLY)
+#include "hw/boards.h"
+#endif
 
 /* CPU models. These are not needed for the AArch64 linux-user build. */
 #if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
@@ -255,6 +258,236 @@ static void arm11mpcore_initfn(Object *obj)
     cpu->reset_auxcr = 1;
 }
 
+static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
+    { .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    { .name = "L2AUXCR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    REGINFO_SENTINEL
+};
+
+static void cortex_a8_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,cortex-a8";
+    set_feature(&cpu->env, ARM_FEATURE_V7);
+    set_feature(&cpu->env, ARM_FEATURE_NEON);
+    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
+    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
+    set_feature(&cpu->env, ARM_FEATURE_EL3);
+    cpu->midr = 0x410fc080;
+    cpu->reset_fpsid = 0x410330c0;
+    cpu->isar.mvfr0 = 0x11110222;
+    cpu->isar.mvfr1 = 0x00011111;
+    cpu->ctr = 0x82048004;
+    cpu->reset_sctlr = 0x00c50078;
+    cpu->isar.id_pfr0 = 0x1031;
+    cpu->isar.id_pfr1 = 0x11;
+    cpu->isar.id_dfr0 = 0x400;
+    cpu->id_afr0 = 0;
+    cpu->isar.id_mmfr0 = 0x31100003;
+    cpu->isar.id_mmfr1 = 0x20000000;
+    cpu->isar.id_mmfr2 = 0x01202000;
+    cpu->isar.id_mmfr3 = 0x11;
+    cpu->isar.id_isar0 = 0x00101111;
+    cpu->isar.id_isar1 = 0x12112111;
+    cpu->isar.id_isar2 = 0x21232031;
+    cpu->isar.id_isar3 = 0x11112131;
+    cpu->isar.id_isar4 = 0x00111142;
+    cpu->isar.dbgdidr = 0x15141000;
+    cpu->clidr = (1 << 27) | (2 << 24) | 3;
+    cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */
+    cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */
+    cpu->ccsidr[2] = 0xf0000000; /* No L2 icache. */
+    cpu->reset_auxcr = 2;
+    define_arm_cp_regs(cpu, cortexa8_cp_reginfo);
+}
+
+static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
+    /*
+     * power_control should be set to maximum latency. Again,
+     * default to 0 and set by private hook
+     */
+    { .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.c15_power_control) },
+    { .name = "A9_DIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 1,
+      .access = PL1_RW, .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.c15_diagnostic) },
+    { .name = "A9_PWRDIAG", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 2,
+      .access = PL1_RW, .resetvalue = 0,
+      .fieldoffset = offsetof(CPUARMState, cp15.c15_power_diagnostic) },
+    { .name = "NEONBUSY", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
+    /* TLB lockdown control */
+    { .name = "TLB_LOCKR", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 2,
+      .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
+    { .name = "TLB_LOCKW", .cp = 15, .crn = 15, .crm = 4, .opc1 = 5, .opc2 = 4,
+      .access = PL1_W, .resetvalue = 0, .type = ARM_CP_NOP },
+    { .name = "TLB_VA", .cp = 15, .crn = 15, .crm = 5, .opc1 = 5, .opc2 = 2,
+      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
+    { .name = "TLB_PA", .cp = 15, .crn = 15, .crm = 6, .opc1 = 5, .opc2 = 2,
+      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
+    { .name = "TLB_ATTR", .cp = 15, .crn = 15, .crm = 7, .opc1 = 5, .opc2 = 2,
+      .access = PL1_RW, .resetvalue = 0, .type = ARM_CP_CONST },
+    REGINFO_SENTINEL
+};
+
+static void cortex_a9_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,cortex-a9";
+    set_feature(&cpu->env, ARM_FEATURE_V7);
+    set_feature(&cpu->env, ARM_FEATURE_NEON);
+    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
+    set_feature(&cpu->env, ARM_FEATURE_EL3);
+    /*
+     * Note that A9 supports the MP extensions even for
+     * A9UP and single-core A9MP (which are both different
+     * and valid configurations; we don't model A9UP).
+     */
+    set_feature(&cpu->env, ARM_FEATURE_V7MP);
+    set_feature(&cpu->env, ARM_FEATURE_CBAR);
+    cpu->midr = 0x410fc090;
+    cpu->reset_fpsid = 0x41033090;
+    cpu->isar.mvfr0 = 0x11110222;
+    cpu->isar.mvfr1 = 0x01111111;
+    cpu->ctr = 0x80038003;
+    cpu->reset_sctlr = 0x00c50078;
+    cpu->isar.id_pfr0 = 0x1031;
+    cpu->isar.id_pfr1 = 0x11;
+    cpu->isar.id_dfr0 = 0x000;
+    cpu->id_afr0 = 0;
+    cpu->isar.id_mmfr0 = 0x00100103;
+    cpu->isar.id_mmfr1 = 0x20000000;
+    cpu->isar.id_mmfr2 = 0x01230000;
+    cpu->isar.id_mmfr3 = 0x00002111;
+    cpu->isar.id_isar0 = 0x00101111;
+    cpu->isar.id_isar1 = 0x13112111;
+    cpu->isar.id_isar2 = 0x21232041;
+    cpu->isar.id_isar3 = 0x11112131;
+    cpu->isar.id_isar4 = 0x00111142;
+    cpu->isar.dbgdidr = 0x35141000;
+    cpu->clidr = (1 << 27) | (1 << 24) | 3;
+    cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */
+    cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */
+    define_arm_cp_regs(cpu, cortexa9_cp_reginfo);
+}
+
+#ifndef CONFIG_USER_ONLY
+static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    MachineState *ms = MACHINE(qdev_get_machine());
+
+    /*
+     * Linux wants the number of processors from here.
+     * Might as well set the interrupt-controller bit too.
+     */
+    return ((ms->smp.cpus - 1) << 24) | (1 << 23);
+}
+#endif
+
+static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
+#ifndef CONFIG_USER_ONLY
+    { .name = "L2CTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 2,
+      .access = PL1_RW, .resetvalue = 0, .readfn = a15_l2ctlr_read,
+      .writefn = arm_cp_write_ignore, },
+#endif
+    { .name = "L2ECTLR", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 3,
+      .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+    REGINFO_SENTINEL
+};
+
+static void cortex_a7_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,cortex-a7";
+    set_feature(&cpu->env, ARM_FEATURE_V7VE);
+    set_feature(&cpu->env, ARM_FEATURE_NEON);
+    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
+    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
+    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
+    set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
+    set_feature(&cpu->env, ARM_FEATURE_EL2);
+    set_feature(&cpu->env, ARM_FEATURE_EL3);
+    set_feature(&cpu->env, ARM_FEATURE_PMU);
+    cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
+    cpu->midr = 0x410fc075;
+    cpu->reset_fpsid = 0x41023075;
+    cpu->isar.mvfr0 = 0x10110222;
+    cpu->isar.mvfr1 = 0x11111111;
+    cpu->ctr = 0x84448003;
+    cpu->reset_sctlr = 0x00c50078;
+    cpu->isar.id_pfr0 = 0x00001131;
+    cpu->isar.id_pfr1 = 0x00011011;
+    cpu->isar.id_dfr0 = 0x02010555;
+    cpu->id_afr0 = 0x00000000;
+    cpu->isar.id_mmfr0 = 0x10101105;
+    cpu->isar.id_mmfr1 = 0x40000000;
+    cpu->isar.id_mmfr2 = 0x01240000;
+    cpu->isar.id_mmfr3 = 0x02102211;
+    /*
+     * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
+     * table 4-41 gives 0x02101110, which includes the arm div insns.
+     */
+    cpu->isar.id_isar0 = 0x02101110;
+    cpu->isar.id_isar1 = 0x13112111;
+    cpu->isar.id_isar2 = 0x21232041;
+    cpu->isar.id_isar3 = 0x11112131;
+    cpu->isar.id_isar4 = 0x10011142;
+    cpu->isar.dbgdidr = 0x3515f005;
+    cpu->clidr = 0x0a200023;
+    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
+    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
+    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
+    define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
+}
+
+static void cortex_a15_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    cpu->dtb_compatible = "arm,cortex-a15";
+    set_feature(&cpu->env, ARM_FEATURE_V7VE);
+    set_feature(&cpu->env, ARM_FEATURE_NEON);
+    set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
+    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
+    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
+    set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
+    set_feature(&cpu->env, ARM_FEATURE_EL2);
+    set_feature(&cpu->env, ARM_FEATURE_EL3);
+    set_feature(&cpu->env, ARM_FEATURE_PMU);
+    cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
+    cpu->midr = 0x412fc0f1;
+    cpu->reset_fpsid = 0x410430f0;
+    cpu->isar.mvfr0 = 0x10110222;
+    cpu->isar.mvfr1 = 0x11111111;
+    cpu->ctr = 0x8444c004;
+    cpu->reset_sctlr = 0x00c50078;
+    cpu->isar.id_pfr0 = 0x00001131;
+    cpu->isar.id_pfr1 = 0x00011011;
+    cpu->isar.id_dfr0 = 0x02010555;
+    cpu->id_afr0 = 0x00000000;
+    cpu->isar.id_mmfr0 = 0x10201105;
+    cpu->isar.id_mmfr1 = 0x20000000;
+    cpu->isar.id_mmfr2 = 0x01240000;
+    cpu->isar.id_mmfr3 = 0x02102211;
+    cpu->isar.id_isar0 = 0x02101110;
+    cpu->isar.id_isar1 = 0x13112111;
+    cpu->isar.id_isar2 = 0x21232041;
+    cpu->isar.id_isar3 = 0x11112131;
+    cpu->isar.id_isar4 = 0x10011142;
+    cpu->isar.dbgdidr = 0x3515f021;
+    cpu->clidr = 0x0a200023;
+    cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
+    cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
+    cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
+    define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
+}
+
 static void cortex_m0_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
@@ -695,6 +928,81 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
     cc->gdb_core_xml_file = "arm-m-profile.xml";
 }
 
+#ifndef TARGET_AARCH64
+/*
+ * -cpu max: a CPU with as many features enabled as our emulation supports.
+ * The version of '-cpu max' for qemu-system-aarch64 is defined in cpu64.c;
+ * this only needs to handle 32 bits, and need not care about KVM.
+ */
+static void arm_max_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+
+    cortex_a15_initfn(obj);
+
+    /* old-style VFP short-vector support */
+    cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
+
+#ifdef CONFIG_USER_ONLY
+    /*
+     * We don't set these in system emulation mode for the moment,
+     * since we don't correctly set (all of) the ID registers to
+     * advertise them.
+     */
+    set_feature(&cpu->env, ARM_FEATURE_V8);
+    {
+        uint32_t t;
+
+        t = cpu->isar.id_isar5;
+        t = FIELD_DP32(t, ID_ISAR5, AES, 2);
+        t = FIELD_DP32(t, ID_ISAR5, SHA1, 1);
+        t = FIELD_DP32(t, ID_ISAR5, SHA2, 1);
+        t = FIELD_DP32(t, ID_ISAR5, CRC32, 1);
+        t = FIELD_DP32(t, ID_ISAR5, RDM, 1);
+        t = FIELD_DP32(t, ID_ISAR5, VCMA, 1);
+        cpu->isar.id_isar5 = t;
+
+        t = cpu->isar.id_isar6;
+        t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1);
+        t = FIELD_DP32(t, ID_ISAR6, DP, 1);
+        t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
+        t = FIELD_DP32(t, ID_ISAR6, SB, 1);
+        t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
+        cpu->isar.id_isar6 = t;
+
+        t = cpu->isar.mvfr1;
+        t = FIELD_DP32(t, MVFR1, FPHP, 3);     /* v8.2-FP16 */
+        t = FIELD_DP32(t, MVFR1, SIMDHP, 2);   /* v8.2-FP16 */
+        cpu->isar.mvfr1 = t;
+
+        t = cpu->isar.mvfr2;
+        t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
+        t = FIELD_DP32(t, MVFR2, FPMISC, 4);   /* FP MaxNum */
+        cpu->isar.mvfr2 = t;
+
+        t = cpu->isar.id_mmfr3;
+        t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
+        cpu->isar.id_mmfr3 = t;
+
+        t = cpu->isar.id_mmfr4;
+        t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
+        t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
+        t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
+        t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */
+        cpu->isar.id_mmfr4 = t;
+
+        t = cpu->isar.id_pfr0;
+        t = FIELD_DP32(t, ID_PFR0, DIT, 1);
+        cpu->isar.id_pfr0 = t;
+
+        t = cpu->isar.id_pfr2;
+        t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
+        cpu->isar.id_pfr2 = t;
+    }
+#endif /* CONFIG_USER_ONLY */
+}
+#endif /* !TARGET_AARCH64 */
+
 static const ARMCPUInfo arm_tcg_cpus[] = {
     { .name = "arm926",      .initfn = arm926_initfn },
     { .name = "arm946",      .initfn = arm946_initfn },
@@ -708,6 +1016,10 @@ static const ARMCPUInfo arm_tcg_cpus[] = {
     { .name = "arm1136",     .initfn = arm1136_initfn },
     { .name = "arm1176",     .initfn = arm1176_initfn },
     { .name = "arm11mpcore", .initfn = arm11mpcore_initfn },
+    { .name = "cortex-a7",   .initfn = cortex_a7_initfn },
+    { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
+    { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
+    { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
     { .name = "cortex-m0",   .initfn = cortex_m0_initfn,
                              .class_init = arm_v7m_class_init },
     { .name = "cortex-m3",   .initfn = cortex_m3_initfn,
@@ -738,6 +1050,12 @@ static const ARMCPUInfo arm_tcg_cpus[] = {
     { .name = "pxa270-b1",   .initfn = pxa270b1_initfn },
     { .name = "pxa270-c0",   .initfn = pxa270c0_initfn },
     { .name = "pxa270-c5",   .initfn = pxa270c5_initfn },
+#ifndef TARGET_AARCH64
+    { .name = "max",         .initfn = arm_max_initfn },
+#endif
+#ifdef CONFIG_USER_ONLY
+    { .name = "any",         .initfn = arm_max_initfn },
+#endif
 };
 
 static const TypeInfo idau_interface_type_info = {
-- 
2.20.1



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

* [PULL 48/54] hw/dma: Implement a Xilinx CSU DMA model
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (46 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 47/54] target/arm: Restrict v7A TCG cpus to TCG accel Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 49/54] hw/arm: xlnx-zynqmp: Clean up coding convention issues Peter Maydell
                   ` (6 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

From: Xuzhou Cheng <xuzhou.cheng@windriver.com>

ZynqMP QSPI supports SPI transfer using DMA mode, but currently this
is unimplemented. When QSPI is programmed to use DMA mode, QEMU will
crash. This is observed when testing VxWorks 7.

This adds a Xilinx CSU DMA model and the implementation is based on
https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c.
The DST part of the model is verified along with ZynqMP GQSPI model.

Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
Signed-off-by: Bin Meng <bin.meng@windriver.com>
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 20210303135254.3970-2-bmeng.cn@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/dma/xlnx_csu_dma.h |  52 +++
 hw/dma/xlnx_csu_dma.c         | 745 ++++++++++++++++++++++++++++++++++
 hw/dma/Kconfig                |   4 +
 hw/dma/meson.build            |   1 +
 4 files changed, 802 insertions(+)
 create mode 100644 include/hw/dma/xlnx_csu_dma.h
 create mode 100644 hw/dma/xlnx_csu_dma.c

diff --git a/include/hw/dma/xlnx_csu_dma.h b/include/hw/dma/xlnx_csu_dma.h
new file mode 100644
index 00000000000..204d94c6737
--- /dev/null
+++ b/include/hw/dma/xlnx_csu_dma.h
@@ -0,0 +1,52 @@
+/*
+ * Xilinx Platform CSU Stream DMA emulation
+ *
+ * This implementation is based on
+ * https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef XLNX_CSU_DMA_H
+#define XLNX_CSU_DMA_H
+
+#define TYPE_XLNX_CSU_DMA "xlnx.csu_dma"
+
+#define XLNX_CSU_DMA_R_MAX (0x2c / 4)
+
+typedef struct XlnxCSUDMA {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    MemTxAttrs attr;
+    MemoryRegion *dma_mr;
+    AddressSpace *dma_as;
+    qemu_irq irq;
+    StreamSink *tx_dev; /* Used as generic StreamSink */
+    ptimer_state *src_timer;
+
+    uint16_t width;
+    bool is_dst;
+    bool r_size_last_word;
+
+    StreamCanPushNotifyFn notify;
+    void *notify_opaque;
+
+    uint32_t regs[XLNX_CSU_DMA_R_MAX];
+    RegisterInfo regs_info[XLNX_CSU_DMA_R_MAX];
+} XlnxCSUDMA;
+
+#define XLNX_CSU_DMA(obj) \
+    OBJECT_CHECK(XlnxCSUDMA, (obj), TYPE_XLNX_CSU_DMA)
+
+#endif
diff --git a/hw/dma/xlnx_csu_dma.c b/hw/dma/xlnx_csu_dma.c
new file mode 100644
index 00000000000..50709a3909b
--- /dev/null
+++ b/hw/dma/xlnx_csu_dma.c
@@ -0,0 +1,745 @@
+/*
+ * Xilinx Platform CSU Stream DMA emulation
+ *
+ * This implementation is based on
+ * https://github.com/Xilinx/qemu/blob/master/hw/dma/csu_stream_dma.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "sysemu/dma.h"
+#include "hw/ptimer.h"
+#include "hw/stream.h"
+#include "hw/register.h"
+#include "hw/dma/xlnx_csu_dma.h"
+
+/*
+ * Ref: UG1087 (v1.7) February 8, 2019
+ * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
+ * CSUDMA Module section
+ */
+REG32(ADDR, 0x0)
+    FIELD(ADDR, ADDR, 2, 30) /* wo */
+REG32(SIZE, 0x4)
+    FIELD(SIZE, SIZE, 2, 27) /* wo */
+    FIELD(SIZE, LAST_WORD, 0, 1) /* rw, only exists in SRC */
+REG32(STATUS, 0x8)
+    FIELD(STATUS, DONE_CNT, 13, 3) /* wtc */
+    FIELD(STATUS, FIFO_LEVEL, 5, 8) /* ro */
+    FIELD(STATUS, OUTSTANDING, 1, 4) /* ro */
+    FIELD(STATUS, BUSY, 0, 1) /* ro */
+REG32(CTRL, 0xc)
+    FIELD(CTRL, FIFOTHRESH, 25, 7) /* rw, only exists in DST, reset 0x40 */
+    FIELD(CTRL, APB_ERR_RESP, 24, 1) /* rw */
+    FIELD(CTRL, ENDIANNESS, 23, 1) /* rw */
+    FIELD(CTRL, AXI_BRST_TYPE, 22, 1) /* rw */
+    FIELD(CTRL, TIMEOUT_VAL, 10, 12) /* rw, reset: 0xFFE */
+    FIELD(CTRL, FIFO_THRESH, 2, 8) /* rw, reset: 0x80 */
+    FIELD(CTRL, PAUSE_STRM, 1, 1) /* rw */
+    FIELD(CTRL, PAUSE_MEM, 0, 1) /* rw */
+REG32(CRC, 0x10)
+REG32(INT_STATUS, 0x14)
+    FIELD(INT_STATUS, FIFO_OVERFLOW, 7, 1) /* wtc */
+    FIELD(INT_STATUS, INVALID_APB, 6, 1) /* wtc */
+    FIELD(INT_STATUS, THRESH_HIT, 5, 1) /* wtc */
+    FIELD(INT_STATUS, TIMEOUT_MEM, 4, 1) /* wtc */
+    FIELD(INT_STATUS, TIMEOUT_STRM, 3, 1) /* wtc */
+    FIELD(INT_STATUS, AXI_BRESP_ERR, 2, 1) /* wtc, SRC: AXI_RDERR */
+    FIELD(INT_STATUS, DONE, 1, 1) /* wtc */
+    FIELD(INT_STATUS, MEM_DONE, 0, 1) /* wtc */
+REG32(INT_ENABLE, 0x18)
+    FIELD(INT_ENABLE, FIFO_OVERFLOW, 7, 1) /* wtc */
+    FIELD(INT_ENABLE, INVALID_APB, 6, 1) /* wtc */
+    FIELD(INT_ENABLE, THRESH_HIT, 5, 1) /* wtc */
+    FIELD(INT_ENABLE, TIMEOUT_MEM, 4, 1) /* wtc */
+    FIELD(INT_ENABLE, TIMEOUT_STRM, 3, 1) /* wtc */
+    FIELD(INT_ENABLE, AXI_BRESP_ERR, 2, 1) /* wtc, SRC: AXI_RDERR */
+    FIELD(INT_ENABLE, DONE, 1, 1) /* wtc */
+    FIELD(INT_ENABLE, MEM_DONE, 0, 1) /* wtc */
+REG32(INT_DISABLE, 0x1c)
+    FIELD(INT_DISABLE, FIFO_OVERFLOW, 7, 1) /* wtc */
+    FIELD(INT_DISABLE, INVALID_APB, 6, 1) /* wtc */
+    FIELD(INT_DISABLE, THRESH_HIT, 5, 1) /* wtc */
+    FIELD(INT_DISABLE, TIMEOUT_MEM, 4, 1) /* wtc */
+    FIELD(INT_DISABLE, TIMEOUT_STRM, 3, 1) /* wtc */
+    FIELD(INT_DISABLE, AXI_BRESP_ERR, 2, 1) /* wtc, SRC: AXI_RDERR */
+    FIELD(INT_DISABLE, DONE, 1, 1) /* wtc */
+    FIELD(INT_DISABLE, MEM_DONE, 0, 1) /* wtc */
+REG32(INT_MASK, 0x20)
+    FIELD(INT_MASK, FIFO_OVERFLOW, 7, 1) /* ro, reset: 0x1 */
+    FIELD(INT_MASK, INVALID_APB, 6, 1) /* ro, reset: 0x1 */
+    FIELD(INT_MASK, THRESH_HIT, 5, 1) /* ro, reset: 0x1 */
+    FIELD(INT_MASK, TIMEOUT_MEM, 4, 1) /* ro, reset: 0x1 */
+    FIELD(INT_MASK, TIMEOUT_STRM, 3, 1) /* ro, reset: 0x1 */
+    FIELD(INT_MASK, AXI_BRESP_ERR, 2, 1) /* ro, reset: 0x1, SRC: AXI_RDERR */
+    FIELD(INT_MASK, DONE, 1, 1) /* ro, reset: 0x1 */
+    FIELD(INT_MASK, MEM_DONE, 0, 1) /* ro, reset: 0x1 */
+REG32(CTRL2, 0x24)
+    FIELD(CTRL2, ARCACHE, 24, 3) /* rw */
+    FIELD(CTRL2, ROUTE_BIT, 23, 1) /* rw */
+    FIELD(CTRL2, TIMEOUT_EN, 22, 1) /* rw */
+    FIELD(CTRL2, TIMEOUT_PRE, 4, 12) /* rw, reset: 0xFFF */
+    FIELD(CTRL2, MAX_OUTS_CMDS, 0, 4) /* rw, reset: 0x8 */
+REG32(ADDR_MSB, 0x28)
+    FIELD(ADDR_MSB, ADDR_MSB, 0, 17) /* wo */
+
+#define R_CTRL_TIMEOUT_VAL_RESET    (0xFFE)
+#define R_CTRL_FIFO_THRESH_RESET    (0x80)
+#define R_CTRL_FIFOTHRESH_RESET     (0x40)
+
+#define R_CTRL2_TIMEOUT_PRE_RESET   (0xFFF)
+#define R_CTRL2_MAX_OUTS_CMDS_RESET (0x8)
+
+#define XLNX_CSU_DMA_ERR_DEBUG      (0)
+#define XLNX_CSU_DMA_INT_R_MASK     (0xff)
+
+/* UG1807: Set the prescaler value for the timeout in clk (~2.5ns) cycles */
+#define XLNX_CSU_DMA_TIMER_FREQ     (400 * 1000 * 1000)
+
+static bool xlnx_csu_dma_is_paused(XlnxCSUDMA *s)
+{
+    bool paused;
+
+    paused = !!(s->regs[R_CTRL] & R_CTRL_PAUSE_STRM_MASK);
+    paused |= !!(s->regs[R_CTRL] & R_CTRL_PAUSE_MEM_MASK);
+
+    return paused;
+}
+
+static bool xlnx_csu_dma_get_eop(XlnxCSUDMA *s)
+{
+    return s->r_size_last_word;
+}
+
+static bool xlnx_csu_dma_burst_is_fixed(XlnxCSUDMA *s)
+{
+    return !!(s->regs[R_CTRL] & R_CTRL_AXI_BRST_TYPE_MASK);
+}
+
+static bool xlnx_csu_dma_timeout_enabled(XlnxCSUDMA *s)
+{
+    return !!(s->regs[R_CTRL2] & R_CTRL2_TIMEOUT_EN_MASK);
+}
+
+static void xlnx_csu_dma_update_done_cnt(XlnxCSUDMA *s, int a)
+{
+    int cnt;
+
+    /* Increase DONE_CNT */
+    cnt = ARRAY_FIELD_EX32(s->regs, STATUS, DONE_CNT) + a;
+    ARRAY_FIELD_DP32(s->regs, STATUS, DONE_CNT, cnt);
+}
+
+static void xlnx_csu_dma_data_process(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
+{
+    uint32_t bswap;
+    uint32_t i;
+
+    bswap = s->regs[R_CTRL] & R_CTRL_ENDIANNESS_MASK;
+    if (s->is_dst && !bswap) {
+        /* Fast when ENDIANNESS cleared */
+        return;
+    }
+
+    for (i = 0; i < len; i += 4) {
+        uint8_t *b = &buf[i];
+        union {
+            uint8_t u8[4];
+            uint32_t u32;
+        } v = {
+            .u8 = { b[0], b[1], b[2], b[3] }
+        };
+
+        if (!s->is_dst) {
+            s->regs[R_CRC] += v.u32;
+        }
+        if (bswap) {
+            /*
+             * No point using bswap, we need to writeback
+             * into a potentially unaligned pointer.
+             */
+            b[0] = v.u8[3];
+            b[1] = v.u8[2];
+            b[2] = v.u8[1];
+            b[3] = v.u8[0];
+        }
+    }
+}
+
+static void xlnx_csu_dma_update_irq(XlnxCSUDMA *s)
+{
+    qemu_set_irq(s->irq, !!(s->regs[R_INT_STATUS] & ~s->regs[R_INT_MASK]));
+}
+
+/* len is in bytes */
+static uint32_t xlnx_csu_dma_read(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
+{
+    hwaddr addr = (hwaddr)s->regs[R_ADDR_MSB] << 32 | s->regs[R_ADDR];
+    MemTxResult result = MEMTX_OK;
+
+    if (xlnx_csu_dma_burst_is_fixed(s)) {
+        uint32_t i;
+
+        for (i = 0; i < len && (result == MEMTX_OK); i += s->width) {
+            uint32_t mlen = MIN(len - i, s->width);
+
+            result = address_space_rw(s->dma_as, addr, s->attr,
+                                      buf + i, mlen, false);
+        }
+    } else {
+        result = address_space_rw(s->dma_as, addr, s->attr, buf, len, false);
+    }
+
+    if (result == MEMTX_OK) {
+        xlnx_csu_dma_data_process(s, buf, len);
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%lx for mem read",
+                      __func__, addr);
+        s->regs[R_INT_STATUS] |= R_INT_STATUS_AXI_BRESP_ERR_MASK;
+        xlnx_csu_dma_update_irq(s);
+    }
+    return len;
+}
+
+/* len is in bytes */
+static uint32_t xlnx_csu_dma_write(XlnxCSUDMA *s, uint8_t *buf, uint32_t len)
+{
+    hwaddr addr = (hwaddr)s->regs[R_ADDR_MSB] << 32 | s->regs[R_ADDR];
+    MemTxResult result = MEMTX_OK;
+
+    xlnx_csu_dma_data_process(s, buf, len);
+    if (xlnx_csu_dma_burst_is_fixed(s)) {
+        uint32_t i;
+
+        for (i = 0; i < len && (result == MEMTX_OK); i += s->width) {
+            uint32_t mlen = MIN(len - i, s->width);
+
+            result = address_space_rw(s->dma_as, addr, s->attr,
+                                      buf, mlen, true);
+            buf += mlen;
+        }
+    } else {
+        result = address_space_rw(s->dma_as, addr, s->attr, buf, len, true);
+    }
+
+    if (result != MEMTX_OK) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%lx for mem write",
+                      __func__, addr);
+        s->regs[R_INT_STATUS] |= R_INT_STATUS_AXI_BRESP_ERR_MASK;
+        xlnx_csu_dma_update_irq(s);
+    }
+    return len;
+}
+
+static void xlnx_csu_dma_done(XlnxCSUDMA *s)
+{
+    s->regs[R_STATUS] &= ~R_STATUS_BUSY_MASK;
+    s->regs[R_INT_STATUS] |= R_INT_STATUS_DONE_MASK;
+
+    if (!s->is_dst) {
+        s->regs[R_INT_STATUS] |= R_INT_STATUS_MEM_DONE_MASK;
+    }
+
+    xlnx_csu_dma_update_done_cnt(s, 1);
+}
+
+static uint32_t xlnx_csu_dma_advance(XlnxCSUDMA *s, uint32_t len)
+{
+    uint32_t size = s->regs[R_SIZE];
+    hwaddr dst = (hwaddr)s->regs[R_ADDR_MSB] << 32 | s->regs[R_ADDR];
+
+    assert(len <= size);
+
+    size -= len;
+    s->regs[R_SIZE] = size;
+
+    if (!xlnx_csu_dma_burst_is_fixed(s)) {
+        dst += len;
+        s->regs[R_ADDR] = (uint32_t) dst;
+        s->regs[R_ADDR_MSB] = dst >> 32;
+    }
+
+    if (size == 0) {
+        xlnx_csu_dma_done(s);
+    }
+
+    return size;
+}
+
+static void xlnx_csu_dma_src_notify(void *opaque)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(opaque);
+    unsigned char buf[4 * 1024];
+    size_t rlen = 0;
+
+    ptimer_transaction_begin(s->src_timer);
+    /* Stop the backpreassure timer */
+    ptimer_stop(s->src_timer);
+
+    while (s->regs[R_SIZE] && !xlnx_csu_dma_is_paused(s) &&
+           stream_can_push(s->tx_dev, xlnx_csu_dma_src_notify, s)) {
+        uint32_t plen = MIN(s->regs[R_SIZE], sizeof buf);
+        bool eop = false;
+
+        /* Did we fit it all? */
+        if (s->regs[R_SIZE] == plen && xlnx_csu_dma_get_eop(s)) {
+            eop = true;
+        }
+
+        /* DMA transfer */
+        xlnx_csu_dma_read(s, buf, plen);
+        rlen = stream_push(s->tx_dev, buf, plen, eop);
+        xlnx_csu_dma_advance(s, rlen);
+    }
+
+    if (xlnx_csu_dma_timeout_enabled(s) && s->regs[R_SIZE] &&
+        !stream_can_push(s->tx_dev, xlnx_csu_dma_src_notify, s)) {
+        uint32_t timeout = ARRAY_FIELD_EX32(s->regs, CTRL, TIMEOUT_VAL);
+        uint32_t div = ARRAY_FIELD_EX32(s->regs, CTRL2, TIMEOUT_PRE) + 1;
+        uint32_t freq = XLNX_CSU_DMA_TIMER_FREQ;
+
+        freq /= div;
+        ptimer_set_freq(s->src_timer, freq);
+        ptimer_set_count(s->src_timer, timeout);
+        ptimer_run(s->src_timer, 1);
+    }
+
+    ptimer_transaction_commit(s->src_timer);
+    xlnx_csu_dma_update_irq(s);
+}
+
+static uint64_t addr_pre_write(RegisterInfo *reg, uint64_t val)
+{
+    /* Address is word aligned */
+    return val & R_ADDR_ADDR_MASK;
+}
+
+static uint64_t size_pre_write(RegisterInfo *reg, uint64_t val)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+
+    if (s->regs[R_SIZE] != 0) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Starting DMA while already running.\n", __func__);
+    }
+
+    if (!s->is_dst) {
+        s->r_size_last_word = !!(val & R_SIZE_LAST_WORD_MASK);
+    }
+
+    /* Size is word aligned */
+    return val & R_SIZE_SIZE_MASK;
+}
+
+static uint64_t size_post_read(RegisterInfo *reg, uint64_t val)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+
+    return val | s->r_size_last_word;
+}
+
+static void size_post_write(RegisterInfo *reg, uint64_t val)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+
+    s->regs[R_STATUS] |= R_STATUS_BUSY_MASK;
+
+    /*
+     * Note that if SIZE is programmed to 0, and the DMA is started,
+     * the interrupts DONE and MEM_DONE will be asserted.
+     */
+    if (s->regs[R_SIZE] == 0) {
+        xlnx_csu_dma_done(s);
+        xlnx_csu_dma_update_irq(s);
+        return;
+    }
+
+    /* Set SIZE is considered the last step in transfer configuration */
+    if (!s->is_dst) {
+        xlnx_csu_dma_src_notify(s);
+    } else {
+        if (s->notify) {
+            s->notify(s->notify_opaque);
+        }
+    }
+}
+
+static uint64_t status_pre_write(RegisterInfo *reg, uint64_t val)
+{
+    return val & (R_STATUS_DONE_CNT_MASK | R_STATUS_BUSY_MASK);
+}
+
+static void ctrl_post_write(RegisterInfo *reg, uint64_t val)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+
+    if (!s->is_dst) {
+        if (!xlnx_csu_dma_is_paused(s)) {
+            xlnx_csu_dma_src_notify(s);
+        }
+    } else {
+        if (!xlnx_csu_dma_is_paused(s) && s->notify) {
+            s->notify(s->notify_opaque);
+        }
+    }
+}
+
+static uint64_t int_status_pre_write(RegisterInfo *reg, uint64_t val)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+
+    /* DMA counter decrements when flag 'DONE' is cleared */
+    if ((val & s->regs[R_INT_STATUS] & R_INT_STATUS_DONE_MASK)) {
+        xlnx_csu_dma_update_done_cnt(s, -1);
+    }
+
+    return s->regs[R_INT_STATUS] & ~val;
+}
+
+static void int_status_post_write(RegisterInfo *reg, uint64_t val)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+
+    xlnx_csu_dma_update_irq(s);
+}
+
+static uint64_t int_enable_pre_write(RegisterInfo *reg, uint64_t val)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+    uint32_t v32 = val;
+
+    /*
+     * R_INT_ENABLE doesn't have its own state.
+     * It is used to indirectly modify R_INT_MASK.
+     *
+     * 1: Enable this interrupt field (the mask bit will be cleared to 0)
+     * 0: No effect
+     */
+    s->regs[R_INT_MASK] &= ~v32;
+    return 0;
+}
+
+static void int_enable_post_write(RegisterInfo *reg, uint64_t val)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+
+    xlnx_csu_dma_update_irq(s);
+}
+
+static uint64_t int_disable_pre_write(RegisterInfo *reg, uint64_t val)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+    uint32_t v32 = val;
+
+    /*
+     * R_INT_DISABLE doesn't have its own state.
+     * It is used to indirectly modify R_INT_MASK.
+     *
+     * 1: Disable this interrupt field (the mask bit will be set to 1)
+     * 0: No effect
+     */
+    s->regs[R_INT_MASK] |= v32;
+    return 0;
+}
+
+static void int_disable_post_write(RegisterInfo *reg, uint64_t val)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque);
+
+    xlnx_csu_dma_update_irq(s);
+}
+
+static uint64_t addr_msb_pre_write(RegisterInfo *reg, uint64_t val)
+{
+    return val & R_ADDR_MSB_ADDR_MSB_MASK;
+}
+
+static const RegisterAccessInfo *xlnx_csu_dma_regs_info[] = {
+#define DMACH_REGINFO(NAME, snd)                                              \
+    (const RegisterAccessInfo []) {                                           \
+        {                                                                     \
+            .name = #NAME "_ADDR",                                            \
+            .addr = A_ADDR,                                                   \
+            .pre_write = addr_pre_write                                       \
+        }, {                                                                  \
+            .name = #NAME "_SIZE",                                            \
+            .addr = A_SIZE,                                                   \
+            .pre_write = size_pre_write,                                      \
+            .post_write = size_post_write,                                    \
+            .post_read = size_post_read                                       \
+        }, {                                                                  \
+            .name = #NAME "_STATUS",                                          \
+            .addr = A_STATUS,                                                 \
+            .pre_write = status_pre_write,                                    \
+            .w1c = R_STATUS_DONE_CNT_MASK,                                    \
+            .ro = (R_STATUS_BUSY_MASK                                         \
+                   | R_STATUS_FIFO_LEVEL_MASK                                 \
+                   | R_STATUS_OUTSTANDING_MASK)                               \
+        }, {                                                                  \
+            .name = #NAME "_CTRL",                                            \
+            .addr = A_CTRL,                                                   \
+            .post_write = ctrl_post_write,                                    \
+            .reset = ((R_CTRL_TIMEOUT_VAL_RESET << R_CTRL_TIMEOUT_VAL_SHIFT)  \
+                      | (R_CTRL_FIFO_THRESH_RESET << R_CTRL_FIFO_THRESH_SHIFT)\
+                      | (snd ? 0 : R_CTRL_FIFOTHRESH_RESET                    \
+                         << R_CTRL_FIFOTHRESH_SHIFT))                         \
+        }, {                                                                  \
+            .name = #NAME "_CRC",                                             \
+            .addr = A_CRC,                                                    \
+        }, {                                                                  \
+            .name =  #NAME "_INT_STATUS",                                     \
+            .addr = A_INT_STATUS,                                             \
+            .pre_write = int_status_pre_write,                                \
+            .post_write = int_status_post_write                               \
+        }, {                                                                  \
+            .name = #NAME "_INT_ENABLE",                                      \
+            .addr = A_INT_ENABLE,                                             \
+            .pre_write = int_enable_pre_write,                                \
+            .post_write = int_enable_post_write                               \
+        }, {                                                                  \
+            .name = #NAME "_INT_DISABLE",                                     \
+            .addr = A_INT_DISABLE,                                            \
+            .pre_write = int_disable_pre_write,                               \
+            .post_write = int_disable_post_write                              \
+        }, {                                                                  \
+            .name = #NAME "_INT_MASK",                                        \
+            .addr = A_INT_MASK,                                               \
+            .ro = ~0,                                                         \
+            .reset = XLNX_CSU_DMA_INT_R_MASK                                  \
+        }, {                                                                  \
+            .name = #NAME "_CTRL2",                                           \
+            .addr = A_CTRL2,                                                  \
+            .reset = ((R_CTRL2_TIMEOUT_PRE_RESET                              \
+                       << R_CTRL2_TIMEOUT_PRE_SHIFT)                          \
+                      | (R_CTRL2_MAX_OUTS_CMDS_RESET                          \
+                         << R_CTRL2_MAX_OUTS_CMDS_SHIFT))                     \
+        }, {                                                                  \
+            .name = #NAME "_ADDR_MSB",                                        \
+            .addr = A_ADDR_MSB,                                               \
+            .pre_write = addr_msb_pre_write                                   \
+        }                                                                     \
+    }
+
+    DMACH_REGINFO(DMA_SRC, true),
+    DMACH_REGINFO(DMA_DST, false)
+};
+
+static const MemoryRegionOps xlnx_csu_dma_ops = {
+    .read = register_read_memory,
+    .write = register_write_memory,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    }
+};
+
+static void xlnx_csu_dma_src_timeout_hit(void *opaque)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(opaque);
+
+    /* Ignore if the timeout is masked */
+    if (!xlnx_csu_dma_timeout_enabled(s)) {
+        return;
+    }
+
+    s->regs[R_INT_STATUS] |= R_INT_STATUS_TIMEOUT_STRM_MASK;
+    xlnx_csu_dma_update_irq(s);
+}
+
+static size_t xlnx_csu_dma_stream_push(StreamSink *obj, uint8_t *buf,
+                                       size_t len, bool eop)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(obj);
+    uint32_t size = s->regs[R_SIZE];
+    uint32_t mlen = MIN(size, len) & (~3); /* Size is word aligned */
+
+    /* Be called when it's DST */
+    assert(s->is_dst);
+
+    if (size == 0 || len <= 0) {
+        return 0;
+    }
+
+    if (len && (xlnx_csu_dma_is_paused(s) || mlen == 0)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "csu-dma: DST channel dropping %zd b of data.\n", len);
+        s->regs[R_INT_STATUS] |= R_INT_STATUS_FIFO_OVERFLOW_MASK;
+        return len;
+    }
+
+    if (xlnx_csu_dma_write(s, buf, mlen) != mlen) {
+        return 0;
+    }
+
+    xlnx_csu_dma_advance(s, mlen);
+    xlnx_csu_dma_update_irq(s);
+
+    return mlen;
+}
+
+static bool xlnx_csu_dma_stream_can_push(StreamSink *obj,
+                                         StreamCanPushNotifyFn notify,
+                                         void *notify_opaque)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(obj);
+
+    if (s->regs[R_SIZE] != 0) {
+        return true;
+    } else {
+        s->notify = notify;
+        s->notify_opaque = notify_opaque;
+        return false;
+    }
+}
+
+static void xlnx_csu_dma_reset(DeviceState *dev)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(dev);
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
+        register_reset(&s->regs_info[i]);
+    }
+}
+
+static void xlnx_csu_dma_realize(DeviceState *dev, Error **errp)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(dev);
+    RegisterInfoArray *reg_array;
+
+    reg_array =
+        register_init_block32(dev, xlnx_csu_dma_regs_info[!!s->is_dst],
+                              XLNX_CSU_DMA_R_MAX,
+                              s->regs_info, s->regs,
+                              &xlnx_csu_dma_ops,
+                              XLNX_CSU_DMA_ERR_DEBUG,
+                              XLNX_CSU_DMA_R_MAX * 4);
+    memory_region_add_subregion(&s->iomem,
+                                0x0,
+                                &reg_array->mem);
+
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+    sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
+
+    if (!s->is_dst && !s->tx_dev) {
+        error_setg(errp, "zynqmp.csu-dma: Stream not connected");
+        return;
+    }
+
+    s->src_timer = ptimer_init(xlnx_csu_dma_src_timeout_hit,
+                               s, PTIMER_POLICY_DEFAULT);
+
+    if (s->dma_mr) {
+        s->dma_as = g_malloc0(sizeof(AddressSpace));
+        address_space_init(s->dma_as, s->dma_mr, NULL);
+    } else {
+        s->dma_as = &address_space_memory;
+    }
+
+    s->attr = MEMTXATTRS_UNSPECIFIED;
+
+    s->r_size_last_word = 0;
+}
+
+static const VMStateDescription vmstate_xlnx_csu_dma = {
+    .name = TYPE_XLNX_CSU_DMA,
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_PTIMER(src_timer, XlnxCSUDMA),
+        VMSTATE_UINT16(width, XlnxCSUDMA),
+        VMSTATE_BOOL(is_dst, XlnxCSUDMA),
+        VMSTATE_BOOL(r_size_last_word, XlnxCSUDMA),
+        VMSTATE_UINT32_ARRAY(regs, XlnxCSUDMA, XLNX_CSU_DMA_R_MAX),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static Property xlnx_csu_dma_properties[] = {
+    /*
+     * Ref PG021, Stream Data Width:
+     * Data width in bits of the AXI S2MM AXI4-Stream Data bus.
+     * This value must be equal or less than the Memory Map Data Width.
+     * Valid values are 8, 16, 32, 64, 128, 512 and 1024.
+     * "dma-width" is the byte value of the "Stream Data Width".
+     */
+    DEFINE_PROP_UINT16("dma-width", XlnxCSUDMA, width, 4),
+    /*
+     * The CSU DMA is a two-channel, simple DMA, allowing separate control of
+     * the SRC (read) channel and DST (write) channel. "is-dst" is used to mark
+     * which channel the device is connected to.
+     */
+    DEFINE_PROP_BOOL("is-dst", XlnxCSUDMA, is_dst, true),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xlnx_csu_dma_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    StreamSinkClass *ssc = STREAM_SINK_CLASS(klass);
+
+    dc->reset = xlnx_csu_dma_reset;
+    dc->realize = xlnx_csu_dma_realize;
+    dc->vmsd = &vmstate_xlnx_csu_dma;
+    device_class_set_props(dc, xlnx_csu_dma_properties);
+
+    ssc->push = xlnx_csu_dma_stream_push;
+    ssc->can_push = xlnx_csu_dma_stream_can_push;
+}
+
+static void xlnx_csu_dma_init(Object *obj)
+{
+    XlnxCSUDMA *s = XLNX_CSU_DMA(obj);
+
+    memory_region_init(&s->iomem, obj, TYPE_XLNX_CSU_DMA,
+                       XLNX_CSU_DMA_R_MAX * 4);
+
+    object_property_add_link(obj, "stream-connected-dma", TYPE_STREAM_SINK,
+                             (Object **)&s->tx_dev,
+                             qdev_prop_allow_set_link_before_realize,
+                             OBJ_PROP_LINK_STRONG);
+    object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
+                             (Object **)&s->dma_mr,
+                             qdev_prop_allow_set_link_before_realize,
+                             OBJ_PROP_LINK_STRONG);
+}
+
+static const TypeInfo xlnx_csu_dma_info = {
+    .name          = TYPE_XLNX_CSU_DMA,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(XlnxCSUDMA),
+    .class_init    = xlnx_csu_dma_class_init,
+    .instance_init = xlnx_csu_dma_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_STREAM_SINK },
+        { }
+    }
+};
+
+static void xlnx_csu_dma_register_types(void)
+{
+    type_register_static(&xlnx_csu_dma_info);
+}
+
+type_init(xlnx_csu_dma_register_types)
diff --git a/hw/dma/Kconfig b/hw/dma/Kconfig
index 5d6be1a7a7a..98fbb1bb049 100644
--- a/hw/dma/Kconfig
+++ b/hw/dma/Kconfig
@@ -26,3 +26,7 @@ config STP2000
 
 config SIFIVE_PDMA
     bool
+
+config XLNX_CSU_DMA
+    bool
+    select REGISTER
diff --git a/hw/dma/meson.build b/hw/dma/meson.build
index 47b4a7cb47b..5c78a4e05ff 100644
--- a/hw/dma/meson.build
+++ b/hw/dma/meson.build
@@ -14,3 +14,4 @@ softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_dma.c', 'soc_dma.c'))
 softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_dma.c'))
 softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_dma.c'))
 softmmu_ss.add(when: 'CONFIG_SIFIVE_PDMA', if_true: files('sifive_pdma.c'))
+softmmu_ss.add(when: 'CONFIG_XLNX_CSU_DMA', if_true: files('xlnx_csu_dma.c'))
-- 
2.20.1



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

* [PULL 49/54] hw/arm: xlnx-zynqmp: Clean up coding convention issues
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (47 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 48/54] hw/dma: Implement a Xilinx CSU DMA model Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 50/54] hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI Peter Maydell
                   ` (5 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

From: Xuzhou Cheng <xuzhou.cheng@windriver.com>

There are some coding convention warnings in xlnx-zynqmp.c and
xlnx-zynqmp.h, as reported by:

  $ ./scripts/checkpatch.pl include/hw/arm/xlnx-zynqmp.h
  $ ./scripts/checkpatch.pl hw/arm/xlnx-zynqmp.c

Let's clean them up.

Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 20210303135254.3970-3-bmeng.cn@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/arm/xlnx-zynqmp.h | 3 ++-
 hw/arm/xlnx-zynqmp.c         | 9 ++++++---
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 0678b419a23..c83ef23e92d 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -60,7 +60,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
 
 #define XLNX_ZYNQMP_GIC_REGIONS 6
 
-/* ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets
+/*
+ * ZynqMP maps the ARM GIC regions (GICC, GICD ...) at consecutive 64k offsets
  * and under-decodes the 64k region. This mirrors the 4k regions to every 4k
  * aligned address in the 64k region. To implement each GIC region needs a
  * number of memory region aliases.
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 46030c1ef81..e2056a764e2 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -301,11 +301,13 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 
     ram_size = memory_region_size(s->ddr_ram);
 
-    /* Create the DDR Memory Regions. User friendly checks should happen at
+    /*
+     * Create the DDR Memory Regions. User friendly checks should happen at
      * the board level
      */
     if (ram_size > XLNX_ZYNQMP_MAX_LOW_RAM_SIZE) {
-        /* The RAM size is above the maximum available for the low DDR.
+        /*
+         * The RAM size is above the maximum available for the low DDR.
          * Create the high DDR memory region as well.
          */
         assert(ram_size <= XLNX_ZYNQMP_MAX_RAM_SIZE);
@@ -521,7 +523,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         SysBusDevice *sbd = SYS_BUS_DEVICE(&s->sdhci[i]);
         Object *sdhci = OBJECT(&s->sdhci[i]);
 
-        /* Compatible with:
+        /*
+         * Compatible with:
          * - SD Host Controller Specification Version 3.00
          * - SDIO Specification Version 3.0
          * - eMMC Specification Version 4.51
-- 
2.20.1



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

* [PULL 50/54] hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (48 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 49/54] hw/arm: xlnx-zynqmp: Clean up coding convention issues Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 51/54] hw/ssi: xilinx_spips: Clean up coding convention issues Peter Maydell
                   ` (4 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

From: Xuzhou Cheng <xuzhou.cheng@windriver.com>

Add a Xilinx CSU DMA module to ZynqMP SoC, and connent the stream
link of GQSPI to CSU DMA.

Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 20210303135254.3970-4-bmeng.cn@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/arm/xlnx-zynqmp.h |  2 ++
 hw/arm/xlnx-zynqmp.c         | 12 ++++++++++++
 hw/arm/Kconfig               |  1 +
 3 files changed, 15 insertions(+)

diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index c83ef23e92d..1676a84ec82 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -35,6 +35,7 @@
 #include "target/arm/cpu.h"
 #include "qom/object.h"
 #include "net/can_emu.h"
+#include "hw/dma/xlnx_csu_dma.h"
 
 #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
 OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
@@ -108,6 +109,7 @@ struct XlnxZynqMPState {
     XlnxZynqMPRTC rtc;
     XlnxZDMA gdma[XLNX_ZYNQMP_NUM_GDMA_CH];
     XlnxZDMA adma[XLNX_ZYNQMP_NUM_ADMA_CH];
+    XlnxCSUDMA qspi_dma;
 
     char *boot_cpu;
     ARMCPU *boot_cpu_ptr;
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index e2056a764e2..7f01284a5c0 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -50,6 +50,7 @@
 #define QSPI_ADDR           0xff0f0000
 #define LQSPI_ADDR          0xc0000000
 #define QSPI_IRQ            15
+#define QSPI_DMA_ADDR       0xff0f0800
 
 #define DP_ADDR             0xfd4a0000
 #define DP_IRQ              113
@@ -284,6 +285,8 @@ static void xlnx_zynqmp_init(Object *obj)
     for (i = 0; i < XLNX_ZYNQMP_NUM_ADMA_CH; i++) {
         object_initialize_child(obj, "adma[*]", &s->adma[i], TYPE_XLNX_ZDMA);
     }
+
+    object_initialize_child(obj, "qspi-dma", &s->qspi_dma, TYPE_XLNX_CSU_DMA);
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -638,6 +641,15 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
         sysbus_connect_irq(SYS_BUS_DEVICE(&s->adma[i]), 0,
                            gic_spi[adma_ch_intr[i]]);
     }
+
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->qspi_dma), errp)) {
+        return;
+    }
+
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->qspi_dma), 0, QSPI_DMA_ADDR);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->qspi_dma), 0, gic_spi[QSPI_IRQ]);
+    object_property_set_link(OBJECT(&s->qspi), "stream-connected-dma",
+                             OBJECT(&s->qspi_dma), errp);
 }
 
 static Property xlnx_zynqmp_props[] = {
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index f2b7a8fc0b0..8c37cf00da7 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -353,6 +353,7 @@ config XLNX_ZYNQMP_ARM
     select SSI_M25P80
     select XILINX_AXI
     select XILINX_SPIPS
+    select XLNX_CSU_DMA
     select XLNX_ZYNQMP
     select XLNX_ZDMA
 
-- 
2.20.1



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

* [PULL 51/54] hw/ssi: xilinx_spips: Clean up coding convention issues
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (49 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 50/54] hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 52/54] hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips Peter Maydell
                   ` (3 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

From: Xuzhou Cheng <xuzhou.cheng@windriver.com>

There are some coding convention warnings in xilinx_spips.c,
as reported by:

  $ ./scripts/checkpatch.pl hw/ssi/xilinx_spips.c

Let's clean them up.

Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 20210303135254.3970-5-bmeng.cn@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/ssi/xilinx_spips.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index a8970346017..8a0cc22d42e 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -176,7 +176,8 @@
     FIELD(GQSPI_FIFO_CTRL, GENERIC_FIFO_RESET, 0, 1)
 #define R_GQSPI_GFIFO_THRESH    (0x150 / 4)
 #define R_GQSPI_DATA_STS (0x15c / 4)
-/* We use the snapshot register to hold the core state for the currently
+/*
+ * We use the snapshot register to hold the core state for the currently
  * or most recently executed command. So the generic fifo format is defined
  * for the snapshot register
  */
@@ -424,7 +425,8 @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
     xlnx_zynqmp_qspips_update_ixr(s);
 }
 
-/* N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
+/*
+ * N way (num) in place bit striper. Lay out row wise bits (MSB to LSB)
  * column wise (from element 0 to N-1). num is the length of x, and dir
  * reverses the direction of the transform. Best illustrated by example:
  * Each digit in the below array is a single bit (num == 3):
@@ -637,8 +639,10 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
                 tx_rx[i] = tx;
             }
         } else {
-            /* Extract a dummy byte and generate dummy cycles according to the
-             * link state */
+            /*
+             * Extract a dummy byte and generate dummy cycles according to the
+             * link state
+             */
             tx = fifo8_pop(&s->tx_fifo);
             dummy_cycles = 8 / s->link_state;
         }
@@ -721,8 +725,9 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
             }
             break;
         case (SNOOP_ADDR):
-            /* Address has been transmitted, transmit dummy cycles now if
-             * needed */
+            /*
+             * Address has been transmitted, transmit dummy cycles now if needed
+             */
             if (s->cmd_dummies < 0) {
                 s->snoop_state = SNOOP_NONE;
             } else {
@@ -876,7 +881,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
 }
 
 static uint64_t xilinx_spips_read(void *opaque, hwaddr addr,
-                                                        unsigned size)
+                                  unsigned size)
 {
     XilinxSPIPS *s = opaque;
     uint32_t mask = ~0;
@@ -970,7 +975,7 @@ static uint64_t xlnx_zynqmp_qspips_read(void *opaque,
 }
 
 static void xilinx_spips_write(void *opaque, hwaddr addr,
-                                        uint64_t value, unsigned size)
+                               uint64_t value, unsigned size)
 {
     int mask = ~0;
     XilinxSPIPS *s = opaque;
@@ -1072,7 +1077,7 @@ static void xilinx_qspips_write(void *opaque, hwaddr addr,
 }
 
 static void xlnx_zynqmp_qspips_write(void *opaque, hwaddr addr,
-                                        uint64_t value, unsigned size)
+                                     uint64_t value, unsigned size)
 {
     XlnxZynqMPQSPIPS *s = XLNX_ZYNQMP_QSPIPS(opaque);
     uint32_t reg = addr / 4;
-- 
2.20.1



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

* [PULL 52/54] hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (50 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 51/54] hw/ssi: xilinx_spips: Clean up coding convention issues Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 53/54] hw/timer/renesas_tmr: Prefix constants for CSS values with CSS_ Peter Maydell
                   ` (2 subsequent siblings)
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

From: Xuzhou Cheng <xuzhou.cheng@windriver.com>

Now that the Xilinx CSU DMA model is implemented, the existing
DMA related dead codes in the ZynqMP QSPI are useless and should
be removed. The maximum register number is also updated to only
include the QSPI registers.

Signed-off-by: Xuzhou Cheng <xuzhou.cheng@windriver.com>
Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 20210303135254.3970-6-bmeng.cn@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/ssi/xilinx_spips.h |  2 +-
 hw/ssi/xilinx_spips.c         | 10 ----------
 2 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h
index 3eae73480e1..06bfd183124 100644
--- a/include/hw/ssi/xilinx_spips.h
+++ b/include/hw/ssi/xilinx_spips.h
@@ -34,7 +34,7 @@
 typedef struct XilinxSPIPS XilinxSPIPS;
 
 #define XLNX_SPIPS_R_MAX        (0x100 / 4)
-#define XLNX_ZYNQMP_SPIPS_R_MAX (0x830 / 4)
+#define XLNX_ZYNQMP_SPIPS_R_MAX (0x200 / 4)
 
 /* Bite off 4k chunks at a time */
 #define LQSPI_CACHE_SIZE 1024
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 8a0cc22d42e..1e9dba20392 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -195,13 +195,6 @@
 #define R_GQSPI_MOD_ID        (0x1fc / 4)
 #define R_GQSPI_MOD_ID_RESET  (0x10a0000)
 
-#define R_QSPIDMA_DST_CTRL         (0x80c / 4)
-#define R_QSPIDMA_DST_CTRL_RESET   (0x803ffa00)
-#define R_QSPIDMA_DST_I_MASK       (0x820 / 4)
-#define R_QSPIDMA_DST_I_MASK_RESET (0xfe)
-#define R_QSPIDMA_DST_CTRL2        (0x824 / 4)
-#define R_QSPIDMA_DST_CTRL2_RESET  (0x081bfff8)
-
 /* size of TXRX FIFOs */
 #define RXFF_A          (128)
 #define TXFF_A          (128)
@@ -417,9 +410,6 @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
     s->regs[R_GQSPI_GPIO] = 1;
     s->regs[R_GQSPI_LPBK_DLY_ADJ] = R_GQSPI_LPBK_DLY_ADJ_RESET;
     s->regs[R_GQSPI_MOD_ID] = R_GQSPI_MOD_ID_RESET;
-    s->regs[R_QSPIDMA_DST_CTRL] = R_QSPIDMA_DST_CTRL_RESET;
-    s->regs[R_QSPIDMA_DST_I_MASK] = R_QSPIDMA_DST_I_MASK_RESET;
-    s->regs[R_QSPIDMA_DST_CTRL2] = R_QSPIDMA_DST_CTRL2_RESET;
     s->man_start_com_g = false;
     s->gqspi_irqline = 0;
     xlnx_zynqmp_qspips_update_ixr(s);
-- 
2.20.1



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

* [PULL 53/54] hw/timer/renesas_tmr: Prefix constants for CSS values with CSS_
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (51 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 52/54] hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 17:32 ` [PULL 54/54] hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() Peter Maydell
  2021-03-08 18:49 ` [PULL 00/54] target-arm queue no-reply
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The #defines INTERNAL and CASCADING represent different possible
values for the TCCR.CSS register field; prefix them with CSS_ to make
this more obvious, before we add more defines to represent the
other possible values of the field in the next commit.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210219223241.16344-2-peter.maydell@linaro.org
---
 hw/timer/renesas_tmr.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
index e03a8155b2b..22260aaaba5 100644
--- a/hw/timer/renesas_tmr.c
+++ b/hw/timer/renesas_tmr.c
@@ -46,8 +46,8 @@ REG8(TCCR, 10)
   FIELD(TCCR, CSS,   3, 2)
   FIELD(TCCR, TMRIS, 7, 1)
 
-#define INTERNAL  0x01
-#define CASCADING 0x03
+#define CSS_INTERNAL  0x01
+#define CSS_CASCADING 0x03
 #define CCLR_A    0x01
 #define CCLR_B    0x02
 
@@ -72,7 +72,7 @@ static void update_events(RTMRState *tmr, int ch)
         /* event not happened */
         return ;
     }
-    if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CASCADING) {
+    if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) == CSS_CASCADING) {
         /* cascading mode */
         if (ch == 1) {
             tmr->next[ch] = none;
@@ -130,7 +130,7 @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
     if (delta > 0) {
         tmr->tick = now;
 
-        if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == INTERNAL) {
+        if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CSS_INTERNAL) {
             /* timer1 count update */
             elapsed = elapsed_time(tmr, 1, delta);
             if (elapsed >= 0x100) {
@@ -139,11 +139,11 @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
             tcnt[1] = tmr->tcnt[1] + (elapsed & 0xff);
         }
         switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) {
-        case INTERNAL:
+        case CSS_INTERNAL:
             elapsed = elapsed_time(tmr, 0, delta);
             tcnt[0] = tmr->tcnt[0] + elapsed;
             break;
-        case CASCADING:
+        case CSS_CASCADING:
             if (ovf > 0) {
                 tcnt[0] = tmr->tcnt[0] + ovf;
             }
@@ -330,7 +330,7 @@ static uint16_t issue_event(RTMRState *tmr, int ch, int sz,
                 qemu_irq_pulse(tmr->cmia[ch]);
             }
             if (sz == 8 && ch == 0 &&
-                FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CASCADING) {
+                FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CSS_CASCADING) {
                 tmr->tcnt[1]++;
                 timer_events(tmr, 1);
             }
@@ -362,7 +362,7 @@ static void timer_events(RTMRState *tmr, int ch)
     uint16_t tcnt;
 
     tmr->tcnt[ch] = read_tcnt(tmr, 1, ch);
-    if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) != CASCADING) {
+    if (FIELD_EX8(tmr->tccr[0], TCCR, CSS) != CSS_CASCADING) {
         tmr->tcnt[ch] = issue_event(tmr, ch, 8,
                                     tmr->tcnt[ch],
                                     tmr->tcora[ch],
-- 
2.20.1



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

* [PULL 54/54] hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt()
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (52 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 53/54] hw/timer/renesas_tmr: Prefix constants for CSS values with CSS_ Peter Maydell
@ 2021-03-08 17:32 ` Peter Maydell
  2021-03-08 18:49 ` [PULL 00/54] target-arm queue no-reply
  54 siblings, 0 replies; 58+ messages in thread
From: Peter Maydell @ 2021-03-08 17:32 UTC (permalink / raw)
  To: qemu-devel

The read_tcnt() function calculates the TCNT register values for the
two channels of the timer module; it sets these up in the local
tcnt[] array, and eventually returns either one or both of them,
depending on whether the access is 8 or 16 bits.  However, not all of
the code paths through this function set both elements of this array:
if the guest has programmed the TCCR.CSS register fields to values
which are either documented as not to be used or which QEMU does not
implement, then the function will return uninitialized data.  (This
was spotted by Coverity.)

Add the missing CSS cases to this code, so that we return a
consistent value instead of uninitialized data, and so the code
structure indicates what's happening.

Fixes: CID 1429976
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210219223241.16344-3-peter.maydell@linaro.org
---
 hw/timer/renesas_tmr.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/hw/timer/renesas_tmr.c b/hw/timer/renesas_tmr.c
index 22260aaaba5..eed39917fec 100644
--- a/hw/timer/renesas_tmr.c
+++ b/hw/timer/renesas_tmr.c
@@ -46,7 +46,9 @@ REG8(TCCR, 10)
   FIELD(TCCR, CSS,   3, 2)
   FIELD(TCCR, TMRIS, 7, 1)
 
+#define CSS_EXTERNAL  0x00
 #define CSS_INTERNAL  0x01
+#define CSS_INVALID   0x02
 #define CSS_CASCADING 0x03
 #define CCLR_A    0x01
 #define CCLR_B    0x02
@@ -130,13 +132,20 @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
     if (delta > 0) {
         tmr->tick = now;
 
-        if (FIELD_EX8(tmr->tccr[1], TCCR, CSS) == CSS_INTERNAL) {
+        switch (FIELD_EX8(tmr->tccr[1], TCCR, CSS)) {
+        case CSS_INTERNAL:
             /* timer1 count update */
             elapsed = elapsed_time(tmr, 1, delta);
             if (elapsed >= 0x100) {
                 ovf = elapsed >> 8;
             }
             tcnt[1] = tmr->tcnt[1] + (elapsed & 0xff);
+            break;
+        case CSS_INVALID: /* guest error to have set this */
+        case CSS_EXTERNAL: /* QEMU doesn't implement these */
+        case CSS_CASCADING:
+            tcnt[1] = tmr->tcnt[1];
+            break;
         }
         switch (FIELD_EX8(tmr->tccr[0], TCCR, CSS)) {
         case CSS_INTERNAL:
@@ -144,9 +153,11 @@ static uint16_t read_tcnt(RTMRState *tmr, unsigned size, int ch)
             tcnt[0] = tmr->tcnt[0] + elapsed;
             break;
         case CSS_CASCADING:
-            if (ovf > 0) {
-                tcnt[0] = tmr->tcnt[0] + ovf;
-            }
+            tcnt[0] = tmr->tcnt[0] + ovf;
+            break;
+        case CSS_INVALID: /* guest error to have set this */
+        case CSS_EXTERNAL: /* QEMU doesn't implement this */
+            tcnt[0] = tmr->tcnt[0];
             break;
         }
     } else {
-- 
2.20.1



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

* Re: [PULL 00/54] target-arm queue
  2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
                   ` (53 preceding siblings ...)
  2021-03-08 17:32 ` [PULL 54/54] hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() Peter Maydell
@ 2021-03-08 18:49 ` no-reply
  54 siblings, 0 replies; 58+ messages in thread
From: no-reply @ 2021-03-08 18:49 UTC (permalink / raw)
  To: peter.maydell; +Cc: qemu-devel

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



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20210308173244.20710-1-peter.maydell@linaro.org
Subject: [PULL 00/54] target-arm queue

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]      patchew/20210225091435.644762-1-eric.auger@redhat.com -> patchew/20210225091435.644762-1-eric.auger@redhat.com
 - [tag update]      patchew/20210303195339.GB3793@redhat.com -> patchew/20210303195339.GB3793@redhat.com
 - [tag update]      patchew/20210308154633.158915-1-thuth@redhat.com -> patchew/20210308154633.158915-1-thuth@redhat.com
 * [new tag]         patchew/20210308173244.20710-1-peter.maydell@linaro.org -> patchew/20210308173244.20710-1-peter.maydell@linaro.org
Switched to a new branch 'test'
07374e1 hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt()
fea8e80 hw/timer/renesas_tmr: Prefix constants for CSS values with CSS_
b9f3dfd hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips
9e3a610 hw/ssi: xilinx_spips: Clean up coding convention issues
bfdae5f hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI
d95d2c2 hw/arm: xlnx-zynqmp: Clean up coding convention issues
b52474c hw/dma: Implement a Xilinx CSU DMA model
f8734d1 target/arm: Restrict v7A TCG cpus to TCG accel
97246f4 tests/qtest/sse-timer-test: Test counter scaling changes
bc7ce41 tests/qtest/sse-timer-test: Test the system timer
1ae3cd2 tests/qtest/sse-timer-test: Add simple test of the SSE counter
3c89ac9 docs/system/arm/mps2.rst: Document the new mps3-an547 board
b2cb63d hw/arm/mps2-tz: Add new mps3-an547 board
feee059 hw/arm/mps2-tz: Make initsvtor0 setting board-specific
654d5b5 hw/arm/mps2-tz: Support running APB peripherals on different clock
84a76c5 hw/misc/mps2-scc: Implement changes for AN547
8225557 hw/misc/mps2-fpgaio: Support AN547 DBGCTRL register
16fac9b hw/misc/mps2-fpgaio: Fold counters subsection into main vmstate
34606d7 hw/arm/mps2-tz: Make UART overflow IRQ board-specific
19c7e52 hw/arm/armsse: Add SSE-300 support
f6003ee hw/arm/armsse: Support variants with ARMSSE_CPU_PWRCTRL block
c6f883c hw/arm/armsse: Add support for TYPE_SSE_TIMER in ARMSSEDeviceInfo
73393b5 hw/arm/armsse: Add support for SSE variants with a system counter
45df240 hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo
9fff473 hw/arm/armsse: Add missing SSE-200 SYS_PPU
7222997 hw/arm/armsse: Move PPUs into data-driven framework
2ef7ec8 hw/arm/armsse: Move sysctl register block into data-driven framework
18a85f7 hw/arm/armsse: Move sysinfo register block into data-driven framework
e4ee1e7 hw/arm/armsse: Move s32ktimer into data-driven framework
8655f07 hw/arm/armsse: Move watchdogs into data-driven framework
f827989 hw/arm/armsse: Move dual-timer device into data-driven framework
79b53b8 hw/arm/armsse: Add framework for data-driven device placement
516eaef hw/arm/armsse: Add a define for number of IRQs used by the SSE itself
517dfb6 hw/arm/armsse: Use an array for apb_ppc fields in the state structure
3d20d2e hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block
e6df0f6 hw/arm/Kconfig: Move ARMSSE_CPUID and ARMSSE_MHU stanzas to hw/misc
9049fd0 hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values
2908277 hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers
2c929f1 hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register
5132688 hw/misc/iotkit-sysctl: Handle INITSVTOR* for SSE-300
8055482 hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300
4d1f059 hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour
3e2ac76 hw/timer/sse-timer: Model the SSE Subsystem System Timer
907d495 hw/timer/sse-counter: Model the SSE Subsystem System Counter
a496eee hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR
093c68d hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300
d75dd6e hw/misc/iotkit-sysinfo.c: Implement SSE-300 PID register values
122ac7a hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values
44fafc0 hw/misc/iotkit-sysctl: Remove is_sse200 flag
a7dd089 hw/arm/armsse: Introduce SSE subsystem version property
9b76681 hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks()
7d51138 clock: Add clock_ns_to_ticks() function
cc6d5be clock: Add ClockPreUpdate callback event type
8a5be7d clock: Add ClockEvent parameter to callbacks

=== OUTPUT BEGIN ===
1/54 Checking commit 8a5be7df4d6d (clock: Add ClockEvent parameter to callbacks)
WARNING: line over 80 characters
#554: FILE: hw/misc/zynq_slcr.c:580:
+    QDEV_CLOCK_IN(ZynqSLCRState, ps_clk, zynq_slcr_ps_clk_callback, ClockUpdate),

total: 0 errors, 1 warnings, 592 lines checked

Patch 1/54 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
2/54 Checking commit cc6d5beb5b61 (clock: Add ClockPreUpdate callback event type)
3/54 Checking commit 7d5113835fc0 (clock: Add clock_ns_to_ticks() function)
4/54 Checking commit 9b76681ce61a (hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks())
5/54 Checking commit a7dd089a76a1 (hw/arm/armsse: Introduce SSE subsystem version property)
Use of uninitialized value $acpi_testexpected in string eq at ./scripts/checkpatch.pl line 1529.
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#132: 
new file mode 100644

total: 0 errors, 1 warnings, 129 lines checked

Patch 5/54 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/54 Checking commit 44fafc03d01f (hw/misc/iotkit-sysctl: Remove is_sse200 flag)
WARNING: line over 80 characters
#247: FILE: hw/misc/iotkit-sysctl.c:375:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");

WARNING: line over 80 characters
#262: FILE: hw/misc/iotkit-sysctl.c:387:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");

WARNING: line over 80 characters
#393: FILE: hw/misc/iotkit-sysctl.c:489:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");

total: 0 errors, 3 warnings, 392 lines checked

Patch 6/54 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
7/54 Checking commit 122ac7a4273b (hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values)
8/54 Checking commit d75dd6eea605 (hw/misc/iotkit-sysinfo.c: Implement SSE-300 PID register values)
9/54 Checking commit 093c68d7ae3d (hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300)
10/54 Checking commit a496eeea5dfd (hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR)
11/54 Checking commit 907d4959db36 (hw/timer/sse-counter: Model the SSE Subsystem System Counter)
12/54 Checking commit 3e2ac7637549 (hw/timer/sse-timer: Model the SSE Subsystem System Timer)
WARNING: line over 80 characters
#527: FILE: hw/timer/sse-timer.c:443:
+    DEFINE_PROP_LINK("counter", SSETimer, counter, TYPE_SSE_COUNTER, SSECounter *),

total: 0 errors, 1 warnings, 561 lines checked

Patch 12/54 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
13/54 Checking commit 4d1f059cd9e6 (hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour)
14/54 Checking commit 8055482d8e88 (hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300)
WARNING: line over 80 characters
#164: FILE: hw/misc/iotkit-sysctl.c:481:
+            qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");

total: 0 errors, 1 warnings, 138 lines checked

Patch 14/54 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
15/54 Checking commit 513268884e16 (hw/misc/iotkit-sysctl: Handle INITSVTOR* for SSE-300)
16/54 Checking commit 2c929f1573cd (hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register)
17/54 Checking commit 2908277c9728 (hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers)
18/54 Checking commit 9049fd01810a (hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values)
19/54 Checking commit e6df0f693f79 (hw/arm/Kconfig: Move ARMSSE_CPUID and ARMSSE_MHU stanzas to hw/misc)
20/54 Checking commit 3d20d2ef460e (hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block)
21/54 Checking commit 517dfb60ff4f (hw/arm/armsse: Use an array for apb_ppc fields in the state structure)
22/54 Checking commit 516eaef11830 (hw/arm/armsse: Add a define for number of IRQs used by the SSE itself)
23/54 Checking commit 79b53b897cc5 (hw/arm/armsse: Add framework for data-driven device placement)
24/54 Checking commit f82798971026 (hw/arm/armsse: Move dual-timer device into data-driven framework)
25/54 Checking commit 8655f0723679 (hw/arm/armsse: Move watchdogs into data-driven framework)
26/54 Checking commit e4ee1e70d8e7 (hw/arm/armsse: Move s32ktimer into data-driven framework)
27/54 Checking commit 18a85f7322cf (hw/arm/armsse: Move sysinfo register block into data-driven framework)
28/54 Checking commit 2ef7ec851e50 (hw/arm/armsse: Move sysctl register block into data-driven framework)
29/54 Checking commit 722299713461 (hw/arm/armsse: Move PPUs into data-driven framework)
30/54 Checking commit 9fff4733371d (hw/arm/armsse: Add missing SSE-200 SYS_PPU)
31/54 Checking commit 45df2400413d (hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo)
32/54 Checking commit 73393b58d18b (hw/arm/armsse: Add support for SSE variants with a system counter)
33/54 Checking commit c6f883cf7f1a (hw/arm/armsse: Add support for TYPE_SSE_TIMER in ARMSSEDeviceInfo)
34/54 Checking commit f6003eefbf67 (hw/arm/armsse: Support variants with ARMSSE_CPU_PWRCTRL block)
35/54 Checking commit 19c7e5298f97 (hw/arm/armsse: Add SSE-300 support)
36/54 Checking commit 34606d763c0e (hw/arm/mps2-tz: Make UART overflow IRQ board-specific)
37/54 Checking commit 16fac9b2dce7 (hw/misc/mps2-fpgaio: Fold counters subsection into main vmstate)
38/54 Checking commit 8225557a3478 (hw/misc/mps2-fpgaio: Support AN547 DBGCTRL register)
39/54 Checking commit 84a76c50b435 (hw/misc/mps2-scc: Implement changes for AN547)
40/54 Checking commit 654d5b5c6741 (hw/arm/mps2-tz: Support running APB peripherals on different clock)
41/54 Checking commit feee0594aeda (hw/arm/mps2-tz: Make initsvtor0 setting board-specific)
42/54 Checking commit b2cb63d1fe88 (hw/arm/mps2-tz: Add new mps3-an547 board)
WARNING: Block comments use a leading /* on a separate line
#145: FILE: hw/arm/mps2-tz.c:963:
+                { /* port 7 reserved */ },

WARNING: line over 80 characters
#152: FILE: hw/arm/mps2-tz.c:970:
+                { "i2s-audio", make_unimp_dev, &mms->i2s_audio, 0x49301000, 0x1000 },

WARNING: line over 80 characters
#154: FILE: hw/arm/mps2-tz.c:972:
+                { "uart0", make_uart, &mms->uart[0], 0x49303000, 0x1000, { 33, 34, 43 } },

WARNING: line over 80 characters
#155: FILE: hw/arm/mps2-tz.c:973:
+                { "uart1", make_uart, &mms->uart[1], 0x49304000, 0x1000, { 35, 36, 44 } },

WARNING: line over 80 characters
#156: FILE: hw/arm/mps2-tz.c:974:
+                { "uart2", make_uart, &mms->uart[2], 0x49305000, 0x1000, { 37, 38, 45 } },

WARNING: line over 80 characters
#157: FILE: hw/arm/mps2-tz.c:975:
+                { "uart3", make_uart, &mms->uart[3], 0x49306000, 0x1000, { 39, 40, 46 } },

WARNING: line over 80 characters
#158: FILE: hw/arm/mps2-tz.c:976:
+                { "uart4", make_uart, &mms->uart[4], 0x49307000, 0x1000, { 41, 42, 47 } },

ERROR: line over 90 characters
#159: FILE: hw/arm/mps2-tz.c:977:
+                { "uart5", make_uart, &mms->uart[5], 0x49308000, 0x1000, { 125, 126, 127 } },

WARNING: Block comments use a leading /* on a separate line
#161: FILE: hw/arm/mps2-tz.c:979:
+                { /* port 9 reserved */ },

total: 1 errors, 8 warnings, 223 lines checked

Patch 42/54 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

43/54 Checking commit 3c89ac98c971 (docs/system/arm/mps2.rst: Document the new mps3-an547 board)
44/54 Checking commit 1ae3cd272093 (tests/qtest/sse-timer-test: Add simple test of the SSE counter)
45/54 Checking commit bc7ce41eee2a (tests/qtest/sse-timer-test: Test the system timer)
46/54 Checking commit 97246f4a39cf (tests/qtest/sse-timer-test: Test counter scaling changes)
47/54 Checking commit f8734d1704c3 (target/arm: Restrict v7A TCG cpus to TCG accel)
48/54 Checking commit b52474c56a66 (hw/dma: Implement a Xilinx CSU DMA model)
Use of uninitialized value $acpi_testexpected in string eq at ./scripts/checkpatch.pl line 1529.
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#51: 
new file mode 100644

total: 0 errors, 1 warnings, 808 lines checked

Patch 48/54 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
49/54 Checking commit d95d2c29b4c5 (hw/arm: xlnx-zynqmp: Clean up coding convention issues)
50/54 Checking commit bfdae5f8b1d0 (hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI)
51/54 Checking commit 9e3a61006a3f (hw/ssi: xilinx_spips: Clean up coding convention issues)
52/54 Checking commit b9f3dfdc6961 (hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips)
53/54 Checking commit fea8e80265e6 (hw/timer/renesas_tmr: Prefix constants for CSS values with CSS_)
54/54 Checking commit 07374e1311fb (hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt())
=== OUTPUT END ===

Test command exited with code: 1


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

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

* Re: [PULL 00/54] target-arm queue
  2022-04-28 14:39 Peter Maydell
@ 2022-04-28 17:10 ` Richard Henderson
  0 siblings, 0 replies; 58+ messages in thread
From: Richard Henderson @ 2022-04-28 17:10 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel

On 4/28/22 07:39, Peter Maydell wrote:
> This is mostly RTH's tcg_constant refactoring work, plus a few
> other things.
> 
> thanks
> -- PMM
> 
> The following changes since commit cf6f26d6f9b2015ee12b4604b79359e76784163a:
> 
>    Merge tag 'kraxel-20220427-pull-request' of git://git.kraxel.org/qemu into staging (2022-04-27 10:49:28 -0700)
> 
> are available in the Git repository at:
> 
>    https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220428
> 
> for you to fetch changes up to f8e7163d9e6740b5cef02bf73a17a59d0bef8bdb:
> 
>    hw/arm/smmuv3: Advertise support for SMMUv3.2-BBML2 (2022-04-28 13:59:23 +0100)
> 
> ----------------------------------------------------------------
> target-arm queue:
>   * refactor to use tcg_constant where appropriate
>   * Advertise support for FEAT_TTL and FEAT_BBM level 2
>   * smmuv3: Cache event fault record
>   * smmuv3: Add space in guest error message
>   * smmuv3: Advertise support for SMMUv3.2-BBML2

Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/7.1 as appropriate.


r~



> 
> ----------------------------------------------------------------
> Damien Hedde (1):
>        target/arm: Disable cryptographic instructions when neon is disabled
> 
> Jean-Philippe Brucker (2):
>        hw/arm/smmuv3: Cache event fault record
>        hw/arm/smmuv3: Add space in guest error message
> 
> Peter Maydell (3):
>        target/arm: Advertise support for FEAT_TTL
>        target/arm: Advertise support for FEAT_BBM level 2
>        hw/arm/smmuv3: Advertise support for SMMUv3.2-BBML2
> 
> Richard Henderson (48):
>        target/arm: Use tcg_constant in gen_probe_access
>        target/arm: Use tcg_constant in gen_mte_check*
>        target/arm: Use tcg_constant in gen_exception*
>        target/arm: Use tcg_constant in gen_adc_CC
>        target/arm: Use tcg_constant in handle_msr_i
>        target/arm: Use tcg_constant in handle_sys
>        target/arm: Use tcg_constant in disas_exc
>        target/arm: Use tcg_constant in gen_compare_and_swap_pair
>        target/arm: Use tcg_constant in disas_ld_lit
>        target/arm: Use tcg_constant in disas_ldst_*
>        target/arm: Use tcg_constant in disas_add_sum_imm*
>        target/arm: Use tcg_constant in disas_movw_imm
>        target/arm: Use tcg_constant in shift_reg_imm
>        target/arm: Use tcg_constant in disas_cond_select
>        target/arm: Use tcg_constant in handle_{rev16,crc32}
>        target/arm: Use tcg_constant in disas_data_proc_2src
>        target/arm: Use tcg_constant in disas_fp*
>        target/arm: Use tcg_constant in simd shift expanders
>        target/arm: Use tcg_constant in simd fp/int conversion
>        target/arm: Use tcg_constant in 2misc expanders
>        target/arm: Use tcg_constant in balance of translate-a64.c
>        target/arm: Use tcg_constant for aa32 exceptions
>        target/arm: Use tcg_constant for disas_iwmmxt_insn
>        target/arm: Use tcg_constant for gen_{msr,mrs}
>        target/arm: Use tcg_constant for vector shift expanders
>        target/arm: Use tcg_constant for do_coproc_insn
>        target/arm: Use tcg_constant for gen_srs
>        target/arm: Use tcg_constant for op_s_{rri,rxi}_rot
>        target/arm: Use tcg_constant for MOVW, UMAAL, CRC32
>        target/arm: Use tcg_constant for v7m MRS, MSR
>        target/arm: Use tcg_constant for TT, SAT, SMMLA
>        target/arm: Use tcg_constant in LDM, STM
>        target/arm: Use tcg_constant in CLRM, DLS, WLS, LE
>        target/arm: Use tcg_constant in trans_CPS_v7m
>        target/arm: Use tcg_constant in trans_CSEL
>        target/arm: Use tcg_constant for trans_INDEX_*
>        target/arm: Use tcg_constant in SINCDEC, INCDEC
>        target/arm: Use tcg_constant in FCPY, CPY
>        target/arm: Use tcg_constant in {incr, wrap}_last_active
>        target/arm: Use tcg_constant in do_clast_scalar
>        target/arm: Use tcg_constant in WHILE
>        target/arm: Use tcg_constant in LD1, ST1
>        target/arm: Use tcg_constant in SUBR
>        target/arm: Use tcg_constant in do_zzi_{sat, ool}, do_fp_imm
>        target/arm: Use tcg_constant for predicate descriptors
>        target/arm: Use tcg_constant for do_brk{2,3}
>        target/arm: Use tcg_constant for vector descriptor
>        target/arm: Use field names for accessing DBGWCRn
> 
>   docs/system/arm/emulation.rst |   2 +
>   hw/arm/smmuv3-internal.h      |   2 +-
>   include/hw/arm/smmu-common.h  |   1 +
>   target/arm/internals.h        |  12 ++
>   hw/arm/smmuv3.c               |  17 +--
>   target/arm/cpu.c              |   9 ++
>   target/arm/cpu64.c            |   2 +
>   target/arm/debug_helper.c     |  10 +-
>   target/arm/helper.c           |   8 +-
>   target/arm/kvm64.c            |  14 +-
>   target/arm/translate-a64.c    | 301 +++++++++++++-----------------------------
>   target/arm/translate-sve.c    | 202 ++++++++++------------------
>   target/arm/translate.c        | 244 ++++++++++++----------------------
>   13 files changed, 293 insertions(+), 531 deletions(-)
> 



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

* [PULL 00/54] target-arm queue
@ 2022-04-28 14:39 Peter Maydell
  2022-04-28 17:10 ` Richard Henderson
  0 siblings, 1 reply; 58+ messages in thread
From: Peter Maydell @ 2022-04-28 14:39 UTC (permalink / raw)
  To: qemu-devel

This is mostly RTH's tcg_constant refactoring work, plus a few
other things.

thanks
-- PMM

The following changes since commit cf6f26d6f9b2015ee12b4604b79359e76784163a:

  Merge tag 'kraxel-20220427-pull-request' of git://git.kraxel.org/qemu into staging (2022-04-27 10:49:28 -0700)

are available in the Git repository at:

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

for you to fetch changes up to f8e7163d9e6740b5cef02bf73a17a59d0bef8bdb:

  hw/arm/smmuv3: Advertise support for SMMUv3.2-BBML2 (2022-04-28 13:59:23 +0100)

----------------------------------------------------------------
target-arm queue:
 * refactor to use tcg_constant where appropriate
 * Advertise support for FEAT_TTL and FEAT_BBM level 2
 * smmuv3: Cache event fault record
 * smmuv3: Add space in guest error message
 * smmuv3: Advertise support for SMMUv3.2-BBML2

----------------------------------------------------------------
Damien Hedde (1):
      target/arm: Disable cryptographic instructions when neon is disabled

Jean-Philippe Brucker (2):
      hw/arm/smmuv3: Cache event fault record
      hw/arm/smmuv3: Add space in guest error message

Peter Maydell (3):
      target/arm: Advertise support for FEAT_TTL
      target/arm: Advertise support for FEAT_BBM level 2
      hw/arm/smmuv3: Advertise support for SMMUv3.2-BBML2

Richard Henderson (48):
      target/arm: Use tcg_constant in gen_probe_access
      target/arm: Use tcg_constant in gen_mte_check*
      target/arm: Use tcg_constant in gen_exception*
      target/arm: Use tcg_constant in gen_adc_CC
      target/arm: Use tcg_constant in handle_msr_i
      target/arm: Use tcg_constant in handle_sys
      target/arm: Use tcg_constant in disas_exc
      target/arm: Use tcg_constant in gen_compare_and_swap_pair
      target/arm: Use tcg_constant in disas_ld_lit
      target/arm: Use tcg_constant in disas_ldst_*
      target/arm: Use tcg_constant in disas_add_sum_imm*
      target/arm: Use tcg_constant in disas_movw_imm
      target/arm: Use tcg_constant in shift_reg_imm
      target/arm: Use tcg_constant in disas_cond_select
      target/arm: Use tcg_constant in handle_{rev16,crc32}
      target/arm: Use tcg_constant in disas_data_proc_2src
      target/arm: Use tcg_constant in disas_fp*
      target/arm: Use tcg_constant in simd shift expanders
      target/arm: Use tcg_constant in simd fp/int conversion
      target/arm: Use tcg_constant in 2misc expanders
      target/arm: Use tcg_constant in balance of translate-a64.c
      target/arm: Use tcg_constant for aa32 exceptions
      target/arm: Use tcg_constant for disas_iwmmxt_insn
      target/arm: Use tcg_constant for gen_{msr,mrs}
      target/arm: Use tcg_constant for vector shift expanders
      target/arm: Use tcg_constant for do_coproc_insn
      target/arm: Use tcg_constant for gen_srs
      target/arm: Use tcg_constant for op_s_{rri,rxi}_rot
      target/arm: Use tcg_constant for MOVW, UMAAL, CRC32
      target/arm: Use tcg_constant for v7m MRS, MSR
      target/arm: Use tcg_constant for TT, SAT, SMMLA
      target/arm: Use tcg_constant in LDM, STM
      target/arm: Use tcg_constant in CLRM, DLS, WLS, LE
      target/arm: Use tcg_constant in trans_CPS_v7m
      target/arm: Use tcg_constant in trans_CSEL
      target/arm: Use tcg_constant for trans_INDEX_*
      target/arm: Use tcg_constant in SINCDEC, INCDEC
      target/arm: Use tcg_constant in FCPY, CPY
      target/arm: Use tcg_constant in {incr, wrap}_last_active
      target/arm: Use tcg_constant in do_clast_scalar
      target/arm: Use tcg_constant in WHILE
      target/arm: Use tcg_constant in LD1, ST1
      target/arm: Use tcg_constant in SUBR
      target/arm: Use tcg_constant in do_zzi_{sat, ool}, do_fp_imm
      target/arm: Use tcg_constant for predicate descriptors
      target/arm: Use tcg_constant for do_brk{2,3}
      target/arm: Use tcg_constant for vector descriptor
      target/arm: Use field names for accessing DBGWCRn

 docs/system/arm/emulation.rst |   2 +
 hw/arm/smmuv3-internal.h      |   2 +-
 include/hw/arm/smmu-common.h  |   1 +
 target/arm/internals.h        |  12 ++
 hw/arm/smmuv3.c               |  17 +--
 target/arm/cpu.c              |   9 ++
 target/arm/cpu64.c            |   2 +
 target/arm/debug_helper.c     |  10 +-
 target/arm/helper.c           |   8 +-
 target/arm/kvm64.c            |  14 +-
 target/arm/translate-a64.c    | 301 +++++++++++++-----------------------------
 target/arm/translate-sve.c    | 202 ++++++++++------------------
 target/arm/translate.c        | 244 ++++++++++++----------------------
 13 files changed, 293 insertions(+), 531 deletions(-)


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

end of thread, other threads:[~2022-04-28 17:12 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-08 17:31 [PULL 00/54] target-arm queue Peter Maydell
2021-03-08 17:31 ` [PULL 01/54] clock: Add ClockEvent parameter to callbacks Peter Maydell
2021-03-08 17:31 ` [PULL 02/54] clock: Add ClockPreUpdate callback event type Peter Maydell
2021-03-08 17:31 ` [PULL 03/54] clock: Add clock_ns_to_ticks() function Peter Maydell
2021-03-08 17:31 ` [PULL 04/54] hw/timer/npcm7xx_timer: Use new clock_ns_to_ticks() Peter Maydell
2021-03-08 17:31 ` [PULL 05/54] hw/arm/armsse: Introduce SSE subsystem version property Peter Maydell
2021-03-08 17:31 ` [PULL 06/54] hw/misc/iotkit-sysctl: Remove is_sse200 flag Peter Maydell
2021-03-08 17:31 ` [PULL 07/54] hw/misc/iotkit-secctl.c: Implement SSE-300 PID register values Peter Maydell
2021-03-08 17:31 ` [PULL 08/54] hw/misc/iotkit-sysinfo.c: " Peter Maydell
2021-03-08 17:31 ` [PULL 09/54] hw/arm/armsse.c: Use correct SYS_CONFIG0 register value for SSE-300 Peter Maydell
2021-03-08 17:32 ` [PULL 10/54] hw/misc/iotkit-sysinfo.c: Implement SYS_CONFIG1 and IIDR Peter Maydell
2021-03-08 17:32 ` [PULL 11/54] hw/timer/sse-counter: Model the SSE Subsystem System Counter Peter Maydell
2021-03-08 17:32 ` [PULL 12/54] hw/timer/sse-timer: Model the SSE Subsystem System Timer Peter Maydell
2021-03-08 17:32 ` [PULL 13/54] hw/misc/iotkit-sysctl: Add SSE-300 cases which match SSE-200 behaviour Peter Maydell
2021-03-08 17:32 ` [PULL 14/54] hw/misc/iotkit-sysctl: Handle CPU_WAIT, NMI_ENABLE for SSE-300 Peter Maydell
2021-03-08 17:32 ` [PULL 15/54] hw/misc/iotkit-sysctl: Handle INITSVTOR* " Peter Maydell
2021-03-08 17:32 ` [PULL 16/54] hw/misc/iotkit-sysctl: Implement dummy version of SSE-300 PWRCTRL register Peter Maydell
2021-03-08 17:32 ` [PULL 17/54] hw/misc/iotkit-sysctl: Handle SSE-300 changes to PDCM_PD_*_SENSE registers Peter Maydell
2021-03-08 17:32 ` [PULL 18/54] hw/misc/iotkit-sysctl: Implement SSE-200 and SSE-300 PID register values Peter Maydell
2021-03-08 17:32 ` [PULL 19/54] hw/arm/Kconfig: Move ARMSSE_CPUID and ARMSSE_MHU stanzas to hw/misc Peter Maydell
2021-03-08 17:32 ` [PULL 20/54] hw/misc/sse-cpu-pwrctrl: Implement SSE-300 CPU<N>_PWRCTRL register block Peter Maydell
2021-03-08 17:32 ` [PULL 21/54] hw/arm/armsse: Use an array for apb_ppc fields in the state structure Peter Maydell
2021-03-08 17:32 ` [PULL 22/54] hw/arm/armsse: Add a define for number of IRQs used by the SSE itself Peter Maydell
2021-03-08 17:32 ` [PULL 23/54] hw/arm/armsse: Add framework for data-driven device placement Peter Maydell
2021-03-08 17:32 ` [PULL 24/54] hw/arm/armsse: Move dual-timer device into data-driven framework Peter Maydell
2021-03-08 17:32 ` [PULL 25/54] hw/arm/armsse: Move watchdogs " Peter Maydell
2021-03-08 17:32 ` [PULL 26/54] hw/arm/armsse: Move s32ktimer " Peter Maydell
2021-03-08 17:32 ` [PULL 27/54] hw/arm/armsse: Move sysinfo register block " Peter Maydell
2021-03-08 17:32 ` [PULL 28/54] hw/arm/armsse: Move sysctl " Peter Maydell
2021-03-08 17:32 ` [PULL 29/54] hw/arm/armsse: Move PPUs " Peter Maydell
2021-03-08 17:32 ` [PULL 30/54] hw/arm/armsse: Add missing SSE-200 SYS_PPU Peter Maydell
2021-03-08 17:32 ` [PULL 31/54] hw/arm/armsse: Indirect irq_is_common[] through ARMSSEInfo Peter Maydell
2021-03-08 17:32 ` [PULL 32/54] hw/arm/armsse: Add support for SSE variants with a system counter Peter Maydell
2021-03-08 17:32 ` [PULL 33/54] hw/arm/armsse: Add support for TYPE_SSE_TIMER in ARMSSEDeviceInfo Peter Maydell
2021-03-08 17:32 ` [PULL 34/54] hw/arm/armsse: Support variants with ARMSSE_CPU_PWRCTRL block Peter Maydell
2021-03-08 17:32 ` [PULL 35/54] hw/arm/armsse: Add SSE-300 support Peter Maydell
2021-03-08 17:32 ` [PULL 36/54] hw/arm/mps2-tz: Make UART overflow IRQ board-specific Peter Maydell
2021-03-08 17:32 ` [PULL 37/54] hw/misc/mps2-fpgaio: Fold counters subsection into main vmstate Peter Maydell
2021-03-08 17:32 ` [PULL 38/54] hw/misc/mps2-fpgaio: Support AN547 DBGCTRL register Peter Maydell
2021-03-08 17:32 ` [PULL 39/54] hw/misc/mps2-scc: Implement changes for AN547 Peter Maydell
2021-03-08 17:32 ` [PULL 40/54] hw/arm/mps2-tz: Support running APB peripherals on different clock Peter Maydell
2021-03-08 17:32 ` [PULL 41/54] hw/arm/mps2-tz: Make initsvtor0 setting board-specific Peter Maydell
2021-03-08 17:32 ` [PULL 42/54] hw/arm/mps2-tz: Add new mps3-an547 board Peter Maydell
2021-03-08 17:32 ` [PULL 43/54] docs/system/arm/mps2.rst: Document the " Peter Maydell
2021-03-08 17:32 ` [PULL 44/54] tests/qtest/sse-timer-test: Add simple test of the SSE counter Peter Maydell
2021-03-08 17:32 ` [PULL 45/54] tests/qtest/sse-timer-test: Test the system timer Peter Maydell
2021-03-08 17:32 ` [PULL 46/54] tests/qtest/sse-timer-test: Test counter scaling changes Peter Maydell
2021-03-08 17:32 ` [PULL 47/54] target/arm: Restrict v7A TCG cpus to TCG accel Peter Maydell
2021-03-08 17:32 ` [PULL 48/54] hw/dma: Implement a Xilinx CSU DMA model Peter Maydell
2021-03-08 17:32 ` [PULL 49/54] hw/arm: xlnx-zynqmp: Clean up coding convention issues Peter Maydell
2021-03-08 17:32 ` [PULL 50/54] hw/arm: xlnx-zynqmp: Connect a Xilinx CSU DMA module for QSPI Peter Maydell
2021-03-08 17:32 ` [PULL 51/54] hw/ssi: xilinx_spips: Clean up coding convention issues Peter Maydell
2021-03-08 17:32 ` [PULL 52/54] hw/ssi: xilinx_spips: Remove DMA related dead codes from zynqmp_spips Peter Maydell
2021-03-08 17:32 ` [PULL 53/54] hw/timer/renesas_tmr: Prefix constants for CSS values with CSS_ Peter Maydell
2021-03-08 17:32 ` [PULL 54/54] hw/timer/renesas_tmr: Fix use of uninitialized data in read_tcnt() Peter Maydell
2021-03-08 18:49 ` [PULL 00/54] target-arm queue no-reply
2022-04-28 14:39 Peter Maydell
2022-04-28 17:10 ` Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.