4 min read

VFIO Gaming Setup unter Linux - Teil 1: Konfiguration des Hosts

In diesem Artikel geht es um mein Gaming Setup, welches durch eine Windows - VM auf meinem Manjaro Desktop PC betreibe. Im folgenden werde ich auf alle Schritte bei der Installation eingehen. Dieser Artikel wird nicht die Installation der VM selbst einschließen, dieser folgt später.

Zunächst einmal ein kleines Vorwort zur verwendeten Hard- & Software, sowie den Gründen und Vorteilen:

Software

Verwendet habe ich Manjaro, einfach weil es ein vorkonfiguriertes Arch ist. Das bietet die Möglichkeit Out of the Box immer sehr aktuelle Software & Kernel Versionen laufen zu lassen, was bei recht aktueller Hardware und diesem Setup eigentlich nur von Vorteil ist. Ebenso natürlich Fedora und Arch, aber das ganze ist auch mit Ubuntu/PopOS! oder anderen Distribution machbar. Genauso möglich wäre ein Hypervisor der eher in Richtung Server OS geht, wir z.B. Unraid, aber auch mit Proxmox oder Esxi sollte der ganze Spaß funktionieren. Das ganze wird Softwareseitig mit KVM/Qemu + libvirt (und optional noch virt-manager) erledigt.

Hardware

An bestehender Hardware ist mein PC mit einem Ryzen 1600X (6 Kerne, insg. 12 Threads), einer GTX 1080, 16 GB DDR4 Ram und SSDs + HDDs ausgestattet. Mein Mainboard ist ein MSI X370 Gaming Pro Carbon. In meinem Falle habe ich dann noch eine GT 710 gekauft, da der Ryzen keine iGPU hat, damit ich während dem die VM läuft auf dem Host noch z.B. Teamspeak, Firefox, usw. laufen lassen kann. Das ganze Setup sollte aber auch problemlos mit einer Intel iGPU oder anderen GPUs funktionieren. Meine 2. SSD reiche ich direkt an die VM durch, und binde die HDDs ein. Hier ist aber keine dedizierte SSD notwendig, jedoch sollte das die Performance verbessern. Die Monitorverkabelung habe ich folgendermaßen realisiert, dass die GT 710 beide Bildschirme über DVI ansteuert und die GTX 1080 per Display Port an meinen Hauptbildschirm angeschlossen ist. So kann ich durch das umstellen meines Monitor - Inputs zur VM wechseln. Ebenso werde ich aber auch auf die Software Lösung Looking Glass eingehen, die den GPU Speicher ausließt und diese Informationen an den Host gibt, welcher dann die Anzeige darstellen kann. So werden sogar 144hz per Softwarelösung übertragen, mehr dazu später.

IOMMU aktivieren

Zuerst muss IOMMU aktiviert werden, um die verschiedenen PCI Geräte in einzelne Gruppe aufzuteilen, welche später an die VM durch gereicht werden. Zunächst sollte diese Option im BIOS aktiviert werden, die entsprechende Einstellung sollte "VT-d" (Intel) oder "AMD-Vi" (Amd) heißen. Dann muss in den Grub Bootoptionen IOMMU aktiviert werden:

In /etc/default/grub:
GRUB_CMDLINE_LINUX_DEFAULT="amd_iommu=on iommu=pt ..."
(Oder intel_iommu=on bei Intel Prozessoren)

Danach die grub.cfg neu generieren:
grub-mkconfig -o /boot/grub/grub.cfg

Nun sollte man mit dmesg | grep -i -e DMAR -e IOMMU überprüfen, ob die Gruppen erfolgreich aktiviert wurden. Der Output sollte so ähnlich aussehen:
[    0.660041] iommu: Default domain type: Passthrough (set via kernel command line)
[    0.768388] pci 0000:00:00.2: AMD-Vi: IOMMU performance counters supported
[    0.768530] pci 0000:00:01.0: Adding to iommu group 0
...
[    0.769175] pci 0000:20:00.3: Adding to iommu group 21
[    0.769383] pci 0000:00:00.2: AMD-Vi: Found IOMMU cap 0x40
[    0.769961] perf/amd_iommu: Detected AMD IOMMU #0 (2 banks, 4 counters/bank).
[    0.800563] AMD-Vi: AMD IOMMUv2 driver by Joerg Roedel jroedel@suse.de

