How do I assign a specific USB device to a specific USB controller in a KVM guest?

Solution Verified - Updated -

Environment

  • Red Hat Enterprise Linux 6
  • KVM virtual machines managed by libvirt
  • USB devices to be passed through to virtual guests

Issue

  • How do I assign a specific USB device to a specific USB controller in a KVM guest?
  • How do I create a USB2 controller within a KVM guest and pass USB devices to it?
  • I have a USB1 device which requires a USB1 controller for the driver to function. I also have a USB2 device which requires a USB2 controller to function. How do I pass both devices through to a KVM guest and have them "attach" to the appropriate USB controllers?
  • I have multiple USB devices of the same type plugged into my KVM virtualization host, I need to pass each device through to a different guest, how can I address the devices to ensure each individual device is passed through to its specific guest?

Resolution

Edit the guest definition with the command: virsh edit guestname

Define the default USB1 (UHCI) controller, and an additional USB2 (EHCI) controller:

    <controller type='usb' index='0' model='piix3-uhci'>
    </controller>
    <controller type='usb' index='1' model='ehci'>
    </controller>

(note: do not add PCI addresses for the controllers, libvirt handles this automatically)

Define a host USB1 device to pass through to the guest (replace AAAA with your USB1 device IDs):

    <hostdev mode='subsystem' type='usb' managed='yes'>
      <source>
        <vendor id='0xAAAA'/>
        <product id='0xAAAA'/>
      </source>
      <address type='usb' bus='0' port='2'/>
    </hostdev>

Define a host USB2 device to pass through to the guest (replace BBBB with your USB2 device IDs):

    <hostdev mode='subsystem' type='usb' managed='yes'>
      <source>
        <vendor id='0xBBBB'/>
        <product id='0xBBBB'/>
      </source>
      <address type='usb' bus='1' port='1'/>
    </hostdev>

Note that the index of the USB controller becomes the destination bus of the device. The USB1 controller is on Index 0 so the USB1 device is on Bus 0. Likewise, the USB2 controller is on Index 1, so the USB2 device is on Bus 1.

Port 0 on any USB controller is always the USB Root Hub, so start adding devices in Port 1 and later.

If your guest has the emulated USB Tablet configured, which qemu-kvm uses for seamless mouse integration, then you must have a UHCI controller defined, and you must add devices to that controller starting at Port 2. The emulated USB Tablet is hard-coded to require a UHCI USB1 controller, and is hard coded to always appear on Port 1 of that controller.

To pass through multiple devices of the same Vendor and Product ID, an additional line is required to address each device individually.

Given the following USB device addressing on the host:

host# lsusb
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 004: ID 0781:5530 SanDisk Corp. Cruzer                      ## this is the device to pass through

Add an address line to the source in the hostdev, for example:

    <hostdev mode='subsystem' type='usb' managed='yes'>
      <source>
        <vendor id='0x0781'/>
        <product id='0x5530'/>
        <address bus='2' device='4'/>
      </source>
      <address type='usb' bus='1' port='2'/>
    </hostdev>

Additional USB devices of the same ID can be passed through to different guests by specifying their host USB Bus and Device addresses in each guest's config files.

The Bus 002 in lsusb becomes bus='2' in the source address, and Device 004 in lsusb becomes device='4' in the source address. Additional Device entries in the host's lsusb specify the device number within each guest.

For example, given the following USB device addressing on the host:

host# lsusb
Bus 002 Device 004: ID 0781:5530 SanDisk Corp. Cruzer
Bus 002 Device 005: ID 0781:5530 SanDisk Corp. Cruzer
Bus 002 Device 006: ID 0781:5530 SanDisk Corp. Cruzer
Bus 002 Device 007: ID 0781:5530 SanDisk Corp. Cruzer

Each guest would have a different address line within hostdev. The first guest would have device='4', the second guest would have device='5', and so on.

It is required to power off the guest (ie: stop the qemu-kvm process running the guest) to make the changes to USB controllers, as the controllers are not hot-pluggable items.

Diagnostic Steps

  • USB controller types:

    • OHCI = USB 1
    • UHCI = USB 1
    • EHCI = USB 2
    • XHCI = USB 3
  • Tried the answer in the mailing list reply at: Re: [libvirt-users] USB Host Controllers

  • However the guest fails to start with the error message:

# virsh start usbtest
error: Failed to start domain usbtest
error: internal error process exited while connecting to monitor: qemu-kvm: -device usb-host,hostbus=1,hostaddr=8,id=hostdev0,bus=usb.0,port=1: Error: usb port 1 (bus usb.0) not found (in use?)

qemu-kvm: -device usb-host,hostbus=1,hostaddr=8,id=hostdev0,bus=usb.0,port=1: Device 'usb-host' could not be initialized
# lspci | grep USB
00:09.0 USB controller: Intel Corporation 82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (rev 10)
00:0a.0 USB controller: Intel Corporation 82371SB PIIX3 USB [Natoma/Triton II] (rev 01)
  • Passed through a USB device to the guest on the EHCI (USB2) controller:
guest# lsusb
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 002: ID 0627:0001 Adomax Technology Co., Ltd 
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 0781:5530 SanDisk Corp. Cruzer
  • Passed through a USB device to the guest on the UHCI (USB1) controller:
guest# lsusb
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 002: ID 0627:0001 Adomax Technology Co., Ltd 
Bus 001 Device 003: ID 0781:5530 SanDisk Corp. Cruzer
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
  • Identified "Adomax Technology Co., Ltd" device as qemu-kvm's emulated USB Tablet device, showing why assigning a USB device to Port 1 of the UHCI controller fails with Error: usb port 1 (bus usb.0) not found (in use?)

  • Tried to start a guest with only an EHCI controller and a USB Tablet, failed with the error:

# virsh start usbtest
error: Failed to start domain usbtest
error: internal error process exited while connecting to monitor: char device redirected to /dev/pts/1
qemu-kvm: -device usb-tablet,id=input0: Warning: speed mismatch trying to attach usb device QEMU USB Tablet to bus usb.0

qemu-kvm: -device usb-tablet,id=input0: Device 'usb-tablet' could not be initialized
  • Component
  • kvm

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments