libvirt GPU Intel UHD 770 13900T passthrough

Du hast Probleme mit Deinem eMail-Programm, Webbrowser oder Textprogramm? Dein Lieblingsprogramm streikt?
Antworten
egophil
Beiträge: 4
Registriert: 25.08.2007 01:25:22

libvirt GPU Intel UHD 770 13900T passthrough

Beitrag von egophil » 02.02.2023 19:27:28

Hallo,

ich versuche meine iGPU in vom Hostsystem in eine Windows 10 VM durchzureichen leider bisher ohne Erfolg. Ich wollte gerne wissen, ob von euch jemand mit ähnlicher Hardware erfolgreich war. Hardware: Gigabyte Auros Elite AX, CPU Intel 13900T

ich benutze einen Kernel in Version 6.1.8 und den Debian unstable Zweig

und übergebe beim booten folgende Parameter (/etc/default/grub)

Code: Alles auswählen

GRUB_CMDLINE_LINUX_DEFAULT="rd_NO_LUKS intel_iommu=on iommu=pt pcie_acs_override=downstream,multifunction initcall_blacklist=sysfb_init video=simplefb:off video=vesafb:off video=efifb:off video=vesa:off disable_vga=1 vfio_iommu_type1.allow_unsafe_interrupts=1 kvm.ignore_msrs=1 modprobe.blacklist=snd_hda_intel,snd_hda_codec_hdmi,i915"
in der /etc/initramfs-tools/modules übergebe ich folgende Parameter:

Code: Alles auswählen

vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
in der Konfigurationsdatei: /etc/modprobe.d/vfio.conf steht folgendes

Code: Alles auswählen

options vfio-pci ids=8086:a780 disable_vga=1


das Kommando: dmesg | grep -e DMAR -e IOMMU
gibt soweit Auskunft darüber, dass IOMMU funktioniert:

Code: Alles auswählen

[    0.032516] ACPI: DMAR 0x00000000370E9000 000088 (v02 INTEL  EDK2     00000002      01000013)
[    0.032627] ACPI: Reserving DMAR table memory at [mem 0x370e9000-0x370e9087]
[    0.374527] DMAR: IOMMU enabled
[    0.686506] DMAR: Host address width 39
[    0.686511] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
[    0.686528] DMAR: dmar0: reg_base_addr fed90000 ver 4:0 cap 1c0000c40660462 ecap 29a00f0505e
[    0.686538] DMAR: DRHD base: 0x000000fed91000 flags: 0x1
[    0.686550] DMAR: dmar1: reg_base_addr fed91000 ver 5:0 cap d2008c40660462 ecap f050da
[    0.686559] DMAR: RMRR base: 0x0000003c000000 end: 0x000000403fffff
[    0.686570] DMAR-IR: IOAPIC id 2 under DRHD base  0xfed91000 IOMMU 1
[    0.686577] DMAR-IR: HPET id 0 under DRHD base 0xfed91000
[    0.686583] DMAR-IR: Queued invalidation will be enabled to support x2apic and Intr-remapping.
[    0.688871] DMAR-IR: Enabled IRQ remapping in x2apic mode
[    3.509677] pci 0000:00:02.0: DMAR: Skip IOMMU disabling for graphics
[    3.669840] DMAR: No ATSR found
[    3.669845] DMAR: No SATC found
[    3.669850] DMAR: IOMMU feature fl1gp_support inconsistent
[    3.669853] DMAR: IOMMU feature pgsel_inv inconsistent
[    3.669878] DMAR: IOMMU feature nwfs inconsistent
[    3.669882] DMAR: IOMMU feature dit inconsistent
[    3.669891] DMAR: IOMMU feature sc_support inconsistent
[    3.669897] DMAR: IOMMU feature dev_iotlb_support inconsistent
[    3.669905] DMAR: dmar0: Using Queued invalidation
[    3.669921] DMAR: dmar1: Using Queued invalidation
[    3.671608] DMAR: Intel(R) Virtualization Technology for Directed I/O
[    4.621052] AMD-Vi: AMD IOMMUv2 functionality not available on this system - This is not a bug.
Die VM habe ich in libvirt eingerichtet: als chipset: pc-q35-7.2 und BIOS ist ein UEFI: UEFI x86_64: /usr/share/OVMF/OVMF_CODE_4M.ms.fd XML-Datei von libvirt:

Code: Alles auswählen

