Virtualization solutions typically include a feature called USB
pass-through: making a USB device attached to the host
machine appear directly as a USB device attached to a virtual
machine. KVM, the fully
open-source virtualization solution for Linux, can do USB pass-through.
It inherits this feature from QEMU, which KVM incorporates to
provide system and device virtualization (KVM proper is focused on
processor virtualization, and runs in kernel space; QEMU runs in user
space).
But there's a hitch: KVM is most often used
via libvirt
and virt-manager,
which provide a virtualization management infrastructure and graphical user interface.
libvirt has some support for USB pass-through; but virt-manager doesn't
support it at all. So here's a guide to using the libvirt command shell to
get to this feature. These instructions require somewhat recent versions of KVM
(74 and up) and libvirt (0.4.4 and up).
You will need to hand-edit the XML documents that libvirt uses to
describe virtual machine instances (domains, in libvirt
terminology). You do this via virsh, the command shell
included with libvirt. virsh is fairly spartan, though it
does have a decent on-line help facility (accessed via
the help command). Run virsh as root, and use
the list command to see your VM instances and their
names:
virsh # list --all
Id Name State
----------------------------------
- windowsxp shut off
If list --all didn't show any VM instances, you should create some using virt-manager.
You can view the domain definition XML with the dumpxml
command:
virsh # dumpxml windowsxp
<domain type='kvm'>
<name>windowsxp</name>
…
</domain>
The edit command will open the domain definition XML in an
editor:
virsh # edit windowsxp
Edit the XML as desired
Domain windowsxp XML configuration edited.
Update: I recently noticed that the edit command only appeared in libvirt version 0.4.5. Some current editions of popular Linux distributions still have an earlier version. In that case, you can edit the XML domain definition files under /etc/libvirt/qemu directly, but you will need to restart libvirtd afterwards.
We want to edit this XML to add a hostdev element as
documented here
on the libvirt site. But first, you need to work out the USB
vendor and product IDs for the relevant device. You can discover these by attaching the device and running /sbin/lsusb on the
host. For example, here's the lsusb output on my laptop:
$ /sbin/lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 012: ID 0a5c:2110 Broadcom Corp. Bluetooth Controller
Bus 005 Device 003: ID 0483:2016 SGS Thomson Microelectronics Fingerprint Reader
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
The pairs of hexadecimal numbers on each line are the vendor and
produce IDs. For example, the bluetooth controller has a vendor ID of
0a5c, and a product ID of 2110.
To forward that to my windowsxp VM, I edit the domain definition as
follows:
<domain type='kvm'>
<name>windowsxp</name>
…
<devices>
…
<hostdev mode='subsystem' type='usb'>
<source>
<vendor id='0x0a5c'/>
<product id='0x2110'/>
</source>
</hostdev>
</devices>
</domain>
Note that it's a good idea to prevent the host from using the
device before attaching it to a VM. In this case, I made sure the
bluetooth controller was not being used by removing the relevant
kernel modules with rmmod. For USB storage devices, it's
sufficient to make sure that they are not mounted by the host kernel.
And for custom USB devices, without drivers in the Linux kernel, it
won't try to do anything with them, so you're usually fine.
There are a couple of limitations to this USB pass-through support.
The first is that the change won't take effect until you next start
the VM. The second is that it only works if the USB device in
question is connect at the time you start the VM. That's quite a
serious restriction. It's often convenient, and sometimes necessary,
to be able to connect a device to, and disconnect it from, a running machine. In
a follow-up post, I'll describe a way to avoid this limitation. It's now up here.
But once it's in operation, this USB pass-through support does work
well. I've used it with a range of USB devices, with complete
success.
1 comments