|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2] xen/arm: gic-v2: disable interrupt bypass on CPU shutdown
On 28-Apr-26 13:57, Mykola Kvach wrote:
> From: Mykola Kvach <mykola_kvach@xxxxxxxx>
>
> The GICv2 CPU shutdown path currently writes 0 to GICC_CTLR.
>
> Per IHI0048B.b section 2.3.1, clearing the architected bypass-disable
> bits selects bypass rather than deasserted interrupt outputs when the
> CPU interface stops driving them. Tables 2-2 and 2-3 show that a zeroed
> GICC_CTLR can fall back to the legacy IRQ/FIQ inputs instead of fully
> disabling the interface.
>
> Fix this by reading GICC_CTLR, then setting the bypass-disable bits and
> clearing the group-enable bits that are architecturally defined for the
> current GICC_CTLR view before writing the value back. When Security
> Extensions are implemented Xen accesses the Non-secure copy of
> GICC_CTLR, where IRQBypDisGrp1 and FIQBypDisGrp1 are at bits [6:5] and
> bits [8:7] are reserved.
>
> Without Security Extensions there is no separate Secure/Non-secure CPU
> interface view, so disabling both group-enable bits affects the shared
> interface state. This is still appropriate for the CPU shutdown path,
> which is expected to stop normal interrupt delivery through the interface
> and rely only on the architecturally separate wakeup event signaling.
>
> Section 2.3.2 also states that wakeup event signals remain available
> even when both GIC interrupt signaling and interrupt bypass are
> disabled, so disabling bypass does not break the power-management use
> case, i.e. suspend modes.
>
> Fixes: 5e40a1b4351e ("arm: SMP CPU shutdown")
> Signed-off-by: Mykola Kvach <mykola_kvach@xxxxxxxx>
>
> ---
> Changes in v2:
> - derive the shutdown masks from the active GICC_CTLR layout
> - use the Non-secure GICC_CTLR layout when GICD_TYPER.SecurityExtn is set
> - stop writing reserved bits [8:7] on Security Extensions systems
> ---
> xen/arch/arm/gic-v2.c | 16 +++++++++++++++-
> xen/arch/arm/include/asm/gic.h | 25 +++++++++++++++++++++++--
> 2 files changed, 38 insertions(+), 3 deletions(-)
>
> diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
> index 014f955967..241c1ff5c5 100644
> --- a/xen/arch/arm/gic-v2.c
> +++ b/xen/arch/arm/gic-v2.c
> @@ -408,7 +408,21 @@ static void gicv2_cpu_init(void)
>
> static void gicv2_cpu_disable(void)
> {
> - writel_gicc(0x0, GICC_CTLR);
> + uint32_t ctlr = readl_gicc(GICC_CTLR);
> +
> + if ( readl_gicd(GICD_TYPER) & GICD_TYPE_SEC )
> + {
> + ctlr |= GICC_NS_CTLR_BYPASS_DISABLE_GRP1_MASK;
> + ctlr &= ~GICC_CTL_ENABLE;
> + }
> + else
> + {
> + ctlr |= GICC_CTLR_BYPASS_DISABLE_GRP0_MASK |
> + GICC_CTLR_BYPASS_DISABLE_GRP1_MASK;
> + ctlr &= ~(GICC_CTL_ENABLE | GICC_CTL_ENABLE_GRP1);
> + }
I don't understand why you want to set both G0 and G1,
Bits 5-6 in the NS view control Group 1, while the same bits in the
Secure/single-security-state view control Group 0. So in the latter case you
don't need to set G1. Without security extensions all interrupts are G0 and with
security extensions (NS access) all interrupts are G1. The spec guarantees the
functional mapping.
~Michal
> +
> + writel_gicc(ctlr, GICC_CTLR);
> }
>
> static void gicv2_hyp_init(void)
> diff --git a/xen/arch/arm/include/asm/gic.h b/xen/arch/arm/include/asm/gic.h
> index 8e713aa477..ff22dea40d 100644
> --- a/xen/arch/arm/include/asm/gic.h
> +++ b/xen/arch/arm/include/asm/gic.h
> @@ -102,8 +102,29 @@
> #define GICD_TYPE_SEC 0x400
> #define GICD_TYPER_DVIS (1U << 18)
>
> -#define GICC_CTL_ENABLE 0x1
> -#define GICC_CTL_EOI (0x1 << 9)
> +/*
> + * Xen runs in the Non-secure world. When Security Extensions are present,
> + * Xen accesses the Non-secure GICC_CTLR view, where bit[0] is EnableGrp1
> + * and bits[6:5] are the Group 1 bypass-disable bits. Otherwise Xen sees the
> + * common GICC_CTLR layout, where bit[0] is EnableGrp0, bit[1] is EnableGrp1,
> + * bits[6:5] are the Group 0 bypass-disable bits, and bits[8:7] are the
> + * Group 1 bypass-disable bits.
> + */
> +#define GICC_CTL_ENABLE (0x1 << 0)
> +#define GICC_CTL_ENABLE_GRP1 (0x1 << 1)
> +#define GICC_CTL_FIQBypDisGrp0 (0x1 << 5)
> +#define GICC_CTL_IRQBypDisGrp0 (0x1 << 6)
> +#define GICC_CTL_FIQBypDisGrp1 (0x1 << 7)
> +#define GICC_CTL_IRQBypDisGrp1 (0x1 << 8)
> +
> +#define GICC_CTLR_BYPASS_DISABLE_GRP0_MASK \
> + (GICC_CTL_FIQBypDisGrp0 | GICC_CTL_IRQBypDisGrp0)
> +#define GICC_CTLR_BYPASS_DISABLE_GRP1_MASK \
> + (GICC_CTL_FIQBypDisGrp1 | GICC_CTL_IRQBypDisGrp1)
> +#define GICC_NS_CTLR_BYPASS_DISABLE_GRP1_MASK \
> + GICC_CTLR_BYPASS_DISABLE_GRP0_MASK
> +
> +#define GICC_CTL_EOI (0x1 << 9)
>
> #define GICC_IA_IRQ 0x03ff
> #define GICC_IA_CPU_MASK 0x1c00
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |