xhci HCIVERSION register read emulation incorrectly handled

Bug #1693050 reported by Robert Mustacchi on 2017-05-23
16
This bug affects 2 people
Affects Status Importance Assigned to Milestone
QEMU
Undecided
Unassigned

Bug Description

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.

Paul Menzel (paulmenzel) wrote :

According to [1], this is still an issue today.

[1]: https://review.coreboot.org/c/coreboot/+/39838/

Odd, this should be fixed by commit 6ee021d41 and 36960b4d66..98f52cdbb5c.

Paul Menzel (paulmenzel) wrote :

According to Duncan, it’s not, and the paragraph from the original issue still applies.

> 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
> (https://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.

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers