Keep all the info about BASER regs in host_its structure to be able to easily
access it later.
Signed-off-by: Mykyta Poturai <mykyta_poturai@epam.com>
---
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