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

Reply via email to