Skip to contentSkip to conversation

kernel: revamp handling of unaligned access

RFC PATCH New Harvey Harrison 1 participant 2 messages Apr 9, 2008 Generic include/asm header files

lore
Share & tools
lore
#0 lore raw

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
index a1d7284..18acc19 100644
@@ -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
index 36f5fd4..28fa20e 100644
@@ -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
index 10081dc..25861cd 100644
@@ -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
index 7fbbb39..8bd3555 100644
@@ -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
index ffb67f4..e8ff49d 100644
@@ -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
index bb85598..2134205 100644
@@ -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
index fccc180..5a4c931 100644
@@ -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
index 804cb3f..94b4a77 100644
@@ -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
index 869e9dd..6b5c7a2 100644
@@ -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
index 3249049..bddbbfb 100644
@@ -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
index 53c9058..865867c 100644
@@ -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
index 6c95dfa..59bcc21 100644
@@ -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
index 8ee86db..1d4a684 100644
@@ -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
index 5250e30..391da8d 100644
@@ -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
index b6f8edd..9f1bb56 100644
@@ -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
index 1ed3ba5..faa18cd 100644
@@ -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
index 913598d..7ba2e1a 100644
@@ -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
index 2822089..45eb203 100644
@@ -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
#1 lore raw

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
index ce42487..dd7e323 100644
@@ -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
index b57c818..7b7de52 100644
@@ -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
index 17a6e21..c117e78 100644
@@ -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