Browse Source

hw/intc/arm_gicv3: Make ITT entry size configurable

An ITT entry is opaque to the OS. The only thing it does get told by HW is
its size. In theory, that size can be any byte aligned number, in practice
HW will always use power of 2s to simplify offset calculation. We currently
expose the size as 12, which is not a power of 2.

To prepare for a future where we expose power of 2 sized entry sizes, let's
make the size itself configurable. We only need to watch out that we don't
have an entry be smaller than the fields we want to access inside. Bigger
is always fine.

Signed-off-by: Alexander Graf <agraf@csgraf.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Joelle van Dyne <j@getutm.app>
Alexander Graf 2 years ago
parent
commit
888bb9e3bf
3 changed files with 13 additions and 4 deletions
  1. 11 3
      hw/intc/arm_gicv3_its.c
  2. 1 1
      hw/intc/gicv3_internal.h
  3. 1 0
      include/hw/intc/arm_gicv3_its_common.h

+ 11 - 3
hw/intc/arm_gicv3_its.c

@@ -215,7 +215,7 @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
 {
 {
     AddressSpace *as = &s->gicv3->dma_as;
     AddressSpace *as = &s->gicv3->dma_as;
     MemTxResult res = MEMTX_OK;
     MemTxResult res = MEMTX_OK;
-    hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
+    hwaddr iteaddr = dte->ittaddr + eventid * s->itt_entry_size;
     uint64_t itel = 0;
     uint64_t itel = 0;
     uint32_t iteh = 0;
     uint32_t iteh = 0;
 
 
@@ -253,7 +253,7 @@ static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid,
     MemTxResult res = MEMTX_OK;
     MemTxResult res = MEMTX_OK;
     uint64_t itel;
     uint64_t itel;
     uint32_t iteh;
     uint32_t iteh;
-    hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
+    hwaddr iteaddr = dte->ittaddr + eventid * s->itt_entry_size;
 
 
     itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, &res);
     itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, &res);
     if (res != MEMTX_OK) {
     if (res != MEMTX_OK) {
@@ -1931,6 +1931,12 @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
         }
         }
     }
     }
 
 
+    if (s->itt_entry_size < MIN_ITS_ITT_ENTRY_SIZE) {
+        error_setg(errp, "ITT entry size must be at least %d",
+                   MIN_ITS_ITT_ENTRY_SIZE);
+        return;
+    }
+
     gicv3_add_its(s->gicv3, dev);
     gicv3_add_its(s->gicv3, dev);
 
 
     gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
     gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
@@ -1938,7 +1944,7 @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
     /* set the ITS default features supported */
     /* set the ITS default features supported */
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1);
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1);
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
-                          ITS_ITT_ENTRY_SIZE - 1);
+                          s->itt_entry_size - 1);
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
     s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
@@ -2005,6 +2011,8 @@ static void gicv3_its_post_load(GICv3ITSState *s)
 static Property gicv3_its_props[] = {
 static Property gicv3_its_props[] = {
     DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
     DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
                      GICv3State *),
                      GICv3State *),
+    DEFINE_PROP_UINT8("itt-entry-size", GICv3ITSState, itt_entry_size,
+                      MIN_ITS_ITT_ENTRY_SIZE),
     DEFINE_PROP_END_OF_LIST(),
     DEFINE_PROP_END_OF_LIST(),
 };
 };
 
 

+ 1 - 1
hw/intc/gicv3_internal.h

@@ -462,7 +462,7 @@ FIELD(VINVALL_1, VPEID, 32, 16)
  * the value of that field in memory cannot be relied upon -- older
  * the value of that field in memory cannot be relied upon -- older
  * versions of QEMU did not correctly write to that memory.)
  * versions of QEMU did not correctly write to that memory.)
  */
  */
-#define ITS_ITT_ENTRY_SIZE            0xC
+#define MIN_ITS_ITT_ENTRY_SIZE            0xC
 
 
 FIELD(ITE_L, VALID, 0, 1)
 FIELD(ITE_L, VALID, 0, 1)
 FIELD(ITE_L, INTTYPE, 1, 1)
 FIELD(ITE_L, INTTYPE, 1, 1)

+ 1 - 0
include/hw/intc/arm_gicv3_its_common.h

@@ -66,6 +66,7 @@ struct GICv3ITSState {
     int dev_fd; /* kvm device fd if backed by kvm vgic support */
     int dev_fd; /* kvm device fd if backed by kvm vgic support */
     uint64_t gits_translater_gpa;
     uint64_t gits_translater_gpa;
     bool translater_gpa_known;
     bool translater_gpa_known;
+    uint8_t itt_entry_size;
 
 
     /* Registers */
     /* Registers */
     uint32_t ctlr;
     uint32_t ctlr;