2006-01-06 18:15:52

by Oliver Neukum

[permalink] [raw]
Subject: need for packed attribute

Hi,

is there any architecture for which packed is required in structures like this:

/* All standard descriptors have these 2 fields at the beginning */
struct usb_descriptor_header {
__u8 bLength;
__u8 bDescriptorType;
};

Regards
Oliver


2006-01-06 18:38:57

by Russell King

[permalink] [raw]
Subject: Re: need for packed attribute

On Fri, Jan 06, 2006 at 07:15:43PM +0100, Oliver Neukum wrote:
> Hi,
>
> is there any architecture for which packed is required in structures like this:
>
> /* All standard descriptors have these 2 fields at the beginning */
> struct usb_descriptor_header {
> __u8 bLength;
> __u8 bDescriptorType;
> };

sizeof(struct usb_descriptor_header) will be 4 on ARM. If this
concerns you, you need to pack the structure thusly:

struct usb_descriptor_header {
__u8 bLength;
__u8 bDescriptorType;
} __attribute__((packed));


--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 Serial core

2006-01-12 12:27:43

by Mikael Pettersson

[permalink] [raw]
Subject: Re: need for packed attribute

On Fri, 6 Jan 2006 18:38:46 +0000, Russell King wrote:
>> is there any architecture for which packed is required in structures like this:
>>
>> /* All standard descriptors have these 2 fields at the beginning */
>> struct usb_descriptor_header {
>> __u8 bLength;
>> __u8 bDescriptorType;
>> };
>
>sizeof(struct usb_descriptor_header) will be 4 on ARM.

I found this surprising, but gcc-3.4.5 for ARM seems to agree with you.

As fas as I can tell, the AAPCS document (v2.03 7th Oct 2005) requires
that a simple "struct foo { unsigned char c; };" should have both size
and alignment equal to 1, but gcc makes them both 4. Do you have any
information about why gcc is doing this on ARM/Linux? Is there an accurate
ABI document for ARM/Linux somewhere?

/Mikael

2006-01-12 13:47:39

by Russell King

[permalink] [raw]
Subject: Re: need for packed attribute

On Thu, Jan 12, 2006 at 01:27:12PM +0100, Mikael Pettersson wrote:
> On Fri, 6 Jan 2006 18:38:46 +0000, Russell King wrote:
> >> is there any architecture for which packed is required in structures like this:
> >>
> >> /* All standard descriptors have these 2 fields at the beginning */
> >> struct usb_descriptor_header {
> >> __u8 bLength;
> >> __u8 bDescriptorType;
> >> };
> >
> >sizeof(struct usb_descriptor_header) will be 4 on ARM.
>
> I found this surprising, but gcc-3.4.5 for ARM seems to agree with you.
>
> As fas as I can tell, the AAPCS document (v2.03 7th Oct 2005) requires
> that a simple "struct foo { unsigned char c; };" should have both size
> and alignment equal to 1, but gcc makes them both 4. Do you have any
> information about why gcc is doing this on ARM/Linux? Is there an accurate
> ABI document for ARM/Linux somewhere?

That's the new EABI, which is a major change to the existing ABI which
the kernel and all of userspace is currently built using.

The old ABI has it's roots in 1993 when the kernel and userland was
initially built using an ANSI C compiler, and the work being done to
port GCC was to make it compliant with that version of the ABI. This
ABI is documented only in dead-tree form.

Due to lack of manpower on the Linux side (iow, more or less just me)
this became the ABI of the early ARM Linux a.out toolchain. At that
time, I did not consider this to be a problem - it wasn't a problem
as far as the kernel was concerned.

When ELF came along, other folk worked on the toolchain, but they stuck
with that ABI - you could not transition between the a.out ABI to the
ELF ABI without breaking the kernel - structure layouts would change.

Hence, this is the existing ABI we have. Changing the padding or
alignment of structures changes the kernel ABI, making it incompatible
with current userland.

