[U-Boot] packed attribute problem

Reinhard Meyer u-boot at emk-elektronik.de
Mon Oct 4 14:43:48 CEST 2010


Dear Wolfgang Denk,

> Dear Reinhard Meyer,
> 
> In message <4CA9BE94.6000401 at emk-elektronik.de> you wrote:
>> Do you imply that the code is really different when the pointer gets
>> its value by assigning it NOT to a packed entity? Hard to believe.
> 
> This is a special "feature" of GCC on ARM.
> 
> -> cat foo.c
> #define writel(v,a)              (*(volatile unsigned int *)(a) = (v))
> 
> struct p {
>         int n;
> } __attribute__ ((packed));
> 
> struct q {
>         int n;
> };
> 
> void foo()
> {
>         struct p *pp = (struct p *)0x1000;
> 
>         pp->n = 5;
> }
> 
> void bar()
> {
>         struct q *qq = (struct q *)0x1000;
> 
>         qq->n = 5;
> }
> -> arm-linux-gcc -O -S foo.c
> -> cat foo.s
>         .file   "foo.c"
>         .text
>         .align  2
>         .global foo
>         .type   foo, %function
> foo:
>         @ Function supports interworking.
>         @ args = 0, pretend = 0, frame = 0
>         @ frame_needed = 0, uses_anonymous_args = 0
>         @ link register save eliminated.
>         @ lr needed for prologue
>         mov     r3, #4096
>         mov     r2, #0
>         orr     r1, r2, #5
>         strb    r1, [r3, #0]
>         strb    r2, [r3, #1]
>         strb    r2, [r3, #2]
>         strb    r2, [r3, #3]
>         bx      lr
>         .size   foo, .-foo
>         .align  2
>         .global bar
>         .type   bar, %function

In a non-packed struct an int will never be unaligned
(unless you use an unaligned pointer to the whole struct)

In a packed struct an int might be unaligned, so it
_might_ make sense for the compiler to handle that
differently on ARM. Assume you overlay (bad idea anyway)
a packed structure over some communication data stream
thats is byte oriented. On most architectures that would
work (besides obvious endianess issues) but on ARM it would
(without raising an exception) malfunction.
[remember the "display_buffer issue"]

> bar:
>         @ Function supports interworking.
>         @ args = 0, pretend = 0, frame = 0
>         @ frame_needed = 0, uses_anonymous_args = 0
>         @ link register save eliminated.
>         @ lr needed for prologue
>         mov     r2, #5
>         mov     r3, #4096
>         str     r2, [r3, #0]
>         bx      lr
>         .size   bar, .-bar
>         .ident  "GCC: (GNU) 4.2.2"
> 
> 
> Note that this is with GCC 4.2.2. Even GCC 4.0.0 behaves the same, so
> this is *not* an issue with very recent tool chains.

OK, for directly adressing elements inside a packed struct;
but the original post said:

"struct xyz {
	int	x;
	int	y;
	int	z[CONST];
} __attribute__ ((packed));

struct xyz *abc;
u32 * status_reg = (u32 *)&abc->z[0];

writel(status, status_reg);"

So the "status_reg" pointer is in a completely unrelated (to the packed struct)
"u32 *" and still the access is done like it was packed. If the
compiler silently drags that attribute along into the "u32 *"
THAT is really sick!

Reinhard



More information about the U-Boot mailing list