The following commit has been merged into the irq/core branch of tip:
Commit-ID: d1cb1437b785f312d63f447e2e79ff768e7ccc29
Gitweb: https://git.kernel.org/tip/d1cb1437b785f312d63f447e2e79ff768e7ccc29
Author: Gregory CLEMENT <gregory.clement@bootlin.com>
AuthorDate: Mon, 28 Oct 2024 18:59:35 +01:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 30 Oct 2024 15:41:32 +01:00
irqchip/mips-gic: Prevent indirect access to clusters without CPU cores
It is possible to have zero CPU cores in a cluster; in such cases, it is
not possible to access the GIC, and any indirect access leads to an
exception.
Prevent access to such clusters by checking the number of cores in the
cluster at all places which issue indirect cluster access.
Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20241028175935.51250-14-arikalo@gmail.com
---
drivers/irqchip/irq-mips-gic.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index f42f69b..bca8053 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -141,7 +141,8 @@ static bool gic_irq_lock_cluster(struct irq_data *d)
cl = cpu_cluster(&cpu_data[cpu]);
if (cl == cpu_cluster(¤t_cpu_data))
return false;
-
+ if (mips_cps_numcores(cl) == 0)
+ return false;
mips_cm_lock_other(cl, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL);
return true;
}
@@ -507,6 +508,9 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d)
struct gic_all_vpes_chip_data *cd;
int intr, cpu;
+ if (!mips_cps_multicluster_cpus())
+ return;
+
intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
cd = irq_data_get_irq_chip_data(d);
cd->mask = false;
@@ -520,6 +524,9 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
struct gic_all_vpes_chip_data *cd;
int intr, cpu;
+ if (!mips_cps_multicluster_cpus())
+ return;
+
intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
cd = irq_data_get_irq_chip_data(d);
cd->mask = true;
@@ -687,8 +694,10 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
if (!gic_local_irq_is_routable(intr))
return -EPERM;
- for_each_online_cpu_gic(cpu, &gic_lock)
- write_gic_vo_map(mips_gic_vx_map_reg(intr), map);
+ if (mips_cps_multicluster_cpus()) {
+ for_each_online_cpu_gic(cpu, &gic_lock)
+ write_gic_vo_map(mips_gic_vx_map_reg(intr), map);
+ }
return 0;
}
@@ -982,7 +991,7 @@ static int __init gic_of_init(struct device_node *node,
change_gic_trig(i, GIC_TRIG_LEVEL);
write_gic_rmask(i);
}
- } else {
+ } else if (mips_cps_numcores(cl) != 0) {
mips_cm_lock_other(cl, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL);
for (i = 0; i < gic_shared_intrs; i++) {
change_gic_redir_pol(i, GIC_POL_ACTIVE_HIGH);
@@ -990,6 +999,9 @@ static int __init gic_of_init(struct device_node *node,
write_gic_redir_rmask(i);
}
mips_cm_unlock_other();
+
+ } else {
+ pr_warn("No CPU cores on the cluster %d skip it\n", cl);
}
}