All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings
@ 2021-12-11 19:11 Peter Maydell
  2021-12-11 19:11 ` [PATCH 01/26] hw/intc: clean-up error reporting for failed ITS cmd Peter Maydell
                   ` (25 more replies)
  0 siblings, 26 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

I've been working on the ITS to add support for the GICv4 functionality.
In the course of that I found a handful of bugs in it and also some
places where the code benefited from refactoring to make it a better
base to put in the GICv4 parts. This patchset is just the bugfixes
and cleanups, because there are enough patches here that I figured it
made sense to send them out now rather than holding on to them.
I've included Alex's "clean up error reporting" patch as patch 1 in
the series to avoid having to use a Based-on: tag.

Bug fixes:
 * Most of the bounds checks on values provided by the guest in
   command packets had off-by-one errors. In almost all cases this
   was completely harmless since the tables being indexed are in
   guest memory, but for rdbase we use it as an index into a C array,
   so there a badly-behaved guest could probably crash QEMU
 * the loop over the GITS_BASER<n> registers in extract_table_params()
   returned early when it found a register with the Valid bit clear,
   rather than continuing to process the other base registers
 * We miscalculated the entry sizes for the Collection and Device
   tables, with the effect that we could potentially corrupt
   guest memory
 * the MAPI command handling was missing an error check on EventID
 * if the guest confgured a DTE with a size of 32 we would have
   shifted off the end of a 32-bit value
 * the calls to process_its_cmd() put the return value in the wrong
   variable
 * if the memory access to read the first word of the command packet
   failed, our error-handling codepath wasn't quite right
 * we weren't actually implementing the "memory access errors cause
   the ITS to stall command processing, parameter errors cause it
   to continue to the next command" logic that the comments claim

Refactorings:
 * the ITS_CTLR_ENABLED define was a duplicate of R_GITS_CTLR_ENABLED_MASK
 * extract_table_params() had unnecessarily duplicated code for
   handling each table type
 * some refactoring and renaming of variables and struct fields used
   in the bounds-check tests so that we have a consistent convention
   that hopefully reduces the risk of future off-by-one errors
 * some parts of the code which were doing open-coded shift-and-mask
   operations have been converted to use the FIELD macro
 * the code for "find the address of an entry in an in-guest-memory
   table" can be factored out into its own function

thanks
-- PMM

Alex Bennée (1):
  hw/intc: clean-up error reporting for failed ITS cmd

Peter Maydell (25):
  hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase
  hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define
  hw/intc/arm_gicv3_its: Remove maxids union from TableDesc
  hw/intc/arm_gicv3_its: Don't return early in extract_table_params()
    loop
  hw/intc/arm_gicv3_its: Reduce code duplication in
    extract_table_params()
  hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz
  hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define
  hw/intc/arm_gicv3_its: Correct handling of MAPI
  hw/intc/arm_gicv3_its: Use FIELD macros for DTEs
  hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1)
  hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size
  hw/intc/arm_gicv3_its: Use FIELD macros for CTEs
  hw/intc/arm_gicv3_its: Fix various off-by-one errors
  hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries
  hw/intc/arm_gicv3_its: Fix event ID bounds checks
  hw/intc/arm_gicv3_its: Convert int ID check to num_intids convention
  hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value
  hw/intc/arm_gicv3_its: Don't use data if reading command failed
  hw/intc/arm_gicv3_its: Use enum for return value of process_*
    functions
  hw/intc/arm_gicv3_its: Fix return codes in process_its_cmd()
  hw/intc/arm_gicv3_its: Refactor process_its_cmd() to reduce nesting
  hw/intc/arm_gicv3_its: Fix return codes in process_mapti()
  hw/intc/arm_gicv3_its: Fix return codes in process_mapc()
  hw/intc/arm_gicv3_its: Fix return codes in process_mapd()
  hw/intc/arm_gicv3_its: Factor out "find address of table entry" code

 hw/intc/gicv3_internal.h               |  40 +-
 include/hw/intc/arm_gicv3_its_common.h |   9 +-
 hw/intc/arm_gicv3_its.c                | 628 +++++++++++--------------
 3 files changed, 303 insertions(+), 374 deletions(-)

-- 
2.25.1



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

* [PATCH 01/26] hw/intc: clean-up error reporting for failed ITS cmd
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 17:31   ` Richard Henderson
  2021-12-11 19:11 ` [PATCH 02/26] hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase Peter Maydell
                   ` (24 subsequent siblings)
  25 siblings, 1 reply; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

From: Alex Bennée <alex.bennee@linaro.org>

While trying to debug a GIC ITS failure I saw some guest errors that
had poor formatting as well as leaving me confused as to what failed.
As most of the checks aren't possible without a valid dte split that
check apart and then check the other conditions in steps. This avoids
us relying on undefined data.

I still get a failure with the current kvm-unit-tests but at least I
know (partially) why now:

  Exception return from AArch64 EL1 to AArch64 EL1 PC 0x40080588
  PASS: gicv3: its-trigger: inv/invall: dev2/eventid=20 now triggers an LPI
  ITS: MAPD devid=2 size = 0x8 itt=0x40430000 valid=0
  INT dev_id=2 event_id=20
  process_its_cmd: invalid command attributes: invalid dte: 0 for 2 (MEM_TX: 0)
  PASS: gicv3: its-trigger: mapd valid=false: no LPI after device unmap
  SUMMARY: 6 tests, 1 unexpected failures

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Cc: Shashi Mallela <shashi.mallela@linaro.org>
Cc: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 39 +++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index c929a9cb5c3..b99e63d58f7 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -274,21 +274,36 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
         if (res != MEMTX_OK) {
             return result;
         }
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: invalid command attributes: "
+                      "invalid dte: %"PRIx64" for %d (MEM_TX: %d)\n",
+                      __func__, dte, devid, res);
+        return result;
     }
 
-    if ((devid > s->dt.maxids.max_devids) || !dte_valid || !ite_valid ||
-            !cte_valid || (eventid > max_eventid)) {
+
+    /*
+     * In this implementation, in case of guest errors we ignore the
+     * command and move onto the next command in the queue.
+     */
+    if (devid > s->dt.maxids.max_devids) {
         qemu_log_mask(LOG_GUEST_ERROR,
-                      "%s: invalid command attributes "
-                      "devid %d or eventid %d or invalid dte %d or"
-                      "invalid cte %d or invalid ite %d\n",
-                      __func__, devid, eventid, dte_valid, cte_valid,
-                      ite_valid);
-        /*
-         * in this implementation, in case of error
-         * we ignore this command and move onto the next
-         * command in the queue
-         */
+                      "%s: invalid command attributes: devid %d>%d",
+                      __func__, devid, s->dt.maxids.max_devids);
+
+    } else if (!dte_valid || !ite_valid || !cte_valid) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: invalid command attributes: "
+                      "dte: %s, ite: %s, cte: %s\n",
+                      __func__,
+                      dte_valid ? "valid" : "invalid",
+                      ite_valid ? "valid" : "invalid",
+                      cte_valid ? "valid" : "invalid");
+    } else if (eventid > max_eventid) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: invalid command attributes: eventid %d > %d\n",
+                      __func__, eventid, max_eventid);
     } else {
         /*
          * Current implementation only supports rdbase == procnum
-- 
2.25.1



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

* [PATCH 02/26] hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
  2021-12-11 19:11 ` [PATCH 01/26] hw/intc: clean-up error reporting for failed ITS cmd Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 17:32   ` Richard Henderson
  2021-12-13 11:22   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 03/26] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define Peter Maydell
                   ` (23 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

The checks in the ITS on the rdbase values in guest commands are
off-by-one: they permit the guest to pass us a value equal to
s->gicv3->num_cpu, but the valid values are 0...num_cpu-1.  This
meant the guest could cause us to index off the end of the
s->gicv3->cpu[] array when calling gicv3_redist_process_lpi(), and we
would probably crash.

Cc: qemu-stable@nongnu.org
Fixes: 17fb5e36aabd4b ("hw/intc: GICv3 redistributor ITS processing")
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
Not a security bug, because only usable with emulation.
---
 hw/intc/arm_gicv3_its.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index b99e63d58f7..677b96dfe23 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -311,7 +311,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
          */
         rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U;
 
-        if (rdbase > s->gicv3->num_cpu) {
+        if (rdbase >= s->gicv3->num_cpu) {
             return result;
         }
 
@@ -505,7 +505,7 @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset)
 
     valid = (value & CMD_FIELD_VALID_MASK);
 
-    if ((icid > s->ct.maxids.max_collids) || (rdbase > s->gicv3->num_cpu)) {
+    if ((icid > s->ct.maxids.max_collids) || (rdbase >= s->gicv3->num_cpu)) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "ITS MAPC: invalid collection table attributes "
                       "icid %d rdbase %" PRIu64 "\n",  icid, rdbase);
-- 
2.25.1



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

* [PATCH 03/26] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
  2021-12-11 19:11 ` [PATCH 01/26] hw/intc: clean-up error reporting for failed ITS cmd Peter Maydell
  2021-12-11 19:11 ` [PATCH 02/26] hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 17:34   ` Richard Henderson
                     ` (2 more replies)
  2021-12-11 19:11 ` [PATCH 04/26] hw/intc/arm_gicv3_its: Remove maxids union from TableDesc Peter Maydell
                   ` (22 subsequent siblings)
  25 siblings, 3 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

We currently define a bitmask for the GITS_CTLR ENABLED bit in
two ways: as ITS_CTLR_ENABLED, and via the FIELD() macro as
R_GITS_CTLR_ENABLED_MASK. Consistently use the FIELD macro version
everywhere and remove the redundant ITS_CTLR_ENABLED define.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/gicv3_internal.h |  2 --
 hw/intc/arm_gicv3_its.c  | 20 ++++++++++----------
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index b9c37453b04..63de8667c61 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -289,8 +289,6 @@ FIELD(GITS_TYPER, CIL, 36, 1)
 
 #define GITS_IDREGS           0xFFD0
 
-#define ITS_CTLR_ENABLED               (1U)  /* ITS Enabled */
-
 #define GITS_BASER_RO_MASK                  (R_GITS_BASER_ENTRYSIZE_MASK | \
                                               R_GITS_BASER_TYPE_MASK)
 
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 677b96dfe23..985ae03f5fc 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -651,7 +651,7 @@ static void process_cmdq(GICv3ITSState *s)
     uint8_t cmd;
     int i;
 
-    if (!(s->ctlr & ITS_CTLR_ENABLED)) {
+    if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
         return;
     }
 
@@ -887,7 +887,7 @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
 
     switch (offset) {
     case GITS_TRANSLATER:
-        if (s->ctlr & ITS_CTLR_ENABLED) {
+        if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
             devid = attrs.requester_id;
             result = process_its_cmd(s, data, devid, NONE);
         }
@@ -912,13 +912,13 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
     switch (offset) {
     case GITS_CTLR:
         if (value & R_GITS_CTLR_ENABLED_MASK) {
-            s->ctlr |= ITS_CTLR_ENABLED;
+            s->ctlr |= R_GITS_CTLR_ENABLED_MASK;
             extract_table_params(s);
             extract_cmdq_params(s);
             s->creadr = 0;
             process_cmdq(s);
         } else {
-            s->ctlr &= ~ITS_CTLR_ENABLED;
+            s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK;
         }
         break;
     case GITS_CBASER:
@@ -926,7 +926,7 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
          * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
          *                 already enabled
          */
-        if (!(s->ctlr & ITS_CTLR_ENABLED)) {
+        if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
             s->cbaser = deposit64(s->cbaser, 0, 32, value);
             s->creadr = 0;
             s->cwriter = s->creadr;
@@ -937,7 +937,7 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
          * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
          *                 already enabled
          */
-        if (!(s->ctlr & ITS_CTLR_ENABLED)) {
+        if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
             s->cbaser = deposit64(s->cbaser, 32, 32, value);
             s->creadr = 0;
             s->cwriter = s->creadr;
@@ -979,7 +979,7 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
          * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
          *                 already enabled
          */
-        if (!(s->ctlr & ITS_CTLR_ENABLED)) {
+        if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
             index = (offset - GITS_BASER) / 8;
 
             if (offset & 7) {
@@ -1076,7 +1076,7 @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
          * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
          *                 already enabled
          */
-        if (!(s->ctlr & ITS_CTLR_ENABLED)) {
+        if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
             index = (offset - GITS_BASER) / 8;
             s->baser[index] &= GITS_BASER_RO_MASK;
             s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
@@ -1087,7 +1087,7 @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
          * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
          *                 already enabled
          */
-        if (!(s->ctlr & ITS_CTLR_ENABLED)) {
+        if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
             s->cbaser = value;
             s->creadr = 0;
             s->cwriter = s->creadr;
@@ -1298,7 +1298,7 @@ static void gicv3_its_reset(DeviceState *dev)
 
 static void gicv3_its_post_load(GICv3ITSState *s)
 {
-    if (s->ctlr & ITS_CTLR_ENABLED) {
+    if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
         extract_table_params(s);
         extract_cmdq_params(s);
     }
-- 
2.25.1



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

* [PATCH 04/26] hw/intc/arm_gicv3_its: Remove maxids union from TableDesc
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (2 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 03/26] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 17:37   ` Richard Henderson
  2021-12-13 11:32   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 05/26] hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop Peter Maydell
                   ` (21 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

The TableDesc struct defines properties of the in-guest-memory tables
which the guest tells us about by writing to the GITS_BASER<n>
registers.  This struct currently has a union 'maxids', but all the
fields of the union have the same type (uint32_t) and do the same
thing (record one-greater-than the maximum ID value that can be used
as an index into the table).

We're about to add another table type (the GICv4 vPE table); rather
than adding another specifically-named union field for that table
type with the same type as the other union fields, remove the union
entirely and just have a 'uint32_t max_ids' struct field.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/intc/arm_gicv3_its_common.h |  5 +----
 hw/intc/arm_gicv3_its.c                | 20 ++++++++++----------
 2 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
index 4e79145dde3..85a144b0e49 100644
--- a/include/hw/intc/arm_gicv3_its_common.h
+++ b/include/hw/intc/arm_gicv3_its_common.h
@@ -47,10 +47,7 @@ typedef struct {
     uint16_t entry_sz;
     uint32_t page_sz;
     uint32_t max_entries;
-    union {
-        uint32_t max_devids;
-        uint32_t max_collids;
-    } maxids;
+    uint32_t max_ids;
     uint64_t base_addr;
 } TableDesc;
 
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 985ae03f5fc..f321f10189e 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -287,10 +287,10 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
      * In this implementation, in case of guest errors we ignore the
      * command and move onto the next command in the queue.
      */
-    if (devid > s->dt.maxids.max_devids) {
+    if (devid > s->dt.max_ids) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes: devid %d>%d",
-                      __func__, devid, s->dt.maxids.max_devids);
+                      __func__, devid, s->dt.max_ids);
 
     } else if (!dte_valid || !ite_valid || !cte_valid) {
         qemu_log_mask(LOG_GUEST_ERROR,
@@ -384,7 +384,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
         max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
     }
 
-    if ((devid > s->dt.maxids.max_devids) || (icid > s->ct.maxids.max_collids)
+    if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids)
             || !dte_valid || (eventid > max_eventid) ||
             (!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) ||
             (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) {
@@ -505,7 +505,7 @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset)
 
     valid = (value & CMD_FIELD_VALID_MASK);
 
-    if ((icid > s->ct.maxids.max_collids) || (rdbase >= s->gicv3->num_cpu)) {
+    if ((icid > s->ct.max_ids) || (rdbase >= s->gicv3->num_cpu)) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "ITS MAPC: invalid collection table attributes "
                       "icid %d rdbase %" PRIu64 "\n",  icid, rdbase);
@@ -618,7 +618,7 @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
 
     valid = (value & CMD_FIELD_VALID_MASK);
 
-    if ((devid > s->dt.maxids.max_devids) ||
+    if ((devid > s->dt.max_ids) ||
         (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "ITS MAPD: invalid device table attributes "
@@ -810,8 +810,8 @@ static void extract_table_params(GICv3ITSState *s)
                                      (page_sz / s->dt.entry_sz));
             }
 
-            s->dt.maxids.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
-                                       DEVBITS) + 1));
+            s->dt.max_ids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
+                                                DEVBITS) + 1));
 
             s->dt.base_addr = baser_base_addr(value, page_sz);
 
@@ -842,11 +842,11 @@ static void extract_table_params(GICv3ITSState *s)
             }
 
             if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
-                s->ct.maxids.max_collids = (1UL << (FIELD_EX64(s->typer,
-                                            GITS_TYPER, CIDBITS) + 1));
+                s->ct.max_ids = (1UL << (FIELD_EX64(s->typer,
+                                                    GITS_TYPER, CIDBITS) + 1));
             } else {
                 /* 16-bit CollectionId supported when CIL == 0 */
-                s->ct.maxids.max_collids = (1UL << 16);
+                s->ct.max_ids = (1UL << 16);
             }
 
             s->ct.base_addr = baser_base_addr(value, page_sz);
-- 
2.25.1



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

* [PATCH 05/26] hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (3 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 04/26] hw/intc/arm_gicv3_its: Remove maxids union from TableDesc Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 17:46   ` Richard Henderson
  2021-12-13 11:33   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 06/26] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params() Peter Maydell
                   ` (20 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

In extract_table_params() we process each GITS_BASER<n> register.  If
the register's Valid bit is not set, this means there is no
in-guest-memory table and so we should not try to interpret the other
fields in the register.  This was incorrectly coded as a 'return'
rather than a 'break', so instead of looping round to process the
next GITS_BASER<n> we would stop entirely, treating any later tables
as being not valid also.

This has no real guest-visible effects because (since we don't have
GITS_TYPER.HCC != 0) the guest must in any case set up all the
GITS_BASER<n> to point to valid tables, so this only happens in an
odd misbehaving-guest corner case.

Fix the check to 'break', so that we leave the case statement and
loop back around to the next GITS_BASER<n>.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
I suspect this was an accidental result from a refactoring at
some point in the development of the ITS code.
---
 hw/intc/arm_gicv3_its.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index f321f10189e..c97b9982ae1 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -795,7 +795,7 @@ static void extract_table_params(GICv3ITSState *s)
             s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
 
             if (!s->dt.valid) {
-                return;
+                break;
             }
 
             s->dt.page_sz = page_sz;
@@ -826,7 +826,7 @@ static void extract_table_params(GICv3ITSState *s)
              * hence writes are discarded if ct.valid is 0
              */
             if (!s->ct.valid) {
-                return;
+                break;
             }
 
             s->ct.page_sz = page_sz;
-- 
2.25.1



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

* [PATCH 06/26] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params()
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (4 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 05/26] hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 18:30   ` Richard Henderson
                     ` (2 more replies)
  2021-12-11 19:11 ` [PATCH 07/26] hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz Peter Maydell
                   ` (19 subsequent siblings)
  25 siblings, 3 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

The extract_table_params() decodes the fields in the GITS_BASER<n>
registers into TableDesc structs.  Since the fields are the same for
all the GITS_BASER<n> registers, there is currently a lot of code
duplication within the switch (type) statement.  Refactor so that the
cases include only what is genuinely different for each type:
the calculation of the number of bits in the ID value that indexes
into the table.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 97 +++++++++++++++++------------------------
 1 file changed, 40 insertions(+), 57 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index c97b9982ae1..84808b1e298 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -758,6 +758,9 @@ static void extract_table_params(GICv3ITSState *s)
     uint64_t value;
 
     for (int i = 0; i < 8; i++) {
+        TableDesc *td;
+        int idbits;
+
         value = s->baser[i];
 
         if (!value) {
@@ -789,73 +792,53 @@ static void extract_table_params(GICv3ITSState *s)
         type = FIELD_EX64(value, GITS_BASER, TYPE);
 
         switch (type) {
-
         case GITS_BASER_TYPE_DEVICE:
-            memset(&s->dt, 0 , sizeof(s->dt));
-            s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
-
-            if (!s->dt.valid) {
-                break;
-            }
-
-            s->dt.page_sz = page_sz;
-            s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
-            s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
-
-            if (!s->dt.indirect) {
-                s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz;
-            } else {
-                s->dt.max_entries = (((num_pages * page_sz) /
-                                     L1TABLE_ENTRY_SIZE) *
-                                     (page_sz / s->dt.entry_sz));
-            }
-
-            s->dt.max_ids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
-                                                DEVBITS) + 1));
-
-            s->dt.base_addr = baser_base_addr(value, page_sz);
-
+            td = &s->dt;
+            idbits = FIELD_EX64(s->typer, GITS_TYPER, DEVBITS) + 1;
             break;
-
         case GITS_BASER_TYPE_COLLECTION:
-            memset(&s->ct, 0 , sizeof(s->ct));
-            s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
-
-            /*
-             * GITS_TYPER.HCC is 0 for this implementation
-             * hence writes are discarded if ct.valid is 0
-             */
-            if (!s->ct.valid) {
-                break;
-            }
-
-            s->ct.page_sz = page_sz;
-            s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
-            s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
-
-            if (!s->ct.indirect) {
-                s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz;
-            } else {
-                s->ct.max_entries = (((num_pages * page_sz) /
-                                     L1TABLE_ENTRY_SIZE) *
-                                     (page_sz / s->ct.entry_sz));
-            }
-
+            td = &s->ct;
             if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
-                s->ct.max_ids = (1UL << (FIELD_EX64(s->typer,
-                                                    GITS_TYPER, CIDBITS) + 1));
+                idbits = FIELD_EX64(s->typer, GITS_TYPER, CIDBITS) + 1;
             } else {
                 /* 16-bit CollectionId supported when CIL == 0 */
-                s->ct.max_ids = (1UL << 16);
+                idbits = 16;
             }
-
-            s->ct.base_addr = baser_base_addr(value, page_sz);
-
             break;
-
         default:
-            break;
+            /*
+             * GITS_BASER<n>.TYPE is read-only, so GITS_BASER_RO_MASK
+             * ensures we will only see type values corresponding to
+             * the values set up in gicv3_its_reset().
+             */
+            g_assert_not_reached();
         }
+
+        memset(td, 0, sizeof(*td));
+        td->valid = FIELD_EX64(value, GITS_BASER, VALID);
+        /*
+         * If GITS_BASER<n>.Valid is 0 for any <n> then we will not process
+         * interrupts. (GITS_TYPER.HCC is 0 for this implementation, so we
+         * do not have a special case where the GITS_BASER<n>.Valid bit is 0
+         * for the register corresponding to the Collection table but we
+         * still have to process interrupts using non-memory-backed
+         * Collection table entries.)
+         */
+        if (!td->valid) {
+            continue;
+        }
+        td->page_sz = page_sz;
+        td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
+        td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
+        td->base_addr = baser_base_addr(value, page_sz);
+        if (!td->indirect) {
+            td->max_entries = (num_pages * page_sz) / td->entry_sz;
+        } else {
+            td->max_entries = (((num_pages * page_sz) /
+                                  L1TABLE_ENTRY_SIZE) *
+                                 (page_sz / td->entry_sz));
+        }
+        td->max_ids = 1ULL << idbits;
     }
 }
 
