[PATCH v2] irqchip/gic-v3: init SRE before poking sysregs
Mark Rutland
mark.rutland at arm.com
Thu Aug 22 03:23:08 PDT 2024
The GICv3 driver pokes GICv3 system registers in gic_prio_init() before
gic_cpu_sys_reg_init() ensures that GICv3 system registers have been
enabled by writing to ICC_SRE_EL1.SRE. On arm64 this is benign as
has_useable_gicv3_cpuif() runs earlier during cpufeature detection, and
this enables the GICv3 system registers. On 32-bit arm we're not so
lucky, and when booting on an FVP using the boot-wrapper, the accesses
in gic_prio_init() end up being UNDEFINED and crash the kernel during
boot.
This is a regression introduced by commit:
d447bf09a4013541 ("irqchip/gic-v3: Detect GICD_CTRL.DS and SCR_EL3.FIQ earlier")
... which added gic_prio_init().
Fix this by factoring out the SRE initialization into a new
gic_cpu_sys_reg_enable(),, and calling this early in the three paths
where SRE may not have been initialized:
(1) gic_init_bases(), before the primary CPU pokes GICv3 sysregs in
gic_prio_init().
(2) gic_starting_cpu(), before secondary CPUs initialize GICv3 sysregs
in gic_cpu_init().
(3) gic_cpu_pm_notifier(), before CPUs re-initialize GICv3 sysregs in
gic_cpu_sys_reg_init().
Fixes: d447bf09a4013541 ("irqchip/gic-v3: Detect GICD_CTRL.DS and SCR_EL3.FIQ earlier")
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reviewed-by: Marc Zyngier <maz at kernel.org>
Cc: Alexandru Elisei <alexandru.elisei at arm.com>
Cc: Andre Przywara <andre.przywara at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Will Deacon <will at kernel.org>
---
drivers/irqchip/irq-gic-v3.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
Since v1 [1]:
* Simplify and cleanup commit message
* Rename gic_sre_init() => gic_cpu_sys_reg_enable()
[1] https://lore.kernel.org/linux-arm-kernel/20240820155506.100164-1-mark.rutland@arm.com
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index c19083bfb9432..74f21e03d4a37 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1154,14 +1154,8 @@ static void gic_update_rdist_properties(void)
gic_data.rdists.has_vpend_valid_dirty ? "Valid+Dirty " : "");
}
-static void gic_cpu_sys_reg_init(void)
+static void gic_cpu_sys_reg_enable(void)
{
- int i, cpu = smp_processor_id();
- u64 mpidr = gic_cpu_to_affinity(cpu);
- u64 need_rss = MPIDR_RS(mpidr);
- bool group0;
- u32 pribits;
-
/*
* Need to check that the SRE bit has actually been set. If
* not, it means that SRE is disabled at EL2. We're going to
@@ -1172,6 +1166,16 @@ static void gic_cpu_sys_reg_init(void)
if (!gic_enable_sre())
pr_err("GIC: unable to set SRE (disabled at EL2), panic ahead\n");
+}
+
+static void gic_cpu_sys_reg_init(void)
+{
+ int i, cpu = smp_processor_id();
+ u64 mpidr = gic_cpu_to_affinity(cpu);
+ u64 need_rss = MPIDR_RS(mpidr);
+ bool group0;
+ u32 pribits;
+
pribits = gic_get_pribits();
group0 = gic_has_group0();
@@ -1333,6 +1337,7 @@ static int gic_check_rdist(unsigned int cpu)
static int gic_starting_cpu(unsigned int cpu)
{
+ gic_cpu_sys_reg_enable();
gic_cpu_init();
if (gic_dist_supports_lpis())
@@ -1498,6 +1503,7 @@ static int gic_cpu_pm_notifier(struct notifier_block *self,
if (cmd == CPU_PM_EXIT) {
if (gic_dist_security_disabled())
gic_enable_redist(true);
+ gic_cpu_sys_reg_enable();
gic_cpu_sys_reg_init();
} else if (cmd == CPU_PM_ENTER && gic_dist_security_disabled()) {
gic_write_grpen1(0);
@@ -2070,6 +2076,7 @@ static int __init gic_init_bases(phys_addr_t dist_phys_base,
gic_update_rdist_properties();
+ gic_cpu_sys_reg_enable();
gic_prio_init();
gic_dist_init();
gic_cpu_init();
--
2.30.2
More information about the linux-arm-kernel
mailing list