[RFC PATCH] kernel: revamp handling of unaligned access - Kernel

This is a discussion on [RFC PATCH] kernel: revamp handling of unaligned access - Kernel ; 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: ...

+ Reply to Thread
Results 1 to 2 of 2

Thread: [RFC PATCH] kernel: revamp handling of unaligned access

  1. [RFC PATCH] 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.

    Signed-off-by: Harvey Harrison
    ---
    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(-)

    diff --git a/include/asm-alpha/unaligned.h b/include/asm-alpha/unaligned.h
    index a1d7284..18acc19 100644
    --- a/include/asm-alpha/unaligned.h
    +++ b/include/asm-alpha/unaligned.h
    @@ -1,6 +1,6 @@
    #ifndef __ALPHA_UNALIGNED_H
    #define __ALPHA_UNALIGNED_H

    -#include
    +#include

    #endif
    diff --git a/include/asm-arm/unaligned.h b/include/asm-arm/unaligned.h
    index 5db03cf..d5cf478 100644
    --- a/include/asm-arm/unaligned.h
    +++ b/include/asm-arm/unaligned.h
    @@ -1,171 +1,7 @@
    #ifndef __ASM_ARM_UNALIGNED_H
    #define __ASM_ARM_UNALIGNED_H

    -#include
    -
    -extern int __bug_unaligned_x(const void *ptr);
    -
    -/*
    - * What is the most efficient way of loading/storing an unaligned value?
    - *
    - * That is the subject of this file. Efficiency here is defined as
    - * minimum code size with minimum register usage for the common cases.
    - * It is currently not believed that long longs are common, so we
    - * trade efficiency for the chars, shorts and longs against the long
    - * longs.
    - *
    - * Current stats with gcc 2.7.2.2 for these functions:
    - *
    - * ptrsize get: code regs put: code regs
    - * 1 1 1 1 2
    - * 2 3 2 3 2
    - * 4 7 3 7 3
    - * 8 20 6 16 6
    - *
    - * gcc 2.95.1 seems to code differently:
    - *
    - * ptrsize get: code regs put: code regs
    - * 1 1 1 1 2
    - * 2 3 2 3 2
    - * 4 7 4 7 4
    - * 8 19 8 15 6
    - *
    - * which may or may not be more efficient (depending upon whether
    - * you can afford the extra registers). Hopefully the gcc 2.95
    - * is inteligent enough to decide if it is better to use the
    - * extra register, but evidence so far seems to suggest otherwise.
    - *
    - * Unfortunately, gcc is not able to optimise the high word
    - * out of long long >> 32, or the low word from long long << 32
    - */
    -
    -#define __get_unaligned_2_le(__p) \
    - (unsigned int)(__p[0] | __p[1] << 8)
    -
    -#define __get_unaligned_2_be(__p) \
    - (unsigned int)(__p[0] << 8 | __p[1])
    -
    -#define __get_unaligned_4_le(__p) \
    - (unsigned int)(__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
    -
    -#define __get_unaligned_4_be(__p) \
    - (unsigned int)(__p[0] << 24 | __p[1] << 16 | __p[2] << 8 | __p[3])
    -
    -#define __get_unaligned_8_le(__p) \
    - ((unsigned long long)__get_unaligned_4_le((__p+4)) << 32 | \
    - __get_unaligned_4_le(__p))
    -
    -#define __get_unaligned_8_be(__p) \
    - ((unsigned long long)__get_unaligned_4_be(__p) << 32 | \
    - __get_unaligned_4_be((__p+4)))
    -
    -#define __get_unaligned_le(ptr) \
    - ((__force typeof(*(ptr)))({ \
    - const __u8 *__p = (const __u8 *)(ptr); \
    - __builtin_choose_expr(sizeof(*(ptr)) == 1, *__p, \
    - __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_le(__p), \
    - __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_le(__p), \
    - __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_le(__p), \
    - (void)__bug_unaligned_x(__p))))); \
    - }))
    -
    -#define __get_unaligned_be(ptr) \
    - ((__force typeof(*(ptr)))({ \
    - const __u8 *__p = (const __u8 *)(ptr); \
    - __builtin_choose_expr(sizeof(*(ptr)) == 1, *__p, \
    - __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_be(__p), \
    - __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_be(__p), \
    - __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_be(__p), \
    - (void)__bug_unaligned_x(__p))))); \
    - }))
    -
    -
    -static inline void __put_unaligned_2_le(__u32 __v, register __u8 *__p)
    -{
    - *__p++ = __v;
    - *__p++ = __v >> 8;
    -}
    -
    -static inline void __put_unaligned_2_be(__u32 __v, register __u8 *__p)
    -{
    - *__p++ = __v >> 8;
    - *__p++ = __v;
    -}
    -
    -static inline void __put_unaligned_4_le(__u32 __v, register __u8 *__p)
    -{
    - __put_unaligned_2_le(__v >> 16, __p + 2);
    - __put_unaligned_2_le(__v, __p);
    -}
    -
    -static inline void __put_unaligned_4_be(__u32 __v, register __u8 *__p)
    -{
    - __put_unaligned_2_be(__v >> 16, __p);
    - __put_unaligned_2_be(__v, __p + 2);
    -}
    -
    -static inline void __put_unaligned_8_le(const unsigned long long __v, register __u8 *__p)
    -{
    - /*
    - * tradeoff: 8 bytes of stack for all unaligned puts (2
    - * instructions), or an extra register in the long long
    - * case - go for the extra register.
    - */
    - __put_unaligned_4_le(__v >> 32, __p+4);
    - __put_unaligned_4_le(__v, __p);
    -}
    -
    -static inline void __put_unaligned_8_be(const unsigned long long __v, register __u8 *__p)
    -{
    - /*
    - * tradeoff: 8 bytes of stack for all unaligned puts (2
    - * instructions), or an extra register in the long long
    - * case - go for the extra register.
    - */
    - __put_unaligned_4_be(__v >> 32, __p);
    - __put_unaligned_4_be(__v, __p+4);
    -}
    -
    -/*
    - * Try to store an unaligned value as efficiently as possible.
    - */
    -#define __put_unaligned_le(val,ptr) \
    - ({ \
    - (void)sizeof(*(ptr) = (val)); \
    - switch (sizeof(*(ptr))) { \
    - case 1: \
    - *(ptr) = (val); \
    - break; \
    - case 2: __put_unaligned_2_le((__force u16)(val),(__u8 *)(ptr)); \
    - break; \
    - case 4: __put_unaligned_4_le((__force u32)(val),(__u8 *)(ptr)); \
    - break; \
    - case 8: __put_unaligned_8_le((__force u64)(val),(__u8 *)(ptr)); \
    - break; \
    - default: __bug_unaligned_x(ptr); \
    - break; \
    - } \
    - (void) 0; \
    - })
    -
    -#define __put_unaligned_be(val,ptr) \
    - ({ \
    - (void)sizeof(*(ptr) = (val)); \
    - switch (sizeof(*(ptr))) { \
    - case 1: \
    - *(ptr) = (val); \
    - break; \
    - case 2: __put_unaligned_2_be((__force u16)(val),(__u8 *)(ptr)); \
    - break; \
    - case 4: __put_unaligned_4_be((__force u32)(val),(__u8 *)(ptr)); \
    - break; \
    - case 8: __put_unaligned_8_be((__force u64)(val),(__u8 *)(ptr)); \
    - break; \
    - default: __bug_unaligned_x(ptr); \
    - break; \
    - } \
    - (void) 0; \
    - })
    +#include

    /*
    * Select endianness
    diff --git a/include/asm-avr32/unaligned.h b/include/asm-avr32/unaligned.h
    index 36f5fd4..28fa20e 100644
    --- a/include/asm-avr32/unaligned.h
    +++ b/include/asm-avr32/unaligned.h
    @@ -11,6 +11,6 @@
    * optimize word loads in general.
    */

    -#include
    +#include

    #endif /* __ASM_AVR32_UNALIGNED_H */
    diff --git a/include/asm-blackfin/unaligned.h b/include/asm-blackfin/unaligned.h
    index 10081dc..25861cd 100644
    --- a/include/asm-blackfin/unaligned.h
    +++ b/include/asm-blackfin/unaligned.h
    @@ -1,6 +1,6 @@
    #ifndef __BFIN_UNALIGNED_H
    #define __BFIN_UNALIGNED_H

    -#include
    +#include

    #endif /* __BFIN_UNALIGNED_H */
    diff --git a/include/asm-cris/unaligned.h b/include/asm-cris/unaligned.h
    index 7fbbb39..8bd3555 100644
    --- a/include/asm-cris/unaligned.h
    +++ b/include/asm-cris/unaligned.h
    @@ -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

    #endif
    diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
    deleted file mode 100644
    index 2fe1b2e..0000000
    --- a/include/asm-generic/unaligned.h
    +++ /dev/null
    @@ -1,124 +0,0 @@
    -#ifndef _ASM_GENERIC_UNALIGNED_H_
    -#define _ASM_GENERIC_UNALIGNED_H_
    -
    -/*
    - * For the benefit of those who are trying to port Linux to another
    - * architecture, here are some C-language equivalents.
    - *
    - * This is based almost entirely upon Richard Henderson's
    - * asm-alpha/unaligned.h implementation. Some comments were
    - * taken from David Mosberger's asm-ia64/unaligned.h header.
    - */
    -
    -#include
    -
    -/*
    - * The main single-value unaligned transfer routines.
    - */
    -#define get_unaligned(ptr) \
    - __get_unaligned((ptr), sizeof(*(ptr)))
    -#define put_unaligned(x,ptr) \
    - ((void)sizeof(*(ptr)=(x)),\
    - __put_unaligned((__force __u64)(x), (ptr), sizeof(*(ptr))))
    -
    -/*
    - * This function doesn't actually exist. The idea is that when
    - * someone uses the macros below with an unsupported size (datatype),
    - * the linker will alert us to the problem via an unresolved reference
    - * error.
    - */
    -extern void bad_unaligned_access_length(void) __attribute__((noreturn));
    -
    -struct __una_u64 { __u64 x __attribute__((packed)); };
    -struct __una_u32 { __u32 x __attribute__((packed)); };
    -struct __una_u16 { __u16 x __attribute__((packed)); };
    -
    -/*
    - * Elemental unaligned loads
    - */
    -
    -static inline __u64 __uldq(const __u64 *addr)
    -{
    - const struct __una_u64 *ptr = (const struct __una_u64 *) addr;
    - return ptr->x;
    -}
    -
    -static inline __u32 __uldl(const __u32 *addr)
    -{
    - const struct __una_u32 *ptr = (const struct __una_u32 *) addr;
    - return ptr->x;
    -}
    -
    -static inline __u16 __uldw(const __u16 *addr)
    -{
    - const struct __una_u16 *ptr = (const struct __una_u16 *) addr;
    - return ptr->x;
    -}
    -
    -/*
    - * Elemental unaligned stores
    - */
    -
    -static inline void __ustq(__u64 val, __u64 *addr)
    -{
    - struct __una_u64 *ptr = (struct __una_u64 *) addr;
    - ptr->x = val;
    -}
    -
    -static inline void __ustl(__u32 val, __u32 *addr)
    -{
    - struct __una_u32 *ptr = (struct __una_u32 *) addr;
    - ptr->x = val;
    -}
    -
    -static inline void __ustw(__u16 val, __u16 *addr)
    -{
    - struct __una_u16 *ptr = (struct __una_u16 *) addr;
    - ptr->x = val;
    -}
    -
    -#define __get_unaligned(ptr, size) ({ \
    - const void *__gu_p = ptr; \
    - __u64 __val; \
    - switch (size) { \
    - case 1: \
    - __val = *(const __u8 *)__gu_p; \
    - break; \
    - case 2: \
    - __val = __uldw(__gu_p); \
    - break; \
    - case 4: \
    - __val = __uldl(__gu_p); \
    - break; \
    - case 8: \
    - __val = __uldq(__gu_p); \
    - break; \
    - default: \
    - bad_unaligned_access_length(); \
    - }; \
    - (__force __typeof__(*(ptr)))__val; \
    -})
    -
    -#define __put_unaligned(val, ptr, size) \
    -({ \
    - void *__gu_p = ptr; \
    - switch (size) { \
    - case 1: \
    - *(__u8 *)__gu_p = (__force __u8)val; \
    - break; \
    - case 2: \
    - __ustw((__force __u16)val, __gu_p); \
    - break; \
    - case 4: \
    - __ustl((__force __u32)val, __gu_p); \
    - break; \
    - case 8: \
    - __ustq(val, __gu_p); \
    - break; \
    - default: \
    - bad_unaligned_access_length(); \
    - }; \
    - (void)0; \
    -})
    -
    -#endif /* _ASM_GENERIC_UNALIGNED_H */
    diff --git a/include/asm-h8300/unaligned.h b/include/asm-h8300/unaligned.h
    index ffb67f4..e8ff49d 100644
    --- a/include/asm-h8300/unaligned.h
    +++ b/include/asm-h8300/unaligned.h
    @@ -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

    #endif
    diff --git a/include/asm-ia64/unaligned.h b/include/asm-ia64/unaligned.h
    index bb85598..2134205 100644
    --- a/include/asm-ia64/unaligned.h
    +++ b/include/asm-ia64/unaligned.h
    @@ -1,6 +1,6 @@
    #ifndef _ASM_IA64_UNALIGNED_H
    #define _ASM_IA64_UNALIGNED_H

    -#include
    +#include

    #endif /* _ASM_IA64_UNALIGNED_H */
    diff --git a/include/asm-m32r/unaligned.h b/include/asm-m32r/unaligned.h
    index fccc180..5a4c931 100644
    --- a/include/asm-m32r/unaligned.h
    +++ b/include/asm-m32r/unaligned.h
    @@ -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
    -
    -#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

    #endif /* _ASM_M32R_UNALIGNED_H */
    diff --git a/include/asm-m68k/unaligned.h b/include/asm-m68k/unaligned.h
    index 804cb3f..94b4a77 100644
    --- a/include/asm-m68k/unaligned.h
    +++ b/include/asm-m68k/unaligned.h
    @@ -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

    #endif
    diff --git a/include/asm-m68knommu/unaligned.h b/include/asm-m68knommu/unaligned.h
    index 869e9dd..6b5c7a2 100644
    --- a/include/asm-m68knommu/unaligned.h
    +++ b/include/asm-m68knommu/unaligned.h
    @@ -4,19 +4,13 @@

    #ifdef CONFIG_COLDFIRE

    -#include
    +#include

    #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

    #endif

    diff --git a/include/asm-mips/unaligned.h b/include/asm-mips/unaligned.h
    index 3249049..bddbbfb 100644
    --- a/include/asm-mips/unaligned.h
    +++ b/include/asm-mips/unaligned.h
    @@ -5,25 +5,15 @@
    *
    * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
    */
    -#ifndef __ASM_GENERIC_UNALIGNED_H
    -#define __ASM_GENERIC_UNALIGNED_H
    +#ifndef __ASM_MIPS_UNALIGNED_H
    +#define __ASM_MIPS_UNALIGNED_H

    -#include
    +#if defined(__MIPSEB__)
    +# include
    +#elif defined(__MIPSEL__)
    +# include
    +#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 */
    diff --git a/include/asm-mn10300/unaligned.h b/include/asm-mn10300/unaligned.h
    index cad3afb..c377ba0 100644
    --- a/include/asm-mn10300/unaligned.h
    +++ b/include/asm-mn10300/unaligned.h
    @@ -8,129 +8,9 @@
    * as published by the Free Software Foundation; either version
    * 2 of the Licence, or (at your option) any later version.
    */
    -#ifndef _ASM_UNALIGNED_H
    -#define _ASM_UNALIGNED_H
    +#ifndef _ASM_MN10300_UNALIGNED_H
    +#define _ASM_MN10300_UNALIGNED_H

    -#include
    -
    -#if 0
    -extern int __bug_unaligned_x(void *ptr);
    -
    -/*
    - * What is the most efficient way of loading/storing an unaligned value?
    - *
    - * That is the subject of this file. Efficiency here is defined as
    - * minimum code size with minimum register usage for the common cases.
    - * It is currently not believed that long longs are common, so we
    - * trade efficiency for the chars, shorts and longs against the long
    - * longs.
    - *
    - * Current stats with gcc 2.7.2.2 for these functions:
    - *
    - * ptrsize get: code regs put: code regs
    - * 1 1 1 1 2
    - * 2 3 2 3 2
    - * 4 7 3 7 3
    - * 8 20 6 16 6
    - *
    - * gcc 2.95.1 seems to code differently:
    - *
    - * ptrsize get: code regs put: code regs
    - * 1 1 1 1 2
    - * 2 3 2 3 2
    - * 4 7 4 7 4
    - * 8 19 8 15 6
    - *
    - * which may or may not be more efficient (depending upon whether
    - * you can afford the extra registers). Hopefully the gcc 2.95
    - * is inteligent enough to decide if it is better to use the
    - * extra register, but evidence so far seems to suggest otherwise.
    - *
    - * Unfortunately, gcc is not able to optimise the high word
    - * out of long long >> 32, or the low word from long long << 32
    - */
    -
    -#define __get_unaligned_2(__p) \
    - (__p[0] | __p[1] << 8)
    -
    -#define __get_unaligned_4(__p) \
    - (__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
    -
    -#define get_unaligned(ptr) \
    -({ \
    - unsigned int __v1, __v2; \
    - __typeof__(*(ptr)) __v; \
    - __u8 *__p = (__u8 *)(ptr); \
    - \
    - switch (sizeof(*(ptr))) { \
    - case 1: __v = *(ptr); break; \
    - case 2: __v = __get_unaligned_2(__p); break; \
    - case 4: __v = __get_unaligned_4(__p); break; \
    - case 8: \
    - __v2 = __get_unaligned_4((__p+4)); \
    - __v1 = __get_unaligned_4(__p); \
    - __v = ((unsigned long long)__v2 << 32 | __v1); \
    - break; \
    - default: __v = __bug_unaligned_x(__p); break; \
    - } \
    - __v; \
    -})
    -
    -
    -static inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
    -{
    - *__p++ = __v;
    - *__p++ = __v >> 8;
    -}
    -
    -static inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
    -{
    - __put_unaligned_2(__v >> 16, __p + 2);
    - __put_unaligned_2(__v, __p);
    -}
    -
    -static inline void __put_unaligned_8(const unsigned long long __v, __u8 *__p)
    -{
    - /*
    - * tradeoff: 8 bytes of stack for all unaligned puts (2
    - * instructions), or an extra register in the long long
    - * case - go for the extra register.
    - */
    - __put_unaligned_4(__v >> 32, __p + 4);
    - __put_unaligned_4(__v, __p);
    -}
    -
    -/*
    - * Try to store an unaligned value as efficiently as possible.
    - */
    -#define put_unaligned(val, ptr) \
    - ({ \
    - switch (sizeof(*(ptr))) { \
    - case 1: \
    - *(ptr) = (val); \
    - break; \
    - case 2: \
    - __put_unaligned_2((val), (__u8 *)(ptr)); \
    - break; \
    - case 4: \
    - __put_unaligned_4((val), (__u8 *)(ptr)); \
    - break; \
    - case 8: \
    - __put_unaligned_8((val), (__u8 *)(ptr)); \
    - break; \
    - default: \
    - __bug_unaligned_x(ptr); \
    - break; \
    - } \
    - (void) 0; \
    - })
    -
    -
    -#else
    -
    -#define get_unaligned(ptr) (*(ptr))
    -#define put_unaligned(val, ptr) ({ *(ptr) = (val); (void) 0; })
    -
    -#endif
    +#include

    #endif
    diff --git a/include/asm-parisc/unaligned.h b/include/asm-parisc/unaligned.h
    index 53c9058..865867c 100644
    --- a/include/asm-parisc/unaligned.h
    +++ b/include/asm-parisc/unaligned.h
    @@ -1,7 +1,7 @@
    #ifndef _ASM_PARISC_UNALIGNED_H_
    #define _ASM_PARISC_UNALIGNED_H_

    -#include
    +#include

    #ifdef __KERNEL__
    struct pt_regs;
    diff --git a/include/asm-powerpc/unaligned.h b/include/asm-powerpc/unaligned.h
    index 6c95dfa..59bcc21 100644
    --- a/include/asm-powerpc/unaligned.h
    +++ b/include/asm-powerpc/unaligned.h
    @@ -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

    #endif /* __KERNEL__ */
    #endif /* _ASM_POWERPC_UNALIGNED_H */
    diff --git a/include/asm-s390/unaligned.h b/include/asm-s390/unaligned.h
    index 8ee86db..1d4a684 100644
    --- a/include/asm-s390/unaligned.h
    +++ b/include/asm-s390/unaligned.h
    @@ -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

    #endif
    diff --git a/include/asm-sh/unaligned.h b/include/asm-sh/unaligned.h
    index 5250e30..391da8d 100644
    --- a/include/asm-sh/unaligned.h
    +++ b/include/asm-sh/unaligned.h
    @@ -2,6 +2,10 @@
    #define __ASM_SH_UNALIGNED_H

    /* SH can't handle unaligned accesses. */
    -#include
    +#ifdef __LITTLE_ENDIAN__
    +#include
    +#else
    +#include
    +#endif

    #endif /* __ASM_SH_UNALIGNED_H */
    diff --git a/include/asm-sparc/unaligned.h b/include/asm-sparc/unaligned.h
    index b6f8edd..9f1bb56 100644
    --- a/include/asm-sparc/unaligned.h
    +++ b/include/asm-sparc/unaligned.h
    @@ -1,6 +1,6 @@
    #ifndef _ASM_SPARC_UNALIGNED_H_
    #define _ASM_SPARC_UNALIGNED_H_

    -#include
    +#include

    #endif /* _ASM_SPARC_UNALIGNED_H */
    diff --git a/include/asm-sparc64/unaligned.h b/include/asm-sparc64/unaligned.h
    index 1ed3ba5..faa18cd 100644
    --- a/include/asm-sparc64/unaligned.h
    +++ b/include/asm-sparc64/unaligned.h
    @@ -1,6 +1,6 @@
    #ifndef _ASM_SPARC64_UNALIGNED_H_
    #define _ASM_SPARC64_UNALIGNED_H_

    -#include
    +#include

    #endif /* _ASM_SPARC64_UNALIGNED_H */
    diff --git a/include/asm-v850/unaligned.h b/include/asm-v850/unaligned.h
    index e30b186..09fc37c 100644
    --- a/include/asm-v850/unaligned.h
    +++ b/include/asm-v850/unaligned.h
    @@ -17,114 +17,9 @@
    #ifndef __V850_UNALIGNED_H__
    #define __V850_UNALIGNED_H__

    -#include
    -
    -extern int __bug_unaligned_x(void *ptr);
    -
    -/*
    - * What is the most efficient way of loading/storing an unaligned value?
    - *
    - * That is the subject of this file. Efficiency here is defined as
    - * minimum code size with minimum register usage for the common cases.
    - * It is currently not believed that long longs are common, so we
    - * trade efficiency for the chars, shorts and longs against the long
    - * longs.
    - *
    - * Current stats with gcc 2.7.2.2 for these functions:
    - *
    - * ptrsize get: code regs put: code regs
    - * 1 1 1 1 2
    - * 2 3 2 3 2
    - * 4 7 3 7 3
    - * 8 20 6 16 6
    - *
    - * gcc 2.95.1 seems to code differently:
    - *
    - * ptrsize get: code regs put: code regs
    - * 1 1 1 1 2
    - * 2 3 2 3 2
    - * 4 7 4 7 4
    - * 8 19 8 15 6
    - *
    - * which may or may not be more efficient (depending upon whether
    - * you can afford the extra registers). Hopefully the gcc 2.95
    - * is inteligent enough to decide if it is better to use the
    - * extra register, but evidence so far seems to suggest otherwise.
    - *
    - * Unfortunately, gcc is not able to optimise the high word
    - * out of long long >> 32, or the low word from long long << 32
    - */
    -
    -#define __get_unaligned_2(__p) \
    - (__p[0] | __p[1] << 8)
    -
    -#define __get_unaligned_4(__p) \
    - (__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
    -
    -#define get_unaligned(ptr) \
    - ({ \
    - __typeof__(*(ptr)) __v; \
    - __u8 *__p = (__u8 *)(ptr); \
    - switch (sizeof(*(ptr))) { \
    - case 1: __v = *(ptr); break; \
    - case 2: __v = __get_unaligned_2(__p); break; \
    - case 4: __v = __get_unaligned_4(__p); break; \
    - case 8: { \
    - unsigned int __v1, __v2; \
    - __v2 = __get_unaligned_4((__p+4)); \
    - __v1 = __get_unaligned_4(__p); \
    - __v = ((unsigned long long)__v2 << 32 | __v1); \
    - } \
    - break; \
    - default: __v = __bug_unaligned_x(__p); break; \
    - } \
    - __v; \
    - })
    -
    -
    -static inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
    -{
    - *__p++ = __v;
    - *__p++ = __v >> 8;
    -}
    -
    -static inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
    -{
    - __put_unaligned_2(__v >> 16, __p + 2);
    - __put_unaligned_2(__v, __p);
    -}
    -
    -static inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p)
    -{
    - /*
    - * tradeoff: 8 bytes of stack for all unaligned puts (2
    - * instructions), or an extra register in the long long
    - * case - go for the extra register.
    - */
    - __put_unaligned_4(__v >> 32, __p+4);
    - __put_unaligned_4(__v, __p);
    -}
    -
    -/*
    - * Try to store an unaligned value as efficiently as possible.
    - */
    -#define put_unaligned(val,ptr) \
    - ({ \
    - switch (sizeof(*(ptr))) { \
    - case 1: \
    - *(ptr) = (val); \
    - break; \
    - case 2: __put_unaligned_2((val),(__u8 *)(ptr)); \
    - break; \
    - case 4: __put_unaligned_4((val),(__u8 *)(ptr)); \
    - break; \
    - case 8: __put_unaligned_8((val),(__u8 *)(ptr)); \
    - break; \
    - default: __bug_unaligned_x(ptr); \
    - break; \
    - } \
    - (void) 0; \
    - })
    +#include

    +#define get_unaligned __get_unaligned_le
    +#define put_unaligned __put_unaligned_le

    #endif /* __V850_UNALIGNED_H__ */
    diff --git a/include/asm-x86/unaligned.h b/include/asm-x86/unaligned.h
    index 913598d..7ba2e1a 100644
    --- a/include/asm-x86/unaligned.h
    +++ b/include/asm-x86/unaligned.h
    @@ -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

    #endif /* _ASM_X86_UNALIGNED_H */
    diff --git a/include/asm-xtensa/unaligned.h b/include/asm-xtensa/unaligned.h
    index 2822089..45eb203 100644
    --- a/include/asm-xtensa/unaligned.h
    +++ b/include/asm-xtensa/unaligned.h
    @@ -13,16 +13,6 @@
    #ifndef _XTENSA_UNALIGNED_H
    #define _XTENSA_UNALIGNED_H

    -#include
    -
    -/* 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

    #endif /* _XTENSA_UNALIGNED_H */
    diff --git a/include/linux/unaligned/access_ok.h b/include/linux/unaligned/access_ok.h
    new file mode 100644
    index 0000000..e9d8ff4
    --- /dev/null
    +++ b/include/linux/unaligned/access_ok.h
    @@ -0,0 +1,70 @@
    +#ifndef _LINUX_UNALIGNED_ACCESS_OK_H_
    +#define _LINUX_UNALIGNED_ACCESS_OK_H_
    +
    +#include
    +#include
    +
    +#define get_unaligned(ptr) (*(ptr))
    +#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
    +
    +static inline u16 get_unaligned_le16(const __le16 *p)
    +{
    + return le16_to_cpup(p);
    +}
    +
    +static inline u32 get_unaligned_le32(const __le32 *p)
    +{
    + return le32_to_cpup(p);
    +}
    +
    +static inline u64 get_unaligned_le64(const __le64 *p)
    +{
    + return le64_to_cpup(p);
    +}
    +
    +static inline u16 get_unaligned_be16(const __be16 *p)
    +{
    + return be16_to_cpup(p);
    +}
    +
    +static inline u32 get_unaligned_be32(const __be32 *p)
    +{
    + return be32_to_cpup(p);
    +}
    +
    +static inline u64 get_unaligned_be64(const __be64 *p)
    +{
    + return be64_to_cpup(p);
    +}
    +
    +static inline void put_unaligned_le16(u16 val, void *p)
    +{
    + *((__le16 *)p) = cpu_to_le16(val);
    +}
    +
    +static inline void put_unaligned_le32(u32 val, void *p)
    +{
    + *((__le32 *)p) = cpu_to_le32(val);
    +}
    +
    +static inline void put_unaligned_le64(u64 val, void *p)
    +{
    + *((__le64 *)p) = cpu_to_le64(val);
    +}
    +
    +static inline void put_unaligned_be16(u16 val, void *p)
    +{
    + *((__be16 *)p) = cpu_to_be16(val);
    +}
    +
    +static inline void put_unaligned_be32(u32 val, void *p)
    +{
    + *((__be32 *)p) = cpu_to_be32(val);
    +}
    +
    +static inline void put_unaligned_be64(u64 val, void *p)
    +{
    + *((__be64 *)p) = cpu_to_be64(val);
    +}
    +
    +#endif /* _LINUX_UNALIGNED_ACCESS_OK_H_ */
    diff --git a/include/linux/unaligned/big_endian.h b/include/linux/unaligned/big_endian.h
    new file mode 100644
    index 0000000..b59fbbc
    --- /dev/null
    +++ b/include/linux/unaligned/big_endian.h
    @@ -0,0 +1,82 @@
    +#ifndef _LINUX_UNALIGNED_BIG_ENDIAN_H_
    +#define _LINUX_UNALIGNED_BIG_ENDIAN_H_
    +
    +#include
    +
    +static inline u16 __get_unaligned_be16(const u8 *p)
    +{
    + return (u16)(p[0] << 8 | p[1]);
    +}
    +
    +static inline u32 __get_unaligned_be32(const u8 *p)
    +{
    + return (u32)(p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]);
    +}
    +
    +static inline u64 __get_unaligned_be64(const u8 *p)
    +{
    + return ((u64)__get_unaligned_be32(p) << 32) |
    + __get_unaligned_be32(p + 4);
    +}
    +
    +#define __get_unaligned_be(ptr) ({ \
    + const void *__gu_p = (ptr); \
    + u64 __val; \
    + switch (sizeof(*(ptr)) { \
    + case 1: \
    + __val = *(const u8 *)__gu_p; \
    + break; \
    + case 2: \
    + __val = __get_unaligned_be16((const u8 *)__gu_p); \
    + break; \
    + case 4: \
    + __val = __get_unaligned_be32((const u8 *)__gu_p); \
    + break; \
    + case 8: \
    + __val = __get_unaligned_be64((const u8 *)__gu_p); \
    + break; \
    + default: \
    + BUILD_BUG_ON(1); \
    + }; \
    + (__force __typeof__(*(ptr)))__val; })
    +
    +static inline void __put_unaligned_be16(u16 val, u8 *p)
    +{
    + *p++ = val >> 8;
    + *p++ = val;
    +}
    +
    +static inline void __put_unaligned_be32(u32 val, u8 *p)
    +{
    + __put_unaligned_be16(val >> 16, p);
    + __put_unaligned_be16(val, p + 2);
    +}
    +
    +static inline void __put_unaligned_be64(u64 val, u8 *p)
    +{
    + __put_unaligned_be32(val >> 32, p);
    + __put_unaligned_be32(val, p + 4);
    +}
    +
    +#define __put_unaligned_be(val, ptr) ({ \
    + (void)sizeof(*(ptr) = (val)); \
    + switch (sizeof(*(ptr))) { \
    + case 1: \
    + *(ptr) = (val); \
    + break; \
    + case 2: \
    + __put_unaligned_be16((__force u16)(val), (u8 *)(ptr)); \
    + break; \
    + case 4: \
    + __put_unaligned_be32((__force u32)(val), (u8 *)(ptr)); \
    + break; \
    + case 8: \
    + __put_unaligned_be64((__force u64)(val), (u8 *)(ptr)); \
    + break; \
    + default: \
    + BUILD_BUG_ON(1); \
    + break; \
    + } \
    + (void)0; })
    +
    +#endif /* _LINUX_UNALIGNED_BIG_ENDIAN_H_ */
    diff --git a/include/linux/unaligned/cpu_endian.h b/include/linux/unaligned/cpu_endian.h
    new file mode 100644
    index 0000000..35fe430
    --- /dev/null
    +++ b/include/linux/unaligned/cpu_endian.h
    @@ -0,0 +1,88 @@
    +#ifndef _LINUX_UNALIGNED_CPU_ENDIAN_H_
    +#define _LINUX_UNALIGNED_CPU_ENDIAN_H_
    +
    +#include
    +
    +struct __una_u16 { u16 x __attribute__((packed)); };
    +struct __una_u32 { u32 x __attribute__((packed)); };
    +struct __una_u64 { u64 x __attribute__((packed)); };
    +
    +static inline u16 __get_unaligned_cpu16(const u8 *p)
    +{
    + const struct __una_u16 *ptr = (const struct __una_u16 *)p;
    + return ptr->x;
    +}
    +
    +static inline u32 __get_unaligned_cpu32(const u8 *p)
    +{
    + const struct __una_u32 *ptr = (const struct __una_u32 *)p;
    + return ptr->x;
    +}
    +
    +static inline u64 __get_unaligned_cpu64(const u8 *p)
    +{
    + const struct __una_u64 *ptr = (const struct __una_u64 *)p;
    + return ptr->x;
    +}
    +
    +#define __get_unaligned_cpu(ptr) ({ \
    + const void *__gu_p = (ptr); \
    + u64 __val; \
    + switch (sizeof(*(ptr)) { \
    + case 1: \
    + __val = *(const u8 *)__gu_p; \
    + break; \
    + case 2: \
    + __val = __get_unaligned_cpu16((const u8 *)__gu_p); \
    + break; \
    + case 4: \
    + __val = __get_unaligned_cpu32((const u8 *)__gu_p); \
    + break; \
    + case 8: \
    + __val = __get_unaligned_cpu64((const u8 *)__gu_p); \
    + break; \
    + default: \
    + BUILD_BUG_ON(1); \
    + }; \
    + (__force __typeof__(*(ptr)))__val; })
    +
    +static inline void __put_unaligned_cpu16(u16 val, u8 *p)
    +{
    + struct __una_u16 *ptr = (struct __una_u16 *)p;
    + ptr->x = val;
    +}
    +
    +static inline void __put_unaligned_cpu32(u32 val, u8 *p)
    +{
    + struct __una_u32 *ptr = (struct __una_u32 *)p;
    + ptr->x = val;
    +}
    +
    +static inline void __put_unaligned_cpu64(u64 val, u8 *p)
    +{
    + struct __una_u64 *ptr = (struct __una_u64 *)p;
    + ptr->x = val;
    +}
    +
    +#define __put_unaligned_cpu(val, ptr) ({ \
    + (void)sizeof(*(ptr) = (val)); \
    + switch (sizeof(*(ptr))) { \
    + case 1: \
    + *(ptr) = (val); \
    + break; \
    + case 2: \
    + __put_unaligned_cpu16((__force u16)(val), (u8 *)(ptr)); \
    + break; \
    + case 4: \
    + __put_unaligned_cpu32((__force u32)(val), (u8 *)(ptr)); \
    + break; \
    + case 8: \
    + __put_unaligned_cpu64((__force u64)(val), (u8 *)(ptr)); \
    + break; \
    + default: \
    + BUILD_BUG_ON(1); \
    + break; \
    + } \
    + (void)0; })
    +
    +#endif /* _LINUX_UNALIGNED_CPU_ENDIAN_H_ */
    diff --git a/include/linux/unaligned/generic.h b/include/linux/unaligned/generic.h
    new file mode 100644
    index 0000000..9cd3fab
    --- /dev/null
    +++ b/include/linux/unaligned/generic.h
    @@ -0,0 +1,67 @@
    +#ifndef _LINUX_UNALIGNED_GENERIC_H_
    +#define _LINUX_UNALIGNED_GENERIC_H_
    +
    +#include
    +#include
    +
    +static inline u16 get_unaligned_le16(const __le16 *p)
    +{
    + return __get_unaligned_le16((const u8 *)p);
    +}
    +
    +static inline u32 get_unaligned_le32(const __le32 *p)
    +{
    + return __get_unaligned_le32((const u8 *)p);
    +}
    +
    +static inline u64 get_unaligned_le64(const __le64 *p)
    +{
    + return __get_unaligned_le64((const u8 *)p);
    +}
    +
    +static inline u16 get_unaligned_be16(const __be16 *p)
    +{
    + return __get_unaligned_be16((const u8 *)p);
    +}
    +
    +static inline u32 get_unaligned_be32(const __be32 *p)
    +{
    + return __get_unaligned_be32((const u8 *)p);
    +}
    +
    +static inline u64 get_unaligned_be64(const __be64 *p)
    +{
    + return __get_unaligned_be64((const u8 *)p);
    +}
    +
    +static inline void put_unaligned_le16(u16 val, void *p)
    +{
    + __put_unaligned_le16(val, p);
    +}
    +
    +static inline void put_unaligned_le32(u32 val, void *p)
    +{
    + __put_unaligned_le32(val, p);
    +}
    +
    +static inline void put_unaligned_le64(u64 val, void *p)
    +{
    + __put_unaligned_le64(val, p);
    +}
    +
    +static inline void put_unaligned_be16(u16 val, void *p)
    +{
    + __put_unaligned_be16(val, p);
    +}
    +
    +static inline void put_unaligned_be32(u32 val, void *p)
    +{
    + __put_unaligned_be32(val, p);
    +}
    +
    +static inline void put_unaligned_be64(u64 val, void *p)
    +{
    + __put_unaligned_be64(val, p);
    +}
    +
    +#endif /* _LINUX_UNALIGNED_GENERIC_H_ */
    diff --git a/include/linux/unaligned/generic_be.h b/include/linux/unaligned/generic_be.h
    new file mode 100644
    index 0000000..ce42487
    --- /dev/null
    +++ b/include/linux/unaligned/generic_be.h
    @@ -0,0 +1,70 @@
    +#ifndef _LINUX_UNALIGNED_GENERIC_BE_H_
    +#define _LINUX_UNALIGNED_GENERIC_BE_H_
    +
    +#include
    +#include
    +
    +#define get_unaligned __get_unaligned_cpu
    +#define put_unaligned __put_unaligned_cpu
    +
    +static inline u16 get_unaligned_le16(const __le16 *p)
    +{
    + return __get_unaligned_le16((const u8 *)p);
    +}
    +
    +static inline u32 get_unaligned_le32(const __le32 *p)
    +{
    + return __get_unaligned_le32((const u8 *)p);
    +}
    +
    +static inline u64 get_unaligned_le64(const __le64 *p)
    +{
    + return __get_unaligned_le64((const u8 *)p);
    +}
    +
    +static inline u16 get_unaligned_be16(const __be16 *p)
    +{
    + return __get_unaligned_cpu16((const u8 *)p);
    +}
    +
    +static inline u32 get_unaligned_be32(const __be32 *p)
    +{
    + return __get_unaligned_cpu32((const u8 *)p);
    +}
    +
    +static inline u64 get_unaligned_be64(const __be64 *p)
    +{
    + return __get_unaligned_cpu64((const u8 *)p);
    +}
    +
    +static inline void put_unaligned_le16(u16 val, void *p)
    +{
    + __put_unaligned_le16(val, p);
    +}
    +
    +static inline void put_unaligned_le32(u32 val, void *p)
    +{
    + __put_unaligned_le32(val, p);
    +}
    +
    +static inline void put_unaligned_le64(u64 val, void *p)
    +{
    + __put_unaligned_le64(val, p);
    +}
    +
    +static inline void put_unaligned_be16(u16 val, void *p)
    +{
    + __put_unaligned_cpu16(val, p);
    +}
    +
    +static inline void put_unaligned_be32(u32 val, void *p)
    +{
    + __put_unaligned_cpu32(val, p);
    +}
    +
    +static inline void put_unaligned_be64(u64 val, void *p)
    +{
    + __put_unaligned_cpu64(val, p);
    +}
    +
    +#endif /* _LINUX_UNALIGNED_GENERIC_BE_H_ */
    diff --git a/include/linux/unaligned/generic_le.h b/include/linux/unaligned/generic_le.h
    new file mode 100644
    index 0000000..b57c818
    --- /dev/null
    +++ b/include/linux/unaligned/generic_le.h
    @@ -0,0 +1,70 @@
    +#ifndef _LINUX_UNALIGNED_GENERIC_LE_H_
    +#define _LINUX_UNALIGNED_GENERIC_LE_H_
    +
    +#include
    +#include
    +
    +#define get_unaligned __get_unaligned_cpu
    +#define put_unaligned __put_unaligned_cpu
    +
    +static inline u16 get_unaligned_le16(const __le16 *p)
    +{
    + return __get_unaligned_cpu16((const u8 *)p);
    +}
    +
    +static inline u32 get_unaligned_le32(const __le32 *p)
    +{
    + return __get_unaligned_cpu32((const u8 *)p);
    +}
    +
    +static inline u64 get_unaligned_le64(const __le64 *p)
    +{
    + return __get_unaligned_cpu64((const u8 *)p);
    +}
    +
    +static inline u16 get_unaligned_be16(const __be16 *p)
    +{
    + return __get_unaligned_be16((const u8 *)p);
    +}
    +
    +static inline u32 get_unaligned_be32(const __be32 *p)
    +{
    + return __get_unaligned_be32((const u8 *)p);
    +}
    +
    +static inline u64 get_unaligned_be64(const __be64 *p)
    +{
    + return __get_unaligned_be64((const u8 *)p);
    +}
    +
    +static inline void put_unaligned_le16(u16 val, void *p)
    +{
    + __put_unaligned_cpu16(val, p);
    +}
    +
    +static inline void put_unaligned_le32(u32 val, void *p)
    +{
    + __put_unaligned_cpu32(val, p);
    +}
    +
    +static inline void put_unaligned_le64(u64 val, void *p)
    +{
    + __put_unaligned_cpu64(val, p);
    +}
    +
    +static inline void put_unaligned_be16(u16 val, void *p)
    +{
    + __put_unaligned_be16(val, p);
    +}
    +
    +static inline void put_unaligned_be32(u32 val, void *p)
    +{
    + __put_unaligned_be32(val, p);
    +}
    +
    +static inline void put_unaligned_be64(u64 val, void *p)
    +{
    + __put_unaligned_be64(val, p);
    +}
    +
    +#endif /* _LINUX_UNALIGNED_GENERIC_LE_H_ */
    diff --git a/include/linux/unaligned/little_endian.h b/include/linux/unaligned/little_endian.h
    new file mode 100644
    index 0000000..43f46c3
    --- /dev/null
    +++ b/include/linux/unaligned/little_endian.h
    @@ -0,0 +1,82 @@
    +#ifndef _LINUX_UNALIGNED_LITTLE_ENDIAN_H_
    +#define _LINUX_UNALIGNED_LITTLE_ENDIAN_H_
    +
    +#include
    +
    +static inline u16 __get_unaligned_le16(const u8 *p)
    +{
    + return (u16)(p[0] | p[1] << 8);
    +}
    +
    +static inline u32 __get_unaligned_le32(const u8 *p)
    +{
    + return (u32)(p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24);
    +}
    +
    +static inline u64 __get_unaligned_le64(const u8 *p)
    +{
    + return ((u64)__get_unaligned_le32(p + 4) << 32) |
    + __get_unaligned_le32(p);
    +}
    +
    +#define __get_unaligned_le(ptr) ({ \
    + const void *__gu_p = (ptr); \
    + u64 __val; \
    + switch (sizeof(*(ptr)) { \
    + case 1: \
    + __val = *(const u8 *)__gu_p; \
    + break; \
    + case 2: \
    + __val = __get_unaligned_le16((const u8 *)__gu_p); \
    + break; \
    + case 4: \
    + __val = __get_unaligned_le32((const u8 *)__gu_p); \
    + break; \
    + case 8: \
    + __val = __get_unaligned_le64((const u8 *)__gu_p); \
    + break; \
    + default: \
    + BUILD_BUG_ON(1); \
    + }; \
    + (__force __typeof__(*(ptr)))__val; })
    +
    +static inline void __put_unaligned_le16(u16 val, u8 *p)
    +{
    + *p++ = val;
    + *p++ = val >> 8;
    +}
    +
    +static inline void __put_unaligned_le32(u32 val, u8 *p)
    +{
    + __put_unaligned_le16(val >> 16, p + 2);
    + __put_unaligned_le16(val, p);
    +}
    +
    +static inline void __put_unaligned_le64(u64 val, u8 *p)
    +{
    + __put_unaligned_le32(val >> 32, p + 4);
    + __put_unaligned_le32(val, p);
    +}
    +
    +#define __put_unaligned_le(val, ptr) ({ \
    + (void)sizeof(*(ptr) = (val)); \
    + switch (sizeof(*(ptr))) { \
    + case 1: \
    + *(ptr) = (val); \
    + break; \
    + case 2: \
    + __put_unaligned_le16((__force u16)(val), (u8 *)(ptr)); \
    + break; \
    + case 4: \
    + __put_unaligned_le32((__force u32)(val), (u8 *)(ptr)); \
    + break; \
    + case 8: \
    + __put_unaligned_le64((__force u64)(val), (u8 *)(ptr)); \
    + break; \
    + default: \
    + BUILD_BUG_ON(1); \
    + break; \
    + } \
    + (void)0; })
    +
    +#endif /* _LINUX_UNALIGNED_LITTLE_ENDIAN_H_ */
    diff --git a/include/linux/unaligned/no_builtin_memcpy.h b/include/linux/unaligned/no_builtin_memcpy.h
    new file mode 100644
    index 0000000..17a6e21
    --- /dev/null
    +++ b/include/linux/unaligned/no_builtin_memcpy.h
    @@ -0,0 +1,79 @@
    +#ifndef _LINUX_UNALIGNED_NO_BUILTIN_MEMCPY_H_
    +#define _LINUX_UNALIGNED_NO_BUILTIN_MEMCPY_H_
    +
    +#include
    +#include
    +
    +/* 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; })
    +
    +static inline u16 get_unaligned_le16(const __le16 *p)
    +{
    + return le16_to_cpu(get_unaligned(p));
    +}
    +
    +static inline u32 get_unaligned_le32(const __le32 *p)
    +{
    + return le32_to_cpu(get_unaligned(p));
    +}
    +
    +static inline u64 get_unaligned_le64(const __le64 *p)
    +{
    + return le64_to_cpu(get_unaligned(p));
    +}
    +
    +static inline u16 get_unaligned_be16(const __be16 *p)
    +{
    + return be16_to_cpu(get_unaligned(p));
    +}
    +
    +static inline u32 get_unaligned_be32(const __be32 *p)
    +{
    + return be32_to_cpu(get_unaligned(p));
    +}
    +
    +static inline u64 get_unaligned_be64(const __be64 *p)
    +{
    + return be64_to_cpu(get_unaligned(p));
    +}
    +
    +static inline void put_unaligned_le16(u16 val, void *p)
    +{
    + return put_unaligned(cpu_to_le16(val), (__le16 *)p);
    +}
    +
    +static inline void put_unaligned_le32(u32 val, void *p)
    +{
    + return put_unaligned(cpu_to_le32(val), (__le32 *)p);
    +}
    +
    +static inline void put_unaligned_le64(u64 val, void *p)
    +{
    + return put_unaligned(cpu_to_le64(val), (__le64 *)p);
    +}
    +
    +static inline void put_unaligned_be16(u16 val, void *p)
    +{
    + return put_unaligned(cpu_to_be16(val), (__be16 *)p);
    +}
    +
    +static inline void put_unaligned_be32(u32 val, void *p)
    +{
    + return put_unaligned(cpu_to_be32(val), (__be32 *)p);
    +}
    +
    +static inline void put_unaligned_be64(u64 val, void *p)
    +{
    + return put_unaligned(cpu_to_be64(val), (__be64 *)p);
    +}
    +
    +#endif
    --
    1.5.5.144.g3e42



    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  2. [PATCH] unaligned access, fix some includes

    Missed a few includes when moving some files around, this makes it
    actually compile.

    Signed-off-by: Harvey Harrison
    ---
    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(-)

    diff --git a/include/linux/unaligned/generic_be.h b/include/linux/unaligned/generic_be.h
    index ce42487..dd7e323 100644
    --- a/include/linux/unaligned/generic_be.h
    +++ b/include/linux/unaligned/generic_be.h
    @@ -1,7 +1,7 @@
    #ifndef _LINUX_UNALIGNED_GENERIC_BE_H_
    #define _LINUX_UNALIGNED_GENERIC_BE_H_

    -#include
    +#include
    #include

    #define get_unaligned __get_unaligned_cpu
    diff --git a/include/linux/unaligned/generic_le.h b/include/linux/unaligned/generic_le.h
    index b57c818..7b7de52 100644
    --- a/include/linux/unaligned/generic_le.h
    +++ b/include/linux/unaligned/generic_le.h
    @@ -1,7 +1,7 @@
    #ifndef _LINUX_UNALIGNED_GENERIC_LE_H_
    #define _LINUX_UNALIGNED_GENERIC_LE_H_

    -#include
    +#include
    #include

    #define get_unaligned __get_unaligned_cpu
    diff --git a/include/linux/unaligned/no_builtin_memcpy.h b/include/linux/unaligned/no_builtin_memcpy.h
    index 17a6e21..c117e78 100644
    --- a/include/linux/unaligned/no_builtin_memcpy.h
    +++ b/include/linux/unaligned/no_builtin_memcpy.h
    @@ -1,6 +1,7 @@
    #ifndef _LINUX_UNALIGNED_NO_BUILTIN_MEMCPY_H_
    #define _LINUX_UNALIGNED_NO_BUILTIN_MEMCPY_H_

    +#include
    #include
    #include

    --
    1.5.5.144.g3e42



    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

+ Reply to Thread