{ 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}
      ]
    '';
  };
}