-- 
2.25.1



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

* [PATCH 07/26] hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (5 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 06/26] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params() Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 18:33   ` Richard Henderson
  2021-12-13 11:37   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 08/26] hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define Peter Maydell
                   ` (18 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

We set the TableDesc entry_sz field from the appropriate
GITS_BASER.ENTRYSIZE field.  That ID register field specifies the
number of bytes per table entry minus one.  However when we use
td->entry_sz we assume it to be the number of bytes per table entry
(for instance we calculate the number of entries in a page by
dividing the page size by the entry size).

The effects of this bug are:
 * we miscalculate the maximum number of entries in the table,
   so our checks on guest index values are wrong (too lax)
 * when looking up an entry in the second level of an indirect
   table, we calculate an incorrect index into the L2 table.
   Because we make the same incorrect calculation on both
   reads and writes of the L2 table, the guest won't notice
   unless it's unlucky enough to use an index value that
   causes us to index off the end of the L2 table page and
   cause guest memory corruption in whatever follows

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 84808b1e298..88f4d730999 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -829,7 +829,7 @@ static void extract_table_params(GICv3ITSState *s)
         }
         td->page_sz = page_sz;
         td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
-        td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
+        td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1;
         td->base_addr = baser_base_addr(value, page_sz);
         if (!td->indirect) {
             td->max_entries = (num_pages * page_sz) / td->entry_sz;
-- 
2.25.1



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

* [PATCH 08/26] hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (6 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 07/26] hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 18:40   ` Richard Henderson
  2021-12-13 11:52   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 09/26] hw/intc/arm_gicv3_its: Correct handling of MAPI Peter Maydell
                   ` (17 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

The GITS_TYPE_PHYSICAL define is the value we set the
GITS_TYPER.Physical field to -- this is 1 to indicate that we support
physical LPIs.  (Support for virtual LPIs is the GITS_TYPER.Virtual
field.) We also use this define as the *value* that we write into an
interrupt translation table entry's INTTYPE field, which should be 1
for a physical interrupt and 0 for a virtual interrupt.  Finally, we
use it as a *mask* when we read the interrupt translation table entry
INTTYPE field.

Untangle this confusion: define an ITE_INTTYPE_VIRTUAL and
ITE_INTTYPE_PHYSICAL to be the valid values of the ITE INTTYPE
field, and replace the ad-hoc collection of ITE_ENTRY_* defines with
use of the FIELD() macro to define the fields of an ITE and the
FIELD_EX64() and FIELD_DP64() macros to read and write them.
We use ITE in the new setup, rather than ITE_ENTRY, because
ITE stands for "Interrupt translation entry" and so the extra
"entry" would be redundant.

We take the opportunity to correct the name of the field that holds
the GICv4 'doorbell' interrupt ID (this is always the value 1023 in a
GICv3, which is why we were calling it the 'spurious' field).

The GITS_TYPE_PHYSICAL define is then used in only one place, where
we set the initial GITS_TYPER value.  Since GITS_TYPER.Physical is
essentially a boolean, hiding the '1' value behind a macro is more
confusing than helpful, so expand out the macro there and remove the
define entirely.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/gicv3_internal.h | 26 ++++++++++++++------------
 hw/intc/arm_gicv3_its.c  | 30 +++++++++++++-----------------
 2 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 63de8667c61..5a63e9ed5ce 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -354,28 +354,30 @@ FIELD(MAPC, RDBASE, 16, 32)
 #define L2_TABLE_VALID_MASK       CMD_FIELD_VALID_MASK
 #define TABLE_ENTRY_VALID_MASK    (1ULL << 0)
 
-/**
- * Default features advertised by this version of ITS
- */
-/* Physical LPIs supported */
-#define GITS_TYPE_PHYSICAL           (1U << 0)
-
 /*
  * 12 bytes Interrupt translation Table Entry size
  * as per Table 5.3 in GICv3 spec
  * ITE Lower 8 Bytes
  *   Bits:    | 49 ... 26 | 25 ... 2 |   1     |   0    |
- *   Values:  |    1023   |  IntNum  | IntType |  Valid |
+ *   Values:  |  Doorbell |  IntNum  | IntType |  Valid |
  * ITE Higher 4 Bytes
  *   Bits:    | 31 ... 16 | 15 ...0 |
  *   Values:  |  vPEID    |  ICID   |
+ * (When Doorbell is unused, as it always is in GICv3, it is 1023)
  */
 #define ITS_ITT_ENTRY_SIZE            0xC
-#define ITE_ENTRY_INTTYPE_SHIFT        1
-#define ITE_ENTRY_INTID_SHIFT          2
-#define ITE_ENTRY_INTID_MASK         MAKE_64BIT_MASK(2, 24)
-#define ITE_ENTRY_INTSP_SHIFT          26
-#define ITE_ENTRY_ICID_MASK          MAKE_64BIT_MASK(0, 16)
+
+FIELD(ITE_L, VALID, 0, 1)
+FIELD(ITE_L, INTTYPE, 1, 1)
+FIELD(ITE_L, INTID, 2, 24)
+FIELD(ITE_L, DOORBELL, 26, 24)
+
+FIELD(ITE_H, ICID, 0, 16)
+FIELD(ITE_H, VPEID, 16, 16)
+
+/* Possible values for ITE_L INTTYPE */
+#define ITE_INTTYPE_VIRTUAL 0
+#define ITE_INTTYPE_PHYSICAL 1
 
 /* 16 bits EventId */
 #define ITS_IDBITS                   GICD_TYPER_IDBITS
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 88f4d730999..15eb72a0a15 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -156,12 +156,11 @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
                                         MEMTXATTRS_UNSPECIFIED, res);
 
         if (*res == MEMTX_OK) {
-            if (ite.itel & TABLE_ENTRY_VALID_MASK) {
-                if ((ite.itel >> ITE_ENTRY_INTTYPE_SHIFT) &
-                    GITS_TYPE_PHYSICAL) {
-                    *pIntid = (ite.itel & ITE_ENTRY_INTID_MASK) >>
-                               ITE_ENTRY_INTID_SHIFT;
-                    *icid = ite.iteh & ITE_ENTRY_ICID_MASK;
+            if (FIELD_EX64(ite.itel, ITE_L, VALID)) {
+                int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
+                if (inttype == ITE_INTTYPE_PHYSICAL) {
+                    *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
+                    *icid = FIELD_EX32(ite.iteh, ITE_H, ICID);
                     status = true;
                 }
             }
@@ -342,8 +341,6 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
     MemTxResult res = MEMTX_OK;
     uint16_t icid = 0;
     uint64_t dte = 0;
-    IteEntry ite;
-    uint32_t int_spurious = INTID_SPURIOUS;
     bool result = false;
 
     devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
@@ -400,16 +397,16 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
          */
     } else {
         /* add ite entry to interrupt translation table */
-        ite.itel = (dte_valid & TABLE_ENTRY_VALID_MASK) |
-                    (GITS_TYPE_PHYSICAL << ITE_ENTRY_INTTYPE_SHIFT);
-
+        IteEntry ite = {};
+        ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid);
+        ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
         if (ignore_pInt) {
-            ite.itel |= (eventid << ITE_ENTRY_INTID_SHIFT);
+            ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, eventid);
         } else {
-            ite.itel |= (pIntid << ITE_ENTRY_INTID_SHIFT);
+            ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
         }
-        ite.itel |= (int_spurious << ITE_ENTRY_INTSP_SHIFT);
-        ite.iteh = icid;
+        ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
+        ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
 
         result = update_ite(s, eventid, dte, ite);
     }
@@ -1237,8 +1234,7 @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
                        "gicv3-its-sysmem");
 
     /* set the ITS default features supported */
-    s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL,
-                          GITS_TYPE_PHYSICAL);
+    s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1);
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
                           ITS_ITT_ENTRY_SIZE - 1);
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
-- 
2.25.1



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

* [PATCH 09/26] hw/intc/arm_gicv3_its: Correct handling of MAPI
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (7 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 08/26] hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 18:48   ` Richard Henderson
  2021-12-13 11:54   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs Peter Maydell
                   ` (16 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

The MAPI command takes arguments DeviceID, EventID, ICID, and is
defined to be equivalent to MAPTI DeviceID, EventID, EventID, ICID.
(That is, where MAPTI takes an explicit pINTID, MAPI uses the EventID
as the pINTID.)

We didn't quite get this right.  In particular the error checks for
MAPI include "EventID does not specify a valid LPI identifier", which
is the same as MAPTI's error check for the pINTID field.  QEMU's code
skips the pINTID error check entirely in the MAPI case.

We can fix this bug and in the process simplify the code by switching
to the obvious implementation of setting pIntid = eventid early
if ignore_pInt is true.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 15eb72a0a15..6f21c56fba2 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -354,7 +354,9 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
 
     eventid = (value & EVENTID_MASK);
 
-    if (!ignore_pInt) {
+    if (ignore_pInt) {
+        pIntid = eventid;
+    } else {
         pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);
     }
 
@@ -377,14 +379,12 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
 
     max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
 
-    if (!ignore_pInt) {
-        max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
-    }
+    max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
 
     if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids)
             || !dte_valid || (eventid > max_eventid) ||
-            (!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) ||
-            (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) {
+            (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) &&
+             (pIntid != INTID_SPURIOUS))) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes "
                       "devid %d or icid %d or eventid %d or pIntid %d or"
@@ -400,11 +400,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
         IteEntry ite = {};
         ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid);
         ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
-        if (ignore_pInt) {
-            ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, eventid);
-        } else {
-            ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
-        }
+        ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
         ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
         ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
 
-- 
2.25.1



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

* [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (8 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 09/26] hw/intc/arm_gicv3_its: Correct handling of MAPI Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 20:23   ` Richard Henderson
                     ` (2 more replies)
  2021-12-11 19:11 ` [PATCH 11/26] hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1) Peter Maydell
                   ` (15 subsequent siblings)
  25 siblings, 3 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

Currently the ITS code that reads and writes DTEs uses open-coded
shift-and-mask to assemble the various fields into the 64-bit DTE
word.  The names of the macros used for mask and shift values are
also somewhat inconsistent, and don't follow our usual convention
that a MASK macro should specify the bits in their place in the word.
Replace all these with use of the FIELD macro.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/gicv3_internal.h |  7 ++++---
 hw/intc/arm_gicv3_its.c  | 20 +++++++++-----------
 2 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 5a63e9ed5ce..6a3b145f377 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -393,9 +393,10 @@ FIELD(ITE_H, VPEID, 16, 16)
  * Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits
  */
 #define GITS_DTE_SIZE                 (0x8ULL)
-#define GITS_DTE_ITTADDR_SHIFT           6
-#define GITS_DTE_ITTADDR_MASK         MAKE_64BIT_MASK(GITS_DTE_ITTADDR_SHIFT, \
-                                                      ITTADDR_LENGTH)
+
+FIELD(DTE, VALID, 0, 1)
+FIELD(DTE, SIZE, 1, 5)
+FIELD(DTE, ITTADDR, 6, 44)
 
 /*
  * 8 bytes Collection Table Entry size
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 6f21c56fba2..7a217b00f89 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -114,7 +114,7 @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
     uint64_t itt_addr;
     MemTxResult res = MEMTX_OK;
 
-    itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
+    itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
     itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
 
     address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
@@ -141,7 +141,7 @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
     bool status = false;
     IteEntry ite = {};
 
-    itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
+    itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
     itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
 
     ite.itel = address_space_ldq_le(as, itt_addr +
@@ -255,10 +255,10 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
     if (res != MEMTX_OK) {
         return result;
     }
-    dte_valid = dte & TABLE_ENTRY_VALID_MASK;
+    dte_valid = FIELD_EX64(dte, DTE, VALID);
 
     if (dte_valid) {
-        max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
+        max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
 
         ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
 
@@ -375,10 +375,8 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
     if (res != MEMTX_OK) {
         return result;
     }
-    dte_valid = dte & TABLE_ENTRY_VALID_MASK;
-
-    max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
-
+    dte_valid = FIELD_EX64(dte, DTE, VALID);
+    max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
     max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
 
     if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids)
@@ -529,9 +527,9 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
     if (s->dt.valid) {
         if (valid) {
             /* add mapping entry to device table */
-            dte = (valid & TABLE_ENTRY_VALID_MASK) |
-                  ((size & SIZE_MASK) << 1U) |
-                  (itt_addr << GITS_DTE_ITTADDR_SHIFT);
+            dte = FIELD_DP64(dte, DTE, VALID, 1);
+            dte = FIELD_DP64(dte, DTE, SIZE, size);
+            dte = FIELD_DP64(dte, DTE, ITTADDR, itt_addr);
         }
     } else {
         return true;
-- 
2.25.1



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

* [PATCH 11/26] hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1)
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (9 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 20:31   ` Richard Henderson
  2021-12-12 20:43   ` Richard Henderson
  2021-12-11 19:11 ` [PATCH 12/26] hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size Peter Maydell
                   ` (14 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

The DTE.SIZE field is 5 bits, which means that DTE.SIZE + 1
might in theory be 32. When calculating 1 << (DTE.SIZE + 1)
use 1ULL to ensure that we don't do this arithmetic at 32 bits
and shift the 1 off the end in this case.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 7a217b00f89..d6637229479 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -258,7 +258,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
     dte_valid = FIELD_EX64(dte, DTE, VALID);
 
     if (dte_valid) {
-        max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
+        max_eventid = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
 
         ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
 
@@ -376,7 +376,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
         return result;
     }
     dte_valid = FIELD_EX64(dte, DTE, VALID);
-    max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
+    max_eventid = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
     max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
 
     if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids)
-- 
2.25.1



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

* [PATCH 12/26] hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (10 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 11/26] hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1) Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 20:34   ` Richard Henderson
  2021-12-13 13:07   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 13/26] hw/intc/arm_gicv3_its: Use FIELD macros for CTEs Peter Maydell
                   ` (13 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

The comment says that in our CTE format the RDBase field is 36 bits;
in fact for us it is only 16 bits, because we use the RDBase format
where it specifies a 16-bit CPU number. The code already uses
RDBASE_PROCNUM_LENGTH (16) as the field width, so fix the comment
to match it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/gicv3_internal.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 6a3b145f377..14e8ef68e02 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -400,7 +400,7 @@ FIELD(DTE, ITTADDR, 6, 44)
 
 /*
  * 8 bytes Collection Table Entry size
- * Valid = 1 bit,RDBase = 36 bits(considering max RDBASE)
+ * Valid = 1 bit, RDBase = 16 bits
  */
 #define GITS_CTE_SIZE                 (0x8ULL)
 #define GITS_CTE_RDBASE_PROCNUM_MASK  MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH)
-- 
2.25.1



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

* [PATCH 13/26] hw/intc/arm_gicv3_its: Use FIELD macros for CTEs
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (11 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 12/26] hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 20:35   ` Richard Henderson
  2021-12-13 13:08   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 14/26] hw/intc/arm_gicv3_its: Fix various off-by-one errors Peter Maydell
                   ` (12 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

Use FIELD macros to handle CTEs, rather than ad-hoc mask-and-shift.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/gicv3_internal.h | 3 ++-
 hw/intc/arm_gicv3_its.c  | 7 ++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 14e8ef68e02..1eeb99035da 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -403,7 +403,8 @@ FIELD(DTE, ITTADDR, 6, 44)
  * Valid = 1 bit, RDBase = 16 bits
  */
 #define GITS_CTE_SIZE                 (0x8ULL)
-#define GITS_CTE_RDBASE_PROCNUM_MASK  MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH)
+FIELD(CTE, VALID, 0, 1)
+FIELD(CTE, RDBASE, 1, RDBASE_PROCNUM_LENGTH)
 
 /* Special interrupt IDs */
 #define INTID_SECURE 1020
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index d6637229479..ab6ce09dbc2 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -104,7 +104,7 @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
                                       MEMTXATTRS_UNSPECIFIED, res);
     }
 
-    return (*cte & TABLE_ENTRY_VALID_MASK) != 0;
+    return FIELD_EX64(*cte, CTE, VALID);
 }
 
 static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
@@ -308,7 +308,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
          * Current implementation only supports rdbase == procnum
          * Hence rdbase physical address is ignored
          */
-        rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U;
+        rdbase = FIELD_EX64(cte, CTE, RDBASE);
 
         if (rdbase >= s->gicv3->num_cpu) {
             return result;
@@ -426,7 +426,8 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
 
     if (valid) {
         /* add mapping entry to collection table */
-        cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL);
+        cte = FIELD_DP64(cte, CTE, VALID, 1);
+        cte = FIELD_DP64(cte, CTE, RDBASE, rdbase);
     }
 
     /*
-- 
2.25.1



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

* [PATCH 14/26] hw/intc/arm_gicv3_its: Fix various off-by-one errors
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (12 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 13/26] hw/intc/arm_gicv3_its: Use FIELD macros for CTEs Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-13 13:35   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 15/26] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries Peter Maydell
                   ` (11 subsequent siblings)
  25 siblings, 1 reply; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

The ITS code has to check whether various parameters passed in
commands are in-bounds, where the limit is defined in terms of the
number of bits that are available for the parameter.  (For example,
the GITS_TYPER.Devbits ID register field specifies the number of
DeviceID bits minus 1, and device IDs passed in the MAPTI and MAPD
command packets must fit in that many bits.)

Currently we have off-by-one bugs in many of these bounds checks.
The typical problem is that we define a max_foo as 1 << n. In
the Devbits example, we set
  s->dt.max_ids = 1UL << (GITS_TYPER.Devbits + 1).
However later when we do the bounds check we write
  if (devid > s->dt.max_ids) { /* command error */ }
which incorrectly permits a devid of 1 << n.

These bugs will not cause QEMU crashes because the ID values being
checked are only used for accesses into tables held in guest memory
which we access with address_space_*() functions, but they are
incorrect behaviour of our emulation.

Fix them by standardizing on this pattern:
 * bounds limits are named num_foos and are the 2^n value
   (equal to the number of valid foo values)
 * bounds checks are either
   if (fooid < num_foos) { good }
   or
   if (fooid >= num_foos) { bad }

In this commit we fix the handling of the number of IDs
in the device table and the collection table, and the number
of commands that will fit in the command queue.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/intc/arm_gicv3_its_common.h |  6 +++---
 hw/intc/arm_gicv3_its.c                | 26 +++++++++++++-------------
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
index 85a144b0e49..b32c697207f 100644
--- a/include/hw/intc/arm_gicv3_its_common.h
+++ b/include/hw/intc/arm_gicv3_its_common.h
@@ -46,14 +46,14 @@ typedef struct {
     bool indirect;
     uint16_t entry_sz;
     uint32_t page_sz;
-    uint32_t max_entries;
-    uint32_t max_ids;
+    uint32_t num_entries;
+    uint32_t num_ids;
     uint64_t base_addr;
 } TableDesc;
 
 typedef struct {
     bool valid;
-    uint32_t max_entries;
+    uint32_t num_entries;
     uint64_t base_addr;
 } CmdQDesc;
 
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index ab6ce09dbc2..7b50d3a29f0 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -286,10 +286,10 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
      * In this implementation, in case of guest errors we ignore the
      * command and move onto the next command in the queue.
      */
-    if (devid > s->dt.max_ids) {
+    if (devid >= s->dt.num_ids) {
         qemu_log_mask(LOG_GUEST_ERROR,
-                      "%s: invalid command attributes: devid %d>%d",
-                      __func__, devid, s->dt.max_ids);
+                      "%s: invalid command attributes: devid %d>=%d",
+                      __func__, devid, s->dt.num_ids);
 
     } else if (!dte_valid || !ite_valid || !cte_valid) {
         qemu_log_mask(LOG_GUEST_ERROR,
@@ -379,7 +379,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
     max_eventid = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
     max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
 
-    if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids)
+    if ((devid >= s->dt.num_ids) || (icid >= s->ct.num_ids)
             || !dte_valid || (eventid > max_eventid) ||
             (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) &&
              (pIntid != INTID_SPURIOUS))) {
@@ -497,7 +497,7 @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset)
 
     valid = (value & CMD_FIELD_VALID_MASK);
 
-    if ((icid > s->ct.max_ids) || (rdbase >= s->gicv3->num_cpu)) {
+    if ((icid >= s->ct.num_ids) || (rdbase >= s->gicv3->num_cpu)) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "ITS MAPC: invalid collection table attributes "
                       "icid %d rdbase %" PRIu64 "\n",  icid, rdbase);
@@ -610,7 +610,7 @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
 
     valid = (value & CMD_FIELD_VALID_MASK);
 
-    if ((devid > s->dt.max_ids) ||
+    if ((devid >= s->dt.num_ids) ||
         (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "ITS MAPD: invalid device table attributes "
@@ -649,7 +649,7 @@ static void process_cmdq(GICv3ITSState *s)
 
     wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
 
-    if (wr_offset > s->cq.max_entries) {
+    if (wr_offset >= s->cq.num_entries) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid write offset "
                       "%d\n", __func__, wr_offset);
@@ -658,7 +658,7 @@ static void process_cmdq(GICv3ITSState *s)
 
     rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
 
-    if (rd_offset > s->cq.max_entries) {
+    if (rd_offset >= s->cq.num_entries) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid read offset "
                       "%d\n", __func__, rd_offset);
@@ -721,7 +721,7 @@ static void process_cmdq(GICv3ITSState *s)
         }
         if (result) {
             rd_offset++;
-            rd_offset %= s->cq.max_entries;
+            rd_offset %= s->cq.num_entries;
             s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
         } else {
             /*
@@ -824,13 +824,13 @@ static void extract_table_params(GICv3ITSState *s)
         td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1;
         td->base_addr = baser_base_addr(value, page_sz);
         if (!td->indirect) {
-            td->max_entries = (num_pages * page_sz) / td->entry_sz;
+            td->num_entries = (num_pages * page_sz) / td->entry_sz;
         } else {
-            td->max_entries = (((num_pages * page_sz) /
+            td->num_entries = (((num_pages * page_sz) /
                                   L1TABLE_ENTRY_SIZE) *
                                  (page_sz / td->entry_sz));
         }
-        td->max_ids = 1ULL << idbits;
+        td->num_ids = 1ULL << idbits;
     }
 }
 
@@ -845,7 +845,7 @@ static void extract_cmdq_params(GICv3ITSState *s)
     s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
 
     if (s->cq.valid) {
-        s->cq.max_entries = (num_pages * GITS_PAGE_SIZE_4K) /
+        s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) /
                              GITS_CMDQ_ENTRY_SIZE;
         s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
         s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
-- 
2.25.1



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

* [PATCH 15/26] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (13 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 14/26] hw/intc/arm_gicv3_its: Fix various off-by-one errors Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 20:38   ` Richard Henderson
                     ` (2 more replies)
  2021-12-11 19:11 ` [PATCH 16/26] hw/intc/arm_gicv3_its: Fix event ID bounds checks Peter Maydell
                   ` (10 subsequent siblings)
  25 siblings, 3 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

In several places we have a local variable max_l2_entries which is
the number of entries which will fit in a level 2 table.  The
calculations done on this value are correct; rename it to
num_l2_entries to fit the convention we're using in this code.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 7b50d3a29f0..e4105282b57 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -74,7 +74,7 @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
     uint64_t value;
     bool valid_l2t;
     uint32_t l2t_id;
-    uint32_t max_l2_entries;
+    uint32_t num_l2_entries;
 
     if (s->ct.indirect) {
         l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
@@ -88,12 +88,12 @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
             valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
 
             if (valid_l2t) {
-                max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
+                num_l2_entries = s->ct.page_sz / s->ct.entry_sz;
 
                 l2t_addr = value & ((1ULL << 51) - 1);
 
                 *cte =  address_space_ldq_le(as, l2t_addr +
-                                    ((icid % max_l2_entries) * GITS_CTE_SIZE),
+                                    ((icid % num_l2_entries) * GITS_CTE_SIZE),
                                     MEMTXATTRS_UNSPECIFIED, res);
            }
        }
@@ -176,7 +176,7 @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
     uint64_t value;
     bool valid_l2t;
     uint32_t l2t_id;
-    uint32_t max_l2_entries;
+    uint32_t num_l2_entries;
 
     if (s->dt.indirect) {
         l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
@@ -190,12 +190,12 @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
             valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
 
             if (valid_l2t) {
-                max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
+                num_l2_entries = s->dt.page_sz / s->dt.entry_sz;
 
                 l2t_addr = value & ((1ULL << 51) - 1);
 
                 value =  address_space_ldq_le(as, l2t_addr +
-                                   ((devid % max_l2_entries) * GITS_DTE_SIZE),
+                                   ((devid % num_l2_entries) * GITS_DTE_SIZE),
                                    MEMTXATTRS_UNSPECIFIED, res);
             }
         }
@@ -416,7 +416,7 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
     uint64_t l2t_addr;
     bool valid_l2t;
     uint32_t l2t_id;
-    uint32_t max_l2_entries;
+    uint32_t num_l2_entries;
     uint64_t cte = 0;
     MemTxResult res = MEMTX_OK;
 
@@ -450,12 +450,12 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
         valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
 
         if (valid_l2t) {
-            max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
+            num_l2_entries = s->ct.page_sz / s->ct.entry_sz;
 
             l2t_addr = value & ((1ULL << 51) - 1);
 
             address_space_stq_le(as, l2t_addr +
-                                 ((icid % max_l2_entries) * GITS_CTE_SIZE),
+                                 ((icid % num_l2_entries) * GITS_CTE_SIZE),
                                  cte, MEMTXATTRS_UNSPECIFIED, &res);
         }
     } else {
@@ -521,7 +521,7 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
     uint64_t l2t_addr;
     bool valid_l2t;
     uint32_t l2t_id;
-    uint32_t max_l2_entries;
+    uint32_t num_l2_entries;
     uint64_t dte = 0;
     MemTxResult res = MEMTX_OK;
 
@@ -556,12 +556,12 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
         valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
 
         if (valid_l2t) {
-            max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
+            num_l2_entries = s->dt.page_sz / s->dt.entry_sz;
 
             l2t_addr = value & ((1ULL << 51) - 1);
 
             address_space_stq_le(as, l2t_addr +
-                                 ((devid % max_l2_entries) * GITS_DTE_SIZE),
+                                 ((devid % num_l2_entries) * GITS_DTE_SIZE),
                                  dte, MEMTXATTRS_UNSPECIFIED, &res);
         }
     } else {
-- 
2.25.1



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

* [PATCH 16/26] hw/intc/arm_gicv3_its: Fix event ID bounds checks
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (14 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 15/26] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-13 13:00   ` Philippe Mathieu-Daudé
  2021-12-13 13:37   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 17/26] hw/intc/arm_gicv3_its: Convert int ID check to num_intids convention Peter Maydell
                   ` (9 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

In process_its_cmd() and process_mapti() we must check the
event ID against a limit defined by the size field in the DTE,
which specifies the number of ID bits minus one. Convert
this code to our num_foo convention, fixing the off-by-one error.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index e4105282b57..8561392fdbe 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -225,7 +225,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
     MemTxResult res = MEMTX_OK;
     bool dte_valid;
     uint64_t dte = 0;
-    uint32_t max_eventid;
+    uint32_t num_eventids;
     uint16_t icid = 0;
     uint32_t pIntid = 0;
     bool ite_valid = false;
@@ -258,7 +258,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
     dte_valid = FIELD_EX64(dte, DTE, VALID);
 
     if (dte_valid) {
-        max_eventid = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
+        num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
 
         ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
 
@@ -299,10 +299,10 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
                       dte_valid ? "valid" : "invalid",
                       ite_valid ? "valid" : "invalid",
                       cte_valid ? "valid" : "invalid");
-    } else if (eventid > max_eventid) {
+    } else if (eventid >= num_eventids) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes: eventid %d > %d\n",
-                      __func__, eventid, max_eventid);
+                      __func__, eventid, num_eventids);
     } else {
         /*
          * Current implementation only supports rdbase == procnum
@@ -336,7 +336,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
     AddressSpace *as = &s->gicv3->dma_as;
     uint32_t devid, eventid;
     uint32_t pIntid = 0;
-    uint32_t max_eventid, max_Intid;
+    uint32_t num_eventids, max_Intid;
     bool dte_valid;
     MemTxResult res = MEMTX_OK;
     uint16_t icid = 0;
@@ -376,11 +376,11 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
         return result;
     }
     dte_valid = FIELD_EX64(dte, DTE, VALID);
-    max_eventid = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
+    num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
     max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
 
     if ((devid >= s->dt.num_ids) || (icid >= s->ct.num_ids)
-            || !dte_valid || (eventid > max_eventid) ||
+            || !dte_valid || (eventid >= num_eventids) ||
             (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) &&
              (pIntid != INTID_SPURIOUS))) {
         qemu_log_mask(LOG_GUEST_ERROR,
-- 
2.25.1



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

* [PATCH 17/26] hw/intc/arm_gicv3_its: Convert int ID check to num_intids convention
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (15 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 16/26] hw/intc/arm_gicv3_its: Fix event ID bounds checks Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-13 13:39   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 18/26] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value Peter Maydell
                   ` (8 subsequent siblings)
  25 siblings, 1 reply; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

The bounds check on the number of interrupt IDs is correct, but
doesn't match our convention; change the variable name, initialize it
to the 2^n value rather than (2^n)-1, and use >= instead of > in the
comparison.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 8561392fdbe..e6b380f663c 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -336,7 +336,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
     AddressSpace *as = &s->gicv3->dma_as;
     uint32_t devid, eventid;
     uint32_t pIntid = 0;
-    uint32_t num_eventids, max_Intid;
+    uint32_t num_eventids, num_intids;
     bool dte_valid;
     MemTxResult res = MEMTX_OK;
     uint16_t icid = 0;
@@ -377,11 +377,11 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
     }
     dte_valid = FIELD_EX64(dte, DTE, VALID);
     num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
-    max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
+    num_intids = 1ULL << (GICD_TYPER_IDBITS + 1);
 
     if ((devid >= s->dt.num_ids) || (icid >= s->ct.num_ids)
             || !dte_valid || (eventid >= num_eventids) ||
-            (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) &&
+            (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)) &&
              (pIntid != INTID_SPURIOUS))) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes "
-- 
2.25.1



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

* [PATCH 18/26] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (16 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 17/26] hw/intc/arm_gicv3_its: Convert int ID check to num_intids convention Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 20:53   ` Richard Henderson
                     ` (2 more replies)
  2021-12-11 19:11 ` [PATCH 19/26] hw/intc/arm_gicv3_its: Don't use data if reading command failed Peter Maydell
                   ` (7 subsequent siblings)
  25 siblings, 3 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

process_its_cmd() returns a bool, like all the other process_ functions.
However we were putting its return value into 'res', not 'result',
which meant we would ignore it when deciding whether to continue
or stall the command queue. Fix the typo.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index e6b380f663c..32cf18c10af 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -676,10 +676,10 @@ static void process_cmdq(GICv3ITSState *s)
 
         switch (cmd) {
         case GITS_CMD_INT:
-            res = process_its_cmd(s, data, cq_offset, INTERRUPT);
+            result = process_its_cmd(s, data, cq_offset, INTERRUPT);
             break;
         case GITS_CMD_CLEAR:
-            res = process_its_cmd(s, data, cq_offset, CLEAR);
+            result = process_its_cmd(s, data, cq_offset, CLEAR);
             break;
         case GITS_CMD_SYNC:
             /*
-- 
2.25.1



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

* [PATCH 19/26] hw/intc/arm_gicv3_its: Don't use data if reading command failed
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (17 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 18/26] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 20:54   ` Richard Henderson
  2021-12-13 14:49   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 20/26] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions Peter Maydell
                   ` (6 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

In process_cmdq(), we read 64 bits of the command packet, which
contain the command identifier, which we then switch() on to dispatch
to an appropriate sub-function.  However, if address_space_ldq_le()
reports a memory transaction failure, we still read the command
identifier out of the data and switch() on it.  Restructure the code
so that we stop immediately (stalling the command queue) in this
case.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 32cf18c10af..f3eba92946d 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -670,8 +670,13 @@ static void process_cmdq(GICv3ITSState *s)
         data = address_space_ldq_le(as, s->cq.base_addr + cq_offset,
                                     MEMTXATTRS_UNSPECIFIED, &res);
         if (res != MEMTX_OK) {
-            result = false;
+            s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: could not read command at 0x%" PRIx64 "\n",
+                          __func__, s->cq.base_addr + cq_offset);
+            break;
         }
+
         cmd = (data & CMD_MASK);
 
         switch (cmd) {
-- 
2.25.1



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

* [PATCH 20/26] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (18 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 19/26] hw/intc/arm_gicv3_its: Don't use data if reading command failed Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 21:06   ` Richard Henderson
                     ` (2 more replies)
  2021-12-11 19:11 ` [PATCH 21/26] hw/intc/arm_gicv3_its: Fix return codes in process_its_cmd() Peter Maydell
                   ` (5 subsequent siblings)
  25 siblings, 3 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

When an ITS detects an error in a command, it has an
implementation-defined (CONSTRAINED UNPREDICTABLE) choice of whether
to ignore the command, proceeding to the next one in the queue, or to
stall the ITS command queue, processing nothing further.  The
behaviour required when the read of the command packet from memory
fails is less clearly documented, but the same set of choices as for
command errors seem reasonable.

The intention of the QEMU implementation, as documented in the
comments, is that if we encounter a memory error reading the command
packet or one of the various data tables then we should stall, but
for command parameter errors we should ignore the queue and continue.
However, we don't actually do this.  To get the desired behaviour,
the various process_* functions need to return true to cause
process_cmdq() to advance to the next command and keep processing,
and false to stall command processing.  What they mostly do is return
false for any kind of error.

To make the code clearer, replace the 'bool' return from the process_
functions with an enum which may be either CMD_STALL or CMD_CONTINUE.
In this commit no behaviour changes; in subsequent commits we will
adjust the error-return paths for the process_ functions one by one.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 59 ++++++++++++++++++++++++++---------------
 1 file changed, 38 insertions(+), 21 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index f3eba92946d..59dd564d91c 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -45,6 +45,23 @@ typedef struct {
     uint64_t itel;
 } IteEntry;
 
+/*
+ * The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
+ * if a command parameter is not correct. These include both "stall
+ * processing of the command queue" and "ignore this command, and
+ * keep processing the queue". In our implementation we choose that
+ * memory transaction errors reading the command packet provoke a
+ * stall, but errors in parameters cause us to ignore the command
+ * and continue processing.
+ * The process_* functions which handle invididual ITS commands all
+ * return an ItsCmdResult which tells process_cmdq() whether it should
+ * stall or keep going.
+ */
+typedef enum ItsCmdResult {
+    CMD_STALL = 0,
+    CMD_CONTINUE = 1,
+} ItsCmdResult;
+
 static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
 {
     uint64_t result = 0;
@@ -217,8 +234,8 @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
  * 3. handling of ITS CLEAR command
  * 4. handling of ITS DISCARD command
  */
-static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
-                            ItsCmdType cmd)
+static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
+                                    uint32_t offset, ItsCmdType cmd)
 {
     AddressSpace *as = &s->gicv3->dma_as;
     uint32_t devid, eventid;
@@ -231,7 +248,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
     bool ite_valid = false;
     uint64_t cte = 0;
     bool cte_valid = false;
-    bool result = false;
+    ItsCmdResult result = CMD_STALL;
     uint64_t rdbase;
 
     if (cmd == NONE) {
@@ -323,15 +340,15 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
         if (cmd == DISCARD) {
             IteEntry ite = {};
             /* remove mapping from interrupt translation table */
-            result = update_ite(s, eventid, dte, ite);
+            result = update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
         }
     }
 
     return result;
 }
 
-static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
-                          bool ignore_pInt)
+static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
+                                  uint32_t offset, bool ignore_pInt)
 {
     AddressSpace *as = &s->gicv3->dma_as;
     uint32_t devid, eventid;
@@ -341,7 +358,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
     MemTxResult res = MEMTX_OK;
     uint16_t icid = 0;
     uint64_t dte = 0;
-    bool result = false;
+    ItsCmdResult result = CMD_STALL;
 
     devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
     offset += NUM_BYTES_IN_DW;
@@ -402,7 +419,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
         ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
         ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
 
-        result = update_ite(s, eventid, dte, ite);
+        result = update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
     }
 
     return result;
