1
1
Fork 0

vm: add gpu passthrough options

Signed-off-by: Myned <dev@bjork.tech>
This commit is contained in:
Myned 2024-12-06 19:51:19 -06:00
parent 67d2373cec
commit c3a1eb812c
Signed by: myned
GPG key ID: C7224454F7881A34
3 changed files with 90 additions and 17 deletions

View file

@ -9,6 +9,15 @@
width = 3440;
height = 1440;
refresh = 100;
vm.passthrough = {
enable = true;
driver = "amdgpu";
guest = "myndows";
id = "1002:73df";
init = true;
intel = true;
node = "pci_0000_03_00_0";
};
};
boot = {

View file

@ -9,14 +9,17 @@ with lib; let
audio = config.home-manager.users.${config.custom.username}.home.file.".local/bin/audio".source;
clipse = "${pkgs.clipse}/bin/clipse";
firefox-esr = "${config.home-manager.users.${config.custom.username}.programs.firefox.finalPackage}/bin/firefox-esr";
grep = "${pkgs.gnugrep}/bin/grep";
left = config.home-manager.users.${config.custom.username}.home.file.".local/bin/left".source;
loupe = "${pkgs.loupe}/bin/loupe";
modprobe = "${pkgs.kmod}/bin/modprobe";
nautilus = "${pkgs.nautilus}/bin/nautilus";
pkill = "${pkgs.procps}/bin/pkill";
rm = "${pkgs.coreutils}/bin/rm";
sleep = "${pkgs.coreutils}/bin/sleep";
sway-audio-idle-inhibit = "${pkgs.sway-audio-idle-inhibit}/bin/sway-audio-idle-inhibit";
systemctl = "${pkgs.systemd}/bin/systemctl";
virsh = "${config.virtualisation.libvirtd.package}/bin/virsh";
waybar = "${config.home-manager.users.${config.custom.username}.programs.waybar.package}/bin/waybar";
cfg = config.custom.desktops.hyprland.settings;
@ -66,8 +69,7 @@ in {
# https://wiki.hyprland.org/Configuring/Keywords/#executing
exec-once =
optionals config.custom.wallpaper ["wallpaper"]
++ [
[
sway-audio-idle-inhibit # Inhibit idle while audio is playing
"${audio} --init" # Enforce audio profile state
"${rm} ~/.cache/walker/clipboard.gob" # Clear clipboard history
@ -77,6 +79,13 @@ in {
# HACK: Launch hidden GTK windows to reduce startup time
"[workspace special:hidden silent] ${loupe}"
"[workspace special:hidden silent] ${nautilus}"
]
++ optionals config.custom.wallpaper [
"wallpaper"
]
# HACK: Delay driver initialization to work around reset issues
++ optionals config.custom.settings.vm.passthrough.init [
"${virsh} list | ${grep} ${config.custom.settings.vm.passthrough.guest} || sudo ${modprobe} ${config.custom.settings.vm.passthrough.driver}"
];
# https://wiki.hyprland.org/Configuring/Variables/#xwayland

View file

@ -6,12 +6,24 @@
...
}:
with lib; let
virsh = "${config.virtualisation.libvirtd.package}/bin/virsh";
cfg = config.custom.settings.vm;
in {
options.custom.settings.vm = {
enable = mkOption {default = false;};
libvirt = mkOption {default = true;};
virtualbox = mkOption {default = false;};
passthrough = {
enable = mkOption {default = false;};
driver = mkOption {default = null;}; #?? lspci -k
guest = mkOption {default = null;}; #?? virsh list --all
id = mkOption {default = null;}; #?? lspci -nn
init = mkOption {default = false;};
intel = mkOption {default = false;};
node = mkOption {default = null;}; #?? virsh nodedev-list
};
};
config = mkIf cfg.enable {
@ -23,12 +35,37 @@ in {
onBoot = "ignore";
onShutdown = "shutdown";
# https://libvirt.org/hooks.html
hooks.qemu = {
# Attach/detach GPU for passthrough
passthrough = mkIf cfg.passthrough.enable (pkgs.writeShellScript "passthrough" ''
if [[ "$1" == "${cfg.passthrough.guest}" ]]; then
case "$2" in
prepare)
${virsh} nodedev-detach ${cfg.passthrough.node}
;;
release)
${virsh} nodedev-reattach ${cfg.passthrough.node}
;;
*)
exit
;;
esac
fi
'');
};
qemu = {
swtpm.enable = true; # TPM emulation
# BUG: Windows requires global mountpoint for some applications (\\.\*: instead of *:)
# https://github.com/virtio-win/kvm-guest-drivers-windows/issues/950
# https://virtio-win.github.io/Knowledge-Base/Virtiofs:-Shared-file-system
#// vhostUserPackages = with pkgs; [virtiofsd]; # virtiofs support
# Build OVMF with Windows 11 support
ovmf.packages = [
(pkgs.OVMF.override {
ovmf.packages = with pkgs; [
(OVMF.override {
secureBoot = true;
tpmSupport = true;
})
@ -77,24 +114,42 @@ in {
++ lib.optionals cfg.virtualbox ["vboxusers"];
systemd = mkIf cfg.libvirt {
# Fix resume messages polluting tty
services.libvirt-guests.serviceConfig.StandardOutput = "journal";
services = {
# Fix resume messages polluting tty
libvirt-guests.serviceConfig = {
StandardOutput = "journal";
};
};
tmpfiles.settings."10-vm" = {
# HACK: Manually link image to default directory
"/var/lib/libvirt/images/virtio-win.iso" = {
"L+" = {
argument = "${inputs.virtio-win}";
};
};
tmpfiles.rules = let
firmware = pkgs.runCommandLocal "qemu-firmware" {} ''
mkdir $out
cp ${pkgs.qemu}/share/qemu/firmware/*.json $out
substituteInPlace $out/*.json --replace ${pkgs.qemu} /run/current-system/sw
'';
in [
# HACK: Fix libvirt not automatically locating firmware
# https://github.com/NixOS/nixpkgs/issues/115996#issuecomment-2224296279
# https://libvirt.org/formatdomain.html#bios-bootloader
"L+ /var/lib/qemu/firmware - - - - ${firmware}"
"/var/lib/qemu/firmware" = {
"L+" = {
argument = "${pkgs.runCommandLocal "qemu-firmware" {} ''
mkdir $out
cp ${pkgs.qemu}/share/qemu/firmware/*.json $out
substituteInPlace $out/*.json --replace ${pkgs.qemu} /run/current-system/sw
''}";
};
};
};
};
# HACK: Manually link image to default directory
"L+ /var/lib/libvirt/images/virtio-win.iso - - - - ${inputs.virtio-win}"
];
boot = mkIf cfg.passthrough.enable {
# https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Isolating_the_GPU
blacklistedKernelModules = mkIf cfg.passthrough.init [cfg.passthrough.driver];
# https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Enabling_IOMMU
kernelParams = mkIf cfg.passthrough.intel ["intel_iommu=on"];
};
};
}