Irregular Behavior in QEMU (again)

As mentioned in last month's blog, there are a few irregularities you need to watch out for when testing your USB code with QEMU. This month I will post another.

Again, don't get me wrong. I think QEMU is a wonderful emulator and use it often. I am simply listing what I think is irregular behavior with QEMU and its USB emulation, so that others who might be having difficulties may make sure this behavior isn't holding them back.


Streams and the nec-usb-xhci controller option (inquired)

Modern Mass Storage Protocol devices may support the use of USB Attached SCSI Protocol (UASP) using streams. This makes for much faster transfers.

The current UASP emulation of QEMU supports streams and works well when you specify the qemu-xhci controller option. However, does not (should not) work with the nec-usb-xhci controller option due to the fact that the latter controller option does not support streams (see note below).

xHC:HCCPARAMS1: Bits 15:12 = 7 on the former and 0 on the latter

Here is the command line I use to test my xHCI UASP driver with. It emulates three LUNs on the drive.

qemu-system-x86_64.exe -m 256 -machine q35 ^
-drive file=fysos64.img,format=raw,if=ide,media=disk,index=0 ^
-drive if=none,id=uas-disk1,format=raw,file=fysos64_lean.img ^
-drive if=none,id=uas-disk2,format=raw,file=fysos64_fat12.img ^
-drive if=none,id=uas-disk3,format=raw,file=fysos64_SFS.img ^
-device qemu-xhci,id=xhci ^
-device usb-uas,id=uas,bus=xhci.0 ^
-device scsi-hd,bus=uas.0,scsi-id=0,lun=0,drive=uas-disk1 ^
-device scsi-hd,bus=uas.0,scsi-id=0,lun=3,drive=uas-disk2 ^
-device scsi-hd,bus=uas.0,scsi-id=0,lun=5,drive=uas-disk3

This gives the following logical units (drives):

 Found Mass Storage Device Interface (Config = 1, Interface = 0)
 Using default interface number of 0.0
 Found 3 total logical units (LUNs) for device.

 QEMU     QEMU HARDDISK    rev: 2.5+
Lun 0: Total Sectors = 20492, Sector size = 512
 Found EFI GUID Partition Table with 1 entries.
 Found valid entry at LBA: 4
 "lean fs"
 Found a LEAN file system.

 QEMU     QEMU HARDDISK    rev: 2.5+
Lun 5: Total Sectors = 20492, Sector size = 512
 Found EFI GUID Partition Table with 1 entries.
 Found valid entry at LBA: 4
 "Simple File System"
 Found Simple File System

 QEMU     QEMU HARDDISK    rev: 2.5+
Lun 3: Total Sectors = 8174, Sector size = 512
 Found EFI GUID Partition Table with 1 entries.
 Found valid entry at LBA: 4
 "fat12"
 Found FAT12...using real Short Filename entries. (patent violation!)

However, if you change the qemu-xhci controller option to the NEC emulation (nec-usb-xhci), my driver no longer works.

After some research I believe it is QEMU's UASP emulation, more specifically at Line 338

  static bool uas_using_streams(UASDevice *uas)
  {
      return uas->dev.speed == USB_SPEED_SUPER;
  }

The code checks to see if streams are supported by merely checking if the device is a super-speed device. In my humble opinion, the QEMU code needs to check if the controller supports streams as well.


Again, I am not trying to say anything bad about QEMU or its USB implementation. I am simply listing a few items that may or may not influence your code, or find that your code doesn't work as expected due to these irregular behaviors.


Update: If you want to make sure either of the xHCI Controller options use streams, add "streams=on" to the command line. You can also turn streams off by using "streams=off". The qemu-xhci option has streams on by default. The nec-usb-xhci option has streams off by default.

I suggest that if you find a controller that does not support streams (which few don't), *and* you find a Mass Storage Device that supports UASP, you should not set the interface to that protocol. Instead, fall back to the (hopefully supported) BOT (Bulk Only Transport) Protocol (aka BBB or Bulk/Bulk/Bulk) Interface.

Conclusion is, when using QEMU and UASP, always make sure streams are enabled using the "streams=on" command line parameter.

-device nec-usb-xhci,id=xhci,streams=on