PCI range checking under qemu-system-sparc64

Marius Strobl marius at alchemy.franken.de
Sun Sep 13 18:01:31 UTC 2015

On Sun, Sep 13, 2015 at 10:39:41AM +0000, Alexey Dokuchaev wrote:
> On Sun, Sep 13, 2015 at 04:21:43AM +0200, Marius Strobl wrote:
> > However, looking at ebus(4), I've spotted a bug in the conversion
> > to NEW_PCIB. Interested parties might want to give the attached
> > patch a try. That bug definitely can lead to the problem seen with
> > QEMU, I'm not sure it's the only one in that regard, though; I'm
> > fairly certain in this case there's no problem with interpreting
> > the device-tree involved, given that the same code is used for
> > ISA busses which - at least in reality - unlike EBus ones use
> > I/O port instead of memory space for the resources of devices
> > such as UARTs etc. There could be other spots not prepared for
> > EBus devices suddenly requesting SYS_RES_IOPORT, too, though.
> I've applied that patch, but it alone is not enough to allow the boot
> to proceed further in QEMU. :(

Err, right, on a second look the bug I thought existed in ebus(4)
actually isn't there; its code I added as part of the conversion
to NEW_PCIB is just a bit unclean/unobvious but in fact does the
right thing, even if a child resource would map to SYS_RES_IOPORT.

However, I noticed that the cause of failure likely is a bug in
the "ranges" property of the QEMU EBus bridge. The following is
an example from a T1-AC200 demonstrating how a correct setup
looks like:
ebus0: <PCI-EBus3 bridge> mem 0xf0000000-0xf0ffffff,0xf1000000-0xf17fffff at device 12.0 on pci1
child_hi child_lo phys_hi  phys_mid phys_lo  size
00000010 00000000 82016010 00000000 f0000000 01000000
00000014 00000000 82016014 00000000 f1000000 00800000

When mapping EBus child resources, their adresses are translated
to the address base specified by (phys_mid << 32) | phys_lo on
the parent side, based on the range the child resource falls
into (determined via child_hi, child_lo and size). For PCI-EBus-
bridges, the parent address range further must [1, p. 113 f.]
match the resources on the PCI side, i. e. the BARs. In the above
case that's 0xf0000000 determined by (phys_mid << 32) | phys_lo
and size 0x1000000 from the ranges property and mem 0xf0000000-
0xf0ffffff from the first BAR (see dmesg snippet) for example.

With QEMU we get (based on the dump from Mark and your dmesg):
ebus0: <PCI-EBus2 bridge> port 0x4000-0x7fff mem 0x3000000-0x3ffffff at device 3.0 on pci0
child_hi child_lo phys_hi  phys_mid phys_lo  size
00000010 00000000 02001810 00000000 00000000 01000000
00000014 00000000 01001814 00000000 00000000 00004000

So here, the parent addresses don't match as for example
0x00000000 determined by (phys_mid << 32) | phys_lo doesn't
match BAR 0, which is mem 0x3000000-0x3ffffff. Likewise for
the second BAR and range combo. Sizes are correct, though.

Note that according to the dump from Mark, the BARs of the
PCI-EBus-bridge at least match its "assigned-addresses"
property. So it might be as simple as fixing phys_mid and
phys_lo in the device tree file shipping with OpenBIOS, iff
such a thing exists and the device tree isn't assembled
dynamically somehow.


1: Peripheral Component Interconnect Input Output Controller,
   Part No.: 802-7837-01, Sun Microelectronics, March 1997

More information about the freebsd-sparc64 mailing list