Skip to content

Commit 1cce91d

Browse files
arndbRussell King
authored andcommitted
ARM: 8715/1: add a private asm/unaligned.h
The asm-generic/unaligned.h header provides two different implementations for accessing unaligned variables: the access_ok.h version used when CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is set pretends that all pointers are in fact aligned, while the le_struct.h version convinces gcc that the alignment of a pointer is '1', to make it issue the correct load/store instructions depending on the architecture flags. On ARMv5 and older, we always use the second version, to let the compiler use byte accesses. On ARMv6 and newer, we currently use the access_ok.h version, so the compiler can use any instruction including stm/ldm and ldrd/strd that will cause an alignment trap. This trap can significantly impact performance when we have to do a lot of fixups and, worse, has led to crashes in the LZ4 decompressor code that does not have a trap handler. This adds an ARM specific version of asm/unaligned.h that uses the le_struct.h/be_struct.h implementation unconditionally. This should lead to essentially the same code on ARMv6+ as before, with the exception of using regular load/store instructions instead of the trapping instructions multi-register variants. The crash in the LZ4 decompressor code was probably introduced by the patch replacing the LZ4 implementation, commit 4e1a33b ("lib: update LZ4 compressor module"), so linux-4.11 and higher would be affected most. However, we probably want to have this backported to all older stable kernels as well, to help with the performance issues. There are two follow-ups that I think we should also work on, but not backport to stable kernels, first to change the asm-generic version of the header to remove the ARM special case, and second to review all other uses of CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS to see if they might be affected by the same problem on ARM. Cc: [email protected] Signed-off-by: Arnd Bergmann <[email protected]> Signed-off-by: Russell King <[email protected]>
1 parent ee3eaee commit 1cce91d

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

arch/arm/include/asm/Kbuild

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ generic-y += simd.h
2020
generic-y += sizes.h
2121
generic-y += timex.h
2222
generic-y += trace_clock.h
23-
generic-y += unaligned.h
2423

2524
generated-y += mach-types.h
2625
generated-y += unistd-nr.h

arch/arm/include/asm/unaligned.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#ifndef __ASM_ARM_UNALIGNED_H
2+
#define __ASM_ARM_UNALIGNED_H
3+
4+
/*
5+
* We generally want to set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS on ARMv6+,
6+
* but we don't want to use linux/unaligned/access_ok.h since that can lead
7+
* to traps on unaligned stm/ldm or strd/ldrd.
8+
*/
9+
#include <asm/byteorder.h>
10+
11+
#if defined(__LITTLE_ENDIAN)
12+
# include <linux/unaligned/le_struct.h>
13+
# include <linux/unaligned/be_byteshift.h>
14+
# include <linux/unaligned/generic.h>
15+
# define get_unaligned __get_unaligned_le
16+
# define put_unaligned __put_unaligned_le
17+
#elif defined(__BIG_ENDIAN)
18+
# include <linux/unaligned/be_struct.h>
19+
# include <linux/unaligned/le_byteshift.h>
20+
# include <linux/unaligned/generic.h>
21+
# define get_unaligned __get_unaligned_be
22+
# define put_unaligned __put_unaligned_be
23+
#else
24+
# error need to define endianess
25+
#endif
26+
27+
#endif /* __ASM_ARM_UNALIGNED_H */

0 commit comments

Comments
 (0)