From 2e0f4c91b472eb56e89314aa904a51fa20073ccc Mon Sep 17 00:00:00 2001 From: Massaki Archambault Date: Thu, 4 Mar 2021 17:03:16 -0500 Subject: [PATCH] improve configuration and optimize --- playbook.yml | 5 ++ roles/win10/defaults/main.yml | 2 + roles/win10/files/hooks/qemu | 50 +++-------- roles/win10/files/vfio-usb | 99 ++++++++++++++++++++++ roles/win10/handlers/main.yml | 4 + roles/win10/tasks/main.yml | 41 +++++---- roles/win10/templates/win10-usb.service.j2 | 8 ++ roles/win10/{files => templates}/win10.xml | 10 +-- 8 files changed, 160 insertions(+), 59 deletions(-) create mode 100755 roles/win10/files/vfio-usb create mode 100644 roles/win10/templates/win10-usb.service.j2 rename roles/win10/{files => templates}/win10.xml (96%) 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(' \n' % id_vendor) + usb_xml.write(' \n' % id_product) + 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 @@ - +