Skip to content

Commit

Permalink
ARM: 9115/1: mm/maccess: fix unaligned copy_{from,to}_kernel_nofault
Browse files Browse the repository at this point in the history
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: Christoph Hellwig <hch@lst.de>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
  • Loading branch information
arndb authored and Russell King (Oracle) committed Aug 20, 2021
1 parent b30d028 commit 2423de2
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions mm/maccess.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
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))
return -ERANGE;

pagefault_disable();
copy_from_kernel_nofault_loop(dst, src, size, u64, Efault);
copy_from_kernel_nofault_loop(dst, src, size, u32, Efault);
copy_from_kernel_nofault_loop(dst, src, size, u16, Efault);
if (!(align & 7))
copy_from_kernel_nofault_loop(dst, src, size, u64, 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);
pagefault_enable();
return 0;
Expand All @@ -50,10 +58,18 @@ EXPORT_SYMBOL_GPL(copy_from_kernel_nofault);

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();
copy_to_kernel_nofault_loop(dst, src, size, u64, Efault);
copy_to_kernel_nofault_loop(dst, src, size, u32, Efault);
copy_to_kernel_nofault_loop(dst, src, size, u16, Efault);
if (!(align & 7))
copy_to_kernel_nofault_loop(dst, src, size, u64, 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);
pagefault_enable();
return 0;
Expand Down

0 comments on commit 2423de2

Please sign in to comment.