Hi,
Leonid Komarianskyi <leonid_komarians...@epam.com> writes: > Introduced appropriate register definitions, helper macros, > and initialization of required GICv3.1 distributor registers > to support eSPI. This type of interrupt is handled in the > same way as regular SPI interrupts, with the following > differences: > > 1) eSPIs can have up to 1024 interrupts, starting from the > beginning of the range, whereas regular SPIs use INTIDs from > 32 to 1019, totaling 988 interrupts; > 2) eSPIs start at INTID 4096, necessitating additional interrupt > index conversion during register operations. > > In case if appropriate config is disabled, or GIC HW doesn't > support eSPI, the existing functionality will remain the same. > > Signed-off-by: Leonid Komarianskyi <leonid_komarians...@epam.com> > > --- > Changes in V2: > - move gic_number_espis function from > [PATCH 08/10] xen/arm: vgic: add resource management for extended SPIs > to use it in the newly introduced gic_is_valid_espi > - add gic_is_valid_espi which checks if IRQ number is in supported > by HW eSPI range > - update gic_is_valid_irq conditions to allow operations with eSPIs > --- > xen/arch/arm/gic-v3.c | 73 ++++++++++++++++++++++++++ > xen/arch/arm/include/asm/gic.h | 17 ++++++ > xen/arch/arm/include/asm/gic_v3_defs.h | 33 ++++++++++++ > 3 files changed, 123 insertions(+) > > diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c > index 8fd78aba44..a0e8ee1a1e 100644 > --- a/xen/arch/arm/gic-v3.c > +++ b/xen/arch/arm/gic-v3.c > @@ -485,6 +485,36 @@ static void __iomem *get_addr_by_offset(struct irq_desc > *irqd, u32 offset) > default: > break; > } > +#ifdef CONFIG_GICV3_ESPI > + case ESPI_BASE_INTID ... ESPI_MAX_INTID: > + { > + u32 irq_index = ESPI_INTID2IDX(irqd->irq); > + > + switch ( offset ) > + { > + case GICD_ISENABLER: > + return (GICD + GICD_ISENABLERnE + (irq_index / 32) * 4); > + case GICD_ICENABLER: > + return (GICD + GICD_ICENABLERnE + (irq_index / 32) * 4); > + case GICD_ISPENDR: > + return (GICD + GICD_ISPENDRnE + (irq_index / 32) * 4); > + case GICD_ICPENDR: > + return (GICD + GICD_ICPENDRnE + (irq_index / 32) * 4); > + case GICD_ISACTIVER: > + return (GICD + GICD_ISACTIVERnE + (irq_index / 32) * 4); > + case GICD_ICACTIVER: > + return (GICD + GICD_ICACTIVERnE + (irq_index / 32) * 4); > + case GICD_ICFGR: > + return (GICD + GICD_ICFGRnE + (irq_index / 16) * 4); > + case GICD_IROUTER: > + return (GICD + GICD_IROUTERnE + irq_index * 8); > + case GICD_IPRIORITYR: > + return (GICD + GICD_IPRIORITYRnE + irq_index); > + default: > + break; > + } > + } > +#endif > default: > break; > } > @@ -645,6 +675,40 @@ static void gicv3_set_irq_priority(struct irq_desc *desc, > spin_unlock(&gicv3.lock); > } > > +#ifdef CONFIG_GICV3_ESPI > +unsigned int gic_number_espis(void) > +{ > + return gic_hw_ops->info->nr_espi; > +} > + > +static void gicv3_dist_espi_common_init(uint32_t type) > +{ > + unsigned int espi_nr; > + int i; > + > + espi_nr = min(1024U, GICD_TYPER_ESPIS_NUM(type)); > + gicv3_info.nr_espi = espi_nr; > + /* The GIC HW doesn't support eSPI, so we can leave from here */ > + if ( gicv3_info.nr_espi == 0 ) > + return; > + > + for ( i = 0; i < espi_nr; i += 16 ) > + writel_relaxed(0, GICD + GICD_ICFGRnE + (i / 16) * 4); > + > + for ( i = 0; i < espi_nr; i += 4 ) > + writel_relaxed(GIC_PRI_IRQ_ALL, GICD + GICD_IPRIORITYRnE + (i / 4) * > 4); > + > + for ( i = 0; i < espi_nr; i += 32 ) > + { > + writel_relaxed(0xffffffffU, GICD + GICD_ICENABLERnE + (i / 32) * 4); Is there are particular reason why you use GENMASK(31,0) below, but open-coded 0xffffffff here? > + writel_relaxed(0xffffffffU, GICD + GICD_ICACTIVERnE + (i / 32) * 4); ... and here? > + } > + > + for ( i = 0; i < espi_nr; i += 32 ) > + writel_relaxed(GENMASK(31, 0), GICD + GICD_IGROUPRnE + (i / 32) * 4); > +} > +#endif > + > static void __init gicv3_dist_init(void) > { > uint32_t type; > @@ -690,6 +754,10 @@ static void __init gicv3_dist_init(void) > for ( i = NR_GIC_LOCAL_IRQS; i < nr_lines; i += 32 ) > writel_relaxed(GENMASK(31, 0), GICD + GICD_IGROUPR + (i / 32) * 4); > > +#ifdef CONFIG_GICV3_ESPI > + gicv3_dist_espi_common_init(type); > +#endif > + > gicv3_dist_wait_for_rwp(); > > /* Turn on the distributor */ > @@ -703,6 +771,11 @@ static void __init gicv3_dist_init(void) > > for ( i = NR_GIC_LOCAL_IRQS; i < nr_lines; i++ ) > writeq_relaxed_non_atomic(affinity, GICD + GICD_IROUTER + i * 8); > + > +#ifdef CONFIG_GICV3_ESPI > + for ( i = 0; i < gicv3_info.nr_espi; i++ ) > + writeq_relaxed_non_atomic(affinity, GICD + GICD_IROUTERnE + i * 8); > +#endif > } > > static int gicv3_enable_redist(void) > diff --git a/xen/arch/arm/include/asm/gic.h b/xen/arch/arm/include/asm/gic.h > index ac0b7b783e..2f570abf70 100644 > --- a/xen/arch/arm/include/asm/gic.h > +++ b/xen/arch/arm/include/asm/gic.h > @@ -306,8 +306,21 @@ extern void gic_dump_vgic_info(struct vcpu *v); > > /* Number of interrupt lines */ > extern unsigned int gic_number_lines(void); > +#ifdef CONFIG_GICV3_ESPI > +extern unsigned int gic_number_espis(void); > + > +static inline bool gic_is_valid_espi(unsigned int irq) > +{ > + return (irq >= ESPI_BASE_INTID && irq < > ESPI_IDX2INTID(gic_number_espis())); > +} > +#endif > + > static inline bool gic_is_valid_irq(unsigned int irq) > { > +#ifdef CONFIG_GICV3_ESPI > + if ( gic_is_valid_espi(irq) ) > + return true; > +#endif > return irq < gic_number_lines(); > } > > @@ -325,6 +338,10 @@ struct gic_info { > enum gic_version hw_version; > /* Number of GIC lines supported */ > unsigned int nr_lines; > +#ifdef CONFIG_GICV3_ESPI > + /* Number of GIC eSPI supported */ > + unsigned int nr_espi; > +#endif > /* Number of LR registers */ > uint8_t nr_lrs; > /* Maintenance irq number */ > diff --git a/xen/arch/arm/include/asm/gic_v3_defs.h > b/xen/arch/arm/include/asm/gic_v3_defs.h > index 2af093e774..7f769b38e3 100644 > --- a/xen/arch/arm/include/asm/gic_v3_defs.h > +++ b/xen/arch/arm/include/asm/gic_v3_defs.h > @@ -37,6 +37,39 @@ > #define GICD_IROUTER1019 (0x7FD8) > #define GICD_PIDR2 (0xFFE8) > > +#ifdef CONFIG_GICV3_ESPI > +/* Additional registers for GICv3.1 */ > +#define GICD_IGROUPRnE (0x1000) > +#define GICD_IGROUPRnEN (0x107C) > +#define GICD_ISENABLERnE (0x1200) > +#define GICD_ISENABLERnEN (0x127C) > +#define GICD_ICENABLERnE (0x1400) > +#define GICD_ICENABLERnEN (0x147C) > +#define GICD_ISPENDRnE (0x1600) > +#define GICD_ISPENDRnEN (0x167C) > +#define GICD_ICPENDRnE (0x1800) > +#define GICD_ICPENDRnEN (0x187C) > +#define GICD_ISACTIVERnE (0x1A00) > +#define GICD_ISACTIVERnEN (0x1A7C) > +#define GICD_ICACTIVERnE (0x1C00) > +#define GICD_ICACTIVERnEN (0x1C7C) > +#define GICD_IPRIORITYRnE (0x2000) > +#define GICD_IPRIORITYRnEN (0x23FC) > +#define GICD_ICFGRnE (0x3000) > +#define GICD_ICFGRnEN (0x30FC) > +#define GICD_IROUTERnE (0x8000) > +#define GICD_IROUTERnEN (0x9FFC) > + > +#define GICD_TYPER_ESPI_SHIFT 8 > +#define GICD_TYPER_ESPI_RANGE_SHIFT 27 > +#define GICD_TYPER_ESPI_RANGE_MASK (0x1F) > +#define GICD_TYPER_ESPI (1U << GICD_TYPER_ESPI_SHIFT) > +#define GICD_TYPER_ESPI_RANGE(typer) ((((typer) & > GICD_TYPER_ESPI_RANGE_MASK) + 1) * 32) Isn't this line a bit long? > +#define GICD_TYPER_ESPIS_NUM(typer) \ > + (((typer) & GICD_TYPER_ESPI) ? \ > + GICD_TYPER_ESPI_RANGE((typer) >> GICD_TYPER_ESPI_RANGE_SHIFT) : 0) I am not sure that this is correct. Probably you wanted to write + GICD_TYPER_ESPI_RANGE((typer >> GICD_TYPER_ESPI_RANGE_SHIFT)) : 0) > +#endif > + > /* Common between GICD_PIDR2 and GICR_PIDR2 */ > #define GIC_PIDR2_ARCH_MASK (0xf0) > #define GIC_PIDR2_ARCH_GICv3 (0x30) -- WBR, Volodymyr