Skip to content

xhci HCIVERSION register read emulation incorrectly handled

This bug has been copied automatically from: https://bugs.launchpad.net/qemu/+bug/1693050
Reported by 'Robert Mustacchi' on 2017-05-23 :

We had an illumos user trying to run illumos in QEMU 2.9.0 with the qemu-
xhci device enabled. Note, that while this was discovered against QEMU
2.9.0, from my current read of the HEAD, it is still present. The illumos
bug at https://www.illumos.org/issues/8173 has additional information on
how the user invoked qemu. While investigating the problem we found that
the illumos driver was reading a version of 0x0000 when reading the
HCIVERSION register from qemu.

In the illumos driver we're performing a 16-bit read of the version
register at offset 0x2. From looking around at other OSes, while Linux
performs a 4 byte read at offset 0x0 and masks out the version, others
that care about the version are doing a two byte read, though not all
actually act on the version and some just discard the information.

The user who hit this was able to enable tracing (note the tracing file is
attached to the illumos bug linked previously) and we hit the
unimplemented register read with offset 0x2 at
http://git.qemu.org/?p=qemu.git;a=blob;f=hw/usb/hcd-xhci.c;hb=HEAD#l2960.
The xhci register specifies today that its allowed for users to do 1-4
byte reads; however, that it implements only four byte reads in its
implementation (http://git.qemu.org/?p=qemu.git;a=blob;f=hw/usb/hcd-
xhci.c;hb=HEAD#l3333). Hence why when we read the HCIVERSION register at
offset 0x2, it isn't handled in xhci_cap_read() which then returns zeros.

From digging into this, I think that we're coming into
memory_region_dispatch_read() and then memory_region_dispatch_read1().
However, I don't see anything in either the general memory region logic or
in the xhci_cap_read() function that would deal with adjusting the offset
that we're reading at and then masking it off again. While the
access_with_adjusted_size() attempts to deal with this, it never adjusts
the hardware address that's passed in to be a multiple of the
implementation defined offset that I can see. I suspect that the FIXME at
line 582 (http://git.qemu.org/?p=qemu.git;a=blob;f=memory.c;hb=HEAD#l582)
and the implementation in the xhci code is the crux of the problem.

For the time being we're working around this in the illumos driver, but I
wanted to point this out such that it might be helpful for other systems
which are assuming that they can do the two byte read like on hardware.
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information