{ lib, pkgs, config, ... }: with lib; let cfg = config.virtualisation.vfio; cfg-libvirtd = config.virtualisation.libvirtd; boolToZeroOne = x: if x then "1" else "0"; aclString = with lib.strings; concatMapStringsSep '' , '' escapeNixString cfg.deviceACL; in { options.virtualisation = { vfio = { enable = mkEnableOption "VFIO Configuration"; IOMMUType = mkOption { type = types.enum [ "intel" "amd" ]; example = "intel"; description = "Type of the IOMMU used"; }; devices = mkOption { type = types.listOf (types.strMatching "[0-9a-f]{4}:[0-9a-f]{4}"); default = [ ]; example = [ "10de:1b80" "10de:10f0" ]; description = "PCI IDs of devices to bind to vfio-pci"; }; disableEFIfb = mkOption { type = types.bool; default = false; example = true; description = "Disables the usage of the EFI framebuffer on boot."; }; blacklistNvidia = mkOption { type = types.bool; default = false; description = "Add Nvidia GPU modules to blacklist"; }; ignoreMSRs = mkOption { type = types.bool; default = false; example = true; description = "Enables or disables kvm guest access to model-specific registers"; }; }; libvirtd = { deviceACL = mkOption { type = types.listOf types.str; default = [ ]; }; clearEmulationCapabilities = mkOption { type = types.bool; default = true; }; }; }; config = lib.mkIf cfg.enable { services.udev.extraRules = '' SUBSYSTEM=="vfio", OWNER="root", GROUP="kvm" ''; boot.kernelParams = (if cfg.IOMMUType == "intel" then [ "intel_iommu=on" "intel_iommu=igfx_off" ] else [ "amd_iommu=on" ]) ++ (optional (builtins.length cfg.devices > 0) ("vfio-pci.ids=" + builtins.concatStringsSep "," cfg.devices)) ++ (optionals cfg.applyACSpatch [ "pcie_acs_override=downstream,multifunction" "pci=nomsi" ]) ++ (optional cfg.disableEFIfb "video=efifb:off") ++ (optionals cfg.ignoreMSRs [ "kvm.ignore_msrs=1" "kvm.report_ignored_msrs=0" ]); boot.kernelModules = [ "vfio_virqfd" "vfio_pci" "vfio_iommu_type1" "vfio" ]; boot.initrd.kernelModules = [ "vfio_virqfd" "vfio_pci" "vfio_iommu_type1" "vfio" ]; boot.blacklistedKernelModules = optionals cfg.blacklistNvidia [ "nvidia" "nouveau" ]; users.users."qemu-libvirtd" = { extraGroups = optionals (!cfg-libvirtd.qemu.runAsRoot) [ "kvm" "input" ]; }; virtualisation.libvirtd.qemu.verbatimConfig = '' clear_emulation_capabilities = ${ boolToZeroOne cfg-libvirtd.clearEmulationCapabilities } cgroup_device_acl = [ ${aclString} ] ''; }; }