{ config, lib, pkgs, ... }: let gpuIDs = [ "1002:7480" # Graphics "1002:ab30" # Audio ]; in { # https://astrid.tech/2022/09/22/0/nixos-gpu-vfio/ Was a huge gem to find with regard to getting this setup working. # Absolutely great. # # Web Archive: http://web.archive.org/web/20241229020334/https://astrid.tech/2022/09/22/0/nixos-gpu-vfio/ options.vfio.enable = with lib; mkEnableOption "Configure the machine for VFIO"; options.vfio.earlyKMS = with lib; mkEnableOption "Configure the machine to load the GPU driver during initramfs"; options.vfio.applyACSpatch = with lib; mkEnableOption ''If set, the following things will happen: - The ACS override patch is applied - Applies the i915-vga-arbiter patch - Adds pcie_acs_override=downstream to the command line ''; config = let cfg = config.vfio; in { # Useful: # https://nixos.mayflower.consulting/blog/2020/06/17/windows-vm-performance/ # TODO: The bridge interface is necessary in order to # have network discovery in the virtual machine. However, # this will cause a massive slowdown in startup time # on the host machine while ethernet is not connected. # Should fix this, but for now it's fine. # # Emily used systemd-analyze a lot in order to help triage # which got us to an alright point. # TODO: Right now, I need to manually start # the network bridge interface with systemctl start network-addresses-winvm0.service, # and potentially toggle the link state in the vm config # to get this working. would be good to fix it. networking.bridges = { "winvm0" = { interfaces = [ "eth0" ]; }; }; environment.systemPackages = [ # For sharing filesystems # I followed https://www.heiko-sieger.info/sharing-files-between-the-linux-host-and-a-windows-vm-using-virtiofs/ # when I was setting up the windows VM (though I already had the guest tools installed). Worked like a charm! # Note that I temporarily need to add the following to the guest OS filesystem xml # # due to this issue https://github.com/NixOS/nixpkgs/issues/347942 pkgs.virtiofsd pkgs.looking-glass-client pkgs.scream ]; # These are needed, since I'm not currently trying to # reserve a static IP for the bridge interface networking.interfaces.eth0.useDHCP = true; networking.interfaces.winvm0.useDHCP = true; # Trying to ensure the bridge network doesn't cause us to wait # on boot systemd.services.network-addresses-eth0.before = lib.mkForce [ ]; systemd.services.network-addresses-winvm0.before = lib.mkForce [ ]; systemd.services.winvm0-netdev.before = lib.mkForce [ ]; programs.virt-manager.enable = true; users.groups.libvirtd.members = ["evar"]; # let me do stuff with vms # TODO: I don't currently have a satisfying way of passing through # my huion tablet when I connect it. I'm pretty sure # that really good blog post I found initially talks about this # and provides a script for mounting/unmounting stuff dynamically # that I could look into for this. virtualisation.spiceUSBRedirection.enable = true; # allows usb passthrough hardware.graphics.enable = true; # needed for display spice opengl virtualisation.libvirtd = { enable = true; qemu.swtpm.enable = true; # for TPM 2.0 support onBoot = "ignore"; # only start autostart vms, not just ones that were running onShutdown = "shutdown"; # always shut down the vm's cleanly }; # shared memory for looking glass # see https://looking-glass.io/docs/B7-rc1/ivshmem_shm/ # or https://alexbakker.me/post/nixos-pci-passthrough-qemu-vfio.html # note that the VM needs 64 MB for the shmem in side the # xml for the full res of the FW laptop systemd.tmpfiles.rules = [ "f /dev/shm/scream 0660 evar qemu-libvirtd -" "f /dev/shm/looking-glass 0660 evar qemu-libvirtd -" ]; # service for hooking up scream for audio systemd.user.services.scream-ivshmem = { enable = true; description = "Scream IVSHMEM"; serviceConfig = { ExecStart = "${pkgs.scream}/bin/scream-ivshmem-pulse /dev/shm/scream"; Restart = "always"; }; wantedBy = [ "multi-user.target" ]; requires = [ "pulseaudio.service" ]; }; boot = { initrd.kernelModules = [ "vfio_pci" "vfio" "vfio_iommu_type1" # "vfio_virqfd" # This is apparently a part of the kernel now ] ++ lib.optional cfg.earlyKMS "amdgpu"; # kernelPatches = [] ++ lib.optional cfg.applyACSpatch # { # name = "add-acs-overrides"; # patch = pkgs.fetchurl { # name = "add-acs-overrides.patch"; # url = "https://aur.archlinux.org/cgit/aur.git/plain/1001-6.8.0-add-acs-overrides.patch?h=linux-vfio"; # sha256 = "1qd68s9r0ppynksbffqn2qbp1whqpbfp93dpccp9griwhx5srx6v"; # }; # }; kernelParams = [ # enable IOMMU "amd_iommu=on" ] ++ lib.optional cfg.enable # isolate the GPU ("vfio-pci.ids=" + lib.concatStringsSep "," gpuIDs); # ++ lib.optional cfg.applyACSpatch "pcie_acs_override=downstream,multifunction"; }; # Samba share. Primarily intended to be used via the # bridged network adapter for speed services.samba = { enable = true; openFirewall = true; settings = { global = { "workgroup" = "WORKGROUP"; "server string" = "Atreus"; "netbios name" = "Atreus"; "security" = "user"; # don't show shares to people who aren't valid to see them "access based share enum" = "yes"; # only allow authenticated users - this might break old windows apps "restrict anonymous" = "2"; "use sendfile" = "yes"; #"max protocol" = "smb2"; # note: localhost is the ipv6 localhost ::1 "hosts allow" = "10. 127.0.0.1 localhost"; "hosts deny" = "0.0.0.0/0"; "guest account" = "nobody"; "map to guest" = "bad user"; }; "Virtio Shared" = { "path" = "/home/evar/Virtio Shared"; "comment" = "Virtio shared directory"; "valid users" = "evar"; "read only" = "no"; "public" = "no"; "guest ok" = "no"; "browseable" = "yes"; }; }; }; services.samba-wsdd = { enable = true; openFirewall = true; }; networking.firewall.enable = true; networking.firewall.allowPing = true; }; }