@@ -470,14 +487,14 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
     }
 }
 
-static bool process_mapc(GICv3ITSState *s, uint32_t offset)
+static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset)
 {
     AddressSpace *as = &s->gicv3->dma_as;
     uint16_t icid;
     uint64_t rdbase;
     bool valid;
     MemTxResult res = MEMTX_OK;
-    bool result = false;
+    ItsCmdResult result = CMD_STALL;
     uint64_t value;
 
     offset += NUM_BYTES_IN_DW;
@@ -507,7 +524,7 @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset)
          * command in the queue
          */
     } else {
-        result = update_cte(s, icid, valid, rdbase);
+        result = update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL;
     }
 
     return result;
@@ -576,7 +593,8 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
     }
 }
 
-static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
+static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
+                                 uint32_t offset)
 {
     AddressSpace *as = &s->gicv3->dma_as;
     uint32_t devid;
@@ -584,7 +602,7 @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
     uint64_t itt_addr;
     bool valid;
     MemTxResult res = MEMTX_OK;
-    bool result = false;
+    ItsCmdResult result = CMD_STALL;
 
     devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
 
@@ -621,7 +639,7 @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
          * command in the queue
          */
     } else {
-        result = update_dte(s, devid, valid, size, itt_addr);
+        result = update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL;
     }
 
     return result;
@@ -639,7 +657,6 @@ static void process_cmdq(GICv3ITSState *s)
     uint64_t data;
     AddressSpace *as = &s->gicv3->dma_as;
     MemTxResult res = MEMTX_OK;
-    bool result = true;
     uint8_t cmd;
     int i;
 
@@ -666,6 +683,8 @@ static void process_cmdq(GICv3ITSState *s)
     }
 
     while (wr_offset != rd_offset) {
+        ItsCmdResult result = CMD_CONTINUE;
+
         cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE);
         data = address_space_ldq_le(as, s->cq.base_addr + cq_offset,
                                     MEMTXATTRS_UNSPECIFIED, &res);
@@ -724,18 +743,16 @@ static void process_cmdq(GICv3ITSState *s)
         default:
             break;
         }
-        if (result) {
+        if (result == CMD_CONTINUE) {
             rd_offset++;
             rd_offset %= s->cq.num_entries;
             s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
         } else {
-            /*
-             * in this implementation, in case of dma read/write error
-             * we stall the command processing
-             */
+            /* CMD_STALL */
             s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
             qemu_log_mask(LOG_GUEST_ERROR,
-                          "%s: %x cmd processing failed\n", __func__, cmd);
+                          "%s: 0x%x cmd processing failed, stalling\n",
+                          __func__, cmd);
             break;
         }
     }
-- 
2.25.1



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

* [PATCH 21/26] hw/intc/arm_gicv3_its: Fix return codes in process_its_cmd()
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (19 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 20/26] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 22:02   ` Richard Henderson
  2021-12-13 14:40   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 22/26] hw/intc/arm_gicv3_its: Refactor process_its_cmd() to reduce nesting Peter Maydell
                   ` (4 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

Fix process_its_cmd() to consistently return CMD_STALL for
memory errors and CMD_CONTINUE for parameter errors, as
we claim in the comments that we do.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 59dd564d91c..3a2254ea7c7 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -248,7 +248,6 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
     bool ite_valid = false;
     uint64_t cte = 0;
     bool cte_valid = false;
-    ItsCmdResult result = CMD_STALL;
     uint64_t rdbase;
 
     if (cmd == NONE) {
@@ -262,7 +261,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
     }
 
     if (res != MEMTX_OK) {
-        return result;
+        return CMD_STALL;
     }
 
     eventid = (value & EVENTID_MASK);
@@ -270,7 +269,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
     dte = get_dte(s, devid, &res);
 
     if (res != MEMTX_OK) {
-        return result;
+        return CMD_STALL;
     }
     dte_valid = FIELD_EX64(dte, DTE, VALID);
 
@@ -280,7 +279,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
         ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
 
         if (res != MEMTX_OK) {
-            return result;
+            return CMD_STALL;
         }
 
         if (ite_valid) {
@@ -288,14 +287,14 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
         }
 
         if (res != MEMTX_OK) {
-            return result;
+            return CMD_STALL;
         }
     } else {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes: "
                       "invalid dte: %"PRIx64" for %d (MEM_TX: %d)\n",
                       __func__, dte, devid, res);
-        return result;
+        return CMD_CONTINUE;
     }
 
 
@@ -307,7 +306,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes: devid %d>=%d",
                       __func__, devid, s->dt.num_ids);
-
+        return CMD_CONTINUE;
     } else if (!dte_valid || !ite_valid || !cte_valid) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes: "
@@ -316,10 +315,12 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
                       dte_valid ? "valid" : "invalid",
                       ite_valid ? "valid" : "invalid",
                       cte_valid ? "valid" : "invalid");
+        return CMD_CONTINUE;
     } else if (eventid >= num_eventids) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes: eventid %d > %d\n",
                       __func__, eventid, num_eventids);
+        return CMD_CONTINUE;
     } else {
         /*
          * Current implementation only supports rdbase == procnum
@@ -328,7 +329,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
         rdbase = FIELD_EX64(cte, CTE, RDBASE);
 
         if (rdbase >= s->gicv3->num_cpu) {
-            return result;
+            return CMD_CONTINUE;
         }
 
         if ((cmd == CLEAR) || (cmd == DISCARD)) {
@@ -340,11 +341,10 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
         if (cmd == DISCARD) {
             IteEntry ite = {};
             /* remove mapping from interrupt translation table */
-            result = update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
+            return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
         }
+        return CMD_CONTINUE;
     }
-
-    return result;
 }
 
 static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
-- 
2.25.1



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

* [PATCH 22/26] hw/intc/arm_gicv3_its: Refactor process_its_cmd() to reduce nesting
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (20 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 21/26] hw/intc/arm_gicv3_its: Fix return codes in process_its_cmd() Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 22:34   ` Richard Henderson
  2021-12-13 14:50   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 23/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapti() Peter Maydell
                   ` (3 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

Refactor process_its_cmd() so that it consistently uses
the structure
  do thing;
  if (error condition) {
      return early;
  }
  do next thing;

rather than doing some of the work nested inside if (not error)
code blocks.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 103 +++++++++++++++++++---------------------
 1 file changed, 50 insertions(+), 53 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 3a2254ea7c7..275af620058 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -273,78 +273,75 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
     }
     dte_valid = FIELD_EX64(dte, DTE, VALID);
 
-    if (dte_valid) {
-        num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
-
-        ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
-
-        if (res != MEMTX_OK) {
-            return CMD_STALL;
-        }
-
-        if (ite_valid) {
-            cte_valid = get_cte(s, icid, &cte, &res);
-        }
-
-        if (res != MEMTX_OK) {
-            return CMD_STALL;
-        }
-    } else {
+    if (!dte_valid) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes: "
-                      "invalid dte: %"PRIx64" for %d (MEM_TX: %d)\n",
-                      __func__, dte, devid, res);
+                      "invalid dte: %"PRIx64" for %d\n",
+                      __func__, dte, devid);
         return CMD_CONTINUE;
     }
 
+    num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
+
+    ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
+    if (res != MEMTX_OK) {
+        return CMD_STALL;
+    }
+
+    if (!ite_valid) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: invalid command attributes: invalid ITE\n",
+                      __func__);
+        return CMD_CONTINUE;
+    }
+
+    cte_valid = get_cte(s, icid, &cte, &res);
+    if (res != MEMTX_OK) {
+        return CMD_STALL;
+    }
+    if (!cte_valid) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: invalid command attributes: "
+                      "invalid cte: %"PRIx64"\n",
+                      __func__, cte);
+        return CMD_CONTINUE;
+    }
 
-    /*
-     * In this implementation, in case of guest errors we ignore the
-     * command and move onto the next command in the queue.
-     */
     if (devid >= s->dt.num_ids) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes: devid %d>=%d",
                       __func__, devid, s->dt.num_ids);
         return CMD_CONTINUE;
-    } else if (!dte_valid || !ite_valid || !cte_valid) {
-        qemu_log_mask(LOG_GUEST_ERROR,
-                      "%s: invalid command attributes: "
-                      "dte: %s, ite: %s, cte: %s\n",
-                      __func__,
-                      dte_valid ? "valid" : "invalid",
-                      ite_valid ? "valid" : "invalid",
-                      cte_valid ? "valid" : "invalid");
-        return CMD_CONTINUE;
-    } else if (eventid >= num_eventids) {
+    }
+    if (eventid >= num_eventids) {
         qemu_log_mask(LOG_GUEST_ERROR,
                       "%s: invalid command attributes: eventid %d > %d\n",
                       __func__, eventid, num_eventids);
         return CMD_CONTINUE;
-    } else {
-        /*
-         * Current implementation only supports rdbase == procnum
-         * Hence rdbase physical address is ignored
-         */
-        rdbase = FIELD_EX64(cte, CTE, RDBASE);
+    }
 
-        if (rdbase >= s->gicv3->num_cpu) {
-            return CMD_CONTINUE;
-        }
+    /*
+     * Current implementation only supports rdbase == procnum
+     * Hence rdbase physical address is ignored
+     */
+    rdbase = FIELD_EX64(cte, CTE, RDBASE);
 
-        if ((cmd == CLEAR) || (cmd == DISCARD)) {
-            gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0);
-        } else {
-            gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1);
-        }
-
-        if (cmd == DISCARD) {
-            IteEntry ite = {};
-            /* remove mapping from interrupt translation table */
-            return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
-        }
+    if (rdbase >= s->gicv3->num_cpu) {
         return CMD_CONTINUE;
     }
+
+    if ((cmd == CLEAR) || (cmd == DISCARD)) {
+        gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0);
+    } else {
+        gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1);
+    }
+
+    if (cmd == DISCARD) {
+        IteEntry ite = {};
+        /* remove mapping from interrupt translation table */
+        return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
+    }
+    return CMD_CONTINUE;
 }
 
 static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
-- 
2.25.1



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

* [PATCH 23/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapti()
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (21 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 22/26] hw/intc/arm_gicv3_its: Refactor process_its_cmd() to reduce nesting Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 22:36   ` Richard Henderson
  2021-12-13 14:51   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 24/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapc() Peter Maydell
                   ` (2 subsequent siblings)
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

Fix process_mapti() to consistently return CMD_STALL for memory
errors and CMD_CONTINUE for parameter errors, as we claim in the
comments that we do.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 275af620058..5b25347de12 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -355,7 +355,7 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
     MemTxResult res = MEMTX_OK;
     uint16_t icid = 0;
     uint64_t dte = 0;
-    ItsCmdResult result = CMD_STALL;
+    IteEntry ite = {};
 
     devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
     offset += NUM_BYTES_IN_DW;
@@ -363,7 +363,7 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
                                  MEMTXATTRS_UNSPECIFIED, &res);
 
     if (res != MEMTX_OK) {
-        return result;
+        return CMD_STALL;
     }
 
     eventid = (value & EVENTID_MASK);
@@ -379,7 +379,7 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
                                  MEMTXATTRS_UNSPECIFIED, &res);
 
     if (res != MEMTX_OK) {
-        return result;
+        return CMD_STALL;
     }
 
     icid = value & ICID_MASK;
@@ -387,7 +387,7 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
     dte = get_dte(s, devid, &res);
 
     if (res != MEMTX_OK) {
-        return result;
+        return CMD_STALL;
     }
     dte_valid = FIELD_EX64(dte, DTE, VALID);
     num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
@@ -407,19 +407,17 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
          * we ignore this command and move onto the next
          * command in the queue
          */
-    } else {
-        /* add ite entry to interrupt translation table */
-        IteEntry ite = {};
-        ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid);
-        ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
-        ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
-        ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
-        ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
-
-        result = update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
+        return CMD_CONTINUE;
     }
 
-    return result;
+    /* add ite entry to interrupt translation table */
+    ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid);
+    ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
+    ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
+    ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
+    ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
+
+    return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
 }
 
 static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
-- 
2.25.1



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

* [PATCH 24/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapc()
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (22 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 23/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapti() Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 22:37   ` Richard Henderson
  2021-12-13 14:51   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 25/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapd() Peter Maydell
  2021-12-11 19:11 ` [PATCH 26/26] hw/intc/arm_gicv3_its: Factor out "find address of table entry" code Peter Maydell
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

Fix process_mapc() to consistently return CMD_STALL for memory
errors and CMD_CONTINUE for parameter errors, as we claim in the
comments that we do.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 5b25347de12..7615e9aa279 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -489,7 +489,6 @@ static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset)
     uint64_t rdbase;
     bool valid;
     MemTxResult res = MEMTX_OK;
-    ItsCmdResult result = CMD_STALL;
     uint64_t value;
 
     offset += NUM_BYTES_IN_DW;
@@ -499,7 +498,7 @@ static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset)
                                  MEMTXATTRS_UNSPECIFIED, &res);
 
     if (res != MEMTX_OK) {
-        return result;
+        return CMD_STALL;
     }
 
     icid = value & ICID_MASK;
@@ -518,11 +517,10 @@ static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset)
          * we ignore this command and move onto the next
          * command in the queue
          */
-    } else {
-        result = update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL;
+        return CMD_CONTINUE;
     }
 
-    return result;
+    return update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL;
 }
 
 static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
-- 
2.25.1



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