We're working on a set of patches to bring ARM Linux to be compatible
with the new EABI (which you've found above). This involves adding a
compatibility layer to the kernel to convert structures between the
old layouts and the new layouts.

I'm sure you can appreciate the size of this problem given the issues
with running 32-bit apps on 64-bit machines - it's the same kind of
issue.

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 Serial core

2006-01-12 13:53:10

by Russell King

[permalink] [raw]
Subject: Re: need for packed attribute

On Thu, Jan 12, 2006 at 01:47:29PM +0000, Russell King wrote:
> Due to lack of manpower on the Linux side (iow, more or less just me)
> this became the ABI of the early ARM Linux a.out toolchain. At that
> time, I did not consider this to be a problem - it wasn't a problem
> as far as the kernel was concerned.

Before someone takes that the wrong way - Richard Earnshaw worked on
porting binutils + gcc to the ARM architecture. I worked on converting
that toolchain to work for ARM Linux - supporting the a.out shared
libraries and other Linux specific features.

Changing the ABI was, and still is completely outside my level of
knowledge of gcc.

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 Serial core

2006-01-12 16:30:52

by Mikael Pettersson

[permalink] [raw]
Subject: Re: need for packed attribute

Russell King writes:
> > As fas as I can tell, the AAPCS document (v2.03 7th Oct 2005) requires
> > that a simple "struct foo { unsigned char c; };" should have both size
> > and alignment equal to 1, but gcc makes them both 4. Do you have any
> > information about why gcc is doing this on ARM/Linux? Is there an accurate
> > ABI document for ARM/Linux somewhere?
>
> That's the new EABI, which is a major change to the existing ABI which
> the kernel and all of userspace is currently built using.
>
> The old ABI has it's roots in 1993 when the kernel and userland was
> initially built using an ANSI C compiler, and the work being done to
> port GCC was to make it compliant with that version of the ABI. This
> ABI is documented only in dead-tree form.
>
> Due to lack of manpower on the Linux side (iow, more or less just me)
> this became the ABI of the early ARM Linux a.out toolchain. At that
> time, I did not consider this to be a problem - it wasn't a problem
> as far as the kernel was concerned.
>
> When ELF came along, other folk worked on the toolchain, but they stuck
> with that ABI - you could not transition between the a.out ABI to the
> ELF ABI without breaking the kernel - structure layouts would change.
>
> Hence, this is the existing ABI we have. Changing the padding or
> alignment of structures changes the kernel ABI, making it incompatible
> with current userland.

OK, thanks for this info. It means that GCC is the definitive authority
on calling conventions and data layouts, not the AAPCS; I wasn't aware of
that before.

(My interest in this issue comes from working on a port of a functional
programming language's JIT compiler and runtime system to XScale.)

/Mikael

2006-01-12 16:46:29

by Russell King

[permalink] [raw]
Subject: Re: need for packed attribute

On Thu, Jan 12, 2006 at 05:30:11PM +0100, Mikael Pettersson wrote:
> OK, thanks for this info. It means that GCC is the definitive authority
> on calling conventions and data layouts, not the AAPCS; I wasn't aware of
> that before.

BTW, it's worth noting that the new EABI stuff has it's own set of
problems. We have r0 to r6 to pass 32-bit or 64-bit arguments.
With EABI, 64-bit arguments will be aligned to an _even_ numbered
register. Hence:

long sys_foo(int a, long long b, int c, long long d);

will result in the following register layouts:

EABI Current
r0 a a
r1 unused \_ b
r2 \_ b /
r3 / c
r4 c \_ d
r5 /
r6 ... out of space for 'd' ... room for one other int.
r7 syscall number

and as such will be uncallable with this argument ordering for EABI.

We've already had to sanitise sys_fadvise64_64() because of this.

So, I forsee more problems appearing with EABI, not less. ;(

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 Serial core

2006-01-12 17:21:03

by Pete Zaitcev

[permalink] [raw]
Subject: Re: need for packed attribute

On Thu, 12 Jan 2006 13:27:12 +0100 (MET), Mikael Pettersson <[email protected]> wrote:

> [...] Do you have any
> information about why gcc is doing this on ARM/Linux?

Russell forgot to explain it, but the reason for this weirdness is real.
It is so you can do things like this:

struct foo {
char x, y;
};

struct bar {
long g;
};

char *p;
struct bar *bp;
p = kmalloc(sizeof(struct foo)+sizeof(struct bar));
bp = p + sizeof(struct foo);

Notice that sizes are aligned even in sensible ABIs whenever you
have anything bigger than a char inside a struct, in order to let
arrays of structures work properly. As a side effect, the construct
above would be aligned whenever struct foo contained a long. So most
of the time we see the same result, ARM or not.

So this is not really a question of whatever some silly document
specifies, but what is workable in real life C programming.

Funnily enough, you are not safe depending on the ABI to make this
sort of padding (so our favourite alloc_netdev() and alloc_ieee80211
only work by accident with the trailing u8 priv[]). For example, on
sparc(32) the ABI alignes to 32 bits only, but the ldd instruction
traps if a 64-bit value is not aligned to 64 bits, so if the struct
bar in the above example had a long long, it would still trap.

Another funny thing about the above is that once you mark struct foo
packed, the example breaks. So, nobody should do use packed structs
in such constructs ... unless everything is packed. The pack attribute
has significant properties of cancer.

-- Pete

P.S. I am repeating myself as Katon, but I am yet to see why any of
this matters. Neither Russell nor Oliver ever presented a case where
an unpacked struct caused breakage in USB.

P.P.S. The USB stack was careful to use correct sizes historically.
One grep of the source will tell you that all this stench emanates from
the newer code, in particular the gadget and its attendant components,
such as usbtest. Guess who wrote it: same gentleman who advocated adding
((packed)) to _all_ structures "used to talk to hardware". He just has
no respect for coding practices, that's all. And some other gentleman,
otherwise highly respected for his sharp eye for races and locking
problems, is only too happy to copy-paste and to forward patches which
offer no justification.

2006-01-12 17:23:03

by David Vrabel

[permalink] [raw]
Subject: Re: [linux-usb-devel] Re: need for packed attribute

Russell King wrote:
> BTW, it's worth noting that the new EABI stuff has it's own set of
> problems. We have r0 to r6 to pass 32-bit or 64-bit arguments.
> With EABI, 64-bit arguments will be aligned to an _even_ numbered
> register.

Is there a reason for this alignment requirement?

David Vrabel
--
David Vrabel, Design Engineer

Arcom, Clifton Road Tel: +44 (0)1223 411200 ext. 3233
Cambridge CB1 7EA, UK Web: http://www.arcom.com/

2006-01-12 17:26:27

by Russell King

[permalink] [raw]
Subject: Re: need for packed attribute

On Thu, Jan 12, 2006 at 09:20:06AM -0800, Pete Zaitcev wrote:
> P.S. I am repeating myself as Katon, but I am yet to see why any of
> this matters. Neither Russell nor Oliver ever presented a case where
> an unpacked struct caused breakage in USB.

If you would like to refresh your memory (which is obviously faulty)
you'll see that my involvement in this thread was merely to answer
a simple question about structure sizes.

It was not a bug report about USB breaking. Therefore, I have no
case to present.

(And WTF do soo many people assume that I'm somehow always reporting
a bloody bug and have to present such cases when I get copied on
emails to answer questions? I don't understand the stupid mentality
there - this is _not_ the first time this has happened in the 12 days
of 2006 so far.)

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 Serial core

2006-01-12 17:34:24

by Russell King

[permalink] [raw]
Subject: Re: [linux-usb-devel] Re: need for packed attribute

On Thu, Jan 12, 2006 at 05:22:47PM +0000, David Vrabel wrote:
> Russell King wrote:
> > BTW, it's worth noting that the new EABI stuff has it's own set of
> > problems. We have r0 to r6 to pass 32-bit or 64-bit arguments.
> > With EABI, 64-bit arguments will be aligned to an _even_ numbered
> > register.
>
> Is there a reason for this alignment requirement?

I think it comes from the 64-bit accessing instructions (ldrd/strd)
having the restriction that they only take an even numbered 32-bit
register. The immediately consecutive higher numbered 32-bit
egister is used as the other half of the number.

Think about it as the x86 32-bit eax register being made up of
16-bit ah and al registers. Only we call then r0, r1 etc not
eax, ah and al (and they're twice the size.)

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 Serial core

2006-01-12 17:37:07

by Pete Zaitcev

[permalink] [raw]
Subject: Re: need for packed attribute

On Thu, 12 Jan 2006 17:26:17 +0000, Russell King <[email protected]> wrote:
> On Thu, Jan 12, 2006 at 09:20:06AM -0800, Pete Zaitcev wrote:

> > P.S. I am repeating myself as Katon, but I am yet to see why any of
> > this matters. Neither Russell nor Oliver ever presented a case where
> > an unpacked struct caused breakage in USB.
>
> If you would like to refresh your memory (which is obviously faulty)
> you'll see that my involvement in this thread was merely to answer
> a simple question about structure sizes.

Isn't it exactly what I just wrote, and you quoted?

> It was not a bug report about USB breaking. Therefore, I have no
> case to present.

The thread started with Oliver posting a patch. And later, he appealed
to your authority.

It seems that we both are saying that there's no problem, no case,
no nothing.

-- Pete

2006-01-12 18:36:35

by Benjamin LaHaise

[permalink] [raw]
Subject: Re: need for packed attribute

On Fri, Jan 06, 2006 at 06:38:46PM +0000, Russell King wrote:
> > /* All standard descriptors have these 2 fields at the beginning */
> > struct usb_descriptor_header {
> > __u8 bLength;
> > __u8 bDescriptorType;
> > };
>
> sizeof(struct usb_descriptor_header) will be 4 on ARM. If this
> concerns you, you need to pack the structure thusly:

Interesting. Perhaps we should add -Wpadded to CFLAGS in order to remind
people, although that might take a fair bit of work to clean up existing
structure definitions.

-ben
--
"You know, I've seen some crystals do some pretty trippy shit, man."
Don't Email: <[email protected]>.

2006-01-12 19:35:42

by David Brownell

[permalink] [raw]
Subject: Re: [linux-usb-devel] Re: need for packed attribute

On Thursday 12 January 2006, Pete Zaitcev wrote (in another snide postscript):
>
> P.P.S. The USB stack was careful to use correct sizes historically.
> One grep of the source will tell you that all this stench emanates from
> the newer code, in particular the gadget and its attendant components,
> such as usbtest. Guess who wrote it: same gentleman who advocated adding
> ((packed)) to _all_ structures "used to talk to hardware". He just has
> no respect for coding practices, that's all.

You were the one who said "talk to hardware", as I had politely pointed
out off-line in previous email ... nobody else.

What you've done a couple times now is try to put those words in someone
else's mouth -- mine! -- which are clearly both (a) not what were actually
said, and (b) wrong. (FWIW it's something I've observed happening a lot
in the "traditional media" here in the US, it's not good there either.)

This what's known as not acting in good faith. "No respect for" ground
rules of discussion, for that matter ... if you're going to argue about
things, please don't put words in anyone's mouth. Certainly not mine.
(Even when the actual words said _are_ inconvenient to your agenda...)


The "packed" attribute is correct, since there's no guarantee that those
structures will be appearing in protocol data structures in GCC-friendly
layouts. Or even that the usb-if will generate protocol data structures
that happen to match GCC alignment rules, for that matter.

It's perfectly legal and common to have two seven-byte structures (like
non-audio endpoint descriptors) adjacent to each other, even when those
structures contain values otherwise subject to alignment restrictions (like
the maxpacket size, a __u16 value).

Moreover, there is no circumstance under which we'd want the compiler
expanding that seven byte data structure into an eight byte one, by
picking some place to insert a padding byte.


And for that matter, many/most of those protocol structures were declared
"packed" even in 2.4 kernels when Linux was extending them with host-side data
structures and making extra copies of them. The packing may have been
declared per-element rather than structure-wide, but it was still declared.
That's another way in which those comments of yours are wrong.

- Dave