diff --git a/playbook.yml b/playbook.yml
index 6515a6f..7878fc3 100644
--- a/playbook.yml
+++ b/playbook.yml
@@ -5,5 +5,10 @@
- '8086:15b8' # Intel Corporation Ethernet Connection (2) I219-V
- '1002:731f' # Advanced Micro Devices, Inc. [AMD/ATI] Navi 10 [Radeon RX 5700 / 5700 XT]
- '1002:ab38' # Advanced Micro Devices, Inc. [AMD/ATI] Navi 10 HDMI Audio
+ usb_device_ids:
+ - '054c:05c4' # Sony Corp. DualShock 4 [CUH-ZCT1x]
+ - '046d:c539' # Logitech, Inc. USB Receiver
+ - '046d:c08d' # Logitech, Inc. G502 LIGHTSPEED Wireless Gaming Mouse
+ kbd_device_path: '/dev/input/by-id/usb-0d3d_USBPS2-event-kbd'
roles:
- win10
diff --git a/roles/win10/defaults/main.yml b/roles/win10/defaults/main.yml
index 01bf06e..9e5462c 100644
--- a/roles/win10/defaults/main.yml
+++ b/roles/win10/defaults/main.yml
@@ -1 +1,3 @@
pcie_device_ids: []
+usb_device_ids: []
+kbd_device_path: ''
\ No newline at end of file
diff --git a/roles/win10/files/hooks/qemu b/roles/win10/files/hooks/qemu
index c2b5120..e5cabfe 100755
--- a/roles/win10/files/hooks/qemu
+++ b/roles/win10/files/hooks/qemu
@@ -1,56 +1,28 @@
#!/bin/bash
prepare() {
- systemctl start vm-usb-helper
+ systemctl start win10-usb
+ vfio-isolate -u /tmp/win10.undo \
+ drop-caches \
+ compact-memory \
+ irq-affinity mask C1-3,5-7 \
+ cpuset-create --cpus C0,4 /host.slice \
+ cpuset-create --cpus C1-3,5-7 -nlb /win10.slice \
+ move-tasks / /host.slice \
+ cpu-governor performance C0-7
- echo "Defrag RAM"
- echo 1 > /proc/sys/vm/compact_memory
for _ in $(seq 5); do
sleep 3
# assign hugepages
sysctl -w vm.nr_hugepages=8192 && break
done
sleep 10
-
- echo "Setup cpuset cgroup for host"
- sudo cset set -c 0,4 -s system
- sudo cset proc -m -f root -t system
- sudo cset proc -k -f root -t system --force
-
- echo "Setup cpumask"
- for i in /sys/devices/virtual/workqueue/*/cpumask; do
- sudo sh -c "echo 001 > $i"
- done;
-
- echo "Setup interrupt affinity"
- for i in $(sed -n -e 's/ \([0-9]\+\):.*vfio.*/\1/p' /proc/interrupts); do
- sudo sh -c "echo 0,4 > /proc/irq/$i/smp_affinity_list"
- done
-
- echo "Set the CPU frequency governor to performance"
- for f in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
- echo performance >$f
- done
}
release() {
echo "Restore system"
- # irq
- for i in $(sed -n -e 's/ \([0-9]\+\):.*vfio.*/\1/p' /proc/interrupts); do
- sudo sh -c "echo ff > /proc/irq/$i/smp_affinity"
- done
- # cpumask
- for i in /sys/devices/virtual/workqueue/*/cpumask; do
- sudo sh -c "echo ff > $i"
- done;
- # cpuset
- sudo cset set -d system &>/dev/null
-
- for f in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
- echo powersave >$f
- done
-
- systemctl stop vm-usb-helper
+ vfio-isolate restore /tmp/win10.undo
+ systemctl stop win10-usb
sysctl -w vm.nr_hugepages=0
}
diff --git a/roles/win10/files/vfio-usb b/roles/win10/files/vfio-usb
new file mode 100755
index 0000000..7ad72a3
--- /dev/null
+++ b/roles/win10/files/vfio-usb
@@ -0,0 +1,99 @@
+#!/bin/python3
+import os
+import sys
+import logging
+import argparse
+import subprocess
+
+from tempfile import NamedTemporaryFile
+
+import evdev
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger()
+virsh_logger = logging.getLogger('virsh')
+
+usb_xmls = []
+
+def listen():
+ logger.info('Listening for events on %s', args.evdev_kbd)
+ device = evdev.InputDevice(args.evdev_kbd)
+ left_ctrl = False
+ right_ctrl = False
+ triggered = False
+ grabbed = False
+ for event in device.read_loop():
+ logger.debug('Got event: %s', event)
+
+ if grabbed and event.code != 0:
+ grabbed = False
+ on_release()
+
+ if event.code == evdev.ecodes.ecodes['KEY_LEFTCTRL']:
+ left_ctrl = event.value != 0
+ elif event.code == evdev.ecodes.ecodes['KEY_RIGHTCTRL']:
+ right_ctrl = event.value != 0
+
+ if left_ctrl and right_ctrl:
+ triggered = True
+ elif triggered and not left_ctrl and not right_ctrl:
+ triggered = False
+ grabbed = True
+ on_grab()
+
+def on_grab():
+ logger.info('Grabbed')
+ for usb_xml in usb_xmls:
+ invoke_virsh('attach-device', args.domain, usb_xml.name)
+
+def on_release():
+ logger.info('Released')
+ for usb_xml in usb_xmls:
+ invoke_virsh('detach-device', args.domain, usb_xml.name)
+
+def invoke_virsh(subcommand, domain, xml_name):
+ proc = subprocess.Popen(('virsh', subcommand, domain, xml_name),
+ encoding='utf8',
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = proc.communicate()
+ for line in stdout.strip().splitlines():
+ virsh_logger.info(line)
+ for line in stderr.strip().splitlines():
+ virsh_logger.error(line)
+
+if __name__ == '__main__':
+ if os.geteuid() != 0:
+ logger.error('This script must be run as root')
+ sys.exit(1)
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--evdev-kbd',
+ help='The evdev keyboard device to read eg: /dev/input/...',
+ required=True)
+ parser.add_argument('domain',
+ help='The libvirt domain to attach the usb devices to')
+ parser.add_argument('usb_ids',
+ help='The ids of the usb devices to attach, formatted as idVendor:idProduct',
+ nargs='+')
+ args = parser.parse_args()
+ logger.debug(args)
+
+ try:
+ for id_vendor, id_product in [x.split(':') for x in args.usb_ids]:
+ usb_xml = NamedTemporaryFile('w+')
+ usb_xml.write('\n')
+ usb_xml.write(' \n')
+ usb_xml.write('')
+
+ usb_xml.seek(0)
+ logger.debug('Created usb device xml:\n%s', usb_xml.read())
+
+ usb_xmls.append(usb_xml)
+ listen()
+ finally:
+ for usb_xml in usb_xmls:
+ usb_xml.close()
diff --git a/roles/win10/handlers/main.yml b/roles/win10/handlers/main.yml
index a3472ab..f905d74 100644
--- a/roles/win10/handlers/main.yml
+++ b/roles/win10/handlers/main.yml
@@ -1,6 +1,10 @@
- name: regenerate linux initramfs
command: /usr/bin/mkinitcpio -p linux
+- name: reload systemd services
+ systemd:
+ daemon_reload: yes
+
- name: restart libvirtd.service
systemd:
name: libvirtd.service
diff --git a/roles/win10/tasks/main.yml b/roles/win10/tasks/main.yml
index 79e354a..ae12bbe 100644
--- a/roles/win10/tasks/main.yml
+++ b/roles/win10/tasks/main.yml
@@ -9,11 +9,35 @@
- restart libvirtd.socket
- restart virtlogd.socket
+# TODO
+# - name: install required packages from aur
+# aur:
+# name:
+# - vfio-isolate
+
- name: create hooks directory
file:
path: /etc/libvirt/hooks
state: directory
+- name: install qemu hook
+ copy:
+ src: hooks/qemu
+ dest: /etc/libvirt/hooks/qemu
+ mode: '755'
+
+- name: install vfio-usb
+ copy:
+ src: vfio-usb
+ dest: /usr/bin/vfio-usb
+ mode: '755'
+
+- name: install win10-usb service
+ template:
+ src: win10-usb.service.j2
+ dest: /etc/systemd/system/win10-usb.service
+ notify: reload systemd services
+
- name: configure kernel modules
lineinfile:
path: /etc/mkinitcpio.conf
@@ -73,35 +97,22 @@
"/dev/random", "/dev/urandom",
"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
"/dev/rtc","/dev/hpet", "/dev/sev",
- "/dev/input/by-path/platform-i8042-serio-0-event-kbd"
+ "{{ kbd_device_path }}"
]
- name: install domain configuration
- copy:
+ template:
src: win10.xml
dest: /etc/libvirt/qemu/win10.xml
validate: /usr/bin/virt-xml-validate %s
notify: restart libvirtd.service
-- name: install qemu hook
- copy:
- src: hooks/qemu
- dest: /etc/libvirt/hooks/qemu
- mode: '755'
-
# - name: configure systemd CPUAffinity
# lineinfile:
# path: /etc/systemd/system.conf
# regexp: '^#?CPUAffinity'
# line: 'CPUAffinity=0 4'
-- name: configure pulseaudio tcp socket
- lineinfile:
- path: /etc/pulse/default.pa
- regexp: '^#?load-module module-native-protocol-tcp'
- line: 'load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1'
-
-
- name: enable libvirtd.socket
systemd:
name: libvirtd.socket
diff --git a/roles/win10/templates/win10-usb.service.j2 b/roles/win10/templates/win10-usb.service.j2
new file mode 100644
index 0000000..484b08e
--- /dev/null
+++ b/roles/win10/templates/win10-usb.service.j2
@@ -0,0 +1,8 @@
+[Unit]
+Description=Attach usb devices to vm
+
+[Service]
+ExecStart=/usr/bin/vfio-usb win10 --evdev-kbd "{{ kbd_device_path }}" {{ ' '.join(usb_device_ids) }}
+Restart=always
+
+
diff --git a/roles/win10/files/win10.xml b/roles/win10/templates/win10.xml
similarity index 96%
rename from roles/win10/files/win10.xml
rename to roles/win10/templates/win10.xml
index 04a34c1..127e5e5 100644
--- a/roles/win10/files/win10.xml
+++ b/roles/win10/templates/win10.xml
@@ -163,17 +163,17 @@
-
+
-
-
+
+
-
+
@@ -217,7 +217,7 @@
-
+