* [PATCH 25/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapd()
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (23 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 24/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapc() Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 22:39   ` Richard Henderson
  2021-12-13 14:51   ` Alex Bennée
  2021-12-11 19:11 ` [PATCH 26/26] hw/intc/arm_gicv3_its: Factor out "find address of table entry" code Peter Maydell
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

Fix process_mapd() to consistently return CMD_STALL for memory
errors and CMD_CONTINUE for parameter errors, as we claim in the
comments that we do.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/intc/arm_gicv3_its.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 7615e9aa279..3bcc4c3db85 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -595,7 +595,6 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
     uint64_t itt_addr;
     bool valid;
     MemTxResult res = MEMTX_OK;
-    ItsCmdResult result = CMD_STALL;
 
     devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
 
@@ -604,7 +603,7 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
                                  MEMTXATTRS_UNSPECIFIED, &res);
 
     if (res != MEMTX_OK) {
-        return result;
+        return CMD_STALL;
     }
 
     size = (value & SIZE_MASK);
@@ -614,7 +613,7 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
                                  MEMTXATTRS_UNSPECIFIED, &res);
 
     if (res != MEMTX_OK) {
-        return result;
+        return CMD_STALL;
     }
 
     itt_addr = (value & ITTADDR_MASK) >> ITTADDR_SHIFT;
@@ -631,11 +630,10 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
          * we ignore this command and move onto the next
          * command in the queue
          */
-    } else {
-        result = update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL;
+        return CMD_CONTINUE;
     }
 
-    return result;
+    return update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL;
 }
 
 /*
-- 
2.25.1



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

* [PATCH 26/26] hw/intc/arm_gicv3_its: Factor out "find address of table entry" code
  2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
                   ` (24 preceding siblings ...)
  2021-12-11 19:11 ` [PATCH 25/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapd() Peter Maydell
@ 2021-12-11 19:11 ` Peter Maydell
  2021-12-12 22:52   ` Richard Henderson
  2021-12-13 14:53   ` Alex Bennée
  25 siblings, 2 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-11 19:11 UTC (permalink / raw)
  To: qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

The ITS has several tables which all share a similar format,
described by the TableDesc struct: the guest may configure them
to be a single-level table or a two-level table. Currently we
open-code the process of finding the table entry in all the
functions which read or write the device table or the collection
table. Factor out the "get the address of the table entry"
logic into a new function, so that the code which needs to
read or write a table entry only needs to call table_entry_addr()
and then perform a suitable load or store to that address.

Note that the error handling is slightly complicated because
we want to handle two cases differently:
 * failure to read the L1 table entry should end up causing
   a command stall, like other kinds of DMA error
 * an L1 table entry that says there is no L2 table for this
   index (ie whose valid bit is 0) must result in us treating
   the table entry as not-valid on read, and discarding
   writes (this is mandated by the spec)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
This is a worthwhile refactoring on its own, but still more
so given that GICv4 adds another table in this format.
---
 hw/intc/arm_gicv3_its.c | 212 +++++++++++++---------------------------
 1 file changed, 70 insertions(+), 142 deletions(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 3bcc4c3db85..90a9fd3b3d4 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -83,44 +83,62 @@ static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
     return result;
 }
 
+static uint64_t table_entry_addr(GICv3ITSState *s, TableDesc *td,
+                                 uint32_t idx, MemTxResult *res)
+{
+    /*
+     * Given a TableDesc describing one of the ITS in-guest-memory
+     * tables and an index into it, return the guest address
+     * corresponding to that table entry.
+     * If there was a memory error reading the L1 table of an
+     * indirect table, *res is set accordingly, and we return -1.
+     * If the L1 table entry is marked not valid, we return -1 with
+     * *res set to MEMTX_OK.
+     *
+     * The specification defines the format of level 1 entries of a
+     * 2-level table, but the format of level 2 entries and the format
+     * of flat-mapped tables is IMPDEF.
+     */
+    AddressSpace *as = &s->gicv3->dma_as;
+    uint32_t l2idx;
+    uint64_t l2;
+    uint32_t num_l2_entries;
+
+    *res = MEMTX_OK;
+
+    if (!td->indirect) {
+        /* Single level table */
+        return td->base_addr + idx * td->entry_sz;
+    }
+
+    /* Two level table */
+    l2idx = idx / (td->page_sz / L1TABLE_ENTRY_SIZE);
+
+    l2 = address_space_ldq_le(as,
+                              td->base_addr + (l2idx * L1TABLE_ENTRY_SIZE),
+                              MEMTXATTRS_UNSPECIFIED, res);
+    if (*res != MEMTX_OK) {
+        return -1;
+    }
+    if (!(l2 & L2_TABLE_VALID_MASK)) {
+        return -1;
+    }
+
+    num_l2_entries = td->page_sz / td->entry_sz;
+    return (l2 & ((1ULL << 51) - 1)) + (idx % num_l2_entries) * td->entry_sz;
+}
+
 static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
                     MemTxResult *res)
 {
     AddressSpace *as = &s->gicv3->dma_as;
-    uint64_t l2t_addr;
-    uint64_t value;
-    bool valid_l2t;
-    uint32_t l2t_id;
-    uint32_t num_l2_entries;
+    uint64_t entry_addr = table_entry_addr(s, &s->ct, icid, res);
 
-    if (s->ct.indirect) {
-        l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
-
-        value = address_space_ldq_le(as,
-                                     s->ct.base_addr +
-                                     (l2t_id * L1TABLE_ENTRY_SIZE),
-                                     MEMTXATTRS_UNSPECIFIED, res);
-
-        if (*res == MEMTX_OK) {
-            valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
-
-            if (valid_l2t) {
-                num_l2_entries = s->ct.page_sz / s->ct.entry_sz;
-
-                l2t_addr = value & ((1ULL << 51) - 1);
-
-                *cte =  address_space_ldq_le(as, l2t_addr +
-                                    ((icid % num_l2_entries) * GITS_CTE_SIZE),
-                                    MEMTXATTRS_UNSPECIFIED, res);
-           }
-       }
-    } else {
-        /* Flat level table */
-        *cte =  address_space_ldq_le(as, s->ct.base_addr +
-                                     (icid * GITS_CTE_SIZE),
-                                      MEMTXATTRS_UNSPECIFIED, res);
+    if (entry_addr == -1) {
+        return false; /* not valid */
     }
 
+    *cte = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, res);
     return FIELD_EX64(*cte, CTE, VALID);
 }
 
@@ -189,41 +207,12 @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
 static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
 {
     AddressSpace *as = &s->gicv3->dma_as;
-    uint64_t l2t_addr;
-    uint64_t value;
-    bool valid_l2t;
-    uint32_t l2t_id;
-    uint32_t num_l2_entries;
+    uint64_t entry_addr = table_entry_addr(s, &s->dt, devid, res);
 
-    if (s->dt.indirect) {
-        l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
-
-        value = address_space_ldq_le(as,
-                                     s->dt.base_addr +
-                                     (l2t_id * L1TABLE_ENTRY_SIZE),
-                                     MEMTXATTRS_UNSPECIFIED, res);
-
-        if (*res == MEMTX_OK) {
-            valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
-
-            if (valid_l2t) {
-                num_l2_entries = s->dt.page_sz / s->dt.entry_sz;
-
-                l2t_addr = value & ((1ULL << 51) - 1);
-
-                value =  address_space_ldq_le(as, l2t_addr +
-                                   ((devid % num_l2_entries) * GITS_DTE_SIZE),
-                                   MEMTXATTRS_UNSPECIFIED, res);
-            }
-        }
-    } else {
-        /* Flat level table */
-        value = address_space_ldq_le(as, s->dt.base_addr +
-                                     (devid * GITS_DTE_SIZE),
-                                     MEMTXATTRS_UNSPECIFIED, res);
+    if (entry_addr == -1) {
+        return 0; /* a DTE entry with the Valid bit clear */
     }
-
-    return value;
+    return address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, res);
 }
 
 /*
@@ -424,11 +413,7 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
                        uint64_t rdbase)
 {
     AddressSpace *as = &s->gicv3->dma_as;
-    uint64_t value;
-    uint64_t l2t_addr;
-    bool valid_l2t;
-    uint32_t l2t_id;
-    uint32_t num_l2_entries;
+    uint64_t entry_addr;
     uint64_t cte = 0;
     MemTxResult res = MEMTX_OK;
 
@@ -442,44 +427,18 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
         cte = FIELD_DP64(cte, CTE, RDBASE, rdbase);
     }
 
-    /*
-     * The specification defines the format of level 1 entries of a
-     * 2-level table, but the format of level 2 entries and the format
-     * of flat-mapped tables is IMPDEF.
-     */
-    if (s->ct.indirect) {
-        l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
-
-        value = address_space_ldq_le(as,
-                                     s->ct.base_addr +
-                                     (l2t_id * L1TABLE_ENTRY_SIZE),
-                                     MEMTXATTRS_UNSPECIFIED, &res);
-
-        if (res != MEMTX_OK) {
-            return false;
-        }
-
-        valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
-
-        if (valid_l2t) {
-            num_l2_entries = s->ct.page_sz / s->ct.entry_sz;
-
-            l2t_addr = value & ((1ULL << 51) - 1);
-
-            address_space_stq_le(as, l2t_addr +
-                                 ((icid % num_l2_entries) * GITS_CTE_SIZE),
-                                 cte, MEMTXATTRS_UNSPECIFIED, &res);
-        }
-    } else {
-        /* Flat level table */
-        address_space_stq_le(as, s->ct.base_addr + (icid * GITS_CTE_SIZE),
-                             cte, MEMTXATTRS_UNSPECIFIED, &res);
-    }
+    entry_addr = table_entry_addr(s, &s->ct, icid, &res);
     if (res != MEMTX_OK) {
+        /* memory access error: stall */
         return false;
-    } else {
+    }
+    if (entry_addr == -1) {
+        /* No L2 table for this index: discard write and continue */
         return true;
     }
+
+    address_space_stq_le(as, entry_addr, cte, MEMTXATTRS_UNSPECIFIED, &res);
+    return res == MEMTX_OK;
 }
 
 static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset)
@@ -527,11 +486,7 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
                        uint8_t size, uint64_t itt_addr)
 {
     AddressSpace *as = &s->gicv3->dma_as;
-    uint64_t value;
-    uint64_t l2t_addr;
-    bool valid_l2t;
-    uint32_t l2t_id;
-    uint32_t num_l2_entries;
+    uint64_t entry_addr;
     uint64_t dte = 0;
     MemTxResult res = MEMTX_OK;
 
@@ -546,44 +501,17 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
         return true;
     }
 
-    /*
-     * The specification defines the format of level 1 entries of a
-     * 2-level table, but the format of level 2 entries and the format
-     * of flat-mapped tables is IMPDEF.
-     */
-    if (s->dt.indirect) {
-        l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
-
-        value = address_space_ldq_le(as,
-                                     s->dt.base_addr +
-                                     (l2t_id * L1TABLE_ENTRY_SIZE),
-                                     MEMTXATTRS_UNSPECIFIED, &res);
-
-        if (res != MEMTX_OK) {
-            return false;
-        }
-
-        valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
-
-        if (valid_l2t) {
-            num_l2_entries = s->dt.page_sz / s->dt.entry_sz;
-
-            l2t_addr = value & ((1ULL << 51) - 1);
-
-            address_space_stq_le(as, l2t_addr +
-                                 ((devid % num_l2_entries) * GITS_DTE_SIZE),
-                                 dte, MEMTXATTRS_UNSPECIFIED, &res);
-        }
-    } else {
-        /* Flat level table */
-        address_space_stq_le(as, s->dt.base_addr + (devid * GITS_DTE_SIZE),
-                             dte, MEMTXATTRS_UNSPECIFIED, &res);
-    }
+    entry_addr = table_entry_addr(s, &s->dt, devid, &res);
     if (res != MEMTX_OK) {
+        /* memory access error: stall */
         return false;
-    } else {
+    }
+    if (entry_addr == -1) {
+        /* No L2 table for this index: discard write and continue */
         return true;
     }
+    address_space_stq_le(as, entry_addr, dte, MEMTXATTRS_UNSPECIFIED, &res);
+    return res == MEMTX_OK;
 }
 
 static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
-- 
2.25.1



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

* Re: [PATCH 01/26] hw/intc: clean-up error reporting for failed ITS cmd
  2021-12-11 19:11 ` [PATCH 01/26] hw/intc: clean-up error reporting for failed ITS cmd Peter Maydell
@ 2021-12-12 17:31   ` Richard Henderson
  0 siblings, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 17:31 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> From: Alex Bennée<alex.bennee@linaro.org>
> 
> While trying to debug a GIC ITS failure I saw some guest errors that
> had poor formatting as well as leaving me confused as to what failed.
> As most of the checks aren't possible without a valid dte split that
> check apart and then check the other conditions in steps. This avoids
> us relying on undefined data.
> 
> I still get a failure with the current kvm-unit-tests but at least I
> know (partially) why now:
> 
>    Exception return from AArch64 EL1 to AArch64 EL1 PC 0x40080588
>    PASS: gicv3: its-trigger: inv/invall: dev2/eventid=20 now triggers an LPI
>    ITS: MAPD devid=2 size = 0x8 itt=0x40430000 valid=0
>    INT dev_id=2 event_id=20
>    process_its_cmd: invalid command attributes: invalid dte: 0 for 2 (MEM_TX: 0)
>    PASS: gicv3: its-trigger: mapd valid=false: no LPI after device unmap
>    SUMMARY: 6 tests, 1 unexpected failures
> 
> Signed-off-by: Alex Bennée<alex.bennee@linaro.org>
> Cc: Shashi Mallela<shashi.mallela@linaro.org>
> Cc: Peter Maydell<peter.maydell@linaro.org>
> Reviewed-by: Peter Maydell<peter.maydell@linaro.org>
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 39 +++++++++++++++++++++++++++------------
>   1 file changed, 27 insertions(+), 12 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 02/26] hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase
  2021-12-11 19:11 ` [PATCH 02/26] hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase Peter Maydell
@ 2021-12-12 17:32   ` Richard Henderson
  2021-12-13 11:22   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 17:32 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> The checks in the ITS on the rdbase values in guest commands are
> off-by-one: they permit the guest to pass us a value equal to
> s->gicv3->num_cpu, but the valid values are 0...num_cpu-1.  This
> meant the guest could cause us to index off the end of the
> s->gicv3->cpu[] array when calling gicv3_redist_process_lpi(), and we
> would probably crash.
> 
> Cc:qemu-stable@nongnu.org
> Fixes: 17fb5e36aabd4b ("hw/intc: GICv3 redistributor ITS processing")
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> Not a security bug, because only usable with emulation.
> ---
>   hw/intc/arm_gicv3_its.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 03/26] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define
  2021-12-11 19:11 ` [PATCH 03/26] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define Peter Maydell
@ 2021-12-12 17:34   ` Richard Henderson
  2021-12-12 20:46   ` Philippe Mathieu-Daudé
  2021-12-13 11:55   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 17:34 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> We currently define a bitmask for the GITS_CTLR ENABLED bit in
> two ways: as ITS_CTLR_ENABLED, and via the FIELD() macro as
> R_GITS_CTLR_ENABLED_MASK. Consistently use the FIELD macro version
> everywhere and remove the redundant ITS_CTLR_ENABLED define.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/intc/gicv3_internal.h |  2 --
>   hw/intc/arm_gicv3_its.c  | 20 ++++++++++----------
>   2 files changed, 10 insertions(+), 12 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 04/26] hw/intc/arm_gicv3_its: Remove maxids union from TableDesc
  2021-12-11 19:11 ` [PATCH 04/26] hw/intc/arm_gicv3_its: Remove maxids union from TableDesc Peter Maydell
@ 2021-12-12 17:37   ` Richard Henderson
  2021-12-13 11:32   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 17:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> The TableDesc struct defines properties of the in-guest-memory tables
> which the guest tells us about by writing to the GITS_BASER<n>
> registers.  This struct currently has a union 'maxids', but all the
> fields of the union have the same type (uint32_t) and do the same
> thing (record one-greater-than the maximum ID value that can be used
> as an index into the table).
> 
> We're about to add another table type (the GICv4 vPE table); rather
> than adding another specifically-named union field for that table
> type with the same type as the other union fields, remove the union
> entirely and just have a 'uint32_t max_ids' struct field.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   include/hw/intc/arm_gicv3_its_common.h |  5 +----
>   hw/intc/arm_gicv3_its.c                | 20 ++++++++++----------
>   2 files changed, 11 insertions(+), 14 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 05/26] hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop
  2021-12-11 19:11 ` [PATCH 05/26] hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop Peter Maydell
@ 2021-12-12 17:46   ` Richard Henderson
  2021-12-13 11:33   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 17:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> In extract_table_params() we process each GITS_BASER<n> register.  If
> the register's Valid bit is not set, this means there is no
> in-guest-memory table and so we should not try to interpret the other
> fields in the register.  This was incorrectly coded as a 'return'
> rather than a 'break', so instead of looping round to process the
> next GITS_BASER<n> we would stop entirely, treating any later tables
> as being not valid also.
> 
> This has no real guest-visible effects because (since we don't have
> GITS_TYPER.HCC != 0) the guest must in any case set up all the
> GITS_BASER<n> to point to valid tables, so this only happens in an
> odd misbehaving-guest corner case.
> 
> Fix the check to 'break', so that we leave the case statement and
> loop back around to the next GITS_BASER<n>.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> I suspect this was an accidental result from a refactoring at
> some point in the development of the ITS code.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 06/26] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params()
  2021-12-11 19:11 ` [PATCH 06/26] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params() Peter Maydell
@ 2021-12-12 18:30   ` Richard Henderson
  2021-12-12 20:47   ` Philippe Mathieu-Daudé
  2021-12-13 11:34   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 18:30 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> The extract_table_params() decodes the fields in the GITS_BASER<n>
> registers into TableDesc structs.  Since the fields are the same for
> all the GITS_BASER<n> registers, there is currently a lot of code
> duplication within the switch (type) statement.  Refactor so that the
> cases include only what is genuinely different for each type:
> the calculation of the number of bits in the ID value that indexes
> into the table.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 97 +++++++++++++++++------------------------
>   1 file changed, 40 insertions(+), 57 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


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

* Re: [PATCH 07/26] hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz
  2021-12-11 19:11 ` [PATCH 07/26] hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz Peter Maydell
@ 2021-12-12 18:33   ` Richard Henderson
  2021-12-13 11:37   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 18:33 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> We set the TableDesc entry_sz field from the appropriate
> GITS_BASER.ENTRYSIZE field.  That ID register field specifies the
> number of bytes per table entry minus one.  However when we use
> td->entry_sz we assume it to be the number of bytes per table entry
> (for instance we calculate the number of entries in a page by
> dividing the page size by the entry size).
> 
> The effects of this bug are:
>   * we miscalculate the maximum number of entries in the table,
>     so our checks on guest index values are wrong (too lax)
>   * when looking up an entry in the second level of an indirect
>     table, we calculate an incorrect index into the L2 table.
>     Because we make the same incorrect calculation on both
>     reads and writes of the L2 table, the guest won't notice
>     unless it's unlucky enough to use an index value that
>     causes us to index off the end of the L2 table page and
>     cause guest memory corruption in whatever follows
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


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

* Re: [PATCH 08/26] hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define
  2021-12-11 19:11 ` [PATCH 08/26] hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define Peter Maydell
@ 2021-12-12 18:40   ` Richard Henderson
  2021-12-13 11:52   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 18:40 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> The GITS_TYPE_PHYSICAL define is the value we set the
> GITS_TYPER.Physical field to -- this is 1 to indicate that we support
> physical LPIs.  (Support for virtual LPIs is the GITS_TYPER.Virtual
> field.) We also use this define as the *value* that we write into an
> interrupt translation table entry's INTTYPE field, which should be 1
> for a physical interrupt and 0 for a virtual interrupt.  Finally, we
> use it as a *mask* when we read the interrupt translation table entry
> INTTYPE field.
> 
> Untangle this confusion: define an ITE_INTTYPE_VIRTUAL and
> ITE_INTTYPE_PHYSICAL to be the valid values of the ITE INTTYPE
> field, and replace the ad-hoc collection of ITE_ENTRY_* defines with
> use of the FIELD() macro to define the fields of an ITE and the
> FIELD_EX64() and FIELD_DP64() macros to read and write them.
> We use ITE in the new setup, rather than ITE_ENTRY, because
> ITE stands for "Interrupt translation entry" and so the extra
> "entry" would be redundant.
> 
> We take the opportunity to correct the name of the field that holds
> the GICv4 'doorbell' interrupt ID (this is always the value 1023 in a
> GICv3, which is why we were calling it the 'spurious' field).
> 
> The GITS_TYPE_PHYSICAL define is then used in only one place, where
> we set the initial GITS_TYPER value.  Since GITS_TYPER.Physical is
> essentially a boolean, hiding the '1' value behind a macro is more
> confusing than helpful, so expand out the macro there and remove the
> define entirely.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/intc/gicv3_internal.h | 26 ++++++++++++++------------
>   hw/intc/arm_gicv3_its.c  | 30 +++++++++++++-----------------
>   2 files changed, 27 insertions(+), 29 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


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

* Re: [PATCH 09/26] hw/intc/arm_gicv3_its: Correct handling of MAPI
  2021-12-11 19:11 ` [PATCH 09/26] hw/intc/arm_gicv3_its: Correct handling of MAPI Peter Maydell
@ 2021-12-12 18:48   ` Richard Henderson
  2021-12-13 11:54   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 18:48 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> The MAPI command takes arguments DeviceID, EventID, ICID, and is
