{ lib, config, pkgs, modulesPath, ... }: let cfg = config.cspark-single-gpu-passthru; in { options.cspark-single-gpu-passthru = { enable = lib.mkEnableOption "Enable Single GPU Passthrough Setup"; vmName = lib.mkOption { default = "win11"; description = '' Name of the virtual machine ''; }; gpuPCI = lib.mkOption { default = "0000:08:00.0"; description = '' PCI ID of GPU VGA ''; }; gpuAudioPCI = lib.mkOption { default = "0000:08:00.1"; description = '' PCI ID of GPU Audio ''; }; }; config = lib.mkIf cfg.enable { # Virtualisation, Virt Manager and Waydroid virtualisation.libvirtd = { enable = true; qemu = { package = pkgs.qemu_kvm; runAsRoot = true; swtpm.enable = true; ovmf = { enable = true; packages = [(pkgs.OVMF.override { secureBoot = true; tpmSupport = true; }).fd]; }; }; }; programs.virt-manager.enable = true; systemd.services.libvirtd = { # Add binaries to path so that hooks can use it path = let env = pkgs.buildEnv { name = "qemu-hook-env"; paths = with pkgs; [ bash libvirt kmod systemd ripgrep sd procps gawk ]; }; in [ env ]; preStart = let qemuscript_source = builtins.readFile ./resources/libvirt/hooks/qemu; startscript_source = builtins.readFile ./resources/libvirt/hooks/qemu.d/vm/prepare/begin/start.sh; revertscript_source = builtins.readFile ./resources/libvirt/hooks/qemu.d/vm/release/end/revert.sh; qemuscript = pkgs.writeShellScript "cspark-single-gpu-passthru-qemu" qemuscript_source; startscript = pkgs.writeShellScript "cspark-single-gpu-passthru-start.sh" startscript_source; revertscript = pkgs.writeShellScript "cspark-single-gpu-passthru-revert.sh" revertscript_source; gpuvbios = ./resources/libvirt/vgabios/gpuvbios.rom; in '' mkdir -p /var/lib/libvirt/hooks mkdir -p /var/lib/libvirt/hooks/qemu.d/${cfg.vmName}/prepare/begin mkdir -p /var/lib/libvirt/hooks/qemu.d/${cfg.vmName}/release/end mkdir -p /var/lib/libvirt/vgabios ln -sf ${qemuscript} /var/lib/libvirt/hooks/qemu ln -sf ${startscript} /var/lib/libvirt/hooks/qemu.d/${cfg.vmName}/prepare/begin/start.sh ln -sf ${revertscript} /var/lib/libvirt/hooks/qemu.d/${cfg.vmName}/release/end/revert.sh ln -sf ${gpuvbios} /var/lib/libvirt/vgabios/gpuvbios.rom # chmod +x /var/lib/libvirt/hooks/qemu # chmod +x /var/lib/libvirt/hooks/qemu.d/${cfg.vmName}/prepare/begin/start.sh # chmod +x /var/lib/libvirt/hooks/qemu.d/${cfg.vmName}/release/end/revert.sh ''; }; # Vendor Reset Patches for Single GPU Passthrough - https://github.com/gnif/vendor-reset boot.extraModulePackages = with config.boot.kernelPackages; [ vendor-reset ]; # Ensures GPU is configured to use vendor reset module systemd.services.vendor-reset-config = { description = "Ensures GPU is configured to use vendor reset module"; wantedBy = [ "multi-user.target" ]; path = [ pkgs.coreutils ]; enable = true; serviceConfig = { User = "root"; Group = "root"; }; script = ''echo device_specific > "/sys/bus/pci/devices/${cfg.gpuPCI}/reset_method"''; }; hardware.opengl.enable = true; virtualisation.spiceUSBRedirection.enable = true; }; }