<domain type="kvm">
  <name>Win10UEFI-konsti</name>
  <uuid>ef6ac324-3eff-46ac-bb44-260d44874a9e</uuid>
  <metadata>
    <libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
      <libosinfo:os id="http://microsoft.com/win/10"/>
    </libosinfo:libosinfo>
  </metadata>
  <memory unit="KiB">4194304</memory>
  <currentMemory unit="KiB">4194304</currentMemory>
  <vcpu placement="static">2</vcpu>
  <os firmware="efi">
    <type arch="x86_64" machine="pc-q35-7.2">hvm</type>
  </os>
  <features>
    <acpi/>
    <apic/>
    <hyperv mode="custom">
      <relaxed state="on"/>
      <vapic state="on"/>
      <spinlocks state="on" retries="8191"/>
    </hyperv>
    <vmport state="off"/>
  </features>
  <cpu mode="host-passthrough" check="none" migratable="on"/>
  <clock offset="localtime">
    <timer name="rtc" tickpolicy="catchup"/>
    <timer name="pit" tickpolicy="delay"/>
    <timer name="hpet" present="no"/>
    <timer name="hypervclock" present="yes"/>
  </clock>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>destroy</on_crash>
  <pm>
    <suspend-to-mem enabled="no"/>
    <suspend-to-disk enabled="no"/>
  </pm>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type="file" device="cdrom">
      <driver name="qemu" type="raw"/>
      <source file="/mnt/daten/vm/virtStorage0/Windows10/virtio-win.iso"/>
      <target dev="sdc" bus="sata"/>
      <readonly/>
      <boot order="3"/>
      <address type="drive" controller="0" bus="0" target="0" unit="2"/>
    </disk>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2"/>
      <source file="/mnt/daten/vm/virtStorage0/Windows10/Konsti_hdd0.qcow2"/>
      <target dev="vda" bus="virtio"/>
      <boot order="2"/>
      <address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>
    </disk>
    <controller type="usb" index="0" model="qemu-xhci" ports="15">
      <address type="pci" domain="0x0000" bus="0x02" slot="0x00" function="0x0"/>
    </controller>
    <controller type="pci" index="0" model="pcie-root"/>
    <controller type="pci" index="1" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="1" port="0x10"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0" multifunction="on"/>
    </controller>
    <controller type="pci" index="2" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="2" port="0x11"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x1"/>
    </controller>
    <controller type="pci" index="3" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="3" port="0x12"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x2"/>
    </controller>
    <controller type="pci" index="4" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="4" port="0x13"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x3"/>
    </controller>
    <controller type="pci" index="5" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="5" port="0x14"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x4"/>
    </controller>
    <controller type="pci" index="6" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="6" port="0x15"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x5"/>
    </controller>
    <controller type="pci" index="7" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="7" port="0x16"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x6"/>
    </controller>
    <controller type="pci" index="8" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="8" port="0x17"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x7"/>
    </controller>
    <controller type="pci" index="9" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="9" port="0x18"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0" multifunction="on"/>
    </controller>
    <controller type="pci" index="10" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="10" port="0x19"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x1"/>
    </controller>
    <controller type="pci" index="11" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="11" port="0x1a"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x2"/>
    </controller>
    <controller type="pci" index="12" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="12" port="0x1b"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x3"/>
    </controller>
    <controller type="pci" index="13" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="13" port="0x1c"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x4"/>
    </controller>
    <controller type="pci" index="14" model="pcie-root-port">
      <model name="pcie-root-port"/>
      <target chassis="14" port="0x1d"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x5"/>
    </controller>
    <controller type="sata" index="0">
      <address type="pci" domain="0x0000" bus="0x00" slot="0x1f" function="0x2"/>
    </controller>
    <controller type="virtio-serial" index="0">
      <address type="pci" domain="0x0000" bus="0x03" slot="0x00" function="0x0"/>
    </controller>
    <interface type="bridge">
      <mac address="52:54:00:10:28:c6"/>
      <source bridge="br0"/>
      <model type="virtio"/>
      <address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
    </interface>
    <serial type="pty">
      <target type="isa-serial" port="0">
        <model name="isa-serial"/>
      </target>
    </serial>
    <console type="pty">
      <target type="serial" port="0"/>
    </console>
    <input type="tablet" bus="usb">
      <address type="usb" bus="0" port="1"/>
    </input>
    <input type="mouse" bus="ps2"/>
    <input type="keyboard" bus="ps2"/>
    <graphics type="spice" autoport="yes" listen="0.0.0.0">
      <listen type="address" address="0.0.0.0"/>
      <gl enable="no"/>
    </graphics>
    <sound model="ich9">
      <address type="pci" domain="0x0000" bus="0x00" slot="0x1b" function="0x0"/>
    </sound>
    <audio id="1" type="none"/>
    <video>
      <model type="virtio" heads="1" primary="yes"/>
      <address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
    </video>
    <hostdev mode="subsystem" type="pci" managed="yes">
      <source>
        <address domain="0x0000" bus="0x00" slot="0x02" function="0x0"/>
      </source>
      <address type="pci" domain="0x0000" bus="0x06" slot="0x00" function="0x0"/>
    </hostdev>
    <memballoon model="virtio">
      <address type="pci" domain="0x0000" bus="0x04" slot="0x00" function="0x0"/>
    </memballoon>
  </devices>
