@@ -12,9 +12,12 @@
* GNU General Public License for more details.
*/
+#include <linux/kdebug.h>
#include <acpi/apei.h>
#include <asm/mce.h>
+#include <asm/nmi.h>
+#include <asm/tlbflush.h>
int apei_arch_enable_cmcff(struct acpi_hest_header *hest_hdr, void *data)
{
@@ -54,3 +57,25 @@ void apei_arch_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
apei_mce_report_mem_error(sev, mem_err);
#endif
}
+
+int arch_apei_register_nmi(int (*nmi_handler)(unsigned int, struct pt_regs *),
+ const char *name)
+{
+ struct nmiaction apei_nmi_action = {
+ .handler = nmi_handler,
+ .name = name,
+ .flags = 0,
+ };
+
+ return __register_nmi_handler(NMI_LOCAL, &apei_nmi_action);
+}
+
+void arch_apei_unregister_nmi(const char *name)
+{
+ unregister_nmi_handler(NMI_LOCAL, name);
+}
+
+void arch_apei_nmi_oops_begin(void)
+{
+ oops_begin();
+}
@@ -758,6 +758,25 @@ void __weak apei_arch_report_mem_error(int sev,
}
EXPORT_SYMBOL_GPL(apei_arch_report_mem_error);
+int __weak arch_apei_register_nmi(
+ __attribute__((unused)) int (*nmi_handler)(unsigned int,
+ struct pt_regs *),
+ const char *name)
+{
+ return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(arch_apei_register_nmi);
+
+void __weak arch_apei_unregister_nmi(const char *name)
+{
+}
+EXPORT_SYMBOL_GPL(arch_apei_unregister_nmi);
+
+void __weak arch_apei_nmi_oops_begin(void)
+{
+}
+EXPORT_SYMBOL_GPL(arch_apei_nmi_oops_begin);
+
int apei_osc_setup(void)
{
static u8 whea_uuid_str[] = "ed855e0c-6c90-47bf-a62a-26de0fc5ad5c";
@@ -51,7 +51,6 @@
#include <acpi/ghes.h>
#include <acpi/apei.h>
#include <asm/tlbflush.h>
-#include <asm/nmi.h>
#include "apei-internal.h"
@@ -817,7 +816,7 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
{
struct ghes *ghes, *ghes_global = NULL;
int sev, sev_global = -1;
- int ret = NMI_DONE;
+ int ret = APEI_NMI_DONE;
BUG_ON(!IS_ENABLED(CONFIG_ACPI_APEI_NMI));
@@ -832,14 +831,14 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
sev_global = sev;
ghes_global = ghes;
}
- ret = NMI_HANDLED;
+ ret = APEI_NMI_HANDLED;
}
- if (ret == NMI_DONE)
+ if (ret == APEI_NMI_DONE)
goto out;
if (sev_global >= GHES_SEV_PANIC) {
- oops_begin();
+ arch_apei_nmi_oops_begin();
ghes_print_queued_estatus();
__ghes_print_estatus(KERN_EMERG, ghes_global->generic,
ghes_global->estatus);
@@ -909,8 +908,7 @@ static int ghes_notify_init_nmi(struct ghes *ghes)
ghes_estatus_pool_expand(len);
mutex_lock(&ghes_list_mutex);
if (list_empty(&ghes_nmi))
- status = register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0,
- "ghes");
+ status = arch_apei_register_nmi(ghes_notify_nmi, "ghes");
list_add_rcu(&ghes->list, &ghes_nmi);
mutex_unlock(&ghes_list_mutex);
@@ -924,7 +922,7 @@ static void ghes_notify_remove_nmi(struct ghes *ghes)
mutex_lock(&ghes_list_mutex);
list_del_rcu(&ghes->list);
if (list_empty(&ghes_nmi))
- unregister_nmi_handler(NMI_LOCAL, "ghes");
+ arch_apei_unregister_nmi("ghes");
mutex_unlock(&ghes_list_mutex);
/*
* To synchronize with NMI handler, ghes can only be
@@ -14,6 +14,9 @@
#define APEI_ERST_CLEAR_RECORD _IOW('E', 1, u64)
#define APEI_ERST_GET_RECORD_COUNT _IOR('E', 2, u32)
+#define APEI_NMI_DONE 0
+#define APEI_NMI_HANDLED 1
+
#ifdef __KERNEL__
extern bool hest_disable;
@@ -44,6 +47,10 @@ int erst_clear(u64 record_id);
int apei_arch_enable_cmcff(struct acpi_hest_header *hest_hdr, void *data);
void apei_arch_report_mem_error(int sev, struct cper_sec_mem_err *mem_err);
+int arch_apei_register_nmi(int (*nmi_handler)(unsigned int, struct pt_regs *),
+ const char *name);
+void arch_apei_unregister_nmi(const char *name);
+void arch_apei_nmi_oops_begin(void);
#endif
#endif
Similar to MCE related patch, all NMI architectural calls are abstracted. Also, we are providing corresponding X86 functions' content. Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org> --- arch/x86/kernel/acpi/apei.c | 25 +++++++++++++++++++++++++ drivers/acpi/apei/apei-base.c | 19 +++++++++++++++++++ drivers/acpi/apei/ghes.c | 14 ++++++-------- include/acpi/apei.h | 7 +++++++ 4 files changed, 57 insertions(+), 8 deletions(-)