Als nächstes sollte mit dem folgenden Skript überprüft werden, ob die Gruppen so in Ordnung sind:
#!/bin/bash
shopt -s nullglob
for g in /sys/kernel/iommugroups/; do
   echo "IOMMU Group ${g##/}:"
   for d in $g/devices/; do
       echo -e "\t$(lspci -nns ${d##/})"
   done;
done;

Der Output sollte dann die Grafikkarten in getrennten Gruppen zeigen:
IOMMU Group 14:
1d:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP104 [GeForce GTX 1080] [10de:1b80] (rev a1)
1d:00.1 Audio device [0403]: NVIDIA Corporation GP104 High Definition Audio Controller [10de:10f0] (rev a1)
IOMMU Group 15:
1e:00.0 VGA compatible controller [0300]: NVIDIA Corporation GK208B [GeForce GT 710] [10de:128b] (rev a1)
1e:00.1 Audio device [0403]: NVIDIA Corporation GK208 HDMI/DP Audio Controller [10de:0e0f] (rev a1)

VFIO einrichten

Im nächsten Schritt wird die GPU für die VM zur Benutzung des vfio Treibers eingerichtet, um diese weiterreichen zu können. Dazu trägt man in der /etc/modprobe.d/vfio.conf diese Zeile ein, wobei die IDs denen der GPU entsprechen, die in der VM benutzt werden soll:
options vfio-pci ids=10de:1b80,10de:10f0

In der /etc/mkinitcpio.conf fügt man die folgenden Module hinzu, hier ist die Reihenfolge wichtig; die vfio Module sollten vor nvidia/noveau/radeon... stehen:
MODULES=(vfio_pci vfio vfio_iommu_type1 vfio_virqfd)

Weiterhin muss noch bei modconf in der Zeile HOOKS= hinzugefügt werden. Meine sieht so aus:
HOOKS="base udev autodetect modconf block keyboard keymap resume filesystems"

Als nächstes generiert man mit mkinitcpio -p linux den Kernel neu. Nach einem Reboot kann mit dmesg | grep -i vfio überprüft werden, ob vfio geladen wurde, der Output sollte ungefähr so aussehen:
[    0.329224] VFIO - User Level meta-driver version: 0.3
[    0.341372] vfio_pci: add [10de:13c2[ffff:ffff]] class 0x000000/00000000
[    0.354704] vfio_pci: add [10de:0fbb[ffff:ffff]] class 0x000000/00000000
[    2.061326] vfio-pci 0000:06:00.0: enabling device (0100 -> 0103)

Nun sollte noch überprüft werden ob den GPUs die richtigen Treiber zugeordnet wurden; lspci -nnk:
1d:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP104 [GeForce GTX 1080] [10de:1b80] (rev a1)
    Subsystem: ASUSTeK Computer Inc. GP104 [GeForce GTX 1080] [1043:85aa]
    Kernel driver in use: vfio-pci
    Kernel modules: nouveau, nvidia_drm, nvidia
1d:00.1 Audio device [0403]: NVIDIA Corporation GP104 High Definition          Audio Controller [10de:10f0] (rev a1)
    Subsystem: ASUSTeK Computer Inc. GP104 High Definition Audio Controller [1043:85aa]
    Kernel driver in use: vfio-pci
    Kernel modules: snd_hda_intel
1e:00.0 VGA compatible controller [0300]: NVIDIA Corporation GK208B [GeForce GT 710] [10de:128b] (rev a1)
    Subsystem: ASUSTeK Computer Inc. GK208B [GeForce GT 710] [1043:8576]
    Kernel driver in use: nvidia
    Kernel modules: nouveau, nvidia_drm, nvidia
1e:00.1 Audio device [0403]: NVIDIA Corporation GK208 HDMI/DP Audio Controller [10de:0e0f] (rev a1)
    Subsystem: ASUSTeK Computer Inc. GK208 HDMI/DP Audio Controller [1043:8576]
    Kernel driver in use: snd_hda_intel
    Kernel modules: snd_hda_intel

Nach diesen Schritten ist der Host grundsätzlich in der Lage die GPU an die VM durchzureichen. Der nächste Teil umfasst dann die Installation der VM. Zu guter letzt bleiben noch einige Spezialfälle (Looking Glass, Audio/Scream, Evdev, Cpu-Pinning, ...), dazu in einem dritten Teil mehr, sobald ich dafür Zeit finde.

Quellen: Reddit: r/vfio, Level1Tech Forum, Arch Wiki: PCI Passthrough

Autor: peterge