From: Xiongfeng Wang <wangxiongfeng2(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: NA
CVE: NA
------------------------------
Firmware may not trigger SDEI event as required frequency. SDEI event
may be triggered too soon, which cause false hardlockup in kernel. Check
the time stamp in sdei_watchdog_callbak and skip the hardlockup check if
it is invoked too soon.
Signed-off-by: Xiongfeng Wang <wangxiongfeng2(a)huawei.com>
Reviewed-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
arch/arm64/kernel/watchdog_sdei.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm64/kernel/watchdog_sdei.c b/arch/arm64/kernel/watchdog_sdei.c
index 05b9a9a223a7..aa980b090598 100644
--- a/arch/arm64/kernel/watchdog_sdei.c
+++ b/arch/arm64/kernel/watchdog_sdei.c
@@ -23,6 +23,7 @@
static int sdei_watchdog_event_num;
static bool disable_sdei_nmi_watchdog;
static bool sdei_watchdog_registered;
+static DEFINE_PER_CPU(ktime_t, last_check_time);
int watchdog_sdei_enable(unsigned int cpu)
{
@@ -35,6 +36,7 @@ int watchdog_sdei_enable(unsigned int cpu)
refresh_hld_last_timestamp();
#endif
+ __this_cpu_write(last_check_time, ktime_get_mono_fast_ns());
sdei_api_set_secure_timer_period(watchdog_thresh);
ret = sdei_api_event_enable(sdei_watchdog_event_num);
@@ -63,6 +65,23 @@ void watchdog_sdei_disable(unsigned int cpu)
static int sdei_watchdog_callback(u32 event,
struct pt_regs *regs, void *arg)
{
+ ktime_t delta, now = ktime_get_mono_fast_ns();
+
+ delta = now - __this_cpu_read(last_check_time);
+ __this_cpu_write(last_check_time, now);
+
+ /*
+ * Set delta to 4/5 of the actual watchdog threshold period so the
+ * hrtimer is guaranteed to fire at least once within the real
+ * watchdog threshold.
+ */
+ if (delta < watchdog_thresh * (u64)NSEC_PER_SEC * 4 / 5) {
+ pr_err(FW_BUG "SDEI Watchdog event triggered too soon, "
+ "time to last check:%lld ns\n", delta);
+ WARN_ON(1);
+ return 0;
+ }
+
watchdog_hardlockup_check(regs);
return 0;
--
2.25.1