Commit 2423de2e authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Russell King (Oracle)

ARM: 9115/1: mm/maccess: fix unaligned copy_{from,to}_kernel_nofault

On machines such as ARMv5 that trap unaligned accesses, these
two functions can be slow when each access needs to be emulated,
or they might not work at all.

Change them so that each loop is only used when both the src
and dst pointers are naturally aligned.
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
parent b30d0289
...@@ -24,13 +24,21 @@ bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src, ...@@ -24,13 +24,21 @@ bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src,
long copy_from_kernel_nofault(void *dst, const void *src, size_t size) long copy_from_kernel_nofault(void *dst, const void *src, size_t size)
{ {
unsigned long align = 0;
if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
align = (unsigned long)dst | (unsigned long)src;
if (!copy_from_kernel_nofault_allowed(src, size)) if (!copy_from_kernel_nofault_allowed(src, size))
return -ERANGE; return -ERANGE;
pagefault_disable(); pagefault_disable();
copy_from_kernel_nofault_loop(dst, src, size, u64, Efault); if (!(align & 7))
copy_from_kernel_nofault_loop(dst, src, size, u32, Efault); copy_from_kernel_nofault_loop(dst, src, size, u64, Efault);
copy_from_kernel_nofault_loop(dst, src, size, u16, Efault); if (!(align & 3))
copy_from_kernel_nofault_loop(dst, src, size, u32, Efault);
if (!(align & 1))
copy_from_kernel_nofault_loop(dst, src, size, u16, Efault);
copy_from_kernel_nofault_loop(dst, src, size, u8, Efault); copy_from_kernel_nofault_loop(dst, src, size, u8, Efault);
pagefault_enable(); pagefault_enable();
return 0; return 0;
...@@ -50,10 +58,18 @@ EXPORT_SYMBOL_GPL(copy_from_kernel_nofault); ...@@ -50,10 +58,18 @@ EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);
long copy_to_kernel_nofault(void *dst, const void *src, size_t size) long copy_to_kernel_nofault(void *dst, const void *src, size_t size)
{ {
unsigned long align = 0;
if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
align = (unsigned long)dst | (unsigned long)src;
pagefault_disable(); pagefault_disable();
copy_to_kernel_nofault_loop(dst, src, size, u64, Efault); if (!(align & 7))
copy_to_kernel_nofault_loop(dst, src, size, u32, Efault); copy_to_kernel_nofault_loop(dst, src, size, u64, Efault);
copy_to_kernel_nofault_loop(dst, src, size, u16, Efault); if (!(align & 3))
copy_to_kernel_nofault_loop(dst, src, size, u32, Efault);
if (!(align & 1))
copy_to_kernel_nofault_loop(dst, src, size, u16, Efault);
copy_to_kernel_nofault_loop(dst, src, size, u8, Efault); copy_to_kernel_nofault_loop(dst, src, size, u8, Efault);
pagefault_enable(); pagefault_enable();
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment