Hi Volodymyr, Thank you for your close review.
On 21.08.25 19:16, Volodymyr Babchuk wrote: > > 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? > No, there is no particular reason to use open-code here. It is just a copy-paste from the code for regular SPI initialization. Thus, I agree it is much better to use GENMASK(31, 0). I will change this in V3. >> + } >> + >> + 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? > Yes, I will revise all patches in the series with such long lines and fix them in V3. >> +#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) > > I double checked - it seems like everything is correct - the typer parameter should be surrounded by parentheses, and GICD_TYPER_ESPI_RANGE should operate with the already shifted value. However, I wrote a slightly confusing macro. At the very least, it would be better to rename in V3 the typer parameter in GICD_TYPER_ESPI_RANGE, because it takes the value of GICD_TYPER that is already shifted by 27, instead of the raw register value. Would that be acceptable? >> +#endif >> + >> /* Common between GICD_PIDR2 and GICR_PIDR2 */ >> #define GIC_PIDR2_ARCH_MASK (0xf0) >> #define GIC_PIDR2_ARCH_GICv3 (0x30) > Best regards, Leonid