include/linux/unaligned: pack the whole struct rather than just the field
authorWill Newton <will.newton@gmail.com>
Wed, 22 Dec 2010 01:24:29 +0000 (17:24 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Dec 2010 03:43:34 +0000 (19:43 -0800)
commit4e06fd14d5fa78826397c891654a37e5a36ee827
tree816fc9951f6a6c1246e7974f95ffd71c7e861f76
parent91facc22dec964683aef88f5620a790a6e46b98a
include/linux/unaligned: pack the whole struct rather than just the field

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:

__get_unaligned_cpu16:
        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:

__get_unaligned_cpu16:
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 <will.newton@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/unaligned/packed_struct.h