7

I'm struggling to connect a usb device, that gets detected correctly by the host, to a kvm vm.

I have a freshly installed Ubuntu Server 14.10 as KVM/QEMU host. I set up an Ubuntu vm using this command:

virt-install --connect qemu:///system \
            -n test01 \
            -r 1024 \
            --vcpus=2 \
            --disk path=/vmstorage/01/test01.img,size=5 \
            --vnc \
            --noautoconsole \
            --os-variant=ubuntuutopic \
            --hvm \
            --cdrom /path/to/ubuntu-14.10-server-i386.iso

After the successful installation a virsh dumpxml test01 returns

<domain type='kvm' id='16'>
  <name>test01</name>
  <uuid>f58ca825-c999-4168-9f5a-616057d9955d</uuid>
  <memory unit='KiB'>1048576</memory>
  <currentMemory unit='KiB'>1048576</currentMemory>
  <vcpu placement='static'>2</vcpu>
  <resource>
    <partition>/machine</partition>
  </resource>
  <os>
    <type arch='x86_64' machine='pc-i440fx-utopic'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <cpu mode='custom' match='exact'>
    <model fallback='allow'>SandyBridge</model>
  </cpu>
  <clock offset='utc'>
    <timer name='rtc' tickpolicy='catchup'/>
    <timer name='pit' tickpolicy='delay'/>
    <timer name='hpet' present='no'/>
  </clock>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/bin/kvm-spice</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='raw'/>
      <source file='/vmstorage/01/test01.img'/>
      <backingStore/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </disk>
    <disk type='block' device='cdrom'>
      <driver name='qemu' type='raw'/>
      <backingStore/>
      <target dev='hda' bus='ide'/>
      <readonly/>
      <alias name='ide0-0-0'/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
    <controller type='usb' index='0' model='ich9-ehci1'>
      <alias name='usb0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x7'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci1'>
      <alias name='usb0'/>
      <master startport='0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' multifunction='on'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci2'>
      <alias name='usb0'/>
      <master startport='2'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci3'>
      <alias name='usb0'/>
      <master startport='4'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x2'/>
    </controller>
    <controller type='pci' index='0' model='pci-root'>
      <alias name='pci.0'/>
    </controller>
    <controller type='ide' index='0'>
      <alias name='ide0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
    </controller>
    <interface type='bridge'>
      <mac address='52:54:00:11:b2:c1'/>
      <source bridge='br0'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
      <source path='/dev/pts/0'/>
      <target port='0'/>
      <alias name='serial0'/>
    </serial>
    <console type='pty' tty='/dev/pts/0'>
      <source path='/dev/pts/0'/>
      <target type='serial' port='0'/>
      <alias name='serial0'/>
    </console>
    <input type='mouse' bus='ps2'/>
    <input type='keyboard' bus='ps2'/>
    <graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'>
      <listen type='address' address='0.0.0.0'/>
    </graphics>
    <video>
      <model type='cirrus' vram='9216' heads='1'/>
      <alias name='video0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
    <memballoon model='virtio'>
      <alias name='balloon0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </memballoon>
  </devices>
  <seclabel type='dynamic' model='apparmor' relabel='yes'>
    <label>libvirt-f58ca825-c999-4168-9f5a-616057d9955d</label>
    <imagelabel>libvirt-f58ca825-c999-4168-9f5a-616057d9955d</imagelabel>
  </seclabel>
</domain>

I now want to attach an USB stick. After some googleing I found some sources that basically all suggest the following approach:

  1. attach stick to host
  2. get vendor- and product-id

    root@host01:~# lsusb
    Bus 002 Device 004: ID 13fe:5100 Kingston Technology Company Inc. Flash Drive
    Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
    Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 001 Device 004: ID 0624:0249 Avocent Corp.
    Bus 001 Device 003: ID 0624:0248 Avocent Corp.
    Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    
  3. add new config-snippet to vm via virsh edit test01

    <devices>
      <!- ... ->
      <hostdev mode='subsystem' type='usb' managed='yes'>
        <source>
          <vendor id='0x13fe'/>
          <product id='0x5100'/>
        </source>
      </hostdev>
    </devices/>
    
  4. restart vm

After that the vm should see the stick via lsusb, but nothing changes. If I try to attach the device to a second vm though, virsh start <othervm> fails with error: Requested operation is not valid: USB device 002:003 is in use by driver QEMU, domain test01 BUT I can still mount and access the stick on the host. I tried different sticks and different vm-operating systems (ubuntu and windows), no success.

Some instructions suggest to turn off apparmor, but a /etc/init.d/apparmor stop didn't change anything.

This is driving me nuts, since I don't get any error or log messages and I have no clue how to find out what's wrong. Any ideas on how to get the usb connected to the vm, or at least, how to analyse it further?

4

It's probably a problem with access rights. Your QEMU deamon is not allowed to access the USB devices. Try:

chown libvirt-qemu /dev/bus/usb/ -R

or whichever user your KVM is running as. This should do the trick.

  • This would only work temporarily until the next reboot; see my answer for a permanent solution. – user186340 Feb 12 '15 at 11:34
  • I had the same issue with ubuntu 16.04 and this didn't work for me. I found I need to modify the apparmor configuration as described in Ubuntu KVM passthrough wiki: help.ubuntu.com/community/KVM/… – Max Jul 15 '17 at 20:01
7

To grant permanent access to the raw USB device nodes to the user the hypervisor runs as, you need to create an udev rule; the chown-based answer will only work until the next reboot.

In /lib/udev/rules.d, create a file like 51-usb_passthrough.rules :

SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{busnum}=="2" ATTRS{devpath}=="1" GROUP="kvm"

Here I used physical bus and port numbers to target the device (as I prefer passing through the physical port no matter what device is plugged in rather than reconfiguring my VM each time I connect a new device), but of course you can use whatever attributes you want; the GROUP argument determines the group that will own the device node, this should be whatever user runs the virtual machines.

Run udevadm control --reload-rules to make the new rule effective immediately (you still need to disconnect/reconnect the USB devices) or simply reboot the host.

  • this didn't solve the problem for me – NateGreat8 Jan 22 '16 at 0:23
2

Easy solution: connect with

nc -U socket-file

to your QEMU monitor, where socket-file is the path to monitor. How to find: ps -FA | grep qemu. You will find there at the command line.

And run the command at the monitor:

device_add usb-host,id=<ANY string>,hostbus=<BUS>,hostport=<PORT>

this is pass-through by port number. You can pass through any device with any VID/PID. You can also pass-through particular devices using

device_add usb-host,id=<ANY string>,vendorid=0x0461,productid= 0x0010

and they can be plugged in to any port of your host.

Helpful commands also:

info usbhost
info usb
  • Note that instead of using netcat, you can likely use libvirt and virsh directly with something like virsh -c qemu:///system qemu-monitor-command --hmp test01 "device_add usb-host,...". – rabexc Nov 26 '17 at 4:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.