/, Tutorials/Evdev Passthrough Explained — Cheap, Seamless VM Input

Evdev Passthrough Explained — Cheap, Seamless VM Input

Input is often the first hurdle presented after getting a passthrough VM up and running. Without Spice or VNC, users often resort to hacks and workarounds to control their virtual machine. Passing through USB devices via evdev has become a popular if badly documented way of handling input. The advantage of evdev is that it has very low latency and overhead. The downside is that it becomes frustrating to switch between the host and guest.

Read also: A Quick And Dirty Arch Passthrough Guide

While a physical KVM switch will always be a viable option, complete solutions with modern video connectors can be very expensive, and start to eat into a build budget when compounded with other hardware quality of life improvements. Evdev passhthrough is a good alternative for those¬† that can’t afford hardware solutions but still want low latency and accurate input.

What is Evdev?

Evdev is an input interface built into the Linux kernel. QEMU’s evdev passthrough support allows a user to redirect evdev events to a guest. These events can include mouse movements and key presses. By hitting both Ctrl keys at the same time, QEMU can toggle the input recipient. QEMU’s evdev passthrough also features almost no latency, making it perfect for gaming. The main downside to evdev passthrough is the lack of button rebinding – and in some cases, macro keys won’t even work at all.

This setup has no requirements besides a keyboard, mouse, and working passthrough setup. This guide assumes you have already configured these.

Configuring Evdev

To start, you will need to find the input device IDs for your mouse and keyboard. This can get a little finicky, as some keyboard manufacturers do this differently. The Linux kernel exposes two different locations for evdev devices: /dev/input, and /dev/input/by-id. /dev/input/by-id is generally preferred, as you can pass through input devices without worrying about the file path changing if you plug/unplug additional devices. List the contents of this directory:
ls /dev/input/by-id

It will contain your input devices. Take note of which ones you want to pass through. Be careful here, as I have noticed two common discrepancies. The first is an “if01” or “if02” or similar near the end of an input device name. The best method to find out which one is correct is to use “cat.” Run:

cat /dev/input/by-id/[input device id]

Press random keys on the keyboard you want to pass through. If garbled characters appear on-screen, you have selected the correct one. If not, try another until you find the correct one. Use Ctrl+C to cancel the “cat” process. Another issue to be wary of is the input device type. A lot of mice will have keyboard inputs, and some keyboards even have mouse inputs. Select the input device that corresponds to your device. For example, if you see two entries for your keyboard, with one ending with “event-kbd”¬† and the other ending with “event-mouse,” you will generally want to pick “event-kbd.” Some hardware manufacturers hate following standards, though, and you might find yourself needing to switch this up.

Now that you’ve noted the devices you want to use evdev with, it’s time to enable it in your libvirt XML. Open the XML with the following, replacing “nano” with your editor of choice, and “win10” with the name of your libvirt domain:

EDITOR=nano virsh edit win10

Make sure the first line looks like this:

<domain type='kvm' id='1' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>

If it doesn’t, replace the first line with that. Next, add the following near the bottom, directly above “</domain>”:

 <qemu:arg value='-object'/>
 <qemu:arg value='input-linux,id=mouse1,evdev=/dev/input/by-id/MOUSE_NAME'/>
 <qemu:arg value='-object'/>
 <qemu:arg value='input-linux,id=kbd1,evdev=/dev/input/by-id/KEYBOARD_NAME,grab_all=on,repeat=on'/>

If you already have qemu:commandline set up for whatever reason, add the qemu:arg options above to that section. Don’t add another set of qemu:commandline arguments. Replace the MOUSE_NAME and KEYBOARD_NAME parts with the id of your input devices. Next, save the XML. In nano, you can do this with Ctrl+X, then Y, then Enter. Boot up your VM. It should now work, with the keyboard and mouse being directly passed to the VM! By hitting both Ctrl keys at the same time, you can switch between hosts. Wonderful, isn’t it?

Switching from PS/2 to VirtIO

As with many other technologies, VirtIO has the capacity to improve evdev virtual input devices’ responsiveness. It is not necessary to remove the PS/2 input devices and replace them. Instead, you can simply add VirtIO input devices to the LibVirt XML file, install the guest drivers, and profit! Find the following section of your XML:

<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>

Add VirtIO mouse and keyboard devices, so in the end it looks like so:

<input type='mouse' bus='virtio'>
        <address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/>
<input type='keyboard' bus='virtio'>
        <address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>

Save the XML file and restart your virtual machine. Now, following the exact same procedure as other VirtIO drivers, install the VirtIO input devices in Windows from the VirtIO driver ISO image:
VirtIO Input Drivers
Complete this step for the mouse and keyboard devices. After this, all should be well.


Permission Errors

There are a wide variety of causes for permission issues with evdev passthrough. To start, let’s set up cgroup_device_acl in libvirt’s configuration. Ensure the following is in /etc/libvirt/qemu.conf, of course replacing KEYBOARD_NAME and MOUSE_NAME:

cgroup_device_acl = [

Now restart libvirtd with

systemctl restart libvirtd

for systemd distributions, and

rc-service libvirtd restart

for OpenRC distributions like Gentoo and Artix.
If this still throws a permission error, try setting the following in the same file:

user = "root"
group = "root"

Note that this will break any PulseAudio passthrough you may have done. If this still throws a permission error, set the following in the same file:

clear_emulator_capabilities = 0

Any permission issues should now be solved.

Mouse/Keyboard perform badly in games

By default, QEMU runs many things on its own watchdog thread. This includes disk I/O and PS/2 keyboards (which evdev passthrough uses). When running on the same thread, sometimes one of these subsystems being under heavy load can affect the other. As a result, after loading into Windows the mouse is smooth, but booting a game immediately causes input performance to drop.
Luckily, libvirt can configure QEMU to separate the I/O off of the main thread, leaving the main thread free for input. Doing this in virt-manager is very simple – go to the settings for your disk and change IO mode from “default” or “native” to “threads.” Be sure to do this for all of your disks – especially those that have games on them.
How has Evdev Passthrough worked out for you? Let us know in the comments below.

Join our Discord to chat with other readers and our writers

Update — 12/25/17: Due to community response to our recommending use of QEMU as root, we would like to note that it is not strictly necessary to do so. You can configure Qemu to use your user, or any other non root user, and add them to the group “input.” To do so, run:

gpasswd -a <your user> input

Update — 3/10/18: Some people are having trouble getting our cgroup_device_acl recommendations working properly. You can add the default options like so:

cgroup_device_acl = [
   "/dev/null", "/dev/full", "/dev/zero",
   "/dev/random", "/dev/urandom",
   "/dev/ptmx", "/dev/kvm", "/dev/kqemu",

Images Courtesy PixaBay
By |2018-07-26T22:13:30+00:00December 22nd, 2017|All Articles, Tutorials|4 Comments|2678 Views

About the Author:

Linux/Unix enthusiast, virtualization power user. I like to experiment with obscure software and use obscure systems.