aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/Kconfig.debug3
-rw-r--r--arch/x86/include/asm/mcsafe_test.h75
-rw-r--r--arch/x86/lib/memcpy_64.S10
-rw-r--r--tools/testing/nvdimm/test/nfit.c104
4 files changed, 192 insertions, 0 deletions
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 192e4d2f9efc..c6dd1d980081 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -72,6 +72,9 @@ config EARLY_PRINTK_USB_XDBC
72 You should normally say N here, unless you want to debug early 72 You should normally say N here, unless you want to debug early
73 crashes or need a very simple printk logging facility. 73 crashes or need a very simple printk logging facility.
74 74
75config MCSAFE_TEST
76 def_bool n
77
75config X86_PTDUMP_CORE 78config X86_PTDUMP_CORE
76 def_bool n 79 def_bool n
77 80
diff --git a/arch/x86/include/asm/mcsafe_test.h b/arch/x86/include/asm/mcsafe_test.h
new file mode 100644
index 000000000000..eb59804b6201
--- /dev/null
+++ b/arch/x86/include/asm/mcsafe_test.h
@@ -0,0 +1,75 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _MCSAFE_TEST_H_
3#define _MCSAFE_TEST_H_
4
5#ifndef __ASSEMBLY__
6#ifdef CONFIG_MCSAFE_TEST
7extern unsigned long mcsafe_test_src;
8extern unsigned long mcsafe_test_dst;
9
10static inline void mcsafe_inject_src(void *addr)
11{
12 if (addr)
13 mcsafe_test_src = (unsigned long) addr;
14 else
15 mcsafe_test_src = ~0UL;
16}
17
18static inline void mcsafe_inject_dst(void *addr)
19{
20 if (addr)
21 mcsafe_test_dst = (unsigned long) addr;
22 else
23 mcsafe_test_dst = ~0UL;
24}
25#else /* CONFIG_MCSAFE_TEST */
26static inline void mcsafe_inject_src(void *addr)
27{
28}
29
30static inline void mcsafe_inject_dst(void *addr)
31{
32}
33#endif /* CONFIG_MCSAFE_TEST */
34
35#else /* __ASSEMBLY__ */
36#include <asm/export.h>
37
38#ifdef CONFIG_MCSAFE_TEST
39.macro MCSAFE_TEST_CTL
40 .pushsection .data
41 .align 8
42 .globl mcsafe_test_src
43 mcsafe_test_src:
44 .quad 0
45 EXPORT_SYMBOL_GPL(mcsafe_test_src)
46 .globl mcsafe_test_dst
47 mcsafe_test_dst:
48 .quad 0
49 EXPORT_SYMBOL_GPL(mcsafe_test_dst)
50 .popsection
51.endm
52
53.macro MCSAFE_TEST_SRC reg count target
54 leaq \count(\reg), %r9
55 cmp mcsafe_test_src, %r9
56 ja \target
57.endm
58
59.macro MCSAFE_TEST_DST reg count target
60 leaq \count(\reg), %r9
61 cmp mcsafe_test_dst, %r9
62 ja \target
63.endm
64#else
65.macro MCSAFE_TEST_CTL
66.endm
67
68.macro MCSAFE_TEST_SRC reg count target
69.endm
70
71.macro MCSAFE_TEST_DST reg count target
72.endm
73#endif /* CONFIG_MCSAFE_TEST */
74#endif /* __ASSEMBLY__ */
75#endif /* _MCSAFE_TEST_H_ */
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
index c3b527a9f95d..298ef1479240 100644
--- a/arch/x86/lib/memcpy_64.S
+++ b/arch/x86/lib/memcpy_64.S
@@ -3,6 +3,7 @@
3#include <linux/linkage.h> 3#include <linux/linkage.h>
4#include <asm/errno.h> 4#include <asm/errno.h>
5#include <asm/cpufeatures.h> 5#include <asm/cpufeatures.h>
6#include <asm/mcsafe_test.h>
6#include <asm/alternative-asm.h> 7#include <asm/alternative-asm.h>
7#include <asm/export.h> 8#include <asm/export.h>
8 9
@@ -183,6 +184,9 @@ ENTRY(memcpy_orig)
183ENDPROC(memcpy_orig) 184ENDPROC(memcpy_orig)
184 185
185#ifndef CONFIG_UML 186#ifndef CONFIG_UML
187
188MCSAFE_TEST_CTL
189
186/* 190/*
187 * __memcpy_mcsafe - memory copy with machine check exception handling 191 * __memcpy_mcsafe - memory copy with machine check exception handling
188 * Note that we only catch machine checks when reading the source addresses. 192 * Note that we only catch machine checks when reading the source addresses.
@@ -206,6 +210,8 @@ ENTRY(__memcpy_mcsafe)
206 subl %ecx, %edx 210 subl %ecx, %edx
207.L_read_leading_bytes: 211.L_read_leading_bytes:
208 movb (%rsi), %al 212 movb (%rsi), %al
213 MCSAFE_TEST_SRC %rsi 1 .E_leading_bytes
214 MCSAFE_TEST_DST %rdi 1 .E_leading_bytes
209.L_write_leading_bytes: 215.L_write_leading_bytes:
210 movb %al, (%rdi) 216 movb %al, (%rdi)
211 incq %rsi 217 incq %rsi
@@ -221,6 +227,8 @@ ENTRY(__memcpy_mcsafe)
221 227
222.L_read_words: 228.L_read_words:
223 movq (%rsi), %r8 229 movq (%rsi), %r8
230 MCSAFE_TEST_SRC %rsi 8 .E_read_words
231 MCSAFE_TEST_DST %rdi 8 .E_write_words
224.L_write_words: 232.L_write_words:
225 movq %r8, (%rdi) 233 movq %r8, (%rdi)
226 addq $8, %rsi 234 addq $8, %rsi
@@ -237,6 +245,8 @@ ENTRY(__memcpy_mcsafe)
237 movl %edx, %ecx 245 movl %edx, %ecx
238.L_read_trailing_bytes: 246.L_read_trailing_bytes:
239 movb (%rsi), %al 247 movb (%rsi), %al
248 MCSAFE_TEST_SRC %rsi 1 .E_trailing_bytes
249 MCSAFE_TEST_DST %rdi 1 .E_trailing_bytes
240.L_write_trailing_bytes: 250.L_write_trailing_bytes:
241 movb %al, (%rdi) 251 movb %al, (%rdi)
242 incq %rsi 252 incq %rsi
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 4ea385be528f..a8fb63edcf89 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -29,6 +29,8 @@
29#include "nfit_test.h" 29#include "nfit_test.h"
30#include "../watermark.h" 30#include "../watermark.h"
31 31
32#include <asm/mcsafe_test.h>
33
32/* 34/*
33 * Generate an NFIT table to describe the following topology: 35 * Generate an NFIT table to describe the following topology:
34 * 36 *
@@ -2681,6 +2683,107 @@ static struct platform_driver nfit_test_driver = {
2681 .id_table = nfit_test_id, 2683 .id_table = nfit_test_id,
2682}; 2684};
2683 2685
2686static char mcsafe_buf[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
2687
2688enum INJECT {
2689 INJECT_NONE,
2690 INJECT_SRC,
2691 INJECT_DST,
2692};
2693
2694static void mcsafe_test_init(char *dst, char *src, size_t size)
2695{
2696 size_t i;
2697
2698 memset(dst, 0xff, size);
2699 for (i = 0; i < size; i++)
2700 src[i] = (char) i;
2701}
2702
2703static bool mcsafe_test_validate(unsigned char *dst, unsigned char *src,
2704 size_t size, unsigned long rem)
2705{
2706 size_t i;
2707
2708 for (i = 0; i < size - rem; i++)
2709 if (dst[i] != (unsigned char) i) {
2710 pr_info_once("%s:%d: offset: %zd got: %#x expect: %#x\n",
2711 __func__, __LINE__, i, dst[i],
2712 (unsigned char) i);
2713 return false;
2714 }
2715 for (i = size - rem; i < size; i++)
2716 if (dst[i] != 0xffU) {
2717 pr_info_once("%s:%d: offset: %zd got: %#x expect: 0xff\n",
2718 __func__, __LINE__, i, dst[i]);
2719 return false;
2720 }
2721 return true;
2722}
2723
2724void mcsafe_test(void)
2725{
2726 char *inject_desc[] = { "none", "source", "destination" };
2727 enum INJECT inj;
2728
2729 if (IS_ENABLED(CONFIG_MCSAFE_TEST)) {
2730 pr_info("%s: run...\n", __func__);
2731 } else {
2732 pr_info("%s: di