Re: ppc32 weirdness with gcc-4.0 in 2.6.11-rc4

From: Mikael Pettersson
Date: Fri Feb 25 2005 - 09:30:50 EST


Mikael Pettersson writes:
> Jakub Jelinek writes:
> > On Thu, Feb 24, 2005 at 04:08:47PM +0100, Mikael Pettersson wrote:
> > > _However_, the 0k data message is due to a gcc-4.0 bug, and below
> > > you'll find a test program which illustrates it.
> >
> > http://gcc.gnu.org/PR20196
>
> Jakub's patch to gcc4 solved the mysterious "0k data" message,
> but my eMac's USB is still dysfunctional. I'll try to look into
> that next week.

CONFIG_USB_DEBUG gave the following dmesg diff between gcc-3.4.3 and 4.0.0:

@@ -118,6 +118,8 @@
hub 1-0:1.0: Single TT
hub 1-0:1.0: TT requires at most 8 FS bit times
hub 1-0:1.0: power on to power good time: 20ms
+hub 1-0:1.0: hub controller current requirement: 0mA
+hub 1-0:1.0: 500mA bus power budget for children
hub 1-0:1.0: local power source is good
hub 1-0:1.0: enabling power on all ports
ohci_hcd: 2004 Nov 08 USB 1.1 'Open' Host Controller (OHCI) Driver (PCI)

There are several more of these diffs, and they are what's eventually
causing USB to label the hub as bus-powered and refuse to connect it.

The root problem is that code like:
get_status(..., &status);
cpu_to_le16s(&status);
if ((status & (1 << BITNO)) == 0) { ... }
gets miscompiled so that the if statement triggers when it shouldn't.

Below is a standalone test program which reproduces the bug.
It does involve some PPC-specific asm(), so the bug may be
in gcc-4.0.0 or it may be in the asm() constraints.

/Mikael

/* gcc4bug2.c
* Written by Mikael Pettersson <mikpe@xxxxxxxxx>, 2005-02-25.
*
* This program is abstracted from drivers/usb/core/hub.c in
* the 2.6.11-rc5 Linux kernel sources.
*
* With gcc-3.4.3, gcc-3.3.5, or gcc-3.2.3, usb_configure()
* correctly returns 0.
*
* With gcc-4.0.0 20050220, usb_configure() erroneously returns 1.
* The error occurs at -O1 and higher. -O0 hides the error.
*
* All gcc versions were configured for powerpc-unknown-linux-gnu.
*/
#include <stdio.h>

extern __inline__ __attribute__((always_inline))
void st_le16(volatile unsigned short *addr, const unsigned val)
{
__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
}

static __inline__ __attribute__((always_inline))
void swab16s(unsigned short *addr)
{
st_le16(addr, *addr);
}

unsigned short raw_hubstatus;

void usb_get_status(unsigned short *hubstatusp)
{
*hubstatusp = raw_hubstatus;
}

int usb_configure(void)
{
unsigned short hubstatus;

usb_get_status(&hubstatus);
swab16s(&hubstatus);
return (hubstatus & 1) == 0;
}

int main(void)
{
int ret;

raw_hubstatus = 0x0300;
ret = usb_configure();
if (ret) {
fprintf(stderr, "gcc bug! usb_configure() returned %d\n", ret);
return 1;
} else
return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/