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

From
Mikael Pettersson <hidden>
Date
2005-02-25 14:28:28
Also in
lkml
Reply to
Mikael Pettersson, 2005-02-25
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 [off-list ref], 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;
}
Thread (7 messages) 7 messages, 4 authors, last reply 2005-02-25
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help