commit 83fc46f00053921dc0bb80460735b5292a6f8243 Author: Paul Schulze Date: Fri Nov 29 16:33:17 2024 +0100 initial commit, full description of my setup (hopefully) diff --git a/README.md b/README.md new file mode 100644 index 0000000..c0363ef --- /dev/null +++ b/README.md @@ -0,0 +1,124 @@ +# PFS libvirt/qemu GPU Passthrough für Windows Gaming VM + +## Links +- Arch Linux Wiki: https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF +- VFIO Subreddit: https://www.reddit.com/r/VFIO/ +- Weitere Links, die ich in Kommentaren der XML gepackt hab. + +## Linux kernel command line args +- `vfio-pci.ids=10de:2684,10de:22ba`: Guest GPU PCI IDs "rausnehmen", dass der kernel + damit nichts macht (GPU und HDMI Audio im Beispiel). Find ich bei mir via `lspci -nn | grep NVIDIA`. +- obsolet: `isolcpus=0-7,16-23`: CPUs für Guest vom System isolieren. + Kann man mittlerweile zur Laufzeit via cgroups machen. +- even obsoleter: `nohz_full=0-7,16-23`: Siehe isolcpus. Bei Interesse docs auf kernel.org lesen. Aber total obsolet. +- `video=efifb:off`: Ich hatte Probleme, weil selbst mit vfio der efifb noch irgendwie die NVIDIA "gegrabt" hat, deshalb efifb:off. +- `module_blacklist=nvidia`: Ich hab bei mir den NVIDIA Treiber UND den AMD Treiber auf dem Host + installiert (AMD = Linux, NVIDIA = Win Guest), weil ich LLMs mit ollama lokal laufen lassen will + und dafür unter Linux auch die NVIDIA Treiber brauche. Wenn ich aber hybrid boote, also VM nutzen + will, dann blackliste ich noch zusätzlich das NVIDIA Modul, macht insgesamt dann weniger Probleme. +- `systemd.unit=pfs-winvm-hybrid.target`: Custom boot target, siehe "rEFInd Config" und "Custom systemd targets". + +## rEfInd Config +``` +$ cat /boot/refind_linux.conf +"Arch Linux vfio NVIDIA 4090 hybrid WinVM off" "[...] amd_iommu=on iommu=pt vfio-pci.ids=10de:2684,10de:22ba video=efifb:off module_blacklist=nvidia" +"Arch Linux vfio NVIDIA 4090 hybrid WinVM on" "[...] amd_iommu=on iommu=pt vfio-pci.ids=10de:2684,10de:22ba video=efifb:off module_blacklist=nvidia systemd.unit=pfs-winvm-hybrid.target" +"Arch Linux vfio NVIDIA 4090 WinVM only" "[...] amd_iommu=on iommu=pt vfio-pci.ids=10de:2684,10de:22ba video=efifb:off module_blacklist=nvidia systemd.unit=pfs-winvm.target" +"Arch Linux vfio NVIDIA 4090 Linux only NO NVIDIA" "[...] amd_iommu=on iommu=pt module_blacklist=nvidia" +"Arch Linux vfio NVIDIA 4090 Linux only" "[...] amd_iommu=on iommu=pt" +``` + +## Custom systemd targets +### Hybrid +```ini +$ systemctl cat pfs-winvm-hybrid.target +# /etc/systemd/system/pfs-winvm-hybrid.target +[Unit] +Description=PFS WinVM hybrid Target +Requires=graphical.target +Conflicts=rescue.service rescue.target +After=graphical.target rescue.service rescue.target +AllowIsolate=yes + +$ systemctl cat pfs-winvm-hybrid.service +# /etc/systemd/system/pfs-winvm-hybrid.service +[Unit] +Description=PFS WinVM hybrid +After=libvirtd.service + +[Service] +ExecStart=virsh start win11new +Restart=no +Type=oneshot + +[Install] +WantedBy=pfs-winvm-hybrid.target +``` + +### Nur VM +```ini +$ systemctl cat pfs-winvm.target +# /etc/systemd/system/pfs-winvm.target +[Unit] +Description=PFS WinVM Target +Requires=multi-user.target +Conflicts=rescue.service rescue.target +After=multi-user.target rescue.service rescue.target +AllowIsolate=yes + +$ systemctl cat pfs-winvm.service +# /etc/systemd/system/pfs-winvm.service +[Unit] +Description=PFS WinVM +After=pfs-winvm.target + +[Service] +ExecStart=virsh start win11new +Restart=no +Type=oneshot + +[Install] +WantedBy=pfs-winvm.target +``` + + +## IOMMU (wichtig) +Damit man einzelne PCI devices zum Guest durchreichen kann, muss im BIOS IOMMU aktiv sein (SVM sowieso für Virtualisierung). + +Es können **immer nur ganze IOMMU Gruppen durchgereicht werden**, nicht einzelne Geräte innerhalb einer Gruppe. + +```ini +IOMMU Group 13: + 01:00.0 VGA compatible controller [0300]: NVIDIA Corporation AD102 [GeForce RTX 4090] [10de:2684] (rev a1) + 01:00.1 Audio device [0403]: NVIDIA Corporation AD102 High Definition Audio Controller [10de:22ba] (rev a1) +IOMMU Group 14: + 02:00.0 Non-Volatile memory controller [0108]: Seagate Technology PLC FireCuda 530 SSD [1bb1:5018] (rev 01) +IOMMU Group 15: + 03:00.0 PCI bridge [0604]: Advanced Micro Devices, Inc. [AMD] Device [1022:43f4] (rev 01) +``` +Hier ist Group 13 die Gruppe in der mein NVIDIA VGA Controller und das NVIDIA Audio Device ist. Deshalb auch beide auf jeden Fall durchreichen! + +USB Controller reiche ich auch durch, aber da musste ich schauen, welche überhaupt einzeln durchreichbar waren. + +Skript um die IOMMU Gruppen schnell zu sehen: +```bash + $ cat iommu_groups.sh +#!/bin/bash + +shopt -s nullglob + +for iommu_group in /sys/kernel/iommu_groups/*; do + echo "IOMMU Group ${iommu_group##*/}:" + for d in "${iommu_group}/devices"/*; do + echo -e "\t$(lspci -nns "${d##*/}")" + done +done +``` + +## CPU Topologie und Cache +`lstopo`: Tool um schnell die Topologie der CPU zu sehen. Also um herauszufinden, welche Kerne auf welchem CCD liegen. + +Bei meiner CPU haben die Cores 0-7 die virtuellen Cores 0-7 und 16-23 und die Cores 8-15 die virtuellen Cores 8-15 und 24-31. +Außerdem ist mit `lstopo` erkennbar, dass die Cores 0-7 mit dem ersten L3 Cache verbunden sind, und die Cores 8-15 mit dem Zweiten. +Es ist ratsam für die Performance, dass sich die VM Cores und die Host Cores keinen Cache teilen, also in meinem Fall alle virtuellen +Cores der Cores 0-7 durchzureichen, sprich 0-7,16-23. Siehe XML File. diff --git a/libvirt_guest_example_with_annotations.xml b/libvirt_guest_example_with_annotations.xml new file mode 100644 index 0000000..d4990a8 --- /dev/null +++ b/libvirt_guest_example_with_annotations.xml @@ -0,0 +1,210 @@ + + win11new + 1fdac169-a106-42f2-b43e-616601c53af1 + + + + + + 50331648 + 50331648 + + + + + 16 + 1 + + + + + + + + + + + + + + + + + + + + + + hvm + /usr/share/edk2-ovmf/x64/OVMF_CODE.secboot.4m.fd + /var/lib/libvirt/qemu/nvram/win11new_VARS.4m.fd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + destroy + restart + destroy + + + + + + /usr/bin/qemu-system-x86_64 + + + + + +
+ + + + + + +
+ + + + + + +
+ + + + + +
+ + +
+ + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + + + + +