Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86, pmem: use memcpy_mcsafe() for memcpy_from_pmem()

Update the definition of memcpy_from_pmem() to return 0 or a negative
error code. Implement x86/arch_memcpy_from_pmem() with memcpy_mcsafe().

Cc: Borislav Petkov <bp@alien8.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Acked-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+27 -8
+9
arch/x86/include/asm/pmem.h
··· 47 47 BUG(); 48 48 } 49 49 50 + static inline int arch_memcpy_from_pmem(void *dst, const void __pmem *src, 51 + size_t n) 52 + { 53 + if (static_cpu_has(X86_FEATURE_MCE_RECOVERY)) 54 + return memcpy_mcsafe(dst, (void __force *) src, n); 55 + memcpy(dst, (void __force *) src, n); 56 + return 0; 57 + } 58 + 50 59 /** 51 60 * arch_wmb_pmem - synchronize writes to persistent memory 52 61 *
+2 -2
drivers/nvdimm/pmem.c
··· 99 99 if (unlikely(bad_pmem)) 100 100 rc = -EIO; 101 101 else { 102 - memcpy_from_pmem(mem + off, pmem_addr, len); 102 + rc = memcpy_from_pmem(mem + off, pmem_addr, len); 103 103 flush_dcache_page(page); 104 104 } 105 105 } else { ··· 295 295 296 296 if (unlikely(is_bad_pmem(&pmem->bb, offset / 512, sz_align))) 297 297 return -EIO; 298 - memcpy_from_pmem(buf, pmem->virt_addr + offset, size); 298 + return memcpy_from_pmem(buf, pmem->virt_addr + offset, size); 299 299 } else { 300 300 memcpy_to_pmem(pmem->virt_addr + offset, buf, size); 301 301 wmb_pmem();
+16 -6
include/linux/pmem.h
··· 42 42 BUG(); 43 43 } 44 44 45 + static inline int arch_memcpy_from_pmem(void *dst, const void __pmem *src, 46 + size_t n) 47 + { 48 + BUG(); 49 + return -EFAULT; 50 + } 51 + 45 52 static inline size_t arch_copy_from_iter_pmem(void __pmem *addr, size_t bytes, 46 53 struct iov_iter *i) 47 54 { ··· 73 66 #endif 74 67 75 68 /* 76 - * Architectures that define ARCH_HAS_PMEM_API must provide 77 - * implementations for arch_memcpy_to_pmem(), arch_wmb_pmem(), 78 - * arch_copy_from_iter_pmem(), arch_clear_pmem(), arch_wb_cache_pmem() 79 - * and arch_has_wmb_pmem(). 69 + * memcpy_from_pmem - read from persistent memory with error handling 70 + * @dst: destination buffer 71 + * @src: source buffer 72 + * @size: transfer length 73 + * 74 + * Returns 0 on success negative error code on failure. 80 75 */ 81 - static inline void memcpy_from_pmem(void *dst, void __pmem const *src, size_t size) 76 + static inline int memcpy_from_pmem(void *dst, void __pmem const *src, 77 + size_t size) 82 78 { 83 - memcpy(dst, (void __force const *) src, size); 79 + return arch_memcpy_from_pmem(dst, src, size); 84 80 } 85 81 86 82 static inline bool arch_has_pmem_api(void)