</domain>


wenn ich die VM starte und anschließend den Befehl: lspci -nnk ausführe
sieht man, dass die GPU von vfio-pci angesprochen wird.

Code: Alles auswählen

00:02.0 VGA compatible controller [0300]: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] [8086:a780] (rev 04)
	DeviceName: Onboard - Video
	Subsystem: Gigabyte Technology Co., Ltd Raptor Lake-S UHD Graphics [1458:d000]
	Kernel driver in use: vfio-pci
	Kernel modules: i915

Ich habe Windows 10 ohne passthrough installiert. Hierzu verwende ich das Grafikinterface virtio. Nachdem Windows 10 installiert war habe ich den aktuellen Windows Patchstand eingespielt. VM Heruntergefahren und in der Konfiguration passthrough aktiviert (siehe libvirt XML-Datei). Windows bootet in diesem Fall ganz normal und man sieht im Gerätemanager ein neues PCI device als Grafikkarte. Windows 10 holt sich automatisch die Treiber installiert sie und zum Schluss steht im Gerätemanager eine UHD 770. Jedoch muss man Windows nach der Treiberinstallation neu starten.

Bisheriges Ergebnis: Die VM startet jedoch bleibt der Bildschirm schwarz und Windows läuft in den Reperaturmodus, da der Bootvorgang nicht erfolgreich war. Die Ausgabe läuft nur auf dem virtio mittels spice interface. Ich habe auch schon versucht nur die GPU der VM zu übergeben ohne virtio und spice-server. Leider ohne Erfolg. Sofern ich den passthrough deaktiviere fährt die VM(Windows 10) normal hoch.

Hat jemand noch Ideen was helfen könnte? Besten Dank,

Phil

Benutzeravatar
towo
Beiträge: 4409
Registriert: 27.02.2007 19:49:44
Lizenz eigener Beiträge: GNU Free Documentation License

Re: libvirt GPU Intel UHD 770 13900T passthrough

Beitrag von towo » 02.02.2023 21:23:58


egophil
Beiträge: 4
Registriert: 25.08.2007 01:25:22

Re: libvirt GPU Intel UHD 770 13900T passthrough

Beitrag von egophil » 03.02.2023 12:30:05

Hi,
vielen Dank für Deinen Kommentar. Jedoch möchte ich hervorheben, dass Intel_GVT-g kein vollständiges GPU passthrough ist. Das heißt, man hat lediglich die Funktionen der iGPU im Gastsystem zur Verfügung. Im Falle, dass man transcodieren will (bspw. Handbrake, Adobe Premiere oder Blue Iris) ist das ein gangbarer Weg, der momentan auch funktioniert. Was hingegen nicht funktioniert ist das Spielen, da der Bildschirm "schwarz" bleibt. Darüber hinaus hat die 13th (raptor lake) Intel CPU keinen offiziellen Support für SR-IOV. Ich habe mich dazu entschlossen ein kleines HowTo nachfolgend zu beschreiben, um für die Leute die hieran Interesse haben eine Anleitung mitzugeben.

Was ist zu tun:
- es muss eine Kernel gebaut werden, welche derzeitig auf dem 6.1 Zweig beruhen muss
- das Kernelmodul i915.ko muss ersetzt werden, hierfür wird dkms verwendet
- grub boot config muss angepasst werden
- sysfsutils werden benötigt
- eine Windows VM mit UEFI und dem i440fx chipsatz der q35 hat bei mir nicht funktioniert

