[powerstation-owners] building SLOF with gcc 4.3

Adrian Reber adrian at lisas.de
Mon Dec 8 09:46:28 MST 2008


On Mon, Dec 08, 2008 at 09:45:00AM +1100, Benjamin Herrenschmidt wrote:
> On Sun, 2008-12-07 at 22:48 +0100, Adrian Reber wrote:
> > +               /* For some reason we need this eieio here. With newer compilers
> > +                * the bios emulator hangs if we do not wait a certain time at
> > +                * this point. It does not need to be an eieio but it seems it
> > +                * wastes enough time to keep us going. This is completely not
> > +                * understood. */
> > +               eieio();
> >                 DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %08x\n", __FUNCTION__,
> >                                 addr, rval);
> >                 return rval;
> > 
> > If anybody knows a better way to fix the hang in the bios emulator
> > I would be happy to fix it the right way and not just wait for
> > some unknown reason.
> 
> Interesting. I have not noticed this problem when running the emulator
> outside of SLOF (I hacked up a userspace variant for my own needs).
> 
> However, there are a few things to consider. First newer gcc's are much
> more aggressive at re-ordering things, it might be that you lack some
> kind of compiler barrier here. Also, I don't know if your read_io
> contains an eieio already but you need to ensure there is no write
> combining and unless you are mapped non-cacheable -and- guarded, you
> need the eieio (and you need it even with I+G in some circumstances).
> 
> So it could just be that you lack a necessary barrier here.

That was also my initial thought, but the read_io() and write_io()
functions are full of barriers because we have to disable the cache
before evey IO access and enabled it afterwards again. So I looked
already at that code a lot and it seems okay.

I have now found a better solution (and probably also correct).

The in32le() function was the problem. It used to be something like that:
asm volatile ("lwbrx  %0, 0, %1":"=r" (val):"r"(addr));

Other examples I found were doing:
asm volatile ("lwbrx  %0, 0, %1":"=r" (val):"r"(addr), "m" (*addr));

that already helped. Then I also found:
asm volatile ("lwbrx %0, %y1" : "=r"(val) : "Z"(*addr));
at http://hardwarebug.org/2008/10/25/gcc-inline-asm-annoyance/
which also makes it work.

I am now using the last version and it works. It also seems to be the
correct solution, althoug using an undocumented feature of gcc might
not be the smartest idea. Any recommendations which of those two
versions is better?

		Adrian


More information about the powerstation-owners mailing list