> defined to be equivalent to MAPTI DeviceID, EventID, EventID, ICID.
> (That is, where MAPTI takes an explicit pINTID, MAPI uses the EventID
> as the pINTID.)
> 
> We didn't quite get this right.  In particular the error checks for
> MAPI include "EventID does not specify a valid LPI identifier", which
> is the same as MAPTI's error check for the pINTID field.  QEMU's code
> skips the pINTID error check entirely in the MAPI case.
> 
> We can fix this bug and in the process simplify the code by switching
> to the obvious implementation of setting pIntid = eventid early
> if ignore_pInt is true.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 18 +++++++-----------
>   1 file changed, 7 insertions(+), 11 deletions(-)


Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


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

* Re: [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs
  2021-12-11 19:11 ` [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs Peter Maydell
@ 2021-12-12 20:23   ` Richard Henderson
  2021-12-12 21:16   ` Philippe Mathieu-Daudé
  2021-12-13 11:56   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 20:23 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> Currently the ITS code that reads and writes DTEs uses open-coded
> shift-and-mask to assemble the various fields into the 64-bit DTE
> word.  The names of the macros used for mask and shift values are
> also somewhat inconsistent, and don't follow our usual convention
> that a MASK macro should specify the bits in their place in the word.
> Replace all these with use of the FIELD macro.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/intc/gicv3_internal.h |  7 ++++---
>   hw/intc/arm_gicv3_its.c  | 20 +++++++++-----------
>   2 files changed, 13 insertions(+), 14 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 11/26] hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1)
  2021-12-11 19:11 ` [PATCH 11/26] hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1) Peter Maydell
@ 2021-12-12 20:31   ` Richard Henderson
  2021-12-12 20:43   ` Richard Henderson
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 20:31 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> The DTE.SIZE field is 5 bits, which means that DTE.SIZE + 1
> might in theory be 32. When calculating 1 << (DTE.SIZE + 1)
> use 1ULL to ensure that we don't do this arithmetic at 32 bits
> and shift the 1 off the end in this case.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)

But then you assign the result to a uint32_t, so the patch is incomplete.


r~


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

* Re: [PATCH 12/26] hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size
  2021-12-11 19:11 ` [PATCH 12/26] hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size Peter Maydell
@ 2021-12-12 20:34   ` Richard Henderson
  2021-12-13 13:07   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 20:34 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> The comment says that in our CTE format the RDBase field is 36 bits;
> in fact for us it is only 16 bits, because we use the RDBase format
> where it specifies a 16-bit CPU number. The code already uses
> RDBASE_PROCNUM_LENGTH (16) as the field width, so fix the comment
> to match it.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


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

* Re: [PATCH 13/26] hw/intc/arm_gicv3_its: Use FIELD macros for CTEs
  2021-12-11 19:11 ` [PATCH 13/26] hw/intc/arm_gicv3_its: Use FIELD macros for CTEs Peter Maydell
@ 2021-12-12 20:35   ` Richard Henderson
  2021-12-13 13:08   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 20:35 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> Use FIELD macros to handle CTEs, rather than ad-hoc mask-and-shift.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/intc/gicv3_internal.h | 3 ++-
>   hw/intc/arm_gicv3_its.c  | 7 ++++---
>   2 files changed, 6 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


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

* Re: [PATCH 15/26] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries
  2021-12-11 19:11 ` [PATCH 15/26] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries Peter Maydell
@ 2021-12-12 20:38   ` Richard Henderson
  2021-12-13 12:58   ` Philippe Mathieu-Daudé
  2021-12-13 13:36   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 20:38 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> In several places we have a local variable max_l2_entries which is
> the number of entries which will fit in a level 2 table.  The
> calculations done on this value are correct; rename it to
> num_l2_entries to fit the convention we're using in this code.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 24 ++++++++++++------------
>   1 file changed, 12 insertions(+), 12 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 11/26] hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1)
  2021-12-11 19:11 ` [PATCH 11/26] hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1) Peter Maydell
  2021-12-12 20:31   ` Richard Henderson
@ 2021-12-12 20:43   ` Richard Henderson
  2021-12-13  9:48     ` Peter Maydell
  1 sibling, 1 reply; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 20:43 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
>   
>       if (dte_valid) {
> -        max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
> +        max_eventid = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);

Without changing the type of max_eventid, I think it'd be easiest to fix the off-by-one 
bug by not changing the comparisions, but changing this computation.  E.g.

   max_eventid = (2 << FIELD_EX64(dte, DTE, SIZE)) - 1;

so that the value becomes UINT32_MAX for SIZE=31.



r~


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

* Re: [PATCH 03/26] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define
  2021-12-11 19:11 ` [PATCH 03/26] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define Peter Maydell
  2021-12-12 17:34   ` Richard Henderson
@ 2021-12-12 20:46   ` Philippe Mathieu-Daudé
  2021-12-13 11:55   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-12-12 20:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 20:11, Peter Maydell wrote:
> We currently define a bitmask for the GITS_CTLR ENABLED bit in
> two ways: as ITS_CTLR_ENABLED, and via the FIELD() macro as
> R_GITS_CTLR_ENABLED_MASK. Consistently use the FIELD macro version
> everywhere and remove the redundant ITS_CTLR_ENABLED define.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/intc/gicv3_internal.h |  2 --
>  hw/intc/arm_gicv3_its.c  | 20 ++++++++++----------
>  2 files changed, 10 insertions(+), 12 deletions(-)

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


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

* Re: [PATCH 06/26] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params()
  2021-12-11 19:11 ` [PATCH 06/26] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params() Peter Maydell
  2021-12-12 18:30   ` Richard Henderson
@ 2021-12-12 20:47   ` Philippe Mathieu-Daudé
  2021-12-13 11:34   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-12-12 20:47 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela

On 12/11/21 20:11, Peter Maydell wrote:
> The extract_table_params() decodes the fields in the GITS_BASER<n>
> registers into TableDesc structs.  Since the fields are the same for
> all the GITS_BASER<n> registers, there is currently a lot of code
> duplication within the switch (type) statement.  Refactor so that the
> cases include only what is genuinely different for each type:
> the calculation of the number of bits in the ID value that indexes
> into the table.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/intc/arm_gicv3_its.c | 97 +++++++++++++++++------------------------
>  1 file changed, 40 insertions(+), 57 deletions(-)

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


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

* Re: [PATCH 18/26] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value
  2021-12-11 19:11 ` [PATCH 18/26] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value Peter Maydell
@ 2021-12-12 20:53   ` Richard Henderson
  2021-12-13 13:01   ` Philippe Mathieu-Daudé
  2021-12-13 13:41   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 20:53 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> process_its_cmd() returns a bool, like all the other process_ functions.
> However we were putting its return value into 'res', not 'result',
> which meant we would ignore it when deciding whether to continue
> or stall the command queue. Fix the typo.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 19/26] hw/intc/arm_gicv3_its: Don't use data if reading command failed
  2021-12-11 19:11 ` [PATCH 19/26] hw/intc/arm_gicv3_its: Don't use data if reading command failed Peter Maydell
@ 2021-12-12 20:54   ` Richard Henderson
  2021-12-13 14:49   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 20:54 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> In process_cmdq(), we read 64 bits of the command packet, which
> contain the command identifier, which we then switch() on to dispatch
> to an appropriate sub-function.  However, if address_space_ldq_le()
> reports a memory transaction failure, we still read the command
> identifier out of the data and switch() on it.  Restructure the code
> so that we stop immediately (stalling the command queue) in this
> case.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 7 ++++++-
>   1 file changed, 6 insertions(+), 1 deletion(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 20/26] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions
  2021-12-11 19:11 ` [PATCH 20/26] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions Peter Maydell
@ 2021-12-12 21:06   ` Richard Henderson
  2021-12-13 13:03   ` Philippe Mathieu-Daudé
  2021-12-13 14:40   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 21:06 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> When an ITS detects an error in a command, it has an
> implementation-defined (CONSTRAINED UNPREDICTABLE) choice of whether
> to ignore the command, proceeding to the next one in the queue, or to
> stall the ITS command queue, processing nothing further.  The
> behaviour required when the read of the command packet from memory
> fails is less clearly documented, but the same set of choices as for
> command errors seem reasonable.
> 
> The intention of the QEMU implementation, as documented in the
> comments, is that if we encounter a memory error reading the command
> packet or one of the various data tables then we should stall, but
> for command parameter errors we should ignore the queue and continue.
> However, we don't actually do this.  To get the desired behaviour,
> the various process_* functions need to return true to cause
> process_cmdq() to advance to the next command and keep processing,
> and false to stall command processing.  What they mostly do is return
> false for any kind of error.
> 
> To make the code clearer, replace the 'bool' return from the process_
> functions with an enum which may be either CMD_STALL or CMD_CONTINUE.
> In this commit no behaviour changes; in subsequent commits we will
> adjust the error-return paths for the process_ functions one by one.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 59 ++++++++++++++++++++++++++---------------
>   1 file changed, 38 insertions(+), 21 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs
  2021-12-11 19:11 ` [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs Peter Maydell
  2021-12-12 20:23   ` Richard Henderson
@ 2021-12-12 21:16   ` Philippe Mathieu-Daudé
  2021-12-13  8:23     ` Philippe Mathieu-Daudé
  2021-12-13 11:56   ` Alex Bennée
  2 siblings, 1 reply; 86+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-12-12 21:16 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela

On 12/11/21 20:11, Peter Maydell wrote:
> Currently the ITS code that reads and writes DTEs uses open-coded
> shift-and-mask to assemble the various fields into the 64-bit DTE
> word.  The names of the macros used for mask and shift values are
> also somewhat inconsistent, and don't follow our usual convention
> that a MASK macro should specify the bits in their place in the word.
> Replace all these with use of the FIELD macro.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/intc/gicv3_internal.h |  7 ++++---
>  hw/intc/arm_gicv3_its.c  | 20 +++++++++-----------
>  2 files changed, 13 insertions(+), 14 deletions(-)
> 
> diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
> index 5a63e9ed5ce..6a3b145f377 100644
> --- a/hw/intc/gicv3_internal.h
> +++ b/hw/intc/gicv3_internal.h
> @@ -393,9 +393,10 @@ FIELD(ITE_H, VPEID, 16, 16)
>   * Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits
>   */
>  #define GITS_DTE_SIZE                 (0x8ULL)
> -#define GITS_DTE_ITTADDR_SHIFT           6
> -#define GITS_DTE_ITTADDR_MASK         MAKE_64BIT_MASK(GITS_DTE_ITTADDR_SHIFT, \
> -                                                      ITTADDR_LENGTH)

Side note, both ITTADDR_LENGTH & ITTADDR_MASK definitions are now unused.


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

* Re: [PATCH 21/26] hw/intc/arm_gicv3_its: Fix return codes in process_its_cmd()
  2021-12-11 19:11 ` [PATCH 21/26] hw/intc/arm_gicv3_its: Fix return codes in process_its_cmd() Peter Maydell
@ 2021-12-12 22:02   ` Richard Henderson
  2021-12-13 14:40   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 22:02 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> Fix process_its_cmd() to consistently return CMD_STALL for
> memory errors and CMD_CONTINUE for parameter errors, as
> we claim in the comments that we do.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 22/26] hw/intc/arm_gicv3_its: Refactor process_its_cmd() to reduce nesting
  2021-12-11 19:11 ` [PATCH 22/26] hw/intc/arm_gicv3_its: Refactor process_its_cmd() to reduce nesting Peter Maydell
@ 2021-12-12 22:34   ` Richard Henderson
  2021-12-13 14:50   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 22:34 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> Refactor process_its_cmd() so that it consistently uses
> the structure
>    do thing;
>    if (error condition) {
>        return early;
>    }
>    do next thing;
> 
> rather than doing some of the work nested inside if (not error)
> code blocks.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 103 +++++++++++++++++++---------------------
>   1 file changed, 50 insertions(+), 53 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 23/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapti()
  2021-12-11 19:11 ` [PATCH 23/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapti() Peter Maydell
@ 2021-12-12 22:36   ` Richard Henderson
  2021-12-13 14:51   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 22:36 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> Fix process_mapti() to consistently return CMD_STALL for memory
> errors and CMD_CONTINUE for parameter errors, as we claim in the
> comments that we do.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 28 +++++++++++++---------------
>   1 file changed, 13 insertions(+), 15 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 24/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapc()
  2021-12-11 19:11 ` [PATCH 24/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapc() Peter Maydell
@ 2021-12-12 22:37   ` Richard Henderson
  2021-12-13 14:51   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 22:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> Fix process_mapc() to consistently return CMD_STALL for memory
> errors and CMD_CONTINUE for parameter errors, as we claim in the
> comments that we do.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 8 +++-----
>   1 file changed, 3 insertions(+), 5 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 25/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapd()
  2021-12-11 19:11 ` [PATCH 25/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapd() Peter Maydell
@ 2021-12-12 22:39   ` Richard Henderson
  2021-12-13 14:51   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 22:39 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> Fix process_mapd() to consistently return CMD_STALL for memory
> errors and CMD_CONTINUE for parameter errors, as we claim in the
> comments that we do.
> 
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
>   hw/intc/arm_gicv3_its.c | 10 ++++------
>   1 file changed, 4 insertions(+), 6 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 26/26] hw/intc/arm_gicv3_its: Factor out "find address of table entry" code
  2021-12-11 19:11 ` [PATCH 26/26] hw/intc/arm_gicv3_its: Factor out "find address of table entry" code Peter Maydell
@ 2021-12-12 22:52   ` Richard Henderson
  2021-12-13 14:53   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Richard Henderson @ 2021-12-12 22:52 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 11:11 AM, Peter Maydell wrote:
> The ITS has several tables which all share a similar format,
> described by the TableDesc struct: the guest may configure them
> to be a single-level table or a two-level table. Currently we
> open-code the process of finding the table entry in all the
> functions which read or write the device table or the collection
> table. Factor out the "get the address of the table entry"
> logic into a new function, so that the code which needs to
> read or write a table entry only needs to call table_entry_addr()
> and then perform a suitable load or store to that address.
> 
> Note that the error handling is slightly complicated because
> we want to handle two cases differently:
>   * failure to read the L1 table entry should end up causing
>     a command stall, like other kinds of DMA error
>   * an L1 table entry that says there is no L2 table for this
>     index (ie whose valid bit is 0) must result in us treating
>     the table entry as not-valid on read, and discarding
>     writes (this is mandated by the spec)
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> This is a worthwhile refactoring on its own, but still more
> so given that GICv4 adds another table in this format.
> ---

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


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

* Re: [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs
  2021-12-12 21:16   ` Philippe Mathieu-Daudé
@ 2021-12-13  8:23     ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 86+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-12-13  8:23 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel@nongnu.org Developers; +Cc: Shashi Mallela

On Sun, Dec 12, 2021 at 10:16 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> On 12/11/21 20:11, Peter Maydell wrote:
> > Currently the ITS code that reads and writes DTEs uses open-coded
> > shift-and-mask to assemble the various fields into the 64-bit DTE
> > word.  The names of the macros used for mask and shift values are
> > also somewhat inconsistent, and don't follow our usual convention
> > that a MASK macro should specify the bits in their place in the word.
> > Replace all these with use of the FIELD macro.
> >
> > Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> > ---
> >  hw/intc/gicv3_internal.h |  7 ++++---
> >  hw/intc/arm_gicv3_its.c  | 20 +++++++++-----------
> >  2 files changed, 13 insertions(+), 14 deletions(-)
> >
> > diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
> > index 5a63e9ed5ce..6a3b145f377 100644
> > --- a/hw/intc/gicv3_internal.h
> > +++ b/hw/intc/gicv3_internal.h
> > @@ -393,9 +393,10 @@ FIELD(ITE_H, VPEID, 16, 16)
> >   * Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits
> >   */
> >  #define GITS_DTE_SIZE                 (0x8ULL)
> > -#define GITS_DTE_ITTADDR_SHIFT           6
> > -#define GITS_DTE_ITTADDR_MASK         MAKE_64BIT_MASK(GITS_DTE_ITTADDR_SHIFT, \
> > -                                                      ITTADDR_LENGTH)
>
> Side note, both ITTADDR_LENGTH & ITTADDR_MASK definitions are now unused.

I misread the diff, once applying the series I noticed ITTADDR_MASK
is still used in process_mapd().


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

* Re: [PATCH 11/26] hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1)
  2021-12-12 20:43   ` Richard Henderson
@ 2021-12-13  9:48     ` Peter Maydell
  2021-12-13 10:56       ` Peter Maydell
  0 siblings, 1 reply; 86+ messages in thread
From: Peter Maydell @ 2021-12-13  9:48 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Shashi Mallela, qemu-arm, Alex Bennée, qemu-devel

On Sun, 12 Dec 2021 at 20:43, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 12/11/21 11:11 AM, Peter Maydell wrote:
> >
> >       if (dte_valid) {
> > -        max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
> > +        max_eventid = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
>
> Without changing the type of max_eventid, I think it'd be easiest to fix the off-by-one
> bug by not changing the comparisions, but changing this computation.  E.g.
>
>    max_eventid = (2 << FIELD_EX64(dte, DTE, SIZE)) - 1;
>
> so that the value becomes UINT32_MAX for SIZE=31.

I think I'd prefer to use a uint64_t. I think that part of the reason
for all these off-by-one errors is a lack of consistency in how we
chose to name variables and whether we put in them the max-allowed
value or the 2^n value, so the series tries to standardize on
"always call it num_thingy and always use the 2^n value". I prefer
to keep the consistency rather than rearrange things in this
one case so it can use a uint32_t.

-- PMM


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

* Re: [PATCH 11/26] hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1)
  2021-12-13  9:48     ` Peter Maydell
@ 2021-12-13 10:56       ` Peter Maydell
  0 siblings, 0 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-13 10:56 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Shashi Mallela, qemu-arm, Alex Bennée, qemu-devel

On Mon, 13 Dec 2021 at 09:48, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Sun, 12 Dec 2021 at 20:43, Richard Henderson
> <richard.henderson@linaro.org> wrote:
> >
> > On 12/11/21 11:11 AM, Peter Maydell wrote:
> > >
> > >       if (dte_valid) {
> > > -        max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
> > > +        max_eventid = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
> >
> > Without changing the type of max_eventid, I think it'd be easiest to fix the off-by-one
> > bug by not changing the comparisions, but changing this computation.  E.g.
> >
> >    max_eventid = (2 << FIELD_EX64(dte, DTE, SIZE)) - 1;
> >
> > so that the value becomes UINT32_MAX for SIZE=31.
>
> I think I'd prefer to use a uint64_t. I think that part of the reason
> for all these off-by-one errors is a lack of consistency in how we
> chose to name variables and whether we put in them the max-allowed
> value or the 2^n value, so the series tries to standardize on
> "always call it num_thingy and always use the 2^n value". I prefer
> to keep the consistency rather than rearrange things in this
> one case so it can use a uint32_t.

Looking at the series, I'm going to squash this patch into the
later "Fix event ID bounds checks" patch, and do all the fixing
of the event ID check there in a single patch.

-- PMM


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

* Re: [PATCH 02/26] hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase
  2021-12-11 19:11 ` [PATCH 02/26] hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase Peter Maydell
  2021-12-12 17:32   ` Richard Henderson
@ 2021-12-13 11:22   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 11:22 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> The checks in the ITS on the rdbase values in guest commands are
> off-by-one: they permit the guest to pass us a value equal to
> s->gicv3->num_cpu, but the valid values are 0...num_cpu-1.  This
> meant the guest could cause us to index off the end of the
> s->gicv3->cpu[] array when calling gicv3_redist_process_lpi(), and we
> would probably crash.
>
> Cc: qemu-stable@nongnu.org
> Fixes: 17fb5e36aabd4b ("hw/intc: GICv3 redistributor ITS processing")
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 04/26] hw/intc/arm_gicv3_its: Remove maxids union from TableDesc
  2021-12-11 19:11 ` [PATCH 04/26] hw/intc/arm_gicv3_its: Remove maxids union from TableDesc Peter Maydell
  2021-12-12 17:37   ` Richard Henderson
@ 2021-12-13 11:32   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 11:32 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> The TableDesc struct defines properties of the in-guest-memory tables
> which the guest tells us about by writing to the GITS_BASER<n>
> registers.  This struct currently has a union 'maxids', but all the
> fields of the union have the same type (uint32_t) and do the same
> thing (record one-greater-than the maximum ID value that can be used
> as an index into the table).
>
> We're about to add another table type (the GICv4 vPE table); rather
> than adding another specifically-named union field for that table
> type with the same type as the other union fields, remove the union
> entirely and just have a 'uint32_t max_ids' struct field.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 05/26] hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop
  2021-12-11 19:11 ` [PATCH 05/26] hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop Peter Maydell
  2021-12-12 17:46   ` Richard Henderson
@ 2021-12-13 11:33   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 11:33 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> In extract_table_params() we process each GITS_BASER<n> register.  If
> the register's Valid bit is not set, this means there is no
> in-guest-memory table and so we should not try to interpret the other
> fields in the register.  This was incorrectly coded as a 'return'
> rather than a 'break', so instead of looping round to process the
> next GITS_BASER<n> we would stop entirely, treating any later tables
> as being not valid also.
>
> This has no real guest-visible effects because (since we don't have
> GITS_TYPER.HCC != 0) the guest must in any case set up all the
> GITS_BASER<n> to point to valid tables, so this only happens in an
> odd misbehaving-guest corner case.
>
> Fix the check to 'break', so that we leave the case statement and
> loop back around to the next GITS_BASER<n>.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 06/26] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params()
  2021-12-11 19:11 ` [PATCH 06/26] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params() Peter Maydell
  2021-12-12 18:30   ` Richard Henderson
  2021-12-12 20:47   ` Philippe Mathieu-Daudé
@ 2021-12-13 11:34   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 11:34 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> The extract_table_params() decodes the fields in the GITS_BASER<n>
> registers into TableDesc structs.  Since the fields are the same for
> all the GITS_BASER<n> registers, there is currently a lot of code
> duplication within the switch (type) statement.  Refactor so that the
> cases include only what is genuinely different for each type:
> the calculation of the number of bits in the ID value that indexes
> into the table.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 07/26] hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz
  2021-12-11 19:11 ` [PATCH 07/26] hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz Peter Maydell
  2021-12-12 18:33   ` Richard Henderson
@ 2021-12-13 11:37   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 11:37 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> We set the TableDesc entry_sz field from the appropriate
> GITS_BASER.ENTRYSIZE field.  That ID register field specifies the
> number of bytes per table entry minus one.  However when we use
> td->entry_sz we assume it to be the number of bytes per table entry
> (for instance we calculate the number of entries in a page by
> dividing the page size by the entry size).
>
> The effects of this bug are:
>  * we miscalculate the maximum number of entries in the table,
>    so our checks on guest index values are wrong (too lax)
>  * when looking up an entry in the second level of an indirect
>    table, we calculate an incorrect index into the L2 table.
>    Because we make the same incorrect calculation on both
>    reads and writes of the L2 table, the guest won't notice
>    unless it's unlucky enough to use an index value that
>    causes us to index off the end of the L2 table page and
>    cause guest memory corruption in whatever follows
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 08/26] hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define
  2021-12-11 19:11 ` [PATCH 08/26] hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define Peter Maydell
  2021-12-12 18:40   ` Richard Henderson
@ 2021-12-13 11:52   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 11:52 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> The GITS_TYPE_PHYSICAL define is the value we set the
> GITS_TYPER.Physical field to -- this is 1 to indicate that we support
> physical LPIs.  (Support for virtual LPIs is the GITS_TYPER.Virtual
> field.) We also use this define as the *value* that we write into an
> interrupt translation table entry's INTTYPE field, which should be 1
> for a physical interrupt and 0 for a virtual interrupt.  Finally, we
> use it as a *mask* when we read the interrupt translation table entry
> INTTYPE field.
>
> Untangle this confusion: define an ITE_INTTYPE_VIRTUAL and
> ITE_INTTYPE_PHYSICAL to be the valid values of the ITE INTTYPE
> field, and replace the ad-hoc collection of ITE_ENTRY_* defines with
> use of the FIELD() macro to define the fields of an ITE and the
> FIELD_EX64() and FIELD_DP64() macros to read and write them.
> We use ITE in the new setup, rather than ITE_ENTRY, because
> ITE stands for "Interrupt translation entry" and so the extra
> "entry" would be redundant.
>
> We take the opportunity to correct the name of the field that holds
> the GICv4 'doorbell' interrupt ID (this is always the value 1023 in a
> GICv3, which is why we were calling it the 'spurious' field).
>
> The GITS_TYPE_PHYSICAL define is then used in only one place, where
> we set the initial GITS_TYPER value.  Since GITS_TYPER.Physical is
> essentially a boolean, hiding the '1' value behind a macro is more
> confusing than helpful, so expand out the macro there and remove the
> define entirely.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 09/26] hw/intc/arm_gicv3_its: Correct handling of MAPI
  2021-12-11 19:11 ` [PATCH 09/26] hw/intc/arm_gicv3_its: Correct handling of MAPI Peter Maydell
  2021-12-12 18:48   ` Richard Henderson
@ 2021-12-13 11:54   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 11:54 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> The MAPI command takes arguments DeviceID, EventID, ICID, and is
> defined to be equivalent to MAPTI DeviceID, EventID, EventID, ICID.
> (That is, where MAPTI takes an explicit pINTID, MAPI uses the EventID
> as the pINTID.)
>
> We didn't quite get this right.  In particular the error checks for
> MAPI include "EventID does not specify a valid LPI identifier", which
> is the same as MAPTI's error check for the pINTID field.  QEMU's code
> skips the pINTID error check entirely in the MAPI case.
>
> We can fix this bug and in the process simplify the code by switching
> to the obvious implementation of setting pIntid = eventid early
> if ignore_pInt is true.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/intc/arm_gicv3_its.c | 18 +++++++-----------
>  1 file changed, 7 insertions(+), 11 deletions(-)
>
> diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
> index 15eb72a0a15..6f21c56fba2 100644
> --- a/hw/intc/arm_gicv3_its.c
> +++ b/hw/intc/arm_gicv3_its.c
> @@ -354,7 +354,9 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
>  
>      eventid = (value & EVENTID_MASK);
>  
> -    if (!ignore_pInt) {
> +    if (ignore_pInt) {
> +        pIntid = eventid;
> +    } else {
>          pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);

This would be worth cleaning up with field accessors at some point.

Anyway:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 03/26] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define
  2021-12-11 19:11 ` [PATCH 03/26] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define Peter Maydell
  2021-12-12 17:34   ` Richard Henderson
  2021-12-12 20:46   ` Philippe Mathieu-Daudé
@ 2021-12-13 11:55   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 11:55 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> We currently define a bitmask for the GITS_CTLR ENABLED bit in
> two ways: as ITS_CTLR_ENABLED, and via the FIELD() macro as
> R_GITS_CTLR_ENABLED_MASK. Consistently use the FIELD macro version
> everywhere and remove the redundant ITS_CTLR_ENABLED define.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs
  2021-12-11 19:11 ` [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs Peter Maydell
  2021-12-12 20:23   ` Richard Henderson
  2021-12-12 21:16   ` Philippe Mathieu-Daudé
@ 2021-12-13 11:56   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 11:56 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> Currently the ITS code that reads and writes DTEs uses open-coded
> shift-and-mask to assemble the various fields into the 64-bit DTE
> word.  The names of the macros used for mask and shift values are
> also somewhat inconsistent, and don't follow our usual convention
> that a MASK macro should specify the bits in their place in the word.
> Replace all these with use of the FIELD macro.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 15/26] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries
  2021-12-11 19:11 ` [PATCH 15/26] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries Peter Maydell
  2021-12-12 20:38   ` Richard Henderson
@ 2021-12-13 12:58   ` Philippe Mathieu-Daudé
  2021-12-13 13:36   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-12-13 12:58 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela

On 12/11/21 20:11, Peter Maydell wrote:
> In several places we have a local variable max_l2_entries which is
> the number of entries which will fit in a level 2 table.  The
> calculations done on this value are correct; rename it to
> num_l2_entries to fit the convention we're using in this code.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/intc/arm_gicv3_its.c | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)

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


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

* Re: [PATCH 16/26] hw/intc/arm_gicv3_its: Fix event ID bounds checks
  2021-12-11 19:11 ` [PATCH 16/26] hw/intc/arm_gicv3_its: Fix event ID bounds checks Peter Maydell
@ 2021-12-13 13:00   ` Philippe Mathieu-Daudé
  2021-12-13 13:37   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-12-13 13:00 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 20:11, Peter Maydell wrote:
> In process_its_cmd() and process_mapti() we must check the
> event ID against a limit defined by the size field in the DTE,
> which specifies the number of ID bits minus one. Convert
> this code to our num_foo convention, fixing the off-by-one error.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/intc/arm_gicv3_its.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)

> @@ -299,10 +299,10 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
>                        dte_valid ? "valid" : "invalid",
>                        ite_valid ? "valid" : "invalid",
>                        cte_valid ? "valid" : "invalid");
> -    } else if (eventid > max_eventid) {
> +    } else if (eventid >= num_eventids) {
>          qemu_log_mask(LOG_GUEST_ERROR,
>                        "%s: invalid command attributes: eventid %d > %d\n",

">=" in format.

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

> -                      __func__, eventid, max_eventid);
> +                      __func__, eventid, num_eventids);


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

* Re: [PATCH 18/26] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value
  2021-12-11 19:11 ` [PATCH 18/26] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value Peter Maydell
  2021-12-12 20:53   ` Richard Henderson
@ 2021-12-13 13:01   ` Philippe Mathieu-Daudé
  2021-12-13 13:41   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-12-13 13:01 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 20:11, Peter Maydell wrote:
> process_its_cmd() returns a bool, like all the other process_ functions.
> However we were putting its return value into 'res', not 'result',
> which meant we would ignore it when deciding whether to continue
> or stall the command queue. Fix the typo.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/intc/arm_gicv3_its.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

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


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

* Re: [PATCH 20/26] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions
  2021-12-11 19:11 ` [PATCH 20/26] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions Peter Maydell
  2021-12-12 21:06   ` Richard Henderson
@ 2021-12-13 13:03   ` Philippe Mathieu-Daudé
  2021-12-13 14:40   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-12-13 13:03 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel; +Cc: Shashi Mallela, Alex Bennée

On 12/11/21 20:11, Peter Maydell wrote:
> When an ITS detects an error in a command, it has an
> implementation-defined (CONSTRAINED UNPREDICTABLE) choice of whether
> to ignore the command, proceeding to the next one in the queue, or to
> stall the ITS command queue, processing nothing further.  The
> behaviour required when the read of the command packet from memory
> fails is less clearly documented, but the same set of choices as for
> command errors seem reasonable.
> 
> The intention of the QEMU implementation, as documented in the
> comments, is that if we encounter a memory error reading the command
> packet or one of the various data tables then we should stall, but
> for command parameter errors we should ignore the queue and continue.
> However, we don't actually do this.  To get the desired behaviour,
> the various process_* functions need to return true to cause
> process_cmdq() to advance to the next command and keep processing,
> and false to stall command processing.  What they mostly do is return
> false for any kind of error.
> 
> To make the code clearer, replace the 'bool' return from the process_
> functions with an enum which may be either CMD_STALL or CMD_CONTINUE.
> In this commit no behaviour changes; in subsequent commits we will
> adjust the error-return paths for the process_ functions one by one.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/intc/arm_gicv3_its.c | 59 ++++++++++++++++++++++++++---------------
>  1 file changed, 38 insertions(+), 21 deletions(-)
> 
> diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
> index f3eba92946d..59dd564d91c 100644
> --- a/hw/intc/arm_gicv3_its.c
> +++ b/hw/intc/arm_gicv3_its.c
> @@ -45,6 +45,23 @@ typedef struct {
>      uint64_t itel;
>  } IteEntry;
>  
> +/*
> + * The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
> + * if a command parameter is not correct. These include both "stall
> + * processing of the command queue" and "ignore this command, and
> + * keep processing the queue". In our implementation we choose that
> + * memory transaction errors reading the command packet provoke a
> + * stall, but errors in parameters cause us to ignore the command
> + * and continue processing.
> + * The process_* functions which handle invididual ITS commands all

Typo "individual".

> + * return an ItsCmdResult which tells process_cmdq() whether it should
> + * stall or keep going.
> + */
> +typedef enum ItsCmdResult {
> +    CMD_STALL = 0,
> +    CMD_CONTINUE = 1,
> +} ItsCmdResult;

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


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

* Re: [PATCH 12/26] hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size
  2021-12-11 19:11 ` [PATCH 12/26] hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size Peter Maydell
  2021-12-12 20:34   ` Richard Henderson
@ 2021-12-13 13:07   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 13:07 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> The comment says that in our CTE format the RDBase field is 36 bits;
> in fact for us it is only 16 bits, because we use the RDBase format
> where it specifies a 16-bit CPU number. The code already uses
> RDBASE_PROCNUM_LENGTH (16) as the field width, so fix the comment
> to match it.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 13/26] hw/intc/arm_gicv3_its: Use FIELD macros for CTEs
  2021-12-11 19:11 ` [PATCH 13/26] hw/intc/arm_gicv3_its: Use FIELD macros for CTEs Peter Maydell
  2021-12-12 20:35   ` Richard Henderson
@ 2021-12-13 13:08   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 13:08 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> Use FIELD macros to handle CTEs, rather than ad-hoc mask-and-shift.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/intc/gicv3_internal.h | 3 ++-
>  hw/intc/arm_gicv3_its.c  | 7 ++++---
>  2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
> index 14e8ef68e02..1eeb99035da 100644
> --- a/hw/intc/gicv3_internal.h
> +++ b/hw/intc/gicv3_internal.h
> @@ -403,7 +403,8 @@ FIELD(DTE, ITTADDR, 6, 44)
>   * Valid = 1 bit, RDBase = 16 bits
>   */
>  #define GITS_CTE_SIZE                 (0x8ULL)
> -#define GITS_CTE_RDBASE_PROCNUM_MASK  MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH)
> +FIELD(CTE, VALID, 0, 1)
> +FIELD(CTE, RDBASE, 1, RDBASE_PROCNUM_LENGTH)
>  
>  /* Special interrupt IDs */
>  #define INTID_SECURE 1020
> diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
> index d6637229479..ab6ce09dbc2 100644
> --- a/hw/intc/arm_gicv3_its.c
> +++ b/hw/intc/arm_gicv3_its.c
> @@ -104,7 +104,7 @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
>                                        MEMTXATTRS_UNSPECIFIED, res);
>      }
>  
> -    return (*cte & TABLE_ENTRY_VALID_MASK) != 0;
> +    return FIELD_EX64(*cte, CTE, VALID);
>  }
>  
>  static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
> @@ -308,7 +308,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
>           * Current implementation only supports rdbase == procnum
>           * Hence rdbase physical address is ignored
>           */
> -        rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U;
> +        rdbase = FIELD_EX64(cte, CTE, RDBASE);
>  
>          if (rdbase >= s->gicv3->num_cpu) {
>              return result;
> @@ -426,7 +426,8 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
>  
>      if (valid) {
>          /* add mapping entry to collection table */
> -        cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL);
> +        cte = FIELD_DP64(cte, CTE, VALID, 1);
> +        cte = FIELD_DP64(cte, CTE, RDBASE, rdbase);

I almost flagged this until I realised the double deposit are additive
and the same as the bare |

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 14/26] hw/intc/arm_gicv3_its: Fix various off-by-one errors
  2021-12-11 19:11 ` [PATCH 14/26] hw/intc/arm_gicv3_its: Fix various off-by-one errors Peter Maydell
@ 2021-12-13 13:35   ` Alex Bennée
  0 siblings, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 13:35 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> The ITS code has to check whether various parameters passed in
> commands are in-bounds, where the limit is defined in terms of the
> number of bits that are available for the parameter.  (For example,
> the GITS_TYPER.Devbits ID register field specifies the number of
> DeviceID bits minus 1, and device IDs passed in the MAPTI and MAPD
> command packets must fit in that many bits.)
>
> Currently we have off-by-one bugs in many of these bounds checks.
> The typical problem is that we define a max_foo as 1 << n. In
> the Devbits example, we set
>   s->dt.max_ids = 1UL << (GITS_TYPER.Devbits + 1).
> However later when we do the bounds check we write
>   if (devid > s->dt.max_ids) { /* command error */ }
> which incorrectly permits a devid of 1 << n.
>
> These bugs will not cause QEMU crashes because the ID values being
> checked are only used for accesses into tables held in guest memory
> which we access with address_space_*() functions, but they are
> incorrect behaviour of our emulation.
>
> Fix them by standardizing on this pattern:
>  * bounds limits are named num_foos and are the 2^n value
>    (equal to the number of valid foo values)
>  * bounds checks are either
>    if (fooid < num_foos) { good }
>    or
>    if (fooid >= num_foos) { bad }
>
> In this commit we fix the handling of the number of IDs
> in the device table and the collection table, and the number
> of commands that will fit in the command queue.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 15/26] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries
  2021-12-11 19:11 ` [PATCH 15/26] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries Peter Maydell
  2021-12-12 20:38   ` Richard Henderson
  2021-12-13 12:58   ` Philippe Mathieu-Daudé
@ 2021-12-13 13:36   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 13:36 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> In several places we have a local variable max_l2_entries which is
> the number of entries which will fit in a level 2 table.  The
> calculations done on this value are correct; rename it to
> num_l2_entries to fit the convention we're using in this code.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 16/26] hw/intc/arm_gicv3_its: Fix event ID bounds checks
  2021-12-11 19:11 ` [PATCH 16/26] hw/intc/arm_gicv3_its: Fix event ID bounds checks Peter Maydell
  2021-12-13 13:00   ` Philippe Mathieu-Daudé
@ 2021-12-13 13:37   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 13:37 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> In process_its_cmd() and process_mapti() we must check the
> event ID against a limit defined by the size field in the DTE,
> which specifies the number of ID bits minus one. Convert
> this code to our num_foo convention, fixing the off-by-one error.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 17/26] hw/intc/arm_gicv3_its: Convert int ID check to num_intids convention
  2021-12-11 19:11 ` [PATCH 17/26] hw/intc/arm_gicv3_its: Convert int ID check to num_intids convention Peter Maydell
@ 2021-12-13 13:39   ` Alex Bennée
  0 siblings, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 13:39 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> The bounds check on the number of interrupt IDs is correct, but
> doesn't match our convention; change the variable name, initialize it
> to the 2^n value rather than (2^n)-1, and use >= instead of > in the
> comparison.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 18/26] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value
  2021-12-11 19:11 ` [PATCH 18/26] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value Peter Maydell
  2021-12-12 20:53   ` Richard Henderson
  2021-12-13 13:01   ` Philippe Mathieu-Daudé
@ 2021-12-13 13:41   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 13:41 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> process_its_cmd() returns a bool, like all the other process_ functions.
> However we were putting its return value into 'res', not 'result',
> which meant we would ignore it when deciding whether to continue
> or stall the command queue. Fix the typo.

Arguably having to generic result types is confusing. Naming things is
hard but maybe it should be a clear:

      MemTxResult memtx_res = MEMTX_OK;
      ItsCmdResult its_res = CMD_CONTINUE;

?

Anyway:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 20/26] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions
  2021-12-11 19:11 ` [PATCH 20/26] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions Peter Maydell
  2021-12-12 21:06   ` Richard Henderson
  2021-12-13 13:03   ` Philippe Mathieu-Daudé
@ 2021-12-13 14:40   ` Alex Bennée
  2 siblings, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 14:40 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> When an ITS detects an error in a command, it has an
> implementation-defined (CONSTRAINED UNPREDICTABLE) choice of whether
> to ignore the command, proceeding to the next one in the queue, or to
> stall the ITS command queue, processing nothing further.  The
> behaviour required when the read of the command packet from memory
> fails is less clearly documented, but the same set of choices as for
> command errors seem reasonable.
>
> The intention of the QEMU implementation, as documented in the
> comments, is that if we encounter a memory error reading the command
> packet or one of the various data tables then we should stall, but
> for command parameter errors we should ignore the queue and continue.
> However, we don't actually do this.  To get the desired behaviour,
> the various process_* functions need to return true to cause
> process_cmdq() to advance to the next command and keep processing,
> and false to stall command processing.  What they mostly do is return
> false for any kind of error.
>
> To make the code clearer, replace the 'bool' return from the process_
> functions with an enum which may be either CMD_STALL or CMD_CONTINUE.
> In this commit no behaviour changes; in subsequent commits we will
> adjust the error-return paths for the process_ functions one by one.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 21/26] hw/intc/arm_gicv3_its: Fix return codes in process_its_cmd()
  2021-12-11 19:11 ` [PATCH 21/26] hw/intc/arm_gicv3_its: Fix return codes in process_its_cmd() Peter Maydell
  2021-12-12 22:02   ` Richard Henderson
@ 2021-12-13 14:40   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 14:40 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> Fix process_its_cmd() to consistently return CMD_STALL for
> memory errors and CMD_CONTINUE for parameter errors, as
> we claim in the comments that we do.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 19/26] hw/intc/arm_gicv3_its: Don't use data if reading command failed
  2021-12-11 19:11 ` [PATCH 19/26] hw/intc/arm_gicv3_its: Don't use data if reading command failed Peter Maydell
  2021-12-12 20:54   ` Richard Henderson
@ 2021-12-13 14:49   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 14:49 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> In process_cmdq(), we read 64 bits of the command packet, which
> contain the command identifier, which we then switch() on to dispatch
> to an appropriate sub-function.  However, if address_space_ldq_le()
> reports a memory transaction failure, we still read the command
> identifier out of the data and switch() on it.  Restructure the code
> so that we stop immediately (stalling the command queue) in this
> case.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 22/26] hw/intc/arm_gicv3_its: Refactor process_its_cmd() to reduce nesting
  2021-12-11 19:11 ` [PATCH 22/26] hw/intc/arm_gicv3_its: Refactor process_its_cmd() to reduce nesting Peter Maydell
  2021-12-12 22:34   ` Richard Henderson
@ 2021-12-13 14:50   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 14:50 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> Refactor process_its_cmd() so that it consistently uses
> the structure
>   do thing;
>   if (error condition) {
>       return early;
>   }
>   do next thing;
>
> rather than doing some of the work nested inside if (not error)
> code blocks.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 23/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapti()
  2021-12-11 19:11 ` [PATCH 23/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapti() Peter Maydell
  2021-12-12 22:36   ` Richard Henderson
@ 2021-12-13 14:51   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 14:51 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> Fix process_mapti() to consistently return CMD_STALL for memory
> errors and CMD_CONTINUE for parameter errors, as we claim in the
> comments that we do.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 24/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapc()
  2021-12-11 19:11 ` [PATCH 24/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapc() Peter Maydell
  2021-12-12 22:37   ` Richard Henderson
@ 2021-12-13 14:51   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 14:51 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> Fix process_mapc() to consistently return CMD_STALL for memory
> errors and CMD_CONTINUE for parameter errors, as we claim in the
> comments that we do.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 25/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapd()
  2021-12-11 19:11 ` [PATCH 25/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapd() Peter Maydell
  2021-12-12 22:39   ` Richard Henderson
@ 2021-12-13 14:51   ` Alex Bennée
  1 sibling, 0 replies; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 14:51 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> Fix process_mapd() to consistently return CMD_STALL for memory
> errors and CMD_CONTINUE for parameter errors, as we claim in the
> comments that we do.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

-- 
Alex Bennée


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

* Re: [PATCH 26/26] hw/intc/arm_gicv3_its: Factor out "find address of table entry" code
  2021-12-11 19:11 ` [PATCH 26/26] hw/intc/arm_gicv3_its: Factor out "find address of table entry" code Peter Maydell
  2021-12-12 22:52   ` Richard Henderson
@ 2021-12-13 14:53   ` Alex Bennée
  2021-12-13 15:48     ` Peter Maydell
  1 sibling, 1 reply; 86+ messages in thread
From: Alex Bennée @ 2021-12-13 14:53 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Shashi Mallela, qemu-arm, qemu-devel


Peter Maydell <peter.maydell@linaro.org> writes:

> The ITS has several tables which all share a similar format,
> described by the TableDesc struct: the guest may configure them
> to be a single-level table or a two-level table. Currently we
> open-code the process of finding the table entry in all the
> functions which read or write the device table or the collection
> table. Factor out the "get the address of the table entry"
> logic into a new function, so that the code which needs to
> read or write a table entry only needs to call table_entry_addr()
> and then perform a suitable load or store to that address.
>
> Note that the error handling is slightly complicated because
> we want to handle two cases differently:
>  * failure to read the L1 table entry should end up causing
>    a command stall, like other kinds of DMA error
>  * an L1 table entry that says there is no L2 table for this
>    index (ie whose valid bit is 0) must result in us treating
>    the table entry as not-valid on read, and discarding
>    writes (this is mandated by the spec)
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> This is a worthwhile refactoring on its own, but still more
> so given that GICv4 adds another table in this format.
> ---
>  hw/intc/arm_gicv3_its.c | 212 +++++++++++++---------------------------
>  1 file changed, 70 insertions(+), 142 deletions(-)
>
> diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
> index 3bcc4c3db85..90a9fd3b3d4 100644
> --- a/hw/intc/arm_gicv3_its.c
> +++ b/hw/intc/arm_gicv3_its.c
> @@ -83,44 +83,62 @@ static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
>      return result;
>  }
>  
> +static uint64_t table_entry_addr(GICv3ITSState *s, TableDesc *td,
> +                                 uint32_t idx, MemTxResult *res)
> +{

It seems odd to have a uint64_t return type when....

> +    /*
> +     * Given a TableDesc describing one of the ITS in-guest-memory
> +     * tables and an index into it, return the guest address
> +     * corresponding to that table entry.
> +     * If there was a memory error reading the L1 table of an
> +     * indirect table, *res is set accordingly, and we return -1.
> +     * If the L1 table entry is marked not valid, we return -1 with
> +     * *res set to MEMTX_OK.
> +     *
> +     * The specification defines the format of level 1 entries of a
> +     * 2-level table, but the format of level 2 entries and the format
> +     * of flat-mapped tables is IMPDEF.
> +     */
> +    AddressSpace *as = &s->gicv3->dma_as;
> +    uint32_t l2idx;
> +    uint64_t l2;
> +    uint32_t num_l2_entries;
> +
> +    *res = MEMTX_OK;
> +
> +    if (!td->indirect) {
> +        /* Single level table */
> +        return td->base_addr + idx * td->entry_sz;
> +    }
> +
> +    /* Two level table */
> +    l2idx = idx / (td->page_sz / L1TABLE_ENTRY_SIZE);
> +
> +    l2 = address_space_ldq_le(as,
> +                              td->base_addr + (l2idx * L1TABLE_ENTRY_SIZE),
> +                              MEMTXATTRS_UNSPECIFIED, res);
> +    if (*res != MEMTX_OK) {
> +        return -1;
> +    }
> +    if (!(l2 & L2_TABLE_VALID_MASK)) {
> +        return -1;
> +    }

We can return signed results. I guess implicit conversion takes care of
it but I wonder if it would be cleaner to return an int (or maybe
compare against UNINT64_MAX == INVALID_TABLE_ENTRY)?

-- 
Alex Bennée


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

* Re: [PATCH 26/26] hw/intc/arm_gicv3_its: Factor out "find address of table entry" code
  2021-12-13 14:53   ` Alex Bennée
@ 2021-12-13 15:48     ` Peter Maydell
  0 siblings, 0 replies; 86+ messages in thread
From: Peter Maydell @ 2021-12-13 15:48 UTC (permalink / raw)
  To: Alex Bennée; +Cc: Shashi Mallela, qemu-arm, qemu-devel

On Mon, 13 Dec 2021 at 15:00, Alex Bennée <alex.bennee@linaro.org> wrote:
>
>
> Peter Maydell <peter.maydell@linaro.org> writes:
>
> > The ITS has several tables which all share a similar format,
> > described by the TableDesc struct: the guest may configure them
> > to be a single-level table or a two-level table. Currently we
> > open-code the process of finding the table entry in all the
> > functions which read or write the device table or the collection
> > table. Factor out the "get the address of the table entry"
> > logic into a new function, so that the code which needs to
> > read or write a table entry only needs to call table_entry_addr()
> > and then perform a suitable load or store to that address.
> >
> > Note that the error handling is slightly complicated because
> > we want to handle two cases differently:
> >  * failure to read the L1 table entry should end up causing
> >    a command stall, like other kinds of DMA error
> >  * an L1 table entry that says there is no L2 table for this
> >    index (ie whose valid bit is 0) must result in us treating
> >    the table entry as not-valid on read, and discarding
> >    writes (this is mandated by the spec)
> >
> > Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> > ---
> > This is a worthwhile refactoring on its own, but still more
> > so given that GICv4 adds another table in this format.
> > ---
> >  hw/intc/arm_gicv3_its.c | 212 +++++++++++++---------------------------
> >  1 file changed, 70 insertions(+), 142 deletions(-)
> >
> > diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
> > index 3bcc4c3db85..90a9fd3b3d4 100644
> > --- a/hw/intc/arm_gicv3_its.c
> > +++ b/hw/intc/arm_gicv3_its.c
> > @@ -83,44 +83,62 @@ static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
> >      return result;
> >  }
> >
> > +static uint64_t table_entry_addr(GICv3ITSState *s, TableDesc *td,
> > +                                 uint32_t idx, MemTxResult *res)
> > +{
>
> It seems odd to have a uint64_t return type when....
>
> > +    /*
> > +     * Given a TableDesc describing one of the ITS in-guest-memory
> > +     * tables and an index into it, return the guest address
> > +     * corresponding to that table entry.
> > +     * If there was a memory error reading the L1 table of an
> > +     * indirect table, *res is set accordingly, and we return -1.
> > +     * If the L1 table entry is marked not valid, we return -1 with
> > +     * *res set to MEMTX_OK.
> > +     *
> > +     * The specification defines the format of level 1 entries of a
> > +     * 2-level table, but the format of level 2 entries and the format
> > +     * of flat-mapped tables is IMPDEF.
> > +     */
> > +    AddressSpace *as = &s->gicv3->dma_as;
> > +    uint32_t l2idx;
> > +    uint64_t l2;
> > +    uint32_t num_l2_entries;
> > +
> > +    *res = MEMTX_OK;
> > +
> > +    if (!td->indirect) {
> > +        /* Single level table */
> > +        return td->base_addr + idx * td->entry_sz;
> > +    }
> > +
> > +    /* Two level table */
> > +    l2idx = idx / (td->page_sz / L1TABLE_ENTRY_SIZE);
> > +
> > +    l2 = address_space_ldq_le(as,
> > +                              td->base_addr + (l2idx * L1TABLE_ENTRY_SIZE),
> > +                              MEMTXATTRS_UNSPECIFIED, res);
> > +    if (*res != MEMTX_OK) {
> > +        return -1;
> > +    }
> > +    if (!(l2 & L2_TABLE_VALID_MASK)) {
> > +        return -1;
> > +    }
>
> We can return signed results. I guess implicit conversion takes care of
> it but I wonder if it would be cleaner to return an int (or maybe
> compare against UNINT64_MAX == INVALID_TABLE_ENTRY)?

-1 is only there to be a "definitely not a valid address" value,
and it's less typing than UINT64_MAX.

-- PMM


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

end of thread, other threads:[~2021-12-13 15:51 UTC | newest]

Thread overview: 86+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-11 19:11 [PATCH 00/26] arm gicv3 ITS: Various bug fixes and refactorings Peter Maydell
2021-12-11 19:11 ` [PATCH 01/26] hw/intc: clean-up error reporting for failed ITS cmd Peter Maydell
2021-12-12 17:31   ` Richard Henderson
2021-12-11 19:11 ` [PATCH 02/26] hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase Peter Maydell
2021-12-12 17:32   ` Richard Henderson
2021-12-13 11:22   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 03/26] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define Peter Maydell
2021-12-12 17:34   ` Richard Henderson
2021-12-12 20:46   ` Philippe Mathieu-Daudé
2021-12-13 11:55   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 04/26] hw/intc/arm_gicv3_its: Remove maxids union from TableDesc Peter Maydell
2021-12-12 17:37   ` Richard Henderson
2021-12-13 11:32   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 05/26] hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop Peter Maydell
2021-12-12 17:46   ` Richard Henderson
2021-12-13 11:33   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 06/26] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params() Peter Maydell
2021-12-12 18:30   ` Richard Henderson
2021-12-12 20:47   ` Philippe Mathieu-Daudé
2021-12-13 11:34   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 07/26] hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz Peter Maydell
2021-12-12 18:33   ` Richard Henderson
2021-12-13 11:37   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 08/26] hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define Peter Maydell
2021-12-12 18:40   ` Richard Henderson
2021-12-13 11:52   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 09/26] hw/intc/arm_gicv3_its: Correct handling of MAPI Peter Maydell
2021-12-12 18:48   ` Richard Henderson
2021-12-13 11:54   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 10/26] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs Peter Maydell
2021-12-12 20:23   ` Richard Henderson
2021-12-12 21:16   ` Philippe Mathieu-Daudé
2021-12-13  8:23     ` Philippe Mathieu-Daudé
2021-12-13 11:56   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 11/26] hw/intc/arm_gicv3_its: Use 1ULL when shifting by (DTE.SIZE + 1) Peter Maydell
2021-12-12 20:31   ` Richard Henderson
2021-12-12 20:43   ` Richard Henderson
2021-12-13  9:48     ` Peter Maydell
2021-12-13 10:56       ` Peter Maydell
2021-12-11 19:11 ` [PATCH 12/26] hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size Peter Maydell
2021-12-12 20:34   ` Richard Henderson
2021-12-13 13:07   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 13/26] hw/intc/arm_gicv3_its: Use FIELD macros for CTEs Peter Maydell
2021-12-12 20:35   ` Richard Henderson
2021-12-13 13:08   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 14/26] hw/intc/arm_gicv3_its: Fix various off-by-one errors Peter Maydell
2021-12-13 13:35   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 15/26] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries Peter Maydell
2021-12-12 20:38   ` Richard Henderson
2021-12-13 12:58   ` Philippe Mathieu-Daudé
2021-12-13 13:36   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 16/26] hw/intc/arm_gicv3_its: Fix event ID bounds checks Peter Maydell
2021-12-13 13:00   ` Philippe Mathieu-Daudé
2021-12-13 13:37   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 17/26] hw/intc/arm_gicv3_its: Convert int ID check to num_intids convention Peter Maydell
2021-12-13 13:39   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 18/26] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value Peter Maydell
2021-12-12 20:53   ` Richard Henderson
2021-12-13 13:01   ` Philippe Mathieu-Daudé
2021-12-13 13:41   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 19/26] hw/intc/arm_gicv3_its: Don't use data if reading command failed Peter Maydell
2021-12-12 20:54   ` Richard Henderson
2021-12-13 14:49   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 20/26] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions Peter Maydell
2021-12-12 21:06   ` Richard Henderson
2021-12-13 13:03   ` Philippe Mathieu-Daudé
2021-12-13 14:40   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 21/26] hw/intc/arm_gicv3_its: Fix return codes in process_its_cmd() Peter Maydell
2021-12-12 22:02   ` Richard Henderson
2021-12-13 14:40   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 22/26] hw/intc/arm_gicv3_its: Refactor process_its_cmd() to reduce nesting Peter Maydell
2021-12-12 22:34   ` Richard Henderson
2021-12-13 14:50   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 23/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapti() Peter Maydell
2021-12-12 22:36   ` Richard Henderson
2021-12-13 14:51   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 24/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapc() Peter Maydell
2021-12-12 22:37   ` Richard Henderson
2021-12-13 14:51   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 25/26] hw/intc/arm_gicv3_its: Fix return codes in process_mapd() Peter Maydell
2021-12-12 22:39   ` Richard Henderson
2021-12-13 14:51   ` Alex Bennée
2021-12-11 19:11 ` [PATCH 26/26] hw/intc/arm_gicv3_its: Factor out "find address of table entry" code Peter Maydell
2021-12-12 22:52   ` Richard Henderson
2021-12-13 14:53   ` Alex Bennée
2021-12-13 15:48     ` Peter Maydell

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.