How do I assign a specific USB device to a specific USB controller in a KVM guest?
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
-
This was tried in RHEL6. Also tried in Fedora 18 (latest current release) to see if this functionality is included in a version of libvirt which was released after RHEL6. The same error happened within F18, so it doesn't seem to be a versioning issue.
-
Read libvirt Domain XML format documentation at:
-
Tried different USB controllers (
piix3-uhci
piix4-uhci
ehci
ich9-ehci1
ich9-uhci1
ich9-uhci2
ich9-uhci3
vt82c686b-uhci
pci-ohci
`nec-xhci) and destination addresses. -
Got EHCI (libvirt
model='ehci'
) and UHCI (livirtmodel='piix3-uhci'
) controllers working in a guest:
# 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 asqemu-kvm
's emulated USB Tablet device, showing why assigning a USB device to Port 1 of the UHCI controller fails withError: 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
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