man benötigt die i915 sr-iov Quellen vom Autor "strongtz" auf git hub, um ein angepasstest i915 Modul zu bauen.

daher muss ein git clone ausgeführt werden ich habe alle meine source files unter "/usr/src"

Code: Alles auswählen

https://github.com/strongtz/i915-sriov-dkms.git
Es sollte daraufhin einen Ordner "i915-sriov-dkms" geben.
Hier ist die erste Stolperfalle: es muss dkms.conf angepasst werden.

Code: Alles auswählen

PACKAGE_NAME="@_PKGBASE@"
PACKAGE_VERSION="@PKGVER@"
anpassen zu

Code: Alles auswählen

PACKAGE_NAME="i915-sriov"
PACKAGE_VERSION="dkms"
Wenn Ihr mit der PACKAGE_VERSION arbeiten wollt, um Revisionen anzulegen müsst ihr den git Ordner anpassen.
Derzeitig (03.02.2023) ist es die Version "5.15.71". Dann könnt Ihr PACKAGE_VERSION="5.15.71" verwenden und euer Ordner vom git hub project muss anstatt:

Code: Alles auswählen

"i915-sriov-dkms"

Code: Alles auswählen

"i915-sriov-5.15.71"
lauten.

Je nachdem wie Ihr euch oben entschieden habt lautete der Befehl zum Bauen des Kernelmoduls:

Code: Alles auswählen

dkms install -m i915-sriov -v dkms --force
oder

Code: Alles auswählen

dkms install -m i915-sriov -v 5.15.71 --force
Das force benötigt man, wenn das Modul aufgrund eures jetzigen Kernels bereits existiert, sonst überschreibt es dkms nicht und wirft einen Fehler.

Sofern es dazu kommen sollte, dass Fehler im build Prozess auftauchen wie zum Beispiel:

Code: Alles auswählen

ERROR: modpost: "intel_pxp_fini" [/var/lib/dkms/i915-sriov-dkms/5.15.49/build/i915.ko] undefined!
müsst Ihr euch einen neuen Kernel bauen. Es führt keinen Weg daran vorbei . Es genügt auch nicht im Makefile das Flag von "CONFIG_DRM_I915_PXP" zu entfernen, dann kracht es später an einer anderen Stelle im build process des dkms i915.ko modul.

Ich musste den Weg über einen neuen Kernel auch gehen, da bei mir der oben beschriebene Umstand aufgetreten ist.
Folgendes muss in der Kernelconfig stehen:

Code: Alles auswählen

CONFIG_INTEL_MEI_PXP=m
CONFIG_DRM_I915=m
CONFIG_DRM_I915_GVT=y
CONFIG_DRM_I915_GVT_KVMGT=m
CONFIG_DRM_I915_PXP=y
Danach könnt Ihr den Kernel bauen mit:

Code: Alles auswählen

ionice -c3 nice -n 19 make -j32 deb-pkg
wenn der kernel build process erfolgreich durchlaufen ist müsst ihr diesen installieren. In meinem Fall lautete es:

Code: Alles auswählen

dpkg -i linux-image-6.1.9_6.1.9-1_amd64.deb linux-headers-6.1.9_6.1.9-1_amd64.deb linux-headers-6.1.9_6.1.9-1_amd64.deb 
danach einmal in den neuen Kernel booten.

Wenn euer System erfolgreich mit dem neuen Kernel gestartet ist sollte der dkms i915 Teil von oben funktionieren.
also dann je nachdem wie Ihr euch am Anfang entschieden habt:

Code: Alles auswählen

dkms install -m i915-sriov -v dkms --force
oder

Code: Alles auswählen

dkms install -m i915-sriov -v 5.15.71 --force
mit dem Befehl "dkms status" könnt ihr prüfen, ob alles geklappt hat. Die Ausgabe sollte etwa so aussehen:

Code: Alles auswählen

dkms status
i915-sriov/5.15.71, 6.1.8, x86_64: installed
i915-sriov/dkms: added
Wenn soweit alles passt geht es an die Konfiguration des Systems.
Zuerst benötigt man noch ein tool: sysfsutils

Code: Alles auswählen

apt install sysfsutils -y
Nun muss grub konfiguriert werden hierzu mit einem Editor "/etc/default/grub" aufrufen
in der Zeile wo: GRUB_CMDLINE_LINUX_DEFAULT muss folgendes ergänzt werden "intel_iommu=on iommu=pt i915.enable_guc=7"
bei mir sieht es so aus:

Code: Alles auswählen

GRUB_CMDLINE_LINUX_DEFAULT="rd_NO_LUKS intel_iommu=on iommu=pt i915.enable_guc=7"
anschließend

Code: Alles auswählen

update-grub
ausführen

Die 7 gibt an wie viele grafik interfaces Ihr haben wollt. Habt ihr also mehrere VMs könnt ihr gleichzeitig bis zu 7 GPUs durchreichen.
Momentan gibt es nicht mehr als 7 interfaces. Mehr lässt das i915 sr-iov modul nicht zu.



Als nächstes ermittelt ihr auf welchem PCIe Bus eure iGPU sitzt, dass macht Ihr mit dem Befehl:

Code: Alles auswählen

lspci | grep "VGA"
Die Ausgabe sieht bei mir so aus:

Code: Alles auswählen

00:02.0 VGA compatible controller: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] (rev 04)
danach konfiguriert man die Zuweisung, passt auf dass ihr die PCIe Nummer mit eurer lspci Ausgabe abgleicht. Bei mir sieht es so aus.

Code: Alles auswählen

echo "devices/pci0000:00/0000:00:02.0/sriov_numvfs = 7" > /etc/sysfs.conf

Als nächstes benötigen wir noch eine Firmware. Prüft ob auf eurem System für die iGPU die passende Firmware da ist (für raptor/alder lake):

Code: Alles auswählen

ls /lib/firmware/i915/tgl_guc_70.1.1.bin
Kommt nichts zurück könnt Ihr, wenn ihr eine alder lake oder raptor lake CPU/GPU habt folgende Firmware herunterladen:

Code: Alles auswählen

wget -P /lib/firmware/i915 https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/i915/tgl_guc_70.1.1.bin
Für alle anderen gilt entsprechend der Hardware die passende Firmware zu organisieren. Der obige Link könnte eine erste Anlaufstelle sein.
Wenn das soweit alles geklappt hat müsst ihr euer System neu starten.


Ist der reboot erfolgreich sollte der Befehl lspci ein anderes Ergebnis im Vergleich zum vorherigen Aufruf zurückgeben. In meinem Fall sieht es so aus:

Code: Alles auswählen

lspci | grep "VGA"
00:02.0 VGA compatible controller: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] (rev 04)
00:02.1 VGA compatible controller: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] (rev 04)
00:02.2 VGA compatible controller: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] (rev 04)
00:02.3 VGA compatible controller: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] (rev 04)
00:02.4 VGA compatible controller: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] (rev 04)
00:02.5 VGA compatible controller: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] (rev 04)
00:02.6 VGA compatible controller: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] (rev 04)
00:02.7 VGA compatible controller: Intel Corporation Raptor Lake-S GT1 [UHD Graphics 770] (rev 04)
Nun können wir die VM konfigurieren. Bisher habe ich es mit einer VM mittels chipset q35 und i440fx probiert. Leider hat es nur mit der i440fx VM geklappt.
Ganz wichtig ihr richtet eure VM ganz normal ein ohne eine GPU Hardware durch zureichen. Aktiviert in windows den RDP remotezugang und kontrolliert, ob die Windowsfirewall den Zugang nicht sperrt, da wir den später benötigen. Gegebenenfalls ist es gut der VM eine statische IP zu geben. Wenn soweit alles passt und der RDP Zugang erfolgreich getestet wurde fahrt Ihr die VM herunter.

Nun müsst ihr eure virtuellen Grafikkarten aus der Konfiguration herausnehmen wirklich alle, kein spice kein vnc oder sonst was. Danach fügt ihr eine von den iGPU (in meinem Fall sind es sieben Stück) eurer VM hinzu.
Danach startet ihr die VM und wartet bis ihr mit dem RDP client eine Verbindung zum Gastsystem aufbauen könnt. Danach wird Windows sicherlich die durchgereichte Grafikkarte initialisieren und die Treiber herunterladen. Ich habe die Inteltreiber verwendet (gfx_win_101.4091).
Anschließen werdet Ihr von Windows aufgefordert Windows neue zu starten. Das sollte dann der letzte reboot von diesem Howto sein. Im Ergebnis sieht dann so aus, siehe Bilder

3957
3958


Gruß,

Phil

Antworten