[PATCH] gic: increase the arch_timer priority to avoid hardlockup
Yifan Wu
wuyifan50 at huawei.com
Wed Oct 15 20:47:33 PDT 2025
From: Qinxin Xia <xiaqinxin at huawei.com>
----------------------------------------------------------------------
On HIP12, when GIC receives multiple interrupts of the same priority and
different types, the interrupts are selected in the following sequence:
SPI > LPI > SGI > PPI. This scheduling rule may cause PPI starvation.
To prevent starvation from triggering system watchdog hardlockup, the
interrupt priority is explicitly increased in the arch_timer driver.
Signed-off-by: Qinxin Xia <xiaqinxin at huawei.com>
Signed-off-by: Hongye Lin <linhongye at h-partners.com>
Signed-off-by: Yifan Wu <wuyifan50 at huawei.com>
---
Documentation/arch/arm64/silicon-errata.rst | 2 +
arch/arm64/Kconfig | 11 ++++++
drivers/clocksource/arm_arch_timer.c | 44 +++++++++++++++++++++
drivers/irqchip/irq-gic-v3.c | 7 +++-
include/linux/irqchip/arm-gic-v3.h | 3 ++
5 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index a7ec57060f64..6e6d5c953c99 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -266,6 +266,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_162100801 |
+----------------+-----------------+-----------------+-----------------------------+
+| Hisilicon | Hip12 | #165010801 | HISILICON_ERRATUM_165010801 |
++----------------+-----------------+-----------------+-----------------------------+
+----------------+-----------------+-----------------+-----------------------------+
| Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
+----------------+-----------------+-----------------+-----------------------------+
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6663ffd23f25..ec75dc0cf14d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1273,6 +1273,17 @@ config HISILICON_ERRATUM_162100801
If unsure, say Y.
+config HISILICON_ERRATUM_165010801
+ bool "Hisilicon erratum 165010801"
+ depends on ARCH_HISI
+ default y
+ help
+ On HIP12, when GIC receives multiple interrupts of the same priority and
+ different types, the interrupts are selected in the following sequence:
+ SPI > LPI > SGI > PPI. This scheduling rule may cause PPI starvation.
+ To prevent starvation from triggering system watchdog hardlockup, the
+ interrupt priority is explicitly increased in the arch_timer driver.
+
config QCOM_FALKOR_ERRATUM_1003
bool "Falkor E1003: Incorrect translation due to ASID change"
default y
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 90aeff44a276..834b904b460c 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -29,6 +29,11 @@
#include <linux/arm-smccc.h>
#include <linux/ptp_kvm.h>
+#ifdef CONFIG_HISILICON_ERRATUM_165010801
+#include <linux/irqchip/arm-gic-common.h>
+#include <linux/irqchip/arm-gic-v3.h>
+#endif
+
#include <asm/arch_timer.h>
#include <asm/virt.h>
@@ -61,6 +66,9 @@ static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_ARCHTIMER;
#else
static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_NONE;
#endif /* CONFIG_GENERIC_GETTIMEOFDAY */
+#ifdef CONFIG_HISILICON_ERRATUM_165010801
+static bool prio_setup;
+#endif
static cpumask_t evtstrm_available = CPU_MASK_NONE;
static bool evtstrm_enable __ro_after_init = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
@@ -254,6 +262,17 @@ static const struct ate_acpi_oem_info hisi_161010101_oem_info[] = {
};
#endif
+#ifdef CONFIG_HISILICON_ERRATUM_165010801
+static struct ate_acpi_oem_info hisi_165010801_oem_info[] = {
+ {
+ .oem_id = "HISI ",
+ .oem_table_id = "HIP12 ",
+ .oem_revision = 0,
+ },
+ { /* Sentinel indicating the end of the OEM array */ },
+};
+#endif
+
#ifdef CONFIG_ARM64_ERRATUM_858921
static u64 notrace arm64_858921_read_cntpct_el0(void)
{
@@ -384,6 +403,13 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = {
.set_next_event_virt = erratum_set_next_event_virt,
},
#endif
+#ifdef CONFIG_HISILICON_ERRATUM_165010801
+ {
+ .match_type = ate_match_acpi_oem_info,
+ .id = hisi_165010801_oem_info,
+ .desc = "HiSilicon erratum 165010801",
+ },
+#endif
#ifdef CONFIG_ARM64_ERRATUM_858921
{
.match_type = ate_match_local_cap_id,
@@ -491,6 +517,12 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa
if (wa->read_cntvct_el0 || wa->read_cntpct_el0)
atomic_set(&timer_unstable_counter_workaround_in_use, 1);
+#ifdef CONFIG_HISILICON_ERRATUM_165010801
+ if (!strncmp(wa->desc, "HiSilicon erratum 165010801",
+ strlen("HiSilicon erratum 165010801")))
+ prio_setup = true;
+#endif
+
/*
* Don't use the vdso fastpath if errata require using the
* out-of-line counter accessor. We may change our mind pretty
@@ -830,6 +862,18 @@ static int arch_timer_starting_cpu(unsigned int cpu)
__arch_timer_setup(clk);
+#ifdef CONFIG_HISILICON_ERRATUM_165010801
+ if (prio_setup && is_kernel_in_hyp_mode()) {
+ struct irq_data *d = irq_get_irq_data(arch_timer_ppi[arch_timer_uses_ppi]);
+
+ if (!d)
+ pr_warn("WARNING: Invalid arch_timer ppi irq: %d!\n",
+ arch_timer_ppi[arch_timer_uses_ppi]);
+ else
+ gic_irq_set_prio(d, GICD_INT_DEF_PRI & (GICD_INT_DEF_PRI - 1));
+ }
+#endif
+
flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]);
enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags);
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 3de351e66ee8..11f737328857 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -584,7 +584,12 @@ static int gic_irq_get_irqchip_state(struct irq_data *d,
return 0;
}
-static void gic_irq_set_prio(struct irq_data *d, u8 prio)
+#ifndef CONFIG_HISILICON_ERRATUM_165010801
+static void
+#else
+void
+#endif
+gic_irq_set_prio(struct irq_data *d, u8 prio)
{
void __iomem *base = gic_dist_base(d);
u32 offset, index;
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 70c0948f978e..1c5ed36fcaf7 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -656,6 +656,9 @@ static inline bool gic_enable_sre(void)
return !!(val & ICC_SRE_EL1_SRE);
}
+#ifdef CONFIG_HISILICON_ERRATUM_165010801
+void gic_irq_set_prio(struct irq_data *d, u8 prio);
+#endif
#endif
#endif
--
2.33.0
More information about the linux-arm-kernel
mailing list