vm: add gpu passthrough options
Signed-off-by: Myned <dev@bjork.tech>
This commit is contained in:
parent
67d2373cec
commit
c3a1eb812c
3 changed files with 90 additions and 17 deletions
|
@ -9,6 +9,15 @@
|
||||||
width = 3440;
|
width = 3440;
|
||||||
height = 1440;
|
height = 1440;
|
||||||
refresh = 100;
|
refresh = 100;
|
||||||
|
vm.passthrough = {
|
||||||
|
enable = true;
|
||||||
|
driver = "amdgpu";
|
||||||
|
guest = "myndows";
|
||||||
|
id = "1002:73df";
|
||||||
|
init = true;
|
||||||
|
intel = true;
|
||||||
|
node = "pci_0000_03_00_0";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
boot = {
|
boot = {
|
||||||
|
|
|
@ -9,14 +9,17 @@ with lib; let
|
||||||
audio = config.home-manager.users.${config.custom.username}.home.file.".local/bin/audio".source;
|
audio = config.home-manager.users.${config.custom.username}.home.file.".local/bin/audio".source;
|
||||||
clipse = "${pkgs.clipse}/bin/clipse";
|
clipse = "${pkgs.clipse}/bin/clipse";
|
||||||
firefox-esr = "${config.home-manager.users.${config.custom.username}.programs.firefox.finalPackage}/bin/firefox-esr";
|
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;
|
left = config.home-manager.users.${config.custom.username}.home.file.".local/bin/left".source;
|
||||||
loupe = "${pkgs.loupe}/bin/loupe";
|
loupe = "${pkgs.loupe}/bin/loupe";
|
||||||
|
modprobe = "${pkgs.kmod}/bin/modprobe";
|
||||||
nautilus = "${pkgs.nautilus}/bin/nautilus";
|
nautilus = "${pkgs.nautilus}/bin/nautilus";
|
||||||
pkill = "${pkgs.procps}/bin/pkill";
|
pkill = "${pkgs.procps}/bin/pkill";
|
||||||
rm = "${pkgs.coreutils}/bin/rm";
|
rm = "${pkgs.coreutils}/bin/rm";
|
||||||
sleep = "${pkgs.coreutils}/bin/sleep";
|
sleep = "${pkgs.coreutils}/bin/sleep";
|
||||||
sway-audio-idle-inhibit = "${pkgs.sway-audio-idle-inhibit}/bin/sway-audio-idle-inhibit";
|
sway-audio-idle-inhibit = "${pkgs.sway-audio-idle-inhibit}/bin/sway-audio-idle-inhibit";
|
||||||
systemctl = "${pkgs.systemd}/bin/systemctl";
|
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";
|
waybar = "${config.home-manager.users.${config.custom.username}.programs.waybar.package}/bin/waybar";
|
||||||
|
|
||||||
cfg = config.custom.desktops.hyprland.settings;
|
cfg = config.custom.desktops.hyprland.settings;
|
||||||
|
@ -66,8 +69,7 @@ in {
|
||||||
|
|
||||||
# https://wiki.hyprland.org/Configuring/Keywords/#executing
|
# https://wiki.hyprland.org/Configuring/Keywords/#executing
|
||||||
exec-once =
|
exec-once =
|
||||||
optionals config.custom.wallpaper ["wallpaper"]
|
[
|
||||||
++ [
|
|
||||||
sway-audio-idle-inhibit # Inhibit idle while audio is playing
|
sway-audio-idle-inhibit # Inhibit idle while audio is playing
|
||||||
"${audio} --init" # Enforce audio profile state
|
"${audio} --init" # Enforce audio profile state
|
||||||
"${rm} ~/.cache/walker/clipboard.gob" # Clear clipboard history
|
"${rm} ~/.cache/walker/clipboard.gob" # Clear clipboard history
|
||||||
|
@ -77,6 +79,13 @@ in {
|
||||||
# HACK: Launch hidden GTK windows to reduce startup time
|
# HACK: Launch hidden GTK windows to reduce startup time
|
||||||
"[workspace special:hidden silent] ${loupe}"
|
"[workspace special:hidden silent] ${loupe}"
|
||||||
"[workspace special:hidden silent] ${nautilus}"
|
"[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
|
# https://wiki.hyprland.org/Configuring/Variables/#xwayland
|
||||||
|
|
|
@ -6,12 +6,24 @@
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
with lib; let
|
with lib; let
|
||||||
|
virsh = "${config.virtualisation.libvirtd.package}/bin/virsh";
|
||||||
|
|
||||||
cfg = config.custom.settings.vm;
|
cfg = config.custom.settings.vm;
|
||||||
in {
|
in {
|
||||||
options.custom.settings.vm = {
|
options.custom.settings.vm = {
|
||||||
enable = mkOption {default = false;};
|
enable = mkOption {default = false;};
|
||||||
libvirt = mkOption {default = true;};
|
libvirt = mkOption {default = true;};
|
||||||
virtualbox = mkOption {default = false;};
|
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 {
|
config = mkIf cfg.enable {
|
||||||
|
@ -23,12 +35,37 @@ in {
|
||||||
onBoot = "ignore";
|
onBoot = "ignore";
|
||||||
onShutdown = "shutdown";
|
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 = {
|
qemu = {
|
||||||
swtpm.enable = true; # TPM emulation
|
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
|
# Build OVMF with Windows 11 support
|
||||||
ovmf.packages = [
|
ovmf.packages = with pkgs; [
|
||||||
(pkgs.OVMF.override {
|
(OVMF.override {
|
||||||
secureBoot = true;
|
secureBoot = true;
|
||||||
tpmSupport = true;
|
tpmSupport = true;
|
||||||
})
|
})
|
||||||
|
@ -77,24 +114,42 @@ in {
|
||||||
++ lib.optionals cfg.virtualbox ["vboxusers"];
|
++ lib.optionals cfg.virtualbox ["vboxusers"];
|
||||||
|
|
||||||
systemd = mkIf cfg.libvirt {
|
systemd = mkIf cfg.libvirt {
|
||||||
# Fix resume messages polluting tty
|
services = {
|
||||||
services.libvirt-guests.serviceConfig.StandardOutput = "journal";
|
# 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
|
# HACK: Fix libvirt not automatically locating firmware
|
||||||
# https://github.com/NixOS/nixpkgs/issues/115996#issuecomment-2224296279
|
# https://github.com/NixOS/nixpkgs/issues/115996#issuecomment-2224296279
|
||||||
# https://libvirt.org/formatdomain.html#bios-bootloader
|
# 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
|
boot = mkIf cfg.passthrough.enable {
|
||||||
"L+ /var/lib/libvirt/images/virtio-win.iso - - - - ${inputs.virtio-win}"
|
# 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"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue