From: Tony Luck <tony.luck@intel.com>
To: Ingo Molnar <mingo@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>,
Andrew Morton <akpm@linux-foundation.org>,
Andy Lutomirski <luto@kernel.org>,
Dan Williams <dan.j.williams@intel.com>,
elliott@hpe.com, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, linux-nvdimm@ml01.01.org, x86@kernel.org
Subject: [PATCHV4 1/3] x86, ras: Add new infrastructure for machine check fixup tables
Date: Tue, 15 Dec 2015 17:29:30 -0800 [thread overview]
Message-ID: <8e88add913a23a434fbbcfc9f63c0849edc2ce6f.1450990481.git.tony.luck@intel.com> (raw)
In-Reply-To: <cover.1450990481.git.tony.luck@intel.com>
Copy the existing page fault fixup mechanisms to create a new table
to be used when fixing machine checks. Note:
1) At this time we only provide a macro to annotate assembly code
2) We assume all fixups will in code builtin to the kernel.
3) Only for x86_64
4) New code under CONFIG_MCE_KERNEL_RECOVERY (default 'n')
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Reviewed-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
arch/x86/Kconfig | 10 ++++++++++
arch/x86/include/asm/asm.h | 10 ++++++++--
arch/x86/include/asm/mce.h | 14 ++++++++++++++
arch/x86/kernel/cpu/mcheck/mce.c | 16 ++++++++++++++++
arch/x86/kernel/vmlinux.lds.S | 6 +++++-
arch/x86/mm/extable.c | 16 ++++++++++++++++
include/asm-generic/vmlinux.lds.h | 12 +++++++-----
7 files changed, 76 insertions(+), 8 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 96d058a87100..42d26b4d1ec4 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1001,6 +1001,16 @@ config X86_MCE_INJECT
If you don't know what a machine check is and you don't do kernel
QA it is safe to say n.
+config MCE_KERNEL_RECOVERY
+ bool "Recovery from machine checks in special kernel memory copy functions"
+ default n
+ depends on X86_MCE && X86_64
+ ---help---
+ This option provides a new memory copy function mcsafe_memcpy()
+ that is annotated to allow the machine check handler to return
+ to an alternate code path to return an error to the caller instead
+ of crashing the system. Say yes if you have a driver that uses this.
+
config X86_THERMAL_VECTOR
def_bool y
depends on X86_MCE_INTEL
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 189679aba703..a5d483ac11fa 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -44,13 +44,19 @@
/* Exception table entry */
#ifdef __ASSEMBLY__
-# define _ASM_EXTABLE(from,to) \
- .pushsection "__ex_table","a" ; \
+# define __ASM_EXTABLE(from, to, table) \
+ .pushsection table, "a" ; \
.balign 8 ; \
.long (from) - . ; \
.long (to) - . ; \
.popsection
+# define _ASM_EXTABLE(from, to) \
+ __ASM_EXTABLE(from, to, "__ex_table")
+
+# define _ASM_MCEXTABLE(from, to) \
+ __ASM_EXTABLE(from, to, "__mcex_table")
+
# define _ASM_EXTABLE_EX(from,to) \
.pushsection "__ex_table","a" ; \
.balign 8 ; \
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 2dbc0bf2b9f3..9dc11d2a9db1 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -279,4 +279,18 @@ struct cper_sec_mem_err;
extern void apei_mce_report_mem_error(int corrected,
struct cper_sec_mem_err *mem_err);
+#ifdef CONFIG_MCE_KERNEL_RECOVERY
+const struct exception_table_entry *search_mcexception_tables(unsigned long a);
+int fixup_mcexception(struct pt_regs *regs);
+#else
+static inline const struct exception_table_entry *search_mcexception_tables(unsigned long a)
+{
+ return 0;
+}
+static inline int fixup_mcexception(struct pt_regs *regs)
+{
+ return 0;
+}
+#endif
+
#endif /* _ASM_X86_MCE_H */
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 9d014b82a124..0111cd49ee94 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -31,6 +31,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/poll.h>
#include <linux/nmi.h>
@@ -2022,8 +2023,23 @@ static int __init mcheck_enable(char *str)
}
__setup("mce", mcheck_enable);
+#ifdef CONFIG_MCE_KERNEL_RECOVERY
+extern struct exception_table_entry __start___mcex_table[];
+extern struct exception_table_entry __stop___mcex_table[];
+
+/* Given an address, look for it in the machine check exception tables. */
+const struct exception_table_entry *search_mcexception_tables(unsigned long addr)
+{
+ return search_extable(__start___mcex_table, __stop___mcex_table-1, addr);
+}
+#endif
+
int __init mcheck_init(void)
{
+#ifdef CONFIG_MCE_KERNEL_RECOVERY
+ if (__stop___mcex_table > __start___mcex_table)
+ sort_extable(__start___mcex_table, __stop___mcex_table);
+#endif
mcheck_intel_therm_init();
mce_register_decode_chain(&mce_srao_nb);
mcheck_vendor_init_severity();
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 74e4bf11f562..a65fa0deda06 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -110,7 +110,11 @@ SECTIONS
NOTES :text :note
- EXCEPTION_TABLE(16) :text = 0x9090
+ EXCEPTION_TABLE(16)
+#ifdef CONFIG_MCE_KERNEL_RECOVERY
+ NAMED_EXCEPTION_TABLE(16, mcex)
+#endif
+ :text = 0x9090
#if defined(CONFIG_DEBUG_RODATA)
/* .text should occupy whole number of pages */
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 903ec1e9c326..4ee867e30c66 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -2,6 +2,7 @@
#include <linux/spinlock.h>
#include <linux/sort.h>
#include <asm/uaccess.h>
+#include <asm/mce.h>
static inline unsigned long
ex_insn_addr(const struct exception_table_entry *x)
@@ -49,6 +50,21 @@ int fixup_exception(struct pt_regs *regs)
return 0;
}
+#ifdef CONFIG_MCE_KERNEL_RECOVERY
+int fixup_mcexception(struct pt_regs *regs)
+{
+ const struct exception_table_entry *fixup;
+
+ fixup = search_mcexception_tables(regs->ip);
+ if (fixup) {
+ regs->ip = ex_fixup_addr(fixup);
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
/* Restricted version used during very early boot */
int __init early_fixup_exception(unsigned long *ip)
{
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 1781e54ea6d3..42ef98de373a 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -467,14 +467,16 @@
/*
* Exception table
*/
-#define EXCEPTION_TABLE(align) \
+#define NAMED_EXCEPTION_TABLE(align, pfx) \
. = ALIGN(align); \
- __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { \
- VMLINUX_SYMBOL(__start___ex_table) = .; \
- *(__ex_table) \
- VMLINUX_SYMBOL(__stop___ex_table) = .; \
+ __##pfx##_table : AT(ADDR(__##pfx##_table) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start___##pfx##_table) = .; \
+ *(__##pfx##_table) \
+ VMLINUX_SYMBOL(__stop___##pfx##_table) = .; \
}
+#define EXCEPTION_TABLE(align) NAMED_EXCEPTION_TABLE(align, ex)
+
/*
* Init task
*/
--
2.1.4
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2015-12-24 21:09 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-24 20:54 [PATCHV4 0/3] Machine check recovery when kernel accesses poison Tony Luck
2015-12-16 1:29 ` Tony Luck [this message]
2015-12-16 1:29 ` [PATCHV4 2/3] x86, ras: Extend machine check recovery code to annotated ring0 areas Tony Luck
2015-12-16 1:30 ` [PATCHV4 3/3] x86, ras: Add __mcsafe_copy() function to recover from machine checks Tony Luck
2015-12-24 21:46 ` Borislav Petkov
2015-12-16 1:30 ` [PATCHV5 " Tony Luck
2015-12-25 11:49 ` Borislav Petkov
2015-12-25 20:05 ` Luck, Tony
2015-12-26 10:32 ` Borislav Petkov
2015-12-26 14:54 ` Andy Lutomirski
2015-12-27 2:08 ` Tony Luck
2015-12-27 2:15 ` Andy Lutomirski
2015-12-27 2:16 ` Andy Lutomirski
2015-12-27 6:57 ` Tony Luck
2015-12-27 10:09 ` Borislav Petkov
2015-12-27 12:19 ` Andy Lutomirski
2015-12-27 13:17 ` Boris Petkov
2015-12-27 13:25 ` Andy Lutomirski
2015-12-27 13:33 ` Borislav Petkov
2015-12-27 13:40 ` Andy Lutomirski
2015-12-27 19:04 ` Dan Williams
2015-12-27 12:18 ` Andy Lutomirski
2015-12-30 23:32 ` Tony Luck
2015-12-31 20:30 ` Tony Luck
2015-12-31 21:22 ` Andy Lutomirski
2016-01-01 22:19 ` Tony Luck
2016-01-03 3:40 ` Andy Lutomirski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8e88add913a23a434fbbcfc9f63c0849edc2ce6f.1450990481.git.tony.luck@intel.com \
--to=tony.luck@intel.com \
--cc=akpm@linux-foundation.org \
--cc=bp@alien8.de \
--cc=dan.j.williams@intel.com \
--cc=elliott@hpe.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-nvdimm@ml01.01.org \
--cc=luto@kernel.org \
--cc=mingo@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).