diff --git a/arch/arm64/kernel/watchdog_sdei.c b/arch/arm64/kernel/watchdog_sdei.c index 99ab9bdfdee6e891afdbb0f560beb72ff3154f01..c342f86560d530790cbb92848c3d03de8da8ed89 100644 --- a/arch/arm64/kernel/watchdog_sdei.c +++ b/arch/arm64/kernel/watchdog_sdei.c @@ -30,7 +30,11 @@ int watchdog_nmi_enable(unsigned int cpu) if (!sdei_watchdog_registered) return -EINVAL; +#ifdef CONFIG_HARDLOCKUP_CHECK_TIMESTAMP refresh_hld_last_timestamp(); +#endif + + sdei_api_set_secure_timer_period(watchdog_thresh); ret = sdei_api_event_enable(sdei_watchdog_event_num); if (ret) { @@ -104,6 +108,17 @@ int __init watchdog_nmi_probe(void) return sdei_watchdog_event_num; } + /* + * After we introduced 'sdei_api_set_secure_timer_period', we disselect + * 'CONFIG_HARDLOCKUP_CHECK_TIMESTAMP'. So we need to make sure that + * firmware can set the period of the secure timer and the timer + * interrupt doesn't trigger too soon. + */ + if (sdei_api_set_secure_timer_period(watchdog_thresh)) { + pr_err("Firmware doesn't support setting the secure timer period, please update your BIOS !\n"); + return -EINVAL; + } + on_each_cpu(sdei_nmi_watchdog_bind, NULL, true); ret = sdei_event_register(sdei_watchdog_event_num, diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c index 8f354769e4f8c46169909963073251961824ec64..49443541d7f1a49de4d5e0af6073c7b2f9532da3 100644 --- a/drivers/firmware/arm_sdei.c +++ b/drivers/firmware/arm_sdei.c @@ -203,6 +203,12 @@ int sdei_api_clear_eoi(int hwirq) NULL); } +int sdei_api_set_secure_timer_period(int sec) +{ + return invoke_sdei_fn(SDEI_1_0_FN_SET_SECURE_TIMER_PERIOD, sec, 0, 0, 0, + 0, NULL); +} + static int sdei_api_event_get_info(u32 event, u32 info, u64 *result) { return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_GET_INFO, event, info, 0, diff --git a/include/linux/arm_sdei.h b/include/linux/arm_sdei.h index 7ca9aad9d3a5f41236ca9fd9544b09fc97695ee6..f3027342c9643fcc45ed8f15e6447abc7348a39d 100644 --- a/include/linux/arm_sdei.h +++ b/include/linux/arm_sdei.h @@ -40,6 +40,7 @@ int sdei_api_event_interrupt_bind(int hwirq); int sdei_api_event_disable(u32 event_num); int sdei_api_event_enable(u32 event_num); int sdei_api_clear_eoi(int hwirq); +int sdei_api_set_secure_timer_period(int sec); /* GHES register/unregister helpers */ int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb, diff --git a/include/uapi/linux/arm_sdei.h b/include/uapi/linux/arm_sdei.h index 1187b1b49c87db86884d9ac50abebced596109b9..a5375679dd503dbef5acc176442ecd073773aef3 100644 --- a/include/uapi/linux/arm_sdei.h +++ b/include/uapi/linux/arm_sdei.h @@ -25,6 +25,7 @@ #define SDEI_1_0_FN_SDEI_PRIVATE_RESET SDEI_1_0_FN(0x11) #define SDEI_1_0_FN_SDEI_SHARED_RESET SDEI_1_0_FN(0x12) #define SDEI_1_0_FN_SDEI_CLEAR_EOI SDEI_1_0_FN(0x18) +#define SDEI_1_0_FN_SET_SECURE_TIMER_PERIOD SDEI_1_0_FN(0x19) #define SDEI_VERSION_MAJOR_SHIFT 48 #define SDEI_VERSION_MAJOR_MASK 0x7fff diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index fdadaeccf79c0e1d8154718606ec1cbd198f773a..4afca654db572757086ea8fc673ac3c71a1ac314 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -968,7 +968,6 @@ config SDEI_WATCHDOG bool "SDEI NMI Watchdog support" depends on ARM_SDE_INTERFACE select HAVE_HARDLOCKUP_DETECTOR_ARCH - select HARDLOCKUP_CHECK_TIMESTAMP select HARDLOCKUP_DETECTOR #