From: Tony Luck <tony.luck@intel.com>
To: Ingo Molnar <mingo@kernel.org>
Cc: linux-kernel@vger.kernel.org,
Linus Torvalds <torvalds@linux-foundation.org>,
Thomas Gleixner <tglx@linutronix.de>,
Tony Luck <tony.luck@intel.com>, Borislav Petkov <bp@alien8.de>,
Andrew Morton <akpm@linux-foundation.org>,
Tony Luck <tony.luck@gmail.com>,
Peter Zijlstra <a.p.zijlstra@chello.nl>,
Ingo Molnar <mingo@kernel.org>, "H. Peter Anvin" <hpa@zytor.com>,
Andy Lutomirski <luto@amacapital.net>
Subject: [PATCH v14] x86, mce: Add memcpy_mcsafe()
Date: Thu, 18 Feb 2016 11:47:26 -0800 [thread overview]
Message-ID: <a44e1055efc2d2a9473307b22c91caa437aa3f8b.1456439214.git.tony.luck@intel.com> (raw)
In-Reply-To: <CALCETrWY+fBPgc+bKHp3BzAsT7bvSbdLJf-h5fEV+_rj+JwxCA@mail.gmail.com>
Make use of the EXTABLE_FAULT exception table entries to write
a kernel copy routine that doesn't crash the system if it
encounters a machine check. Prime use case for this is to copy
from large arrays of non-volatile memory used as storage.
We have to use an unrolled copy loop for now because current
hardware implementations treat a machine check in "rep mov"
as fatal. When that is fixed we can simplify.
Signed-off-by: Tony Luck <tony.luck@intel.com>
---
Is this what we want now? Return type is a "bool". True means
that we copied OK, false means that it didn't (this is all that
Dan says that he needs). Dropped all the complex code to figure
out how many bytes we didn't copy as Linus says this isn't the
right place to do this (and besides we should just make "rep mov"
work). Changed the name from "_trap" since we no longer return
the trap number. I'm not wedded to "memcpy_mcsafe" though, so
feel free to suggest alternates.
Nothing to do with copy_from_user() in here ... just completing
the patch series that we need for non-volatile storage.
arch/x86/include/asm/string_64.h | 13 +++++
arch/x86/kernel/x8664_ksyms_64.c | 2 +
arch/x86/lib/memcpy_64.S | 117 +++++++++++++++++++++++++++++++++++++++
3 files changed, 132 insertions(+)
diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h
index ff8b9a17dc4b..ca6ba3607705 100644
--- a/arch/x86/include/asm/string_64.h
+++ b/arch/x86/include/asm/string_64.h
@@ -78,6 +78,19 @@ int strcmp(const char *cs, const char *ct);
#define memset(s, c, n) __memset(s, c, n)
#endif
+/**
+ * memcpy_mcsafe - copy memory with indication if a machine check happened
+ *
+ * @dst: destination address
+ * @src: source address
+ * @cnt: number of bytes to copy
+ *
+ * Low level memory copy function that catches machine checks
+ *
+ * Return true for success, false for fail
+ */
+bool memcpy_mcsafe(void *dst, const void *src, size_t cnt);
+
#endif /* __KERNEL__ */
#endif /* _ASM_X86_STRING_64_H */
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index a0695be19864..cd05942bc918 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -37,6 +37,8 @@ EXPORT_SYMBOL(__copy_user_nocache);
EXPORT_SYMBOL(_copy_from_user);
EXPORT_SYMBOL(_copy_to_user);
+EXPORT_SYMBOL_GPL(memcpy_mcsafe);
+
EXPORT_SYMBOL(copy_page);
EXPORT_SYMBOL(clear_page);
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
index 16698bba87de..7d37641ada5b 100644
--- a/arch/x86/lib/memcpy_64.S
+++ b/arch/x86/lib/memcpy_64.S
@@ -177,3 +177,120 @@ ENTRY(memcpy_orig)
.Lend:
retq
ENDPROC(memcpy_orig)
+
+#ifndef CONFIG_UML
+/*
+ * memcpy_mcsafe - memory copy with machine check exception handling
+ * Note that we only catch machine checks when reading the source addresses.
+ * Writes to target are posted and don't generate machine checks.
+ */
+ENTRY(memcpy_mcsafe)
+ cmpl $8, %edx
+ /* Less than 8 bytes? Go to byte copy loop */
+ jb .L_no_whole_words
+
+ /* Check for bad alignment of source */
+ testl $7, %esi
+ /* Already aligned */
+ jz .L_8byte_aligned
+
+ /* Copy one byte at a time until source is 8-byte aligned */
+ movl %esi, %ecx
+ andl $7, %ecx
+ subl $8, %ecx
+ negl %ecx
+ subl %ecx, %edx
+.L_copy_leading_bytes:
+ movb (%rsi), %al
+ movb %al, (%rdi)
+ incq %rsi
+ incq %rdi
+ decl %ecx
+ jnz .L_copy_leading_bytes
+
+.L_8byte_aligned:
+ /* Figure out how many whole cache lines (64-bytes) to copy */
+ movl %edx, %ecx
+ andl $63, %edx
+ shrl $6, %ecx
+ jz .L_no_whole_cache_lines
+
+ /* Loop copying whole cache lines */
+.L_cache_w0: movq (%rsi), %r8
+.L_cache_w1: movq 1*8(%rsi), %r9
+.L_cache_w2: movq 2*8(%rsi), %r10
+.L_cache_w3: movq 3*8(%rsi), %r11
+ movq %r8, (%rdi)
+ movq %r9, 1*8(%rdi)
+ movq %r10, 2*8(%rdi)
+ movq %r11, 3*8(%rdi)
+.L_cache_w4: movq 4*8(%rsi), %r8
+.L_cache_w5: movq 5*8(%rsi), %r9
+.L_cache_w6: movq 6*8(%rsi), %r10
+.L_cache_w7: movq 7*8(%rsi), %r11
+ movq %r8, 4*8(%rdi)
+ movq %r9, 5*8(%rdi)
+ movq %r10, 6*8(%rdi)
+ movq %r11, 7*8(%rdi)
+ leaq 64(%rsi), %rsi
+ leaq 64(%rdi), %rdi
+ decl %ecx
+ jnz .L_cache_w0
+
+ /* Are there any trailing 8-byte words? */
+.L_no_whole_cache_lines:
+ movl %edx, %ecx
+ andl $7, %edx
+ shrl $3, %ecx
+ jz .L_no_whole_words
+
+ /* Copy trailing words */
+.L_copy_trailing_words:
+ movq (%rsi), %r8
+ mov %r8, (%rdi)
+ leaq 8(%rsi), %rsi
+ leaq 8(%rdi), %rdi
+ decl %ecx
+ jnz .L_copy_trailing_words
+
+ /* Any trailing bytes? */
+.L_no_whole_words:
+ andl %edx, %edx
+ jz .L_done_memcpy_trap
+
+ /* Copy trailing bytes */
+ movl %edx, %ecx
+.L_copy_trailing_bytes:
+ movb (%rsi), %al
+ movb %al, (%rdi)
+ incq %rsi
+ incq %rdi
+ decl %ecx
+ jnz .L_copy_trailing_bytes
+
+ /* Copy successful. Return true */
+.L_done_memcpy_trap:
+ xorq %rax, %rax
+ ret
+ENDPROC(memcpy_mcsafe)
+
+ .section .fixup, "ax"
+ /* Return false for any failure */
+.L_memcpy_mcsafe_fail:
+ mov $1, %rax
+ ret
+
+ .previous
+
+ _ASM_EXTABLE_FAULT(.L_copy_leading_bytes, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_cache_w0, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_cache_w1, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_cache_w4, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_cache_w5, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_cache_w6, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_cache_w7, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_copy_trailing_words, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_copy_trailing_bytes, .L_memcpy_mcsafe_fail)
+#endif
--
2.5.0
next prev parent reply other threads:[~2016-02-25 22:40 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-17 18:20 [PATCH v11 0/4] Machine check recovery when kernel accesses poison Tony Luck
2016-02-17 18:20 ` [PATCH v11 1/4] x86: Expand exception table to allow new handling options Tony Luck
2016-02-18 10:19 ` [tip:ras/core] x86/mm: Expand the exception table logic " tip-bot for Tony Luck
2016-02-17 18:20 ` [PATCH v11 2/4] x86, mce: Check for faults tagged in EXTABLE_CLASS_FAULT exception table entries Tony Luck
2016-02-18 10:19 ` [tip:ras/core] x86/mce: " tip-bot for Tony Luck
2016-02-17 18:20 ` [PATCH v11 3/4] x86, mce: Add __mcsafe_copy() Tony Luck
2016-02-18 8:21 ` Ingo Molnar
2016-02-18 9:59 ` Peter Zijlstra
2016-02-18 10:19 ` Ingo Molnar
2016-02-18 10:29 ` Borislav Petkov
2016-02-18 10:35 ` Peter Zijlstra
2016-02-18 14:59 ` Luck, Tony
2016-02-19 7:58 ` Ingo Molnar
2016-02-19 8:43 ` Peter Zijlstra
2016-02-19 9:51 ` Ingo Molnar
2016-02-18 10:29 ` Borislav Petkov
2016-02-18 10:34 ` Ingo Molnar
2016-02-18 10:36 ` Borislav Petkov
2016-02-18 18:48 ` Ingo Molnar
2016-02-18 21:14 ` [PATCH v12] x86, mce: Add memcpy_trap() Luck, Tony
2016-02-19 9:10 ` Ingo Molnar
2016-02-19 17:53 ` [PATCH v13] " Luck, Tony
2016-02-24 17:38 ` Tony Luck
2016-02-24 18:35 ` Linus Torvalds
2016-02-24 19:27 ` Tony Luck
2016-02-24 19:37 ` Linus Torvalds
2016-02-25 8:56 ` Ingo Molnar
2016-02-25 19:33 ` Luck, Tony
2016-02-25 20:39 ` Linus Torvalds
2016-02-25 22:11 ` Andy Lutomirski
2016-02-18 19:47 ` Tony Luck [this message]
2016-03-02 20:47 ` [PATCH v14] x86, mce: Add memcpy_mcsafe() Luck, Tony
2016-03-08 17:37 ` [tip:ras/core] x86/mm, x86/mce: " tip-bot for Tony Luck
2016-03-10 19:26 ` [PATCH v14] x86, mce: " Mika Penttilä
2016-03-10 19:37 ` Luck, Tony
2016-03-11 22:10 ` Tony Luck
2016-03-11 22:14 ` Dan Williams
2016-03-12 17:16 ` Ingo Molnar
2016-03-13 1:12 ` Linus Torvalds
2016-03-13 9:25 ` Ingo Molnar
2016-03-14 22:33 ` [PATCH] x86/mm, x86/mce: Fix return type/value for memcpy_mcsafe() Tony Luck
2016-03-16 8:06 ` [tip:x86/urgent] " tip-bot for Tony Luck
2016-02-26 0:58 ` [PATCH v13] x86, mce: Add memcpy_trap() Linus Torvalds
2016-02-26 1:19 ` Andy Lutomirski
2016-02-26 2:38 ` Linus Torvalds
2016-02-18 18:12 ` [PATCH v11 3/4] x86, mce: Add __mcsafe_copy() Linus Torvalds
2016-02-18 18:51 ` Ingo Molnar
2016-02-18 18:52 ` Luck, Tony
2016-02-18 20:14 ` Ingo Molnar
2016-02-18 21:33 ` Dan Williams
2016-02-17 18:20 ` [PATCH v11 4/4] x86: Create a new synthetic cpu capability for machine check recovery Tony Luck
2016-02-18 10:19 ` [tip:x86/asm] x86/cpufeature: " tip-bot for Tony Luck
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=a44e1055efc2d2a9473307b22c91caa437aa3f8b.1456439214.git.tony.luck@intel.com \
--to=tony.luck@intel.com \
--cc=a.p.zijlstra@chello.nl \
--cc=akpm@linux-foundation.org \
--cc=bp@alien8.de \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=mingo@kernel.org \
--cc=tglx@linutronix.de \
--cc=tony.luck@gmail.com \
--cc=torvalds@linux-foundation.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
all inboxes | Powered by JetHome®