|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 05/10] xen/arm: gicv3: implement handling of GICv3.1 eSPI
Hi,
Leonid Komarianskyi <Leonid_Komarianskyi@xxxxxxxx> 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_komarianskyi@xxxxxxxx>
>
> ---
> 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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |