{ pkgs, ... }: { environment.etc = { "evdev-proxy/config.toml".source = pkgs.writeText "config.toml" '' log_level = "INFO" [[device]] [device.Simple] name = "EvdevProxyMouse" vendor = 0x1337 model = 0x1337 class = "Mouse" [[device.Simple.selector]] USBIDClass = {vendor=0x046d, model=0xc531, class="Mouse"} [[device.Simple.selector]] USBIDClass = {vendor=0x046d, model=0xc07c, class="Mouse"} [[device]] [device.Simple] name = "EvdevProxyTartarus" vendor = 0x1337 model = 0x1338 class = "Keyboard" # This is to give a deterministic /dev/input/by-id/ path to # the mapped version of the Tartarus evdev node. # (Useful for qemu) [[device.Simple.selector]] EVDEVClass = {phys="\"key-mapper\""} ''; "libvirt/hooks/qemu".source = let vfio-isolate-state = "/tmp/vfio-isolate-state"; in pkgs.writeScript "qemu" '' #!${pkgs.stdenv.shell} guest=$1 action=$2 phase=$3 extra=$4 if [[ "$guest" = "win10" ]]; then case "$action" in prepare) # Only do this while in preparation [[ ! "$phase" = "prepare" ]] && exit 0 sudo -u alexander systemctl --user start evdev-proxy.service sudo -u alexander systemctl --user start scream.service sleep 2 ${pkgs.vfio-isolate}/bin/vfio-isolate \ -u ${vfio-isolate-state} \ cpu-governor performance "$GUEST_CORES" \ cpuset-create --cpus "$GUEST_CORES" /guest.slice \ cpuset-create --cpus C0,4 /host.slice \ move-tasks / /host.slice \ irq-affinity mask "$GUEST_CORES" ;; stopped) # Only run when the VM is fully stopped [[ ! "$phase" = "end" ]] && exit 0 sudo -u alexander systemctl --user stop evdev-proxy.service sudo -u alexander systemctl --user stop scream.service ${pkgs.vfio-isolate}/bin/vfio-isolate \ restore ${vfio-isolate-state} esac fi ''; }; virtualisation.libvirtd = { enable = true; #qemuRunAsRoot = false; qemuOvmf = true; qemuPackage = pkgs.unstable.qemu; qemuVerbatimConfig = '' seccomp_sandbox = 0 cgroup_device_acl = [ "/dev/null", "/dev/full", "/dev/zero", "/dev/random", "/dev/urandom", "/dev/ptmx", "/dev/kvm", "/dev/kqemu", "/dev/rtc","/dev/hpet", "/dev/input/by-id/usb-Logitech_USB_Receiver-if02-event-mouse", "/dev/input/by-id/usb-Razer_Razer_Tartarus_V2-event-kbd", "/dev/input/by-id/virtual-event-EvdevProxyMouse", "/dev/input/by-id/virtual-event-EvdevProxyTartarus", "/dev/input/by-id/usb-Razer_Razer_BlackWidow_Ultimate-event-kbd" ] ''; }; # NOTE: Workaround for libvirt's SYSCONFDIR being set to /var/lib # (See https://github.com/NixOS/nixpkgs/issues/51152#issuecomment-899374407) system.activationScripts.libvirt-hooks.text = '' ln -Tfs /etc/libvirt/hooks /var/lib/libvirt/hooks ''; systemd = { services.libvirtd.path = with pkgs; [ vfio-isolate systemd bash ]; user.services.evdev-proxy = { description = "Creates virtual device to proxy evdev devices events"; #wantedBy = [ "default.target" ]; serviceConfig = { Type = "simple"; ExecStart = "${pkgs.evdev-proxy}/bin/evdev-proxy"; Restart = "always"; }; }; }; }