kernel: revamp handling of unaligned access
RFC PATCH 1/1 kernel: revamp handling of unaligned access
Create a linux/unaligned folder similar in spirit to the linux/byteorder folder to hold generic implementations collected from various arches.
Currently there are five implementations:
1) cpu_endian.h: C-struct based, from asm-generic/unaligned.h
2) little_endian.h: Open coded byte-swapping, taken from arm
3) big_endian.h: Open coded byte-swapping, taken from arm
4) no_builtin_memcpy.h: multiple implementations
5) access_ok.h: x86 and others, unaligned access is ok.
There is also the addition of some byteorder unaligned accesses api:
get_unaligned_{le16|le32|le64|be16|be32|be64}(p) which is meant to replace code of the form:le16_to_cpu(get_unaligned((__le16 *)p));
put_unaligned_{le16|le32|le64|be16|be32|be64}(val, pointer) which is meant to replace code of the form:put_unaligned(cpu_to_le16(val), (__le16 *)p);
Helpers to create these based on the selected implementation and define the appropriate get_unaligned() and put_unaligned() macros are:
generic_le.h: Use the C-struct for get/put_unaligned and the le helpers, use the opencoded be byteswapping implementation for be.
generic_be.h: Use the C-struct for get/put_unaligned and the be helpers, use the opencoded le byteswapping implementation for le.
generic.h: Use opencoded byteswapping for all helpers, leaves it to the arch to define get/put_unaligned
Only frv has a custom implementation that has not been included.
--- include/asm-alpha/unaligned.h | 2 +- include/asm-arm/unaligned.h | 166 +-------------------------- include/asm-avr32/unaligned.h | 2 +- include/asm-blackfin/unaligned.h | 2 +- include/asm-cris/unaligned.h | 8 +- include/asm-generic/unaligned.h | 124 -------------------- include/asm-h8300/unaligned.h | 11 +-- include/asm-ia64/unaligned.h | 2 +- include/asm-m32r/unaligned.h | 15 +--- include/asm-m68k/unaligned.h | 9 +-- include/asm-m68knommu/unaligned.h | 10 +-- include/asm-mips/unaligned.h | 30 ++--- include/asm-mn10300/unaligned.h | 126 +-------------------- include/asm-parisc/unaligned.h | 2 +- include/asm-powerpc/unaligned.h | 9 +-- include/asm-s390/unaligned.h | 9 +-- include/asm-sh/unaligned.h | 6 +- include/asm-sparc/unaligned.h | 2 +- include/asm-sparc64/unaligned.h | 2 +- include/asm-v850/unaligned.h | 111 +----------------- include/asm-x86/unaligned.h | 30 +----- include/asm-xtensa/unaligned.h | 12 +-- include/linux/unaligned/access_ok.h | 70 +++++++++++ include/linux/unaligned/big_endian.h | 82 +++++++++++++ include/linux/unaligned/cpu_endian.h | 88 ++++++++++++++ include/linux/unaligned/generic.h | 67 +++++++++++ include/linux/unaligned/generic_be.h | 70 +++++++++++ include/linux/unaligned/generic_le.h | 70 +++++++++++ include/linux/unaligned/little_endian.h | 82 +++++++++++++ include/linux/unaligned/no_builtin_memcpy.h | 79 +++++++++++++ 30 files changed, 647 insertions(+), 651 deletions(-)
include/asm-alpha/unaligned.h +1 -1
@@ -1,6 +1,6 @@#ifndef __ALPHA_UNALIGNED_H#define __ALPHA_UNALIGNED_H -#include <asm-generic/unaligned.h> +#include <linux/unaligned/generic_le.h> #endif
include/asm-arm/unaligned.h +1 -165
172 lines not on this page · raw message
include/asm-avr32/unaligned.h +1 -1
@@ -11,6 +11,6 @@* optimize word loads in general. */ -#include <asm-generic/unaligned.h> +#include <linux/unaligned/generic_be.h> #endif /* __ASM_AVR32_UNALIGNED_H */
include/asm-blackfin/unaligned.h +1 -1
@@ -1,6 +1,6 @@#ifndef __BFIN_UNALIGNED_H#define __BFIN_UNALIGNED_H -#include <asm-generic/unaligned.h> +#include <linux/unaligned/generic_le.h> #endif /* __BFIN_UNALIGNED_H */
include/asm-cris/unaligned.h +1 -7
@@ -3,14 +3,8 @@/* * CRIS can do unaligned accesses itself. -* -* The strange macros are there to make sure these can't -* be misused in a way that makes them not work on other -* architectures where unaligned accesses aren't as simple. */ -#define get_unaligned (ptr) (*(ptr)) - -#define put_unaligned (val, ptr) ((void)( *(ptr) = (val) )) +#include <linux/unaligned/access_ok.h> #endif
include/asm-generic/unaligned.h deleted +0 -124
124 lines not on this page · raw message
include/asm-h8300/unaligned.h +1 -10
@@ -1,15 +1,6 @@#ifndef __H8300_UNALIGNED_H#define __H8300_UNALIGNED_H - -/* Use memmove here, so gcc does not insert a __builtin_memcpy. */ - -#define get_unaligned (ptr) \ - ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) - -#define put_unaligned (val, ptr) \ - ({ __typeof__(*(ptr)) __tmp = (val); \ - memmove((ptr), &__tmp, sizeof(*(ptr))); \ - (void)0; }) +#include <linux/unaligned/no_builtin_memcpy.h> #endif
include/asm-ia64/unaligned.h +1 -1
@@ -1,6 +1,6 @@#ifndef _ASM_IA64_UNALIGNED_H#define _ASM_IA64_UNALIGNED_H -#include <asm-generic/unaligned.h> +#include <linux/unaligned/generic_le.h> #endif /* _ASM_IA64_UNALIGNED_H */
include/asm-m32r/unaligned.h +1 -14
@@ -1,19 +1,6 @@#ifndef _ASM_M32R_UNALIGNED_H#define _ASM_M32R_UNALIGNED_H -/* -* For the benefit of those who are trying to port Linux to another -* architecture, here are some C-language equivalents. -*/ - -#include <asm/string.h> - -#define get_unaligned (ptr) \ - ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) - -#define put_unaligned (val, ptr) \ - ({ __typeof__(*(ptr)) __tmp = (val); \ - memmove((ptr), &__tmp, sizeof(*(ptr))); \ - (void)0; }) +#include <linux/unaligned/no_builtin_memcpy.h> #endif /* _ASM_M32R_UNALIGNED_H */
include/asm-m68k/unaligned.h +1 -8
@@ -3,14 +3,7 @@/* * The m68k can do unaligned accesses itself. -* -* The strange macros are there to make sure these can't -* be misused in a way that makes them not work on other -* architectures where unaligned accesses aren't as simple. */ - -#define get_unaligned (ptr) (*(ptr)) - -#define put_unaligned (val, ptr) ((void)( *(ptr) = (val) )) +#include <linux/unaligned/access_ok.h> #endif
include/asm-m68knommu/unaligned.h +2 -8
@@ -4,19 +4,13 @@#ifdef CONFIG_COLDFIRE -#include <asm-generic/unaligned.h> +#include <linux/unaligned/generic_be.h> #else /* * The m68k can do unaligned accesses itself. -* -* The strange macros are there to make sure these can't -* be misused in a way that makes them not work on other -* architectures where unaligned accesses aren't as simple. */ - -#define get_unaligned (ptr) (*(ptr)) -#define put_unaligned (val, ptr) ((void)( *(ptr) = (val) )) +#include <linux/unaligned/access_ok.h> #endif
include/asm-mips/unaligned.h +10 -20
@@ -5,25 +5,15 @@* * Copyright (C) 2007 Ralf Baechle ([email protected]) */ -#ifndef __ASM_GENERIC_UNALIGNED_H -#define __ASM_GENERIC_UNALIGNED_H +#ifndef __ASM_MIPS_UNALIGNED_H +#define __ASM_MIPS_UNALIGNED_H -#include <linux/compiler.h> +#if defined(__MIPSEB__) +# include <linux/unaligned/generic_be.h> +#elif defined(__MIPSEL__) +# include <linux/unaligned/generic_le.h> +#else +# error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???" +#endif -#define get_unaligned (ptr) \ -({ \ - struct __packed { \ - typeof(*(ptr)) __v; \ - } *__p = (void *) (ptr); \ - __p->__v; \ -}) - -#define put_unaligned (val, ptr) \ -do { \ - struct __packed { \ - typeof(*(ptr)) __v; \ - } *__p = (void *) (ptr); \ - __p->__v = (val); \ -} while(0) - -#endif /* __ASM_GENERIC_UNALIGNED_H */ +#endif /* __ASM_MIPS_UNALIGNED_H */
include/asm-mn10300/unaligned.h +3 -123
132 lines not on this page · raw message
include/asm-parisc/unaligned.h +1 -1
@@ -1,7 +1,7 @@#ifndef _ASM_PARISC_UNALIGNED_H_#define _ASM_PARISC_UNALIGNED_H_ -#include <asm-generic/unaligned.h> +#include <linux/unaligned/generic_be.h> #ifdef __KERNEL__struct pt_regs ;
include/asm-powerpc/unaligned.h +1 -8
@@ -5,15 +5,8 @@/* * The PowerPC can do unaligned accesses itself in big endian mode. -* -* The strange macros are there to make sure these can't -* be misused in a way that makes them not work on other -* architectures where unaligned accesses aren't as simple. */ - -#define get_unaligned (ptr) (*(ptr)) - -#define put_unaligned (val, ptr) ((void)( *(ptr) = (val) )) +#include <linux/unaligned/access_ok.h> #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_UNALIGNED_H */
include/asm-s390/unaligned.h +1 -8
@@ -11,14 +11,7 @@/* * The S390 can do unaligned accesses itself. -* -* The strange macros are there to make sure these can't -* be misused in a way that makes them not work on other -* architectures where unaligned accesses aren't as simple. */ - -#define get_unaligned (ptr) (*(ptr)) - -#define put_unaligned (val, ptr) ((void)( *(ptr) = (val) )) +#include <linux/unaligned/access_ok.h> #endif
include/asm-sh/unaligned.h +5 -1
@@ -2,6 +2,10 @@#define __ASM_SH_UNALIGNED_H/* SH can't handle unaligned accesses. */ -#include <asm-generic/unaligned.h> +#ifdef __LITTLE_ENDIAN__ +#include <linux/unaligned/generic_le.h> +#else +#include <linux/unaligned/generic_be.h> +#endif #endif /* __ASM_SH_UNALIGNED_H */
include/asm-sparc/unaligned.h +1 -1
@@ -1,6 +1,6 @@#ifndef _ASM_SPARC_UNALIGNED_H_#define _ASM_SPARC_UNALIGNED_H_ -#include <asm-generic/unaligned.h> +#include <linux/unaligned/generic_be.h> #endif /* _ASM_SPARC_UNALIGNED_H */
include/asm-sparc64/unaligned.h +1 -1
@@ -1,6 +1,6 @@#ifndef _ASM_SPARC64_UNALIGNED_H_#define _ASM_SPARC64_UNALIGNED_H_ -#include <asm-generic/unaligned.h> +#include <linux/unaligned/generic_be.h> #endif /* _ASM_SPARC64_UNALIGNED_H */
include/asm-v850/unaligned.h +3 -108
117 lines not on this page · raw message
include/asm-x86/unaligned.h +1 -29
@@ -3,35 +3,7 @@/* * The x86 can do unaligned accesses itself. -* -* The strange macros are there to make sure these can't -* be misused in a way that makes them not work on other -* architectures where unaligned accesses aren't as simple. */ - -/** -* get_unaligned - get value from possibly mis-aligned location -* @ptr: pointer to value -* -* This macro should be used for accessing values larger in size than -* single bytes at locations that are expected to be improperly aligned, -* e.g. retrieving a u16 value from a location not u16-aligned. -* -* Note that unaligned accesses can be very expensive on some architectures. -*/ -#define get_unaligned (ptr) (*(ptr)) - -/** -* put_unaligned - put value to a possibly mis-aligned location -* @val: value to place -* @ptr: pointer to location -* -* This macro should be used for placing values larger in size than -* single bytes at locations that are expected to be improperly aligned, -* e.g. writing a u16 value to a location not u16-aligned. -* -* Note that unaligned accesses can be very expensive on some architectures. -*/ -#define put_unaligned (val, ptr) ((void)( *(ptr) = (val) )) +#include <linux/unaligned/access_ok.h> #endif /* _ASM_X86_UNALIGNED_H */
include/asm-xtensa/unaligned.h +1 -11
@@ -13,16 +13,6 @@#ifndef _XTENSA_UNALIGNED_H#define _XTENSA_UNALIGNED_H -#include <linux/string.h> - -/* Use memmove here, so gcc does not insert a __builtin_memcpy. */ - -#define get_unaligned (ptr) \ - ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) - -#define put_unaligned (val, ptr) \ - ({ __typeof__(*(ptr)) __tmp = (val); \ - memmove((ptr), &__tmp, sizeof(*(ptr))); \ - (void)0; }) +#include <linux/unaligned/no_builtin_memcpy.h> #endif /* _XTENSA_UNALIGNED_H */
include/linux/unaligned/access_ok.h new file +70 -0
70 lines not on this page · raw message
include/linux/unaligned/big_endian.h new file +82 -0
82 lines not on this page · raw message
include/linux/unaligned/cpu_endian.h new file +88 -0
88 lines not on this page · raw message
include/linux/unaligned/generic.h new file +67 -0
67 lines not on this page · raw message
include/linux/unaligned/generic_be.h new file +70 -0
70 lines not on this page · raw message
include/linux/unaligned/generic_le.h new file +70 -0
70 lines not on this page · raw message
include/linux/unaligned/little_endian.h new file +82 -0
82 lines not on this page · raw message
include/linux/unaligned/no_builtin_memcpy.h new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
1.5.5.144.g3e42
PATCH 1/1 unaligned access, fix some includes
Missed a few includes when moving some files around, this makes it actually compile.
---
Applies on top of the unaligned access revamp, missed when moving files around.
include/linux/unaligned/generic_be.h | 2 +- include/linux/unaligned/generic_le.h | 2 +- include/linux/unaligned/no_builtin_memcpy.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-)
include/linux/unaligned/generic_be.h +1 -1
@@ -1,7 +1,7 @@#ifndef _LINUX_UNALIGNED_GENERIC_BE_H_#define _LINUX_UNALIGNED_GENERIC_BE_H_ -#include <linux/unaligned/generic.h> +#include <linux/unaligned/cpu_endian.h> #include <linux/unaligned/little_endian.h> #define get_unaligned __get_unaligned_cpu
include/linux/unaligned/generic_le.h +1 -1
@@ -1,7 +1,7 @@#ifndef _LINUX_UNALIGNED_GENERIC_LE_H_#define _LINUX_UNALIGNED_GENERIC_LE_H_ -#include <linux/unaligned/generic.h> +#include <linux/unaligned/cpu_endian.h> #include <linux/unaligned/big_endian.h> #define get_unaligned __get_unaligned_cpu
include/linux/unaligned/no_builtin_memcpy.h +1 -0
@@ -1,6 +1,7 @@#ifndef _LINUX_UNALIGNED_NO_BUILTIN_MEMCPY_H_#define _LINUX_UNALIGNED_NO_BUILTIN_MEMCPY_H_ +#include <linux/kernel.h> #include <asm/byteorder.h> #include <asm/string.h>
Signature · 1 line
1.5.5.144.g3e42