[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] xen/arm: gic-v2: disable interrupt bypass on CPU shutdown



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 IRQBypDisGrp{0,1} and
FIQBypDisGrp{0,1} 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, setting the bypass-disable bits, and
clearing both group-enable bits before writing the value back. Keep the
existing GICC_CTL_ENABLE definition for the init path and use a separate
mask for the shutdown-side group-enable handling.

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>
---
 xen/arch/arm/gic-v2.c          |  7 ++++++-
 xen/arch/arm/include/asm/gic.h | 21 +++++++++++++++++++--
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
index b23e72a3d0..22aa25bad0 100644
--- a/xen/arch/arm/gic-v2.c
+++ b/xen/arch/arm/gic-v2.c
@@ -408,7 +408,12 @@ static void gicv2_cpu_init(void)
 
 static void gicv2_cpu_disable(void)
 {
-    writel_gicc(0x0, GICC_CTLR);
+    uint32_t ctlr = readl_gicc(GICC_CTLR);
+
+    ctlr |= GICC_CTL_BYP_DIS_MASK;
+    ctlr &= ~GICC_CTL_ENABLE_GRP_MASK;
+
+    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..da285adb83 100644
--- a/xen/arch/arm/include/asm/gic.h
+++ b/xen/arch/arm/include/asm/gic.h
@@ -102,8 +102,25 @@
 #define GICD_TYPE_SEC   0x400
 #define GICD_TYPER_DVIS (1U << 18)
 
-#define GICC_CTL_ENABLE 0x1
-#define GICC_CTL_EOI    (0x1 << 9)
+/*
+ * Keep the legacy name for bit[0]. In the Non-secure view of a GICv2 with
+ * Security Extensions this is the Group 1 enable bit; otherwise it is the
+ * Group 0.
+ */
+#define GICC_CTL_ENABLE        (0x1 << 0)
+/* Bit[1] is the second group-enable bit when separate group enables exist. */
+#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_CTL_EOI           (0x1 << 9)
+
+/* Shutdown clears both possible group-enable bits, regardless of layout. */
+#define GICC_CTL_ENABLE_GRP_MASK (GICC_CTL_ENABLE | GICC_CTL_ENABLE_GRP1)
+#define GICC_CTL_BYP_DIS_MASK                          \
+    (GICC_CTL_FIQBypDisGrp0 | GICC_CTL_IRQBypDisGrp0 | \
+     GICC_CTL_FIQBypDisGrp1 | GICC_CTL_IRQBypDisGrp1)
 
 #define GICC_IA_IRQ       0x03ff
 #define GICC_IA_CPU_MASK  0x1c00
-- 
2.43.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.