* [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V
@ 2025-11-14 3:32 Yunhui Cui
2025-11-14 3:32 ` [PATCH v6 1/2] watchdog: move arm64 watchdog_hld into common code Yunhui Cui
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Yunhui Cui @ 2025-11-14 3:32 UTC (permalink / raw)
To: akpm, alex, anup, aou, atish.patra, catalin.marinas, cuiyunhui,
dianders, johannes, lihuafei1, mark.rutland, masahiroy, maz,
mingo, nicolas.schier, palmer, paul.walmsley, suzuki.poulose,
thorsten.blum, wangjinchao600, will, yangyicong, zhanjie9,
linux-arm-kernel, linux-kernel, linux-perf-users, linux-riscv
After discussion [1],[2], hardlockup_perf cannot be completely replaced by
the hardlockup_buddy approach, so this patch is still being submitted.
v1->v2:
The contents of arch/arm64/watchdog_hld.c are directly consolidated into
kernel/watchdog_perf.c.
v2->v3:
Add CONFIG_WATCHDOG_PERF_ADJUST_PERIOD to enclose the period update logic,
select it by default on arm64 and riscv, without affecting other arches
like x86 and PPC.
v3->v4:
Place the line "select WATCHDOG_PERF_ADJUST_PERIOD if HARDLOCKUP_DETECTOR_PERF && CPU_FREQ"
in the Kconfig files for arm64 and riscv in one line, with no line breaks.
v4->v5:
Remove __weak from hw_nmi_get_sample_period()
v5->v6:
Removed the dependency on CPU_FREQ for WATCHDOG_PERF_ADJUST_PERIOD in Kconfig, which fixes the
issue reported at: https://lore.kernel.org/oe-kbuild-all/202510240701.eB6r97V3-lkp@intel.com/
Link: https://lore.kernel.org/all/CAD=FV=UEhVCD6JehQi1wor2sSmtTLDyf=37xfo-DOTK1=u1xzA@mail.gmail.com/ [1]
Link: https://lore.kernel.org/all/20250916145122.416128-1-wangjinchao600@gmail.com/ [2]
Yunhui Cui (2):
watchdog: move arm64 watchdog_hld into common code
riscv: add HARDLOCKUP_DETECTOR_PERF support
arch/arm64/Kconfig | 1 +
arch/arm64/kernel/Makefile | 1 -
arch/arm64/kernel/watchdog_hld.c | 94 --------------------------------
arch/riscv/Kconfig | 3 +
drivers/perf/arm_pmu.c | 10 +++-
drivers/perf/riscv_pmu_sbi.c | 10 ++++
include/linux/perf/arm_pmu.h | 2 -
kernel/watchdog_perf.c | 83 ++++++++++++++++++++++++++++
lib/Kconfig.debug | 8 +++
9 files changed, 114 insertions(+), 98 deletions(-)
delete mode 100644 arch/arm64/kernel/watchdog_hld.c
--
2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v6 1/2] watchdog: move arm64 watchdog_hld into common code
2025-11-14 3:32 [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V Yunhui Cui
@ 2025-11-14 3:32 ` Yunhui Cui
2025-12-05 6:53 ` Yicong Yang
2025-11-14 3:32 ` [PATCH v6 2/2] riscv: add HARDLOCKUP_DETECTOR_PERF support Yunhui Cui
2025-11-14 19:13 ` [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V Doug Anderson
2 siblings, 1 reply; 7+ messages in thread
From: Yunhui Cui @ 2025-11-14 3:32 UTC (permalink / raw)
To: akpm, alex, anup, aou, atish.patra, catalin.marinas, cuiyunhui,
dianders, johannes, lihuafei1, mark.rutland, masahiroy, maz,
mingo, nicolas.schier, palmer, paul.walmsley, suzuki.poulose,
thorsten.blum, wangjinchao600, will, yangyicong, zhanjie9,
linux-arm-kernel, linux-kernel, linux-perf-users, linux-riscv
Move the contents of arch/arm64/watchdog_hld.c to kernel/watchdog_perf.c
to create a generic implementation that can be reused by other arch,
such as RISC-V.
Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
arch/arm64/Kconfig | 1 +
arch/arm64/kernel/Makefile | 1 -
arch/arm64/kernel/watchdog_hld.c | 94 --------------------------------
drivers/perf/arm_pmu.c | 10 +++-
include/linux/perf/arm_pmu.h | 2 -
kernel/watchdog_perf.c | 83 ++++++++++++++++++++++++++++
lib/Kconfig.debug | 8 +++
7 files changed, 101 insertions(+), 98 deletions(-)
delete mode 100644 arch/arm64/kernel/watchdog_hld.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6663ffd23f252..6614ff45b1e06 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -231,6 +231,7 @@ config ARM64
select HAVE_GCC_PLUGINS
select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \
HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI
+ select WATCHDOG_PERF_ADJUST_PERIOD if HARDLOCKUP_DETECTOR_PERF
select HAVE_HW_BREAKPOINT if PERF_EVENTS
select HAVE_IOREMAP_PROT
select HAVE_IRQ_TIME_ACCOUNTING
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 76f32e424065e..12d77f373fea4 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -44,7 +44,6 @@ obj-$(CONFIG_KUSER_HELPERS) += kuser32.o
obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
obj-$(CONFIG_MODULES) += module.o module-plts.o
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
-obj-$(CONFIG_HARDLOCKUP_DETECTOR_PERF) += watchdog_hld.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
obj-$(CONFIG_KGDB) += kgdb.o
diff --git a/arch/arm64/kernel/watchdog_hld.c b/arch/arm64/kernel/watchdog_hld.c
deleted file mode 100644
index 3093037dcb7be..0000000000000
--- a/arch/arm64/kernel/watchdog_hld.c
+++ /dev/null
@@ -1,94 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/nmi.h>
-#include <linux/cpufreq.h>
-#include <linux/perf/arm_pmu.h>
-
-/*
- * Safe maximum CPU frequency in case a particular platform doesn't implement
- * cpufreq driver. Although, architecture doesn't put any restrictions on
- * maximum frequency but 5 GHz seems to be safe maximum given the available
- * Arm CPUs in the market which are clocked much less than 5 GHz. On the other
- * hand, we can't make it much higher as it would lead to a large hard-lockup
- * detection timeout on parts which are running slower (eg. 1GHz on
- * Developerbox) and doesn't possess a cpufreq driver.
- */
-#define SAFE_MAX_CPU_FREQ 5000000000UL // 5 GHz
-u64 hw_nmi_get_sample_period(int watchdog_thresh)
-{
- unsigned int cpu = smp_processor_id();
- unsigned long max_cpu_freq;
-
- max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
- if (!max_cpu_freq)
- max_cpu_freq = SAFE_MAX_CPU_FREQ;
-
- return (u64)max_cpu_freq * watchdog_thresh;
-}
-
-bool __init arch_perf_nmi_is_available(void)
-{
- /*
- * hardlockup_detector_perf_init() will success even if Pseudo-NMI turns off,
- * however, the pmu interrupts will act like a normal interrupt instead of
- * NMI and the hardlockup detector would be broken.
- */
- return arm_pmu_irq_is_nmi();
-}
-
-static int watchdog_perf_update_period(void *data)
-{
- int cpu = smp_processor_id();
- u64 max_cpu_freq, new_period;
-
- max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
- if (!max_cpu_freq)
- return 0;
-
- new_period = watchdog_thresh * max_cpu_freq;
- hardlockup_detector_perf_adjust_period(new_period);
-
- return 0;
-}
-
-static int watchdog_freq_notifier_callback(struct notifier_block *nb,
- unsigned long val, void *data)
-{
- struct cpufreq_policy *policy = data;
- int cpu;
-
- if (val != CPUFREQ_CREATE_POLICY)
- return NOTIFY_DONE;
-
- /*
- * Let each online CPU related to the policy update the period by their
- * own. This will serialize with the framework on start/stop the lockup
- * detector (softlockup_{start,stop}_all) and avoid potential race
- * condition. Otherwise we may have below theoretical race condition:
- * (core 0/1 share the same policy)
- * [core 0] [core 1]
- * hardlockup_detector_event_create()
- * hw_nmi_get_sample_period()
- * (cpufreq registered, notifier callback invoked)
- * watchdog_freq_notifier_callback()
- * watchdog_perf_update_period()
- * (since core 1's event's not yet created,
- * the period is not set)
- * perf_event_create_kernel_counter()
- * (event's period is SAFE_MAX_CPU_FREQ)
- */
- for_each_cpu(cpu, policy->cpus)
- smp_call_on_cpu(cpu, watchdog_perf_update_period, NULL, false);
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block watchdog_freq_notifier = {
- .notifier_call = watchdog_freq_notifier_callback,
-};
-
-static int __init init_watchdog_freq_notifier(void)
-{
- return cpufreq_register_notifier(&watchdog_freq_notifier,
- CPUFREQ_POLICY_NOTIFIER);
-}
-core_initcall(init_watchdog_freq_notifier);
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 973a027d90639..294a5c3438ad1 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -17,6 +17,7 @@
#include <linux/cpu_pm.h>
#include <linux/export.h>
#include <linux/kernel.h>
+#include <linux/nmi.h>
#include <linux/perf/arm_pmu.h>
#include <linux/slab.h>
#include <linux/sched/clock.h>
@@ -703,10 +704,17 @@ static int armpmu_get_cpu_irq(struct arm_pmu *pmu, int cpu)
return per_cpu(hw_events->irq, cpu);
}
-bool arm_pmu_irq_is_nmi(void)
+#ifdef CONFIG_HARDLOCKUP_DETECTOR_PERF
+bool arch_perf_nmi_is_available(void)
{
+ /*
+ * watchdog_hardlockup_probe() will success even if Pseudo-NMI turns off,
+ * however, the pmu interrupts will act like a normal interrupt instead of
+ * NMI and the hardlockup detector would be broken.
+ */
return has_nmi;
}
+#endif
/*
* PMU hardware loses all context when a CPU goes offline.
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index 52b37f7bdbf9e..8f06751f1e176 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -183,8 +183,6 @@ void kvm_host_pmu_init(struct arm_pmu *pmu);
#define kvm_host_pmu_init(x) do { } while(0)
#endif
-bool arm_pmu_irq_is_nmi(void);
-
/* Internal functions only for core arm_pmu code */
struct arm_pmu *armpmu_alloc(void);
void armpmu_free(struct arm_pmu *pmu);
diff --git a/kernel/watchdog_perf.c b/kernel/watchdog_perf.c
index d3ca70e3c256a..8aa5e9a0ba20a 100644
--- a/kernel/watchdog_perf.c
+++ b/kernel/watchdog_perf.c
@@ -15,6 +15,7 @@
#include <linux/panic.h>
#include <linux/nmi.h>
#include <linux/atomic.h>
+#include <linux/cpufreq.h>
#include <linux/module.h>
#include <linux/sched/debug.h>
@@ -306,3 +307,85 @@ void __init hardlockup_config_perf_event(const char *str)
wd_hw_attr.type = PERF_TYPE_RAW;
wd_hw_attr.config = config;
}
+
+#ifdef CONFIG_WATCHDOG_PERF_ADJUST_PERIOD
+/*
+ * Safe maximum CPU frequency in case a particular platform doesn't implement
+ * cpufreq driver. Although, architecture doesn't put any restrictions on
+ * maximum frequency but 5 GHz seems to be safe maximum given the available
+ * CPUs in the market which are clocked much less than 5 GHz. On the other
+ * hand, we can't make it much higher as it would lead to a large hard-lockup
+ * detection timeout on parts which are running slower (eg. 1GHz on
+ * Developerbox) and doesn't possess a cpufreq driver.
+ */
+#define SAFE_MAX_CPU_FREQ 5000000000UL // 5 GHz
+u64 hw_nmi_get_sample_period(int watchdog_thresh)
+{
+ unsigned int cpu = smp_processor_id();
+ unsigned long max_cpu_freq;
+
+ max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
+ if (!max_cpu_freq)
+ max_cpu_freq = SAFE_MAX_CPU_FREQ;
+
+ return (u64)max_cpu_freq * watchdog_thresh;
+}
+
+static int watchdog_perf_update_period(void *data)
+{
+ int cpu = smp_processor_id();
+ u64 max_cpu_freq, new_period;
+
+ max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
+ if (!max_cpu_freq)
+ return 0;
+
+ new_period = watchdog_thresh * max_cpu_freq;
+ hardlockup_detector_perf_adjust_period(new_period);
+
+ return 0;
+}
+
+static int watchdog_freq_notifier_callback(struct notifier_block *nb,
+ unsigned long val, void *data)
+{
+ struct cpufreq_policy *policy = data;
+ int cpu;
+
+ if (val != CPUFREQ_CREATE_POLICY)
+ return NOTIFY_DONE;
+
+ /*
+ * Let each online CPU related to the policy update the period by their
+ * own. This will serialize with the framework on start/stop the lockup
+ * detector (softlockup_{start,stop}_all) and avoid potential race
+ * condition. Otherwise we may have below theoretical race condition:
+ * (core 0/1 share the same policy)
+ * [core 0] [core 1]
+ * hardlockup_detector_event_create()
+ * hw_nmi_get_sample_period()
+ * (cpufreq registered, notifier callback invoked)
+ * watchdog_freq_notifier_callback()
+ * watchdog_perf_update_period()
+ * (since core 1's event's not yet created,
+ * the period is not set)
+ * perf_event_create_kernel_counter()
+ * (event's period is SAFE_MAX_CPU_FREQ)
+ */
+ for_each_cpu(cpu, policy->cpus)
+ smp_call_on_cpu(cpu, watchdog_perf_update_period, NULL, false);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block watchdog_freq_notifier = {
+ .notifier_call = watchdog_freq_notifier_callback,
+};
+
+static int __init init_watchdog_freq_notifier(void)
+{
+ return cpufreq_register_notifier(&watchdog_freq_notifier,
+ CPUFREQ_POLICY_NOTIFIER);
+}
+core_initcall(init_watchdog_freq_notifier);
+#endif
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 2cbfa3dead0be..85fdfa9b52346 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1193,6 +1193,14 @@ config HARDLOCKUP_DETECTOR_PERF
depends on !HAVE_HARDLOCKUP_DETECTOR_ARCH
select HARDLOCKUP_DETECTOR_COUNTS_HRTIMER
+config WATCHDOG_PERF_ADJUST_PERIOD
+ bool
+ help
+ Adjust the watchdog hardlockup detector's period based on CPU max
+ frequency. Uses cpufreq if available; falls back to a safe 5 GHz
+ default otherwise. Registers a cpufreq notifier to update the period
+ automatically.
+
config HARDLOCKUP_DETECTOR_BUDDY
bool
depends on HARDLOCKUP_DETECTOR
--
2.39.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v6 2/2] riscv: add HARDLOCKUP_DETECTOR_PERF support
2025-11-14 3:32 [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V Yunhui Cui
2025-11-14 3:32 ` [PATCH v6 1/2] watchdog: move arm64 watchdog_hld into common code Yunhui Cui
@ 2025-11-14 3:32 ` Yunhui Cui
2025-12-05 6:12 ` Yicong Yang
2025-11-14 19:13 ` [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V Doug Anderson
2 siblings, 1 reply; 7+ messages in thread
From: Yunhui Cui @ 2025-11-14 3:32 UTC (permalink / raw)
To: akpm, alex, anup, aou, atish.patra, catalin.marinas, cuiyunhui,
dianders, johannes, lihuafei1, mark.rutland, masahiroy, maz,
mingo, nicolas.schier, palmer, paul.walmsley, suzuki.poulose,
thorsten.blum, wangjinchao600, will, yangyicong, zhanjie9,
linux-arm-kernel, linux-kernel, linux-perf-users, linux-riscv
Cc: Paul Walmsley
Enable the HARDLOCKUP_DETECTOR_PERF function based on RISC-V SSE.
Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Acked-by: Paul Walmsley <pjw@kernel.org>
---
arch/riscv/Kconfig | 3 +++
drivers/perf/riscv_pmu_sbi.c | 10 ++++++++++
2 files changed, 13 insertions(+)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index fadec20b87a8e..46ccd33732fa8 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -186,6 +186,9 @@ config RISCV
select HAVE_PAGE_SIZE_4KB
select HAVE_PCI
select HAVE_PERF_EVENTS
+ select HAVE_PERF_EVENTS_NMI if RISCV_PMU_SBI_SSE
+ select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI
+ select WATCHDOG_PERF_ADJUST_PERIOD if HARDLOCKUP_DETECTOR_PERF
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
select HAVE_POSIX_CPU_TIMERS_TASK_WORK
diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index c852f64a50221..0c7c5924687c9 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -22,6 +22,7 @@
#include <linux/sched/clock.h>
#include <linux/soc/andes/irq.h>
#include <linux/workqueue.h>
+#include <linux/nmi.h>
#include <asm/errata_list.h>
#include <asm/sbi.h>
@@ -1192,6 +1193,13 @@ static int pmu_sbi_setup_sse(struct riscv_pmu *pmu)
}
#endif
+#ifdef CONFIG_HARDLOCKUP_DETECTOR_PERF
+bool arch_perf_nmi_is_available(void)
+{
+ return IS_ENABLED(CONFIG_RISCV_PMU_SBI_SSE);
+}
+#endif
+
static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node)
{
struct riscv_pmu *pmu = hlist_entry_safe(node, struct riscv_pmu, node);
@@ -1618,6 +1626,8 @@ static int __init pmu_sbi_devinit(void)
/* Notify legacy implementation that SBI pmu is available*/
riscv_pmu_legacy_skip_init();
+ lockup_detector_retry_init();
+
return ret;
}
device_initcall(pmu_sbi_devinit)
--
2.39.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V
2025-11-14 3:32 [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V Yunhui Cui
2025-11-14 3:32 ` [PATCH v6 1/2] watchdog: move arm64 watchdog_hld into common code Yunhui Cui
2025-11-14 3:32 ` [PATCH v6 2/2] riscv: add HARDLOCKUP_DETECTOR_PERF support Yunhui Cui
@ 2025-11-14 19:13 ` Doug Anderson
2025-12-04 5:00 ` [External] " yunhui cui
2 siblings, 1 reply; 7+ messages in thread
From: Doug Anderson @ 2025-11-14 19:13 UTC (permalink / raw)
To: Yunhui Cui
Cc: akpm, alex, anup, aou, atish.patra, catalin.marinas, johannes,
lihuafei1, mark.rutland, masahiroy, maz, mingo, nicolas.schier,
palmer, paul.walmsley, suzuki.poulose, thorsten.blum,
wangjinchao600, will, yangyicong, zhanjie9, linux-arm-kernel,
linux-kernel, linux-perf-users, linux-riscv
Hi,
On Thu, Nov 13, 2025 at 7:33 PM Yunhui Cui <cuiyunhui@bytedance.com> wrote:
>
> After discussion [1],[2], hardlockup_perf cannot be completely replaced by
> the hardlockup_buddy approach, so this patch is still being submitted.
>
> v1->v2:
> The contents of arch/arm64/watchdog_hld.c are directly consolidated into
> kernel/watchdog_perf.c.
>
>
> v2->v3:
> Add CONFIG_WATCHDOG_PERF_ADJUST_PERIOD to enclose the period update logic,
> select it by default on arm64 and riscv, without affecting other arches
> like x86 and PPC.
>
> v3->v4:
> Place the line "select WATCHDOG_PERF_ADJUST_PERIOD if HARDLOCKUP_DETECTOR_PERF && CPU_FREQ"
> in the Kconfig files for arm64 and riscv in one line, with no line breaks.
>
> v4->v5:
> Remove __weak from hw_nmi_get_sample_period()
>
> v5->v6:
> Removed the dependency on CPU_FREQ for WATCHDOG_PERF_ADJUST_PERIOD in Kconfig, which fixes the
> issue reported at: https://lore.kernel.org/oe-kbuild-all/202510240701.eB6r97V3-lkp@intel.com/
I haven't tried compiling this myself, but it seems like an OK
solution for the compile-time error to me.
-Doug
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [External] Re: [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V
2025-11-14 19:13 ` [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V Doug Anderson
@ 2025-12-04 5:00 ` yunhui cui
0 siblings, 0 replies; 7+ messages in thread
From: yunhui cui @ 2025-12-04 5:00 UTC (permalink / raw)
To: Doug Anderson
Cc: akpm, alex, anup, aou, atish.patra, catalin.marinas, johannes,
lihuafei1, mark.rutland, masahiroy, maz, mingo, nicolas.schier,
palmer, paul.walmsley, suzuki.poulose, thorsten.blum,
wangjinchao600, will, yangyicong, zhanjie9, linux-arm-kernel,
linux-kernel, linux-perf-users, linux-riscv
Hi Andrew,
On Sat, Nov 15, 2025 at 3:21 AM Doug Anderson <dianders@chromium.org> wrote:
>
> Hi,
>
> On Thu, Nov 13, 2025 at 7:33 PM Yunhui Cui <cuiyunhui@bytedance.com> wrote:
> >
> > After discussion [1],[2], hardlockup_perf cannot be completely replaced by
> > the hardlockup_buddy approach, so this patch is still being submitted.
> >
> > v1->v2:
> > The contents of arch/arm64/watchdog_hld.c are directly consolidated into
> > kernel/watchdog_perf.c.
> >
> >
> > v2->v3:
> > Add CONFIG_WATCHDOG_PERF_ADJUST_PERIOD to enclose the period update logic,
> > select it by default on arm64 and riscv, without affecting other arches
> > like x86 and PPC.
> >
> > v3->v4:
> > Place the line "select WATCHDOG_PERF_ADJUST_PERIOD if HARDLOCKUP_DETECTOR_PERF && CPU_FREQ"
> > in the Kconfig files for arm64 and riscv in one line, with no line breaks.
> >
> > v4->v5:
> > Remove __weak from hw_nmi_get_sample_period()
> >
> > v5->v6:
> > Removed the dependency on CPU_FREQ for WATCHDOG_PERF_ADJUST_PERIOD in Kconfig, which fixes the
> > issue reported at: https://lore.kernel.org/oe-kbuild-all/202510240701.eB6r97V3-lkp@intel.com/
>
> I haven't tried compiling this myself, but it seems like an OK
> solution for the compile-time error to me.
>
> -Doug
Could you please help review and merge this again? Thank you!
>
Thanks,
Yunhui
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6 2/2] riscv: add HARDLOCKUP_DETECTOR_PERF support
2025-11-14 3:32 ` [PATCH v6 2/2] riscv: add HARDLOCKUP_DETECTOR_PERF support Yunhui Cui
@ 2025-12-05 6:12 ` Yicong Yang
0 siblings, 0 replies; 7+ messages in thread
From: Yicong Yang @ 2025-12-05 6:12 UTC (permalink / raw)
To: Yunhui Cui
Cc: akpm, alex, anup, aou, atish.patra, catalin.marinas, dianders,
johannes, lihuafei1, mark.rutland, masahiroy, maz, mingo,
nicolas.schier, palmer, paul.walmsley, suzuki.poulose,
thorsten.blum, wangjinchao600, will, yangyicong, zhanjie9,
linux-arm-kernel, linux-kernel, linux-perf-users, linux-riscv,
Paul Walmsley, yang.yicong, geshijian
Hi Yunhui,
this has conflicts on the mainline master. looks like you have a dependency
on the SSE PMU support patchset [1], need to mention it for the maintainer
to apply.
[1] https://lore.kernel.org/linux-riscv/20250908181717.1997461-5-cleger@rivosinc.com/
one comment below.
On 2025/11/14 11:32, Yunhui Cui wrote:
> Enable the HARDLOCKUP_DETECTOR_PERF function based on RISC-V SSE.
>
> Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>
> Acked-by: Paul Walmsley <pjw@kernel.org>
> ---
> arch/riscv/Kconfig | 3 +++
> drivers/perf/riscv_pmu_sbi.c | 10 ++++++++++
> 2 files changed, 13 insertions(+)
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index fadec20b87a8e..46ccd33732fa8 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -186,6 +186,9 @@ config RISCV
> select HAVE_PAGE_SIZE_4KB
> select HAVE_PCI
> select HAVE_PERF_EVENTS
> + select HAVE_PERF_EVENTS_NMI if RISCV_PMU_SBI_SSE
> + select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI
> + select WATCHDOG_PERF_ADJUST_PERIOD if HARDLOCKUP_DETECTOR_PERF
> select HAVE_PERF_REGS
> select HAVE_PERF_USER_STACK_DUMP
> select HAVE_POSIX_CPU_TIMERS_TASK_WORK
> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> index c852f64a50221..0c7c5924687c9 100644
> --- a/drivers/perf/riscv_pmu_sbi.c
> +++ b/drivers/perf/riscv_pmu_sbi.c
> @@ -22,6 +22,7 @@
> #include <linux/sched/clock.h>
> #include <linux/soc/andes/irq.h>
> #include <linux/workqueue.h>
> +#include <linux/nmi.h>
>
> #include <asm/errata_list.h>
> #include <asm/sbi.h>
> @@ -1192,6 +1193,13 @@ static int pmu_sbi_setup_sse(struct riscv_pmu *pmu)
> }
> #endif
>
> +#ifdef CONFIG_HARDLOCKUP_DETECTOR_PERF
> +bool arch_perf_nmi_is_available(void)
> +{
> + return IS_ENABLED(CONFIG_RISCV_PMU_SBI_SSE);
this looks incorrect per implementation in [1]. we'll fallback to the normal
interrupt if failed to register the SSE event, in which case NMI is not
available for the PMU. Check the kconfig is not sufficient.
you can check pmu->sse_evt instead for the NMI support here, or cached the
NMI status somewhere like how arm_pmu does.
Thanks.
> +}
> +#endif
> +
> static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node)
> {
> struct riscv_pmu *pmu = hlist_entry_safe(node, struct riscv_pmu, node);
> @@ -1618,6 +1626,8 @@ static int __init pmu_sbi_devinit(void)
> /* Notify legacy implementation that SBI pmu is available*/
> riscv_pmu_legacy_skip_init();
>
> + lockup_detector_retry_init();
> +
> return ret;
> }
> device_initcall(pmu_sbi_devinit)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6 1/2] watchdog: move arm64 watchdog_hld into common code
2025-11-14 3:32 ` [PATCH v6 1/2] watchdog: move arm64 watchdog_hld into common code Yunhui Cui
@ 2025-12-05 6:53 ` Yicong Yang
0 siblings, 0 replies; 7+ messages in thread
From: Yicong Yang @ 2025-12-05 6:53 UTC (permalink / raw)
To: Yunhui Cui
Cc: akpm, alex, anup, aou, atish.patra, catalin.marinas, dianders,
johannes, lihuafei1, mark.rutland, masahiroy, maz, mingo,
nicolas.schier, palmer, paul.walmsley, suzuki.poulose,
thorsten.blum, wangjinchao600, will, yangyicong, zhanjie9,
linux-arm-kernel, linux-kernel, linux-perf-users, linux-riscv,
yang.yicong, geshijian
On 2025/11/14 11:32, Yunhui Cui wrote:
> Move the contents of arch/arm64/watchdog_hld.c to kernel/watchdog_perf.c
> to create a generic implementation that can be reused by other arch,
> such as RISC-V.
>
> Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>
> ---
> arch/arm64/Kconfig | 1 +
> arch/arm64/kernel/Makefile | 1 -
> arch/arm64/kernel/watchdog_hld.c | 94 --------------------------------
> drivers/perf/arm_pmu.c | 10 +++-
> include/linux/perf/arm_pmu.h | 2 -
> kernel/watchdog_perf.c | 83 ++++++++++++++++++++++++++++
> lib/Kconfig.debug | 8 +++
> 7 files changed, 101 insertions(+), 98 deletions(-)
> delete mode 100644 arch/arm64/kernel/watchdog_hld.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 6663ffd23f252..6614ff45b1e06 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -231,6 +231,7 @@ config ARM64
> select HAVE_GCC_PLUGINS
> select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \
> HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI
> + select WATCHDOG_PERF_ADJUST_PERIOD if HARDLOCKUP_DETECTOR_PERF
> select HAVE_HW_BREAKPOINT if PERF_EVENTS
> select HAVE_IOREMAP_PROT
> select HAVE_IRQ_TIME_ACCOUNTING
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 76f32e424065e..12d77f373fea4 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -44,7 +44,6 @@ obj-$(CONFIG_KUSER_HELPERS) += kuser32.o
> obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
> obj-$(CONFIG_MODULES) += module.o module-plts.o
> obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
> -obj-$(CONFIG_HARDLOCKUP_DETECTOR_PERF) += watchdog_hld.o
> obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
> obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
> obj-$(CONFIG_KGDB) += kgdb.o
> diff --git a/arch/arm64/kernel/watchdog_hld.c b/arch/arm64/kernel/watchdog_hld.c
> deleted file mode 100644
> index 3093037dcb7be..0000000000000
> --- a/arch/arm64/kernel/watchdog_hld.c
> +++ /dev/null
> @@ -1,94 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -#include <linux/nmi.h>
> -#include <linux/cpufreq.h>
> -#include <linux/perf/arm_pmu.h>
> -
> -/*
> - * Safe maximum CPU frequency in case a particular platform doesn't implement
> - * cpufreq driver. Although, architecture doesn't put any restrictions on
> - * maximum frequency but 5 GHz seems to be safe maximum given the available
> - * Arm CPUs in the market which are clocked much less than 5 GHz. On the other
> - * hand, we can't make it much higher as it would lead to a large hard-lockup
> - * detection timeout on parts which are running slower (eg. 1GHz on
> - * Developerbox) and doesn't possess a cpufreq driver.
> - */
> -#define SAFE_MAX_CPU_FREQ 5000000000UL // 5 GHz
> -u64 hw_nmi_get_sample_period(int watchdog_thresh)
> -{
> - unsigned int cpu = smp_processor_id();
> - unsigned long max_cpu_freq;
> -
> - max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
> - if (!max_cpu_freq)
> - max_cpu_freq = SAFE_MAX_CPU_FREQ;
> -
> - return (u64)max_cpu_freq * watchdog_thresh;
> -}
> -
> -bool __init arch_perf_nmi_is_available(void)
> -{
> - /*
> - * hardlockup_detector_perf_init() will success even if Pseudo-NMI turns off,
> - * however, the pmu interrupts will act like a normal interrupt instead of
> - * NMI and the hardlockup detector would be broken.
> - */
> - return arm_pmu_irq_is_nmi();
> -}
> -
> -static int watchdog_perf_update_period(void *data)
> -{
> - int cpu = smp_processor_id();
> - u64 max_cpu_freq, new_period;
> -
> - max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
> - if (!max_cpu_freq)
> - return 0;
> -
> - new_period = watchdog_thresh * max_cpu_freq;
> - hardlockup_detector_perf_adjust_period(new_period);
> -
> - return 0;
> -}
> -
> -static int watchdog_freq_notifier_callback(struct notifier_block *nb,
> - unsigned long val, void *data)
> -{
> - struct cpufreq_policy *policy = data;
> - int cpu;
> -
> - if (val != CPUFREQ_CREATE_POLICY)
> - return NOTIFY_DONE;
> -
> - /*
> - * Let each online CPU related to the policy update the period by their
> - * own. This will serialize with the framework on start/stop the lockup
> - * detector (softlockup_{start,stop}_all) and avoid potential race
> - * condition. Otherwise we may have below theoretical race condition:
> - * (core 0/1 share the same policy)
> - * [core 0] [core 1]
> - * hardlockup_detector_event_create()
> - * hw_nmi_get_sample_period()
> - * (cpufreq registered, notifier callback invoked)
> - * watchdog_freq_notifier_callback()
> - * watchdog_perf_update_period()
> - * (since core 1's event's not yet created,
> - * the period is not set)
> - * perf_event_create_kernel_counter()
> - * (event's period is SAFE_MAX_CPU_FREQ)
> - */
> - for_each_cpu(cpu, policy->cpus)
> - smp_call_on_cpu(cpu, watchdog_perf_update_period, NULL, false);
> -
> - return NOTIFY_DONE;
> -}
> -
> -static struct notifier_block watchdog_freq_notifier = {
> - .notifier_call = watchdog_freq_notifier_callback,
> -};
> -
> -static int __init init_watchdog_freq_notifier(void)
> -{
> - return cpufreq_register_notifier(&watchdog_freq_notifier,
> - CPUFREQ_POLICY_NOTIFIER);
> -}
> -core_initcall(init_watchdog_freq_notifier);
> diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
> index 973a027d90639..294a5c3438ad1 100644
> --- a/drivers/perf/arm_pmu.c
> +++ b/drivers/perf/arm_pmu.c
> @@ -17,6 +17,7 @@
> #include <linux/cpu_pm.h>
> #include <linux/export.h>
> #include <linux/kernel.h>
> +#include <linux/nmi.h>
> #include <linux/perf/arm_pmu.h>
> #include <linux/slab.h>
> #include <linux/sched/clock.h>
> @@ -703,10 +704,17 @@ static int armpmu_get_cpu_irq(struct arm_pmu *pmu, int cpu)
> return per_cpu(hw_events->irq, cpu);
> }
>
> -bool arm_pmu_irq_is_nmi(void)
> +#ifdef CONFIG_HARDLOCKUP_DETECTOR_PERF
> +bool arch_perf_nmi_is_available(void)
> {
> + /*
> + * watchdog_hardlockup_probe() will success even if Pseudo-NMI turns off,
> + * however, the pmu interrupts will act like a normal interrupt instead of
> + * NMI and the hardlockup detector would be broken.
> + */
the comment makes me a bit confused. we'll only declare the NMI support if we successfully
registered the PMU interrupt as NMI interrupt. If pseudo-nmi is turned off, we'll
failed to register the NMI interrupt since neither the gicv3 irqchip will declare NMI
suppport [1] nor the irq_chip::irq_nmi_setup() will success [2], then the has_nmi will
be false. In this case the hardlockup detector is not probed at all [3].
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/irqchip/irq-gic-v3.c#n1956
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/irqchip/irq-gic-v3.c#n602
[3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/watchdog_perf.c#n268
> return has_nmi;
> }
> +#endif
>
> /*
> * PMU hardware loses all context when a CPU goes offline.
> diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
> index 52b37f7bdbf9e..8f06751f1e176 100644
> --- a/include/linux/perf/arm_pmu.h
> +++ b/include/linux/perf/arm_pmu.h
> @@ -183,8 +183,6 @@ void kvm_host_pmu_init(struct arm_pmu *pmu);
> #define kvm_host_pmu_init(x) do { } while(0)
> #endif
>
> -bool arm_pmu_irq_is_nmi(void);
> -
> /* Internal functions only for core arm_pmu code */
> struct arm_pmu *armpmu_alloc(void);
> void armpmu_free(struct arm_pmu *pmu);
> diff --git a/kernel/watchdog_perf.c b/kernel/watchdog_perf.c
> index d3ca70e3c256a..8aa5e9a0ba20a 100644
> --- a/kernel/watchdog_perf.c
> +++ b/kernel/watchdog_perf.c
> @@ -15,6 +15,7 @@
> #include <linux/panic.h>
> #include <linux/nmi.h>
> #include <linux/atomic.h>
> +#include <linux/cpufreq.h>
> #include <linux/module.h>
> #include <linux/sched/debug.h>
>
> @@ -306,3 +307,85 @@ void __init hardlockup_config_perf_event(const char *str)
> wd_hw_attr.type = PERF_TYPE_RAW;
> wd_hw_attr.config = config;
> }
> +
> +#ifdef CONFIG_WATCHDOG_PERF_ADJUST_PERIOD
> +/*
> + * Safe maximum CPU frequency in case a particular platform doesn't implement
> + * cpufreq driver. Although, architecture doesn't put any restrictions on
> + * maximum frequency but 5 GHz seems to be safe maximum given the available
> + * CPUs in the market which are clocked much less than 5 GHz. On the other
> + * hand, we can't make it much higher as it would lead to a large hard-lockup
> + * detection timeout on parts which are running slower (eg. 1GHz on
> + * Developerbox) and doesn't possess a cpufreq driver.
> + */
> +#define SAFE_MAX_CPU_FREQ 5000000000UL // 5 GHz
> +u64 hw_nmi_get_sample_period(int watchdog_thresh)
> +{
> + unsigned int cpu = smp_processor_id();
> + unsigned long max_cpu_freq;
> +
> + max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
> + if (!max_cpu_freq)
> + max_cpu_freq = SAFE_MAX_CPU_FREQ;
> +
> + return (u64)max_cpu_freq * watchdog_thresh;
> +}
> +
> +static int watchdog_perf_update_period(void *data)
> +{
> + int cpu = smp_processor_id();
> + u64 max_cpu_freq, new_period;
> +
> + max_cpu_freq = cpufreq_get_hw_max_freq(cpu) * 1000UL;
> + if (!max_cpu_freq)
> + return 0;
> +
> + new_period = watchdog_thresh * max_cpu_freq;
> + hardlockup_detector_perf_adjust_period(new_period);
> +
> + return 0;
> +}
> +
> +static int watchdog_freq_notifier_callback(struct notifier_block *nb,
> + unsigned long val, void *data)
> +{
> + struct cpufreq_policy *policy = data;
> + int cpu;
> +
> + if (val != CPUFREQ_CREATE_POLICY)
> + return NOTIFY_DONE;
> +
> + /*
> + * Let each online CPU related to the policy update the period by their
> + * own. This will serialize with the framework on start/stop the lockup
> + * detector (softlockup_{start,stop}_all) and avoid potential race
> + * condition. Otherwise we may have below theoretical race condition:
> + * (core 0/1 share the same policy)
> + * [core 0] [core 1]
> + * hardlockup_detector_event_create()
> + * hw_nmi_get_sample_period()
> + * (cpufreq registered, notifier callback invoked)
> + * watchdog_freq_notifier_callback()
> + * watchdog_perf_update_period()
> + * (since core 1's event's not yet created,
> + * the period is not set)
> + * perf_event_create_kernel_counter()
> + * (event's period is SAFE_MAX_CPU_FREQ)
> + */
> + for_each_cpu(cpu, policy->cpus)
> + smp_call_on_cpu(cpu, watchdog_perf_update_period, NULL, false);
> +
> + return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block watchdog_freq_notifier = {
> + .notifier_call = watchdog_freq_notifier_callback,
> +};
> +
> +static int __init init_watchdog_freq_notifier(void)
> +{
> + return cpufreq_register_notifier(&watchdog_freq_notifier,
> + CPUFREQ_POLICY_NOTIFIER);
> +}
> +core_initcall(init_watchdog_freq_notifier);
> +#endif
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index 2cbfa3dead0be..85fdfa9b52346 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -1193,6 +1193,14 @@ config HARDLOCKUP_DETECTOR_PERF
> depends on !HAVE_HARDLOCKUP_DETECTOR_ARCH
> select HARDLOCKUP_DETECTOR_COUNTS_HRTIMER
>
> +config WATCHDOG_PERF_ADJUST_PERIOD
> + bool
it's reasonable to make it depends on HARDLOCKUP_DETECTOR_PERF.
otherwise looks good to me :)
Thanks.
> + help
> + Adjust the watchdog hardlockup detector's period based on CPU max
> + frequency. Uses cpufreq if available; falls back to a safe 5 GHz
> + default otherwise. Registers a cpufreq notifier to update the period
> + automatically.
> +
> config HARDLOCKUP_DETECTOR_BUDDY
> bool
> depends on HARDLOCKUP_DETECTOR
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-12-05 6:55 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-14 3:32 [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V Yunhui Cui
2025-11-14 3:32 ` [PATCH v6 1/2] watchdog: move arm64 watchdog_hld into common code Yunhui Cui
2025-12-05 6:53 ` Yicong Yang
2025-11-14 3:32 ` [PATCH v6 2/2] riscv: add HARDLOCKUP_DETECTOR_PERF support Yunhui Cui
2025-12-05 6:12 ` Yicong Yang
2025-11-14 19:13 ` [PATCH v6 0/2] Add HARDLOCKUP_DETECTOR_PERF support for RISC-V Doug Anderson
2025-12-04 5:00 ` [External] " yunhui cui
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).