include/linux/unaligned: pack the whole struct rather than just the field
authorWill Newton <>
Wed, 22 Dec 2010 01:24:29 +0000 (17:24 -0800)
committerLinus Torvalds <>
Thu, 23 Dec 2010 03:43:34 +0000 (19:43 -0800)
The current packed struct implementation of unaligned access adds the
packed attribute only to the field within the unaligned struct rather than
to the struct as a whole.  This is not sufficient to enforce proper
behaviour on architectures with a default struct alignment of more than
one byte.

For example, the current implementation of __get_unaligned_cpu16 when
compiled for arm with gcc -O1 -mstructure-size-boundary=32 assumes the
struct is on a 4 byte boundary so performs the load of the 16bit packed
field as if it were on a 4 byte boundary:

        ldrh    r0, [r0, #0]
        bx      lr

Moving the packed attribute to the struct rather than the field causes the
proper unaligned access code to be generated:

ldrb r3, [r0, #0] @ zero_extendqisi2
ldrb r0, [r0, #1] @ zero_extendqisi2
orr r0, r3, r0, asl #8
bx lr

Signed-off-by: Will Newton <>
Cc: Arnd Bergmann <>
Signed-off-by: Andrew Morton <>
Signed-off-by: Linus Torvalds <>

index 2498bb9fe002a4bafee70389e70c57b842ede507..c9a6abd972a142e7aea4129da8a8e5b9bc64b6ce 100644 (file)
@@ -3,9 +3,9 @@
 #include <linux/kernel.h>
-struct __una_u16 { u16 x __attribute__((packed)); };
-struct __una_u32 { u32 x __attribute__((packed)); };
-struct __una_u64 { u64 x __attribute__((packed)); };
+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 void *p)