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
