Keep all the info about BASER regs in host_its structure to be able to easily
access it later.

Signed-off-by: Mykyta Poturai <[email protected]>
---
 xen/arch/arm/gic-v3-its.c             | 36 +++++++++++++++++++++------
 xen/arch/arm/include/asm/gic_v3_its.h | 14 +++++++++++
 2 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index c628959f42..2328595a85 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -430,16 +430,32 @@ static void *its_map_cbaser(struct host_its *its)
 /* The ITS BASE registers work with page sizes of 4K, 16K or 64K. */
 #define BASER_PAGE_BITS(sz) ((sz) * 2 + 12)
 
+struct its_baser *its_get_baser(struct host_its *hw_its, uint32_t type)
+{
+    unsigned int i;
+
+    for ( i = 0; i < GITS_BASER_NR_REGS; i++ )
+    {
+        if (GITS_BASER_TYPE(hw_its->tables[i].val) == type)
+            return &hw_its->tables[i];
+    }
+
+    return NULL;
+}
+
 static int its_map_baser(void __iomem *basereg, uint64_t regc,
-                         unsigned int nr_items)
+                         unsigned int nr_items, struct its_baser *baser)
 {
     uint64_t attr, reg;
     unsigned int entry_size = GITS_BASER_ENTRY_SIZE(regc);
-    unsigned int pagesz = 2;    /* try 64K pages first, then go down. */
+    unsigned int page_size[4] = {SZ_4K, SZ_16K, SZ_64K, SZ_64K};
+    unsigned int pagesz = 0;    /* try 64K pages first, then go down. */
     unsigned int table_size;
     unsigned int order;
     void *buffer;
+    uint32_t type;
 
+    type = GITS_BASER_TYPE(regc);
     attr  = gicv3_its_get_shareability() << GITS_BASER_SHAREABILITY_SHIFT;
     attr |= GIC_BASER_CACHE_SameAsInner << GITS_BASER_OUTER_CACHEABILITY_SHIFT;
     attr |= gicv3_its_get_cacheability() << 
GITS_BASER_INNER_CACHEABILITY_SHIFT;
@@ -479,6 +495,11 @@ retry:
     writeq_relaxed(reg, basereg);
     regc = readq_relaxed(basereg);
 
+    baser->val = regc;
+    baser->base = buffer;
+    baser->table_size = table_size;
+    baser->pagesz = page_size[pagesz];
+
     /* The host didn't like our attributes, just use what it returned. */
     if ( (regc & BASER_ATTR_MASK) != attr )
     {
@@ -490,7 +511,7 @@ retry:
         }
         attr = regc & BASER_ATTR_MASK;
     }
-    if ( (regc & GITS_BASER_INNER_CACHEABILITY_MASK) <= GIC_BASER_CACHE_nC )
+    if ( gicv3_its_get_cacheability() <= GIC_BASER_CACHE_nC )
         clean_and_invalidate_dcache_va_range(buffer, table_size);
 
     /* If the host accepted our page size, we are done. */
@@ -568,26 +589,27 @@ static int gicv3_its_init_single_its(struct host_its 
*hw_its)
     {
         void __iomem *basereg = hw_its->its_base + GITS_BASER0 + i * 8;
         unsigned int type;
+        struct its_baser *baser = hw_its->tables + i;
 
         reg = readq_relaxed(basereg);
-        type = (reg & GITS_BASER_TYPE_MASK) >> GITS_BASER_TYPE_SHIFT;
+        type = GITS_BASER_TYPE(reg);
         switch ( type )
         {
         case GITS_BASER_TYPE_NONE:
             continue;
         case GITS_BASER_TYPE_DEVICE:
-            ret = its_map_baser(basereg, reg, BIT(hw_its->devid_bits, UL));
+            ret = its_map_baser(basereg, reg, BIT(hw_its->devid_bits, UL), 
baser);
             if ( ret )
                 return ret;
             break;
         case GITS_BASER_TYPE_COLLECTION:
-            ret = its_map_baser(basereg, reg, num_possible_cpus());
+            ret = its_map_baser(basereg, reg, num_possible_cpus(), baser);
             if ( ret )
                 return ret;
             break;
         /* In case this is a GICv4, provide a (dummy) vPE table as well. */
         case GITS_BASER_TYPE_VCPU:
-            ret = its_map_baser(basereg, reg, 1);
+            ret = its_map_baser(basereg, reg, 32, baser);
             if ( ret )
                 return ret;
             break;
diff --git a/xen/arch/arm/include/asm/gic_v3_its.h 
b/xen/arch/arm/include/asm/gic_v3_its.h
index 973ca6acdd..bd2696f354 100644
--- a/xen/arch/arm/include/asm/gic_v3_its.h
+++ b/xen/arch/arm/include/asm/gic_v3_its.h
@@ -64,6 +64,7 @@
 #define GITS_BASER_INNER_CACHEABILITY_SHIFT        59
 #define GITS_BASER_TYPE_SHIFT           56
 #define GITS_BASER_TYPE_MASK            (7ULL << GITS_BASER_TYPE_SHIFT)
+#define GITS_BASER_TYPE(reg)            ((reg & GITS_BASER_TYPE_MASK) >> 
GITS_BASER_TYPE_SHIFT)
 #define GITS_BASER_OUTER_CACHEABILITY_SHIFT        53
 #define GITS_BASER_TYPE_NONE            0UL
 #define GITS_BASER_TYPE_DEVICE          1UL
@@ -143,6 +144,17 @@ struct its_device {
 #endif
 };
 
+/*
+ * The ITS_BASER structure - contains memory information, cached
+ * value of BASER register configuration.
+ */
+struct its_baser {
+    void            *base;
+    uint64_t        val;
+    unsigned int    table_size;
+    unsigned int    pagesz;
+};
+
 /* data structure for each hardware ITS */
 struct host_its {
     struct list_head entry;
@@ -156,6 +168,7 @@ struct host_its {
     spinlock_t cmd_lock;
     void *cmd_buf;
     unsigned int flags;
+    struct its_baser tables[GITS_BASER_NR_REGS];
 };
 
 /* Map a collection for this host CPU to each host ITS. */
@@ -259,6 +272,7 @@ struct pending_irq *gicv3_assign_guest_event(struct domain 
*d,
                                              uint32_t virt_lpi);
 void gicv3_lpi_update_host_entry(uint32_t host_lpi, int domain_id,
                                  uint32_t virt_lpi);
+struct its_baser *its_get_baser(struct host_its *hw_its, uint32_t type);
 void lpi_write_config(uint8_t *prop_table, uint32_t lpi, uint8_t clr,
                       uint8_t set);
 int its_send_command(struct host_its *hw_its, const void *its_cmd);
-- 
2.51.2

Reply via email to