dev-arm: Fix GITS_BASER initialization/access

The patch is fixing/improving GITS_BASER registers initialization.

* Not using reserved table types anymore (GITS_BASER.TYPE)
* Using write mask for handling WI bits

Change-Id: Ibe24667fdf22b42b86496167c19fc00bbb0ba191
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20328
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/dev/arm/gic_v3_its.cc b/src/dev/arm/gic_v3_its.cc
index ddf06f4..692bbd0 100644
--- a/src/dev/arm/gic_v3_its.cc
+++ b/src/dev/arm/gic_v3_its.cc
@@ -780,18 +780,22 @@
    gitsTyper(params->gits_typer),
    gitsCbaser(0), gitsCreadr(0),
    gitsCwriter(0), gitsIidr(0),
+   tableBases(NUM_BASER_REGS, 0),
    masterId(params->system->getMasterId(this)),
    gic(nullptr),
    commandEvent([this] { checkCommandQueue(); }, name()),
    pendingCommands(false),
    pendingTranslations(0)
 {
-    for (auto idx = 0; idx < NUM_BASER_REGS; idx++) {
-        BASER gits_baser = 0;
-        gits_baser.type = idx;
-        gits_baser.entrySize = sizeof(uint64_t) - 1;
-        tableBases.push_back(gits_baser);
-    }
+    BASER device_baser = 0;
+    device_baser.type = DEVICE_TABLE;
+    device_baser.entrySize = sizeof(uint64_t) - 1;
+    tableBases[0] = device_baser;
+
+    BASER icollect_baser = 0;
+    icollect_baser.type = COLLECTION_TABLE;
+    icollect_baser.entrySize = sizeof(uint64_t) - 1;
+    tableBases[1] = icollect_baser;
 }
 
 void
@@ -958,12 +962,12 @@
             auto relative_addr = addr - GITS_BASER.start();
             auto baser_index = relative_addr / sizeof(uint64_t);
 
-            BASER val = pkt->getLE<uint64_t>();
+            const uint64_t table_base = tableBases[baser_index];
+            const uint64_t w_mask = tableBases[baser_index].type ?
+                BASER_WMASK : BASER_WMASK_UNIMPL;
+            const uint64_t val = pkt->getLE<uint64_t>() & w_mask;
 
-            panic_if(val.indirect,
-                "We currently don't support two level ITS tables");
-
-            tableBases[baser_index] = val;
+            tableBases[baser_index] = table_base | val;
             break;
         } else {
             panic("Unrecognized register access\n");
@@ -1224,7 +1228,16 @@
 Addr
 Gicv3Its::pageAddress(Gicv3Its::ItsTables table)
 {
-    const BASER base = tableBases[table];
+    auto base_it = std::find_if(
+        tableBases.begin(), tableBases.end(),
+        [table] (const BASER &b) { return b.type == table; }
+    );
+
+    panic_if(base_it == tableBases.end(),
+        "ITS Table not recognised\n");
+
+    const BASER base = *base_it;
+
     // real address depends on page size
     switch (base.pageSize) {
       case SIZE_4K:
diff --git a/src/dev/arm/gic_v3_its.hh b/src/dev/arm/gic_v3_its.hh
index 1ca98a8..40d95c8 100644
--- a/src/dev/arm/gic_v3_its.hh
+++ b/src/dev/arm/gic_v3_its.hh
@@ -114,6 +114,18 @@
 
     static const uint32_t NUM_BASER_REGS = 8;
 
+    // We currently don't support two level ITS tables
+    // The indirect bit is RAZ/WI for implementations that only
+    // support flat tables.
+    static const uint64_t BASER_INDIRECT = 0x4000000000000000;
+    static const uint64_t BASER_TYPE = 0x0700000000000000;
+    static const uint64_t BASER_ESZ = 0x001F000000000000;
+    static const uint64_t BASER_SZ = 0x00000000000000FF;
+    static const uint64_t BASER_WMASK =
+        ~(BASER_INDIRECT | BASER_TYPE | BASER_ESZ);
+    static const uint64_t BASER_WMASK_UNIMPL =
+        ~(BASER_INDIRECT | BASER_TYPE | BASER_ESZ | BASER_SZ);
+
     // GITS_CTLR.quiescent mask
     static const uint32_t CTLR_QUIESCENT;