From 76c89eaf74ae37983af713274769e8aa6caa65f1 Mon Sep 17 00:00:00 2001 From: Xiongfeng Wang Date: Sat, 2 Feb 2019 16:23:28 +0800 Subject: [PATCH] sdei_watchdog: use the secure arch timer as SDEI watchdog timer euler inclusion category: feature Bugzilla: 5515 CVE: N/A ---------------------------------------- This patch change the SDEI watchdog timer hardware IRQ number to use secure arm_arch_timer as SDEI watchdog timer, so that host os can also use SDEI NMI watchdog when there is a guest running on it. BIOS will program the secure timer, so this patch remove the code programming the timer.Also the secure can not be programmed in non-secure state. Signed-off-by: Xiongfeng Wang Reviewed-by: Hanjun Guo Signed-off-by: Yang Yingliang --- arch/arm64/kernel/watchdog_sdei.c | 38 ++++--------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/arch/arm64/kernel/watchdog_sdei.c b/arch/arm64/kernel/watchdog_sdei.c index fab1c575803f..874d51363f6c 100644 --- a/arch/arm64/kernel/watchdog_sdei.c +++ b/arch/arm64/kernel/watchdog_sdei.c @@ -16,26 +16,12 @@ #include #include -/* We use the arch virt timer as SDEI NMI watchdog timer */ -#define SDEI_NMI_WATCHDOG_HWIRQ 27 -#define SDEI_TIMER_INTERVAL 3 +/* We use the secure physical timer as SDEI NMI watchdog timer */ +#define SDEI_NMI_WATCHDOG_HWIRQ 29 static int sdei_watchdog_event_num; static bool disable_sdei_nmi_watchdog; -static void start_arch_virt_timer(int seconds) -{ - int timer_freq = arch_timer_get_rate(); - - write_sysreg_el0(1, cntv_ctl); - write_sysreg_el0(timer_freq * seconds, cntv_tval); -} - -static void stop_arch_virt_timer(void) -{ - write_sysreg_el0(0, cntv_ctl); -} - int watchdog_nmi_enable(unsigned int cpu) { int ret; @@ -47,8 +33,6 @@ int watchdog_nmi_enable(unsigned int cpu) return ret; } - start_arch_virt_timer(SDEI_TIMER_INTERVAL); - return 0; } @@ -60,15 +44,11 @@ void watchdog_nmi_disable(unsigned int cpu) if (ret) pr_err("Disable NMI Watchdog failed on cpu%d\n", smp_processor_id()); - - stop_arch_virt_timer(); } static int sdei_watchdog_callback(u32 event, struct pt_regs *regs, void *arg) { - /* reprogram the arch virt timer */ - start_arch_virt_timer(SDEI_TIMER_INTERVAL); watchdog_hardlockup_check(regs); return 0; @@ -84,11 +64,6 @@ static void sdei_nmi_watchdog_bind(void *data) smp_processor_id(), ret); } -/* Before BIOS implements SDEI platform event, the host OS will use arch - * virt timer as SDEI watchdog timer, so the guest os will failed to start - * because it can not use arch virt timer. We provide a mechanism to disable - * SDEI NMI watchdog in the host. - */ static int __init disable_sdei_nmi_watchdog_setup(char *str) { disable_sdei_nmi_watchdog = true; @@ -103,13 +78,8 @@ int __init watchdog_nmi_probe(void) if (disable_sdei_nmi_watchdog) return -EINVAL; - /* - * When hyp mode is not available and kernel is not in hyp mode, the system - * will use arch virt timer, which will conflict with SDEI NMI Watchdog. - * Refer to 'arch_timer_select_ppi'. - */ - if (!is_kernel_in_hyp_mode() && !is_hyp_mode_available()) { - pr_err("Disable SDEI NMI Watchdog because the system will use virt timer\n"); + if (!is_hyp_mode_available()) { + pr_err("Disable SDEI NMI Watchdog in VM\n"); return -EINVAL; } -- GitLab