Add a helper to write LPI configuration entries. Expose lpi_data structure in the header to be used in said helper.
Signed-off-by: Mykyta Poturai <[email protected]> --- xen/arch/arm/gic-v3-lpi.c | 39 +++++++++++---------------- xen/arch/arm/include/asm/gic_v3_its.h | 27 +++++++++++++++++++ 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c index de5052e5cf..c029d5d7a4 100644 --- a/xen/arch/arm/gic-v3-lpi.c +++ b/xen/arch/arm/gic-v3-lpi.c @@ -46,29 +46,7 @@ union host_lpi { #define LPI_PROPTABLE_NEEDS_FLUSHING (1U << 0) /* Global state */ -static struct { - /* The global LPI property table, shared by all redistributors. */ - uint8_t *lpi_property; - /* - * A two-level table to lookup LPIs firing on the host and look up the - * VCPU and virtual LPI number to inject into. - */ - union host_lpi **host_lpis; - /* - * Number of physical LPIs the host supports. This is a property of - * the GIC hardware. We depart from the habit of naming these things - * "physical" in Xen, as the GICv3/4 spec uses the term "physical LPI" - * in a different context to differentiate them from "virtual LPIs". - */ - unsigned long int max_host_lpi_ids; - /* - * Protects allocation and deallocation of host LPIs and next_free_lpi, - * but not the actual data stored in the host_lpi entry. - */ - spinlock_t host_lpis_lock; - uint32_t next_free_lpi; - unsigned int flags; -} lpi_data; +struct __lpi_data lpi_data; struct lpi_redist_data { paddr_t redist_addr; @@ -492,6 +470,21 @@ static int find_unused_host_lpi(uint32_t start, uint32_t *index) return -1; } +void lpi_write_config(uint8_t *prop_table, uint32_t lpi, uint8_t clr, + uint8_t set) +{ + u8 *cfg; + + cfg = prop_table + lpi - LPI_OFFSET; + *cfg &= ~clr; + *cfg |= set | LPI_PROP_RES1; + + /* Make the above write visible to the redistributors. */ + if ( lpi_data.flags & LPI_PROPTABLE_NEEDS_FLUSHING ) { + clean_and_invalidate_dcache_va_range(cfg, sizeof(*cfg)); + } +} + /* * Allocate a block of 32 LPIs on the given host ITS for device "devid", * starting with "eventid". Put them into the respective ITT by issuing a diff --git a/xen/arch/arm/include/asm/gic_v3_its.h b/xen/arch/arm/include/asm/gic_v3_its.h index aa54e9a364..9f0ea9ccb1 100644 --- a/xen/arch/arm/include/asm/gic_v3_its.h +++ b/xen/arch/arm/include/asm/gic_v3_its.h @@ -157,6 +157,31 @@ int gicv3_its_setup_collection(unsigned int cpu); #ifdef CONFIG_HAS_ITS +struct __lpi_data { + /* The global LPI property table, shared by all redistributors. */ + uint8_t *lpi_property; + /* + * A two-level table to lookup LPIs firing on the host and look up the + * VCPU and virtual LPI number to inject into. + */ + union host_lpi **host_lpis; + /* + * Number of physical LPIs the host supports. This is a property of + * the GIC hardware. We depart from the habit of naming these things + * "physical" in Xen, as the GICv3/4 spec uses the term "physical LPI" + * in a different context to differentiate them from "virtual LPIs". + */ + unsigned long int max_host_lpi_ids; + /* + * Protects allocation and deallocation of host LPIs and next_free_lpi, + * but not the actual data stored in the host_lpi entry. + */ + spinlock_t host_lpis_lock; + uint32_t next_free_lpi; + unsigned int flags; +}; +extern struct __lpi_data lpi_data; + extern struct list_head host_its_list; int its_send_cmd_inv(struct host_its *its, uint32_t deviceid, uint32_t eventid); @@ -223,6 +248,8 @@ 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); +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); struct its_device *get_its_device(struct domain *d, paddr_t vdoorbell, -- 2.51.2
