The HPET-based hardlockup detector relies on the TSC to determine if an
observed NMI interrupt was originated by HPET timer. Hence, this detector
can no longer be used with an unstable TSC.
In such case, permanently stop the HPET-based hardlockup detector and
start the perf-based detector.
Signed-off-by: Ricardo Neri <[email protected]>
---
arch/x86/include/asm/hpet.h | 2 ++
arch/x86/kernel/tsc.c | 2 ++
arch/x86/kernel/watchdog_hld.c | 7 +++++++
3 files changed, 11 insertions(+)
diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
index fd99f2390714..a82cbe17479d 100644
--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -128,6 +128,7 @@ extern int hardlockup_detector_hpet_init(void);
extern void hardlockup_detector_hpet_stop(void);
extern void hardlockup_detector_hpet_enable(unsigned int cpu);
extern void hardlockup_detector_hpet_disable(unsigned int cpu);
+extern void hardlockup_detector_switch_to_perf(void);
#else
static inline struct hpet_hld_data *hpet_hardlockup_detector_assign_timer(void)
{ return NULL; }
@@ -136,6 +137,7 @@ static inline int hardlockup_detector_hpet_init(void)
static inline void hardlockup_detector_hpet_stop(void) {}
static inline void hardlockup_detector_hpet_enable(unsigned int cpu) {}
static inline void hardlockup_detector_hpet_disable(unsigned int cpu) {}
+static void harrdlockup_detector_switch_to_perf(void) {}
#endif /* CONFIG_X86_HARDLOCKUP_DETECTOR_HPET */
#else /* CONFIG_HPET_TIMER */
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 59b57605e66c..b2210728ce3d 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -1158,6 +1158,8 @@ void mark_tsc_unstable(char *reason)
clocksource_mark_unstable(&clocksource_tsc_early);
clocksource_mark_unstable(&clocksource_tsc);
+
+ hardlockup_detector_switch_to_perf();
}
EXPORT_SYMBOL_GPL(mark_tsc_unstable);
diff --git a/arch/x86/kernel/watchdog_hld.c b/arch/x86/kernel/watchdog_hld.c
index c2512d4c79c5..c8547c227a41 100644
--- a/arch/x86/kernel/watchdog_hld.c
+++ b/arch/x86/kernel/watchdog_hld.c
@@ -76,3 +76,10 @@ void watchdog_nmi_stop(void)
if (detector_type == X86_HARDLOCKUP_DETECTOR_HPET)
hardlockup_detector_hpet_stop();
}
+
+void hardlockup_detector_switch_to_perf(void)
+{
+ detector_type = X86_HARDLOCKUP_DETECTOR_PERF;
+ hardlockup_detector_hpet_stop();
+ hardlockup_start_all();
+}
--
2.17.1
Hi Ricardo,
Thanks for your contribution here. It is very important to move the
watchdog out of the PMU wherever possible.
On Thu, May 23, 2019 at 6:17 PM Ricardo Neri
<[email protected]> wrote:
>
> The HPET-based hardlockup detector relies on the TSC to determine if an
> observed NMI interrupt was originated by HPET timer. Hence, this detector
> can no longer be used with an unstable TSC.
>
> In such case, permanently stop the HPET-based hardlockup detector and
> start the perf-based detector.
>
> Signed-off-by: Ricardo Neri <[email protected]>
> ---
> arch/x86/include/asm/hpet.h | 2 ++
> arch/x86/kernel/tsc.c | 2 ++
> arch/x86/kernel/watchdog_hld.c | 7 +++++++
> 3 files changed, 11 insertions(+)
>
> diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
> index fd99f2390714..a82cbe17479d 100644
> --- a/arch/x86/include/asm/hpet.h
> +++ b/arch/x86/include/asm/hpet.h
> @@ -128,6 +128,7 @@ extern int hardlockup_detector_hpet_init(void);
> extern void hardlockup_detector_hpet_stop(void);
> extern void hardlockup_detector_hpet_enable(unsigned int cpu);
> extern void hardlockup_detector_hpet_disable(unsigned int cpu);
> +extern void hardlockup_detector_switch_to_perf(void);
> #else
> static inline struct hpet_hld_data *hpet_hardlockup_detector_assign_timer(void)
> { return NULL; }
> @@ -136,6 +137,7 @@ static inline int hardlockup_detector_hpet_init(void)
> static inline void hardlockup_detector_hpet_stop(void) {}
> static inline void hardlockup_detector_hpet_enable(unsigned int cpu) {}
> static inline void hardlockup_detector_hpet_disable(unsigned int cpu) {}
> +static void harrdlockup_detector_switch_to_perf(void) {}
> #endif /* CONFIG_X86_HARDLOCKUP_DETECTOR_HPET */
>
This does not compile for me when CONFIG_X86_HARDLOCKUP_DETECTOR_HPET
is not enabled.
because:
1- you have a typo on the function name
2- you are missing the inline keyword
> #else /* CONFIG_HPET_TIMER */
> diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
> index 59b57605e66c..b2210728ce3d 100644
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -1158,6 +1158,8 @@ void mark_tsc_unstable(char *reason)
>
> clocksource_mark_unstable(&clocksource_tsc_early);
> clocksource_mark_unstable(&clocksource_tsc);
> +
> + hardlockup_detector_switch_to_perf();
> }
>
> EXPORT_SYMBOL_GPL(mark_tsc_unstable);
> diff --git a/arch/x86/kernel/watchdog_hld.c b/arch/x86/kernel/watchdog_hld.c
> index c2512d4c79c5..c8547c227a41 100644
> --- a/arch/x86/kernel/watchdog_hld.c
> +++ b/arch/x86/kernel/watchdog_hld.c
> @@ -76,3 +76,10 @@ void watchdog_nmi_stop(void)
> if (detector_type == X86_HARDLOCKUP_DETECTOR_HPET)
> hardlockup_detector_hpet_stop();
> }
> +
> +void hardlockup_detector_switch_to_perf(void)
> +{
> + detector_type = X86_HARDLOCKUP_DETECTOR_PERF;
> + hardlockup_detector_hpet_stop();
> + hardlockup_start_all();
> +}
> --
> 2.17.1
>
On Thu, Jun 06, 2019 at 05:35:51PM -0700, Stephane Eranian wrote:
> Hi Ricardo,
Hi Stephane,
> Thanks for your contribution here. It is very important to move the
> watchdog out of the PMU wherever possible.
Indeed, using the PMU for the hardlockup detector is still the default
option. This patch series proposes a new kernel command line to switch
to use the HPET.
>
> On Thu, May 23, 2019 at 6:17 PM Ricardo Neri
> <[email protected]> wrote:
> >
> > The HPET-based hardlockup detector relies on the TSC to determine if an
> > observed NMI interrupt was originated by HPET timer. Hence, this detector
> > can no longer be used with an unstable TSC.
> >
> > In such case, permanently stop the HPET-based hardlockup detector and
> > start the perf-based detector.
> >
> > Signed-off-by: Ricardo Neri <[email protected]>
> > ---
> > arch/x86/include/asm/hpet.h | 2 ++
> > arch/x86/kernel/tsc.c | 2 ++
> > arch/x86/kernel/watchdog_hld.c | 7 +++++++
> > 3 files changed, 11 insertions(+)
> >
> > diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
> > index fd99f2390714..a82cbe17479d 100644
> > --- a/arch/x86/include/asm/hpet.h
> > +++ b/arch/x86/include/asm/hpet.h
> > @@ -128,6 +128,7 @@ extern int hardlockup_detector_hpet_init(void);
> > extern void hardlockup_detector_hpet_stop(void);
> > extern void hardlockup_detector_hpet_enable(unsigned int cpu);
> > extern void hardlockup_detector_hpet_disable(unsigned int cpu);
> > +extern void hardlockup_detector_switch_to_perf(void);
> > #else
> > static inline struct hpet_hld_data *hpet_hardlockup_detector_assign_timer(void)
> > { return NULL; }
> > @@ -136,6 +137,7 @@ static inline int hardlockup_detector_hpet_init(void)
> > static inline void hardlockup_detector_hpet_stop(void) {}
> > static inline void hardlockup_detector_hpet_enable(unsigned int cpu) {}
> > static inline void hardlockup_detector_hpet_disable(unsigned int cpu) {}
> > +static void harrdlockup_detector_switch_to_perf(void) {}
> > #endif /* CONFIG_X86_HARDLOCKUP_DETECTOR_HPET */
> >
> This does not compile for me when CONFIG_X86_HARDLOCKUP_DETECTOR_HPET
> is not enabled.
> because:
> 1- you have a typo on the function name
> 2- you are missing the inline keyword
I am sorry. This was an oversight on my side. I have corrected this in
preparation for a v5.
Thanks and BR,
Ricardo