提交 75ac7be9 编写于 作者: X Xiongfeng Wang 提交者: Zheng Zengkai

sdei_watchdog: clear EOI of the secure timer before kdump

hulk inclusion
category: feature
bugzilla: 48046
CVE: NA

-------------------------------------------------------------------------

When we panic in hardlockup, the secure timer interrupt remains activate
because firmware clear eoi after dispatch is completed. This will cause
arm_arch_timer interrupt failed to trigger in the second kernel.

This patch add a new SMC helper to clear eoi of a certain interrupt and
clear eoi of the secure timer before booting the second kernel.
Signed-off-by: NXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NXiongfeng Wang <wangxiongfeng2@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 5bc048a1
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/nmi.h>
#include <linux/page-flags.h> #include <linux/page-flags.h>
#include <linux/smp.h> #include <linux/smp.h>
...@@ -254,6 +255,15 @@ void machine_crash_shutdown(struct pt_regs *regs) ...@@ -254,6 +255,15 @@ void machine_crash_shutdown(struct pt_regs *regs)
/* shutdown non-crashing cpus */ /* shutdown non-crashing cpus */
crash_smp_send_stop(); crash_smp_send_stop();
/*
* when we panic in hardlockup detected by sdei_watchdog, the secure
* timer interrupt remains activate here because firmware clear eoi
* after dispatch is completed. This will cause arm_arch_timer
* interrupt failed to trigger in the second kernel. So we clear eoi
* of the secure timer before booting the second kernel.
*/
sdei_watchdog_clear_eoi();
/* for crashing cpu */ /* for crashing cpu */
crash_save_cpu(regs, smp_processor_id()); crash_save_cpu(regs, smp_processor_id());
machine_kexec_mask_interrupts(); machine_kexec_mask_interrupts();
......
...@@ -80,6 +80,12 @@ static int __init disable_sdei_nmi_watchdog_setup(char *str) ...@@ -80,6 +80,12 @@ static int __init disable_sdei_nmi_watchdog_setup(char *str)
} }
__setup("disable_sdei_nmi_watchdog", disable_sdei_nmi_watchdog_setup); __setup("disable_sdei_nmi_watchdog", disable_sdei_nmi_watchdog_setup);
void sdei_watchdog_clear_eoi(void)
{
if (sdei_watchdog_registered)
sdei_api_clear_eoi(SDEI_NMI_WATCHDOG_HWIRQ);
}
int __init watchdog_nmi_probe(void) int __init watchdog_nmi_probe(void)
{ {
int ret; int ret;
......
...@@ -197,6 +197,12 @@ int sdei_api_event_interrupt_bind(int hwirq) ...@@ -197,6 +197,12 @@ int sdei_api_event_interrupt_bind(int hwirq)
return (int)event_number; return (int)event_number;
} }
int sdei_api_clear_eoi(int hwirq)
{
return invoke_sdei_fn(SDEI_1_0_FN_SDEI_CLEAR_EOI, hwirq, 0, 0, 0, 0,
NULL);
}
static int sdei_api_event_get_info(u32 event, u32 info, u64 *result) 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, return invoke_sdei_fn(SDEI_1_0_FN_SDEI_EVENT_GET_INFO, event, info, 0,
......
...@@ -39,6 +39,7 @@ int sdei_event_disable(u32 event_num); ...@@ -39,6 +39,7 @@ int sdei_event_disable(u32 event_num);
int sdei_api_event_interrupt_bind(int hwirq); int sdei_api_event_interrupt_bind(int hwirq);
int sdei_api_event_disable(u32 event_num); int sdei_api_event_disable(u32 event_num);
int sdei_api_event_enable(u32 event_num); int sdei_api_event_enable(u32 event_num);
int sdei_api_clear_eoi(int hwirq);
/* GHES register/unregister helpers */ /* GHES register/unregister helpers */
int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb, int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb,
......
...@@ -222,4 +222,10 @@ int proc_watchdog_cpumask(struct ctl_table *, int, void *, size_t *, loff_t *); ...@@ -222,4 +222,10 @@ int proc_watchdog_cpumask(struct ctl_table *, int, void *, size_t *, loff_t *);
#include <asm/nmi.h> #include <asm/nmi.h>
#endif #endif
#ifdef CONFIG_SDEI_WATCHDOG
void sdei_watchdog_clear_eoi(void);
#else
static inline void sdei_watchdog_clear_eoi(void) { }
#endif
#endif #endif
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define SDEI_1_0_FN_SDEI_INTERRUPT_RELEASE SDEI_1_0_FN(0x0E) #define SDEI_1_0_FN_SDEI_INTERRUPT_RELEASE SDEI_1_0_FN(0x0E)
#define SDEI_1_0_FN_SDEI_PRIVATE_RESET SDEI_1_0_FN(0x11) #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_SHARED_RESET SDEI_1_0_FN(0x12)
#define SDEI_1_0_FN_SDEI_CLEAR_EOI SDEI_1_0_FN(0x18)
#define SDEI_VERSION_MAJOR_SHIFT 48 #define SDEI_VERSION_MAJOR_SHIFT 48
#define SDEI_VERSION_MAJOR_MASK 0x7fff #define SDEI_VERSION_MAJOR_MASK 0x7fff
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册