From: tip-bot for Tony Luck <tipbot@zytor.com>
To: linux-tip-commits@vger.kernel.org
Cc: akpm@linux-foundation.org, tony.luck@gmail.com, hpa@zytor.com,
luto@amacapital.net, bp@alien8.de, linux-kernel@vger.kernel.org,
tglx@linutronix.de, tony.luck@intel.com,
torvalds@linux-foundation.org, mingo@kernel.org,
peterz@infradead.org, a.p.zijlstra@chello.nl
Subject: [tip:ras/core] x86/mm, x86/mce: Add memcpy_mcsafe()
Date: Tue, 8 Mar 2016 09:37:03 -0800 [thread overview]
Message-ID: <tip-92b0729c34cab1f46d89aace3e66015f0bb4a682@git.kernel.org> (raw)
In-Reply-To: <a44e1055efc2d2a9473307b22c91caa437aa3f8b.1456439214.git.tony.luck@intel.com>
Commit-ID: 92b0729c34cab1f46d89aace3e66015f0bb4a682
Gitweb: http://git.kernel.org/tip/92b0729c34cab1f46d89aace3e66015f0bb4a682
Author: Tony Luck <tony.luck@intel.com>
AuthorDate: Thu, 18 Feb 2016 11:47:26 -0800
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Tue, 8 Mar 2016 17:54:38 +0100
x86/mm, x86/mce: Add memcpy_mcsafe()
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.
Return type is a "bool". True means that we copied OK, false means
that it didn't.
Signed-off-by: Tony Luck <tony.luck@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Luck <tony.luck@gmail.com>
Link: http://lkml.kernel.org/r/a44e1055efc2d2a9473307b22c91caa437aa3f8b.1456439214.git.tony.luck@intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
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 ff8b9a1..ca6ba36 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 a0695be..cd05942 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 16698bb..7d37641 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
next prev parent reply other threads:[~2016-03-08 17:38 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 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
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 ` [PATCH v14] x86, mce: Add memcpy_mcsafe() Tony Luck
2016-03-02 20:47 ` Luck, Tony
2016-03-08 17:37 ` tip-bot for Tony Luck [this message]
2016-03-10 19:26 ` 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
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=tip-92b0729c34cab1f46d89aace3e66015f0bb4a682@git.kernel.org \
--to=tipbot@zytor.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=linux-tip-commits@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=tony.luck@gmail.com \
--cc=tony.luck@intel.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;
as well as URLs for NNTP newsgroup(s).