Single GPU Passthrough megvalósítása KVM alapú virtuális géppel

Sokan mérlegelik, érdemes-e teljesen Linuxra váltani, vagy megőrizni a Windowst külön meghajtón. A döntés nemcsak technikai, hanem kényelmi kérdés is: a teljes Linuxra történő átállás nagy szabadságot ad, de ha speciális szoftvereket használsz vagy ha online játszol, akkor a Windows fenntartása indokolt. Ha nem akarsz dual-boottal és újraindításokkal bajlódni, jó megoldás lehet a single-GPU passthrough: a fizikai videokártyát közvetlenül egy KVM/QEMU alapú Windows virtuális gépnek adod át, így szinte natív grafikus teljesítményt kapsz, és újraindítás nélkül válthatsz a két rendszer között. Régen ehhez két GPU kellett, ma már egy kártyával is megoldható néhány tudatos beállítással.

Jelen oktatóanyag az azonos című youtube videóhoz készült. Ez az oktatóanyag haladó felhasználóknak szól, és Linux, valamint és virtualizációs alaptudás szükséges hozzá. Az oktatóanyag alapját joeknock90 GitHub single-gpu-passthrough github repoja adta.

Single GPU Passthrough megvalósítása KVM alapú virtuális géppel

Szükséges feltételek a single GPU passthrough-hoz

A Single GPU Passthrough nagyon fontos feltétele hogy elegendő erőforrást adjunk a virtuális gépnek.

Az általam használt konfiguráció:

TulajdonságÉrték
Operációs rendszerEndeavourOS
Rendszermag verzió6.17.2-zen1-1-zen (64 bit)
ProcesszorAMD Ryzen 9 7900X (12 mag)
Memória32 GiB RAM
Grafikai feldolgozóegység (GPU)NVIDIA GeForce RTX 3060
Tárhely1 TB NAND NVMe SSD

CPU és memória: Fontos, hogy a gazda (host) rendszer számára hagyjunk elegendő erőforrást. Legalább 2 fizikai magot (4 logikai szálat) érdemes fenntartani a Linux host számára, különben a Linux és a hozzá kapcsolódó I/O folyamatok akadozhatnak. Ha túl sok magot adunk a virtuális gépnek, az a teljesítmény drasztikus romlását vagy akár a rendszer lefagyását okozhatja.

A vendég (guest) rendszer CPU-beállításánál a host-passthrough mód ajánlott, mert ez biztosítja a CPU képességek teljes kihasználását és a legjobb kompatibilitást. Memóriából általános szabályként 32 GB fizikai RAM esetén 16 GB-ot adhatunk a vendégnek és 16 GB-ot hagyunk a hostnak. Kevesebb memória esetén a swap intenzív használata a teljesítményt jelentősen visszaveti.

Tárhely: Lehetőség szerint NVMe SSD-re telepítsük a vendég rendszert a gyors I/O érdekében. Ha fájl alapú lemezképet használunk, legalább 100 GB méretű QCOW2 image javasolt, hogy a Windows és alkalmazásai kényelmesen elférjenek. A QCOW2 előnye a helytakarékosság és a snapshot lehetőség, hátránya viszont egy kis teljesítmény-overhead ( kb 5%-os lassulás a RAW lemezképhez képest). RAW lemezkép használatával enyhén gyorsabb lemezműveleteket érhetünk el, cserébe lemondunk a dinamikus méret és snapshot funkciókról.

GPU kompatibilitás (VFIO): A GPU passthrough csak akkor működik, ha a rendszerünk IOMMU-kompatibilis és a videokártyát képesek vagyunk VFIO-n (Virtual Function I/O) keresztül a vendégnek átadni. Nvidia fronton a GeForce GTX 10-es sorozattól felfelé általában sikeres a passthrough – AMD oldalon az RX 500-as szériától felfelé a Radeon kártyák többsége gond nélkül átadható, bár egyes modelleknél előfordulhat az ún. “reset bug” (ilyenkor a kártya egy vendég leállítása után nem inicializálható újra, amit kernel patch ( vendor-reset) orvosolhat).

IOMMU és BIOS beállítások: Ellenőrizzük, hogy a processzorunk támogatja a virtualizációt és az IOMMU-t (Intel VT-d vagy AMD-Vi), és ez be van kapcsolva a BIOS/UEFI menüben.

Ezek az opciók gyakran “Virtualization Technology” néven szerepelnek a BIOS-ban, vagy az Advanced CPU beállítások között. Bekapcsolás után a Linux indulását követően futtassuk:

$ dmesg | grep -i IOMMU

A kimenetben intel esetén Intel-IOMMU: enabled

AMD esetén AMD-Vi: IOMMU performance counters supported sor jelenik meg

ami egyértelműen jelzi, hogy a kernel felismerte és aktiválta az IOMMU-t. Ha nem látunk ilyet, akkor manuálisan is kell engedélyezni a kernelben, melyhez a /etc/default/grub fájlt kell szerkeszteni.

Keressük meg a GRUB_CMDLINE_LINUX_DEFAULT kezdetű sort, majd Intel rendszeren adjuk hozzá a boot paraméterekhez az intel_iommu=on iommu=pt, (szóközzel elválasztva) AMD esetén az amd_iommu=on iommu=pt opciókat. Emellett kulcsfontosságú az EFI framebuffer letiltása is: adjuk meg a video=efifb:off paramétert, hogy kikapcsoljuk az UEFI firmware által biztosított ideiglenes grafikus megjelenítést. Ez megakadályozza, hogy a host rendszer a boot folyamat során az efifb illesztőprogrammal lefoglalja a GPU-t, így a videokártya szabadon elérhető marad a vendég rendszer számára.

Összefoglalva,az alábbiakat kell hogy lássuk a GRUB konfigurációban Intel esetén:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash intel_iommu=on iommu=pt video=efifb:off"

AMD esetén:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash amd_iommu=on iommu=pt video=efifb:off"

A módosítás után futtassuk az alábbi parancsot, majd indítsuk újra a gépet.

$ sudo grub-mkconfig -o /boot/grub/grub.cfg

Újraindítás után a dmesg ellenőrzésekor már látnunk kell az IOMMU-ra utaló sorokat, és az eszközök külön IOMMU csoportban az ls -l paranccsal listázhatóak az /sys/kernel/iommu_groups/alatt.

Virtualizációs szoftverek telepítése: Szükségünk lesz a KVM alapú virtualizációs stackre: QEMU, libvirt, virt-manager és a VFIO kernel modulokra. Modern Linux disztribúciók (Arch, Fedora, openSUSE Tumbleweed, Ubuntu stb.) új kernel verziókkal érkeznek, de a VFIO támogatás már évek óta stabil része a kernelinek, nincs szükség speciális (pl. patchelt) kernelre. Győződjünk meg róla, hogy a rendszerünkön telepítve van a következő csomagok többsége: qemu, libvirt (és esetleg libvirt-daemon), virt-manager (grafikus VM-kezelő), virt-viewer, továbbá a segédcsomagok ( dnsmasq, bridge-utils, iptables-nft stb. disztrófüggő). Arch Linuxon például:

$ sudo pacman -S qemu libvirt virt-manager virt-viewer dnsmasq vde2 bridge-utils openbsd-netcat ebtables iptables-nft
sudo systemctl enable --now libvirtd.service

A csomagok nevei természetesen disztribuciónként eltérhetnek.

DisztribúcióSzükséges csomagok
Fedoraqemu-kvm, libvirt, virt-manager, virt-viewer, dnsmasq, vde2, bridge-utils, nmap-ncat, ebtables, iptables-nft
openSUSE Tumbleweedqemu-kvm, libvirt, virt-manager, virt-viewer, dnsmasq, vde2, bridge-utils, netcat-openbsd, ebtables, iptables
Ubuntu / Debian alapú rendszerekqemu-kvm, libvirt-daemon-system, virt-manager, virt-viewer, dnsmasq-base, vde2, bridge-utils, netcat-openbsd, ebtables, iptables

Telepítés után adjuk hozzá felhasználó nevünket a libvirt csoporthoz a jogosultságok miatt. Ehhez a /etc/libvirt/libvirtd.conf fájlban kommenteljük ki az unix_sock_group = "libvirt" és az unix_sock_rw_perms = "0770" beállításokat, majd terminálban adjuk meg az alábbi parancsokat:

$ sudo groupadd libvirt 
sudo usermod -aG libvirt $(whoami)
newgrp libvirt
sudo systemctl restart libvirtd.service

Ez biztosítja, hogy a felhasználónk jogosult legyen a libvirt sockethez csatlakozni (pl. a virt-manager használatához).

Miután minden szükséges szoftveres előkészület befejeződött, a virt-managerben létrehozhatunk egy új virtuális gépet, például Windows 10 vagy 11 vagy egyéb más rendszer telepítéséhez. Ezt had ne kelljen leírnunk, hisz az oktatóanyag készítői feltételezik hogy ezzel már tisztában vagy :):) Egyvalamit azonban mégis érdemes megemlíteni: A kezdeti beállítás során célszerű virtuális GPU-t használni QXL típusú grafikus kártyával és SPICE megjelenítővel, mivel így a vendég rendszer képernyője elérhető marad a virt-manager beépített konzolján. A telepítéshez válaszd ki a megfelelő ISO-fájlt, add meg az operációs rendszer típusát, majd a hardverlista végén ellenőrizd, hogy a „Videó” eszköz QXL legyen. Ez biztosítja, hogy a telepítés grafikus felülete gond nélkül megjelenjen és irányítható legyen a hostról, de még Linux felületen keresztül.

Windows vendég alatt töltsük le és telepítsük a virtio-win nevű illesztőprogram csomagot, melynek a lényege, hogy a Windows a lehető legnagyobb sebességgel és stabilitással tudjon kommunikálni a virtualizált hardverrel — vagyis ne „emulált” régi eszközöket használjon, hanem paravirtualizált (VirtIO) interfészeket, amiket közvetlenül a hypervisor szolgál ki.

A telepítés befejezése után, mielőtt a fizikai GPU-t átadnánk a vendég rendszernek, érdemes a SPICE megjelenítést VNC-re cserélni, hogy a hosthoz akkor is hozzáférjünk, amikor annak kijelzőjét már a virtuális gép használja.

A host elérése VNC-vel a VM futása közben

Ehhez nyisd meg a virtuális gép beállításait, válaszd a „Hardver hozzáadása” opciót, majd a „Grafika” szekciót. Itt a „Spice” helyett állítsd be a „VNC server” lehetőséget. A portot hagyhatod automatikus beállításon, a „Listen Type” értékét pedig „Address” módra állítsd, és a cím opciót módosítsd „Összes csatolóra”. Amikor így indítod a gépet, a virtuális kijelzőt a beépített VNC-szerver biztosítja, így a vendég rendszer képernyőjéhez bármilyen VNC klienssel csatlakozhatsz – akár a virt-manager saját nézőjével, akár külső programmal, például a TigerVNC klienssel, amit az egyszerűsége miatt érdemes használni. A csatlakozáshoz a host gép lokális IP-címét kell megadni.

Ez a megoldás különösen hasznos single GPU-s beállítás esetén, főleg Windows vendégrendszernél, ahol a telepítéskor még nincs grafikus driver. A teljes képátvitel ilyenkor a QEMU saját VNC-szerverén keresztül történik, így a GPU átadása után is elérheted a vendég képernyőjét hálózaton keresztül, miközben a host kijelzője már inaktív.

Mindezek mellett nem árt a kettős védelem sem: érdemes a hoston egy SSH-hozzáférést is beállítani, hogy probléma esetén – például ha a VNC kapcsolat megszakad, vagy a grafikus felület nem reagál – távolról is be tudj lépni a host rendszerbe és ellenőrizni tudd, mi történik a háttérben. Az SSH stabil és biztonságos módja annak, hogy a GPU átadási folyamat közben is irányításod maradjon a host felett. Erre a célra az openssh-t ajánlom, és ne felejtsd el a systemd-ben engedélyezni az sshd szolgáltatást az alábbi paranccsal:

$ sudo systemctl enable —now sshd

Az alábbi paranccsal pedig ellenőrizni tudod hogy fut-e:

$ sudo systemctl status sshd

Ha a virtuális gép elindul az alábbi paranccsal csatlakozhatsz az SSH terminálhoz:

$ ssh felhasználóneved@ipcím

Ekkor sor kerülhet a tényleges GPU-átadásra:

A fizikai kártyát a virtuális gép beállításokban a "Hardver hozzáadása" gomb lenyomásával tudod hozzárendelni a VM-hez. Ha van beépített HDMI Hang eszköze a kártyának, azt is adjuk hozzá. A QXL és VNC eszközt még ne távolítsuk el, erre a driver telepítését követően kerülhet majd sor.

Következő lépésként készítsünk elő egy automatizált indító és leállító scriptet.

Libvirt hook script mechanizmus

A libvirt egy úgynevezett „hook” rendszert biztosít, amely lehetővé teszi, hogy automatizált szkriptek fussanak le a virtuális gépek életciklusának különböző pontjain. Ennek kiemelt szerepe van a single GPU passthrough esetében, mivel ilyenkor a gazdarendszer grafikus környezetét le kell állítani, és a GPU-t le kell választani a Linuxról, mielőtt azt a virtuális gép átvenné. A vendég leállítása után pedig mindezt vissza kell állítani, hogy a host újra használhassa a grafikus eszközt.

A hook rendszer működése egyszerű: amikor egy libvirt által kezelt virtuális gép elindul, leáll vagy állapotot vált, a libvirt ellenőrzi, található-e a /etc/libvirt/hooks/ könyvtárban az adott eseményhez kapcsolódó szkript. QEMU-alapú gépek esetében ilyenkor a /etc/libvirt/hooks/qemu fájl kerül meghívásra, amely további, az adott géphez tartozó al-szkripteket indíthat a /etc/libvirt/hooks/qemu.d/<VM-név>/{prepare/begin, release/end}/ elérési útvonal alatt, attól függően, hogy a virtuális gép éppen milyen fázisban van.

Például, ha a virtuális gép neve mondjuk win10, akkor létrehozhatunk egy ilyen struktúrát:

/etc/libvirt/hooks/qemu.d/
└── win10
├── prepare
│ └── begin
│ └── start.sh # Indulás előtti teendők
└── release
└── end
└── revert.sh # Leállás utáni teendők

A libvirt induláskor a start.sh scriptet fogja futtatni, leállítás után pedig a revert.sh-t. Ezekben a szkriptekben tudjuk automatizálni a szükséges lépéseket

A folyamat elején a script leállítja a display managert, például az SDDM-et vagy a GDM-et. Ezzel a Linux grafikus környezete elengedi a GPU-t. Ezután a script leválasztja a virtuális konzolokat, vagyis azokat a szöveges terminálokat, amik normál esetben a videokártyán keresztül jelennek meg. Így a kernel sem tartja többé „fogva” az eszközt.

Ezt követően jön a legfontosabb rész: a videokártya és a hozzá tartozó HDMI-hang eszköz leválasztása a host rendszer driveréről, ami a virtualizációs réteg számára biztosítja a hozzáférést. Végül a script betölti a VFIO-PCI modult, ami a GPU-t a vendég rendszerhez rendeli. Innentől a kártya teljesen a virtuális gép irányítása alatt áll.

Amikor a virtuális gépet leállítjuk, a revert script lép működésbe.

Ennek célja, hogy mindent visszaállítson, vagyis a GPU-t újra a Linux alá rendelje. Ehhez először visszacsatolja a kártyát a host rendszerhez, majd betölti a hozzá tartozó kernelmodulokat – például az nvidia vagy amdgpu modulokat. Visszacsatolja a konzolokat, majd utolsó lépésként elindítja a display managert, így pár másodpercen belül ismét megjelenik a bejelentkező képernyő, és a desktop újra használható.

Fontos megjegyezni, hogy a folyamat közben a Linux gyakorlatilag „vakon” fut – ilyenkor a monitor a vendég rendszerhez tartozik, a host pedig háttérben dolgozik. Ezért érdemes a tesztelés idejére SSH-n keresztül figyelni a folyamatot, így ha valami hibázik, könnyen be tudunk avatkozni.

A scriptek lépései természetesen rendszer- és hardverfüggők, ezért mindig érdemes először manuálisan kipróbálni a teljes folyamatot, mielőtt automatizáljuk. Ha egyszer minden rendben működik, onnantól a GPU átadása és visszavétele teljesen automatikusan történik minden virtuális gép indításakor és leállításakor.

A hook script mechanizmus lehetővé teszi, hogy a teljes átadás-átvétel emberi beavatkozás nélkül történjen. Ha mindent jól beállítunk, akkor a virtuális gép indításakor a host grafikája automatikusan lekapcsol, a kártya átkerül a vendéghez, majd a vendég leállításakor pár másodperc után visszatér a Linux grafikus felület.

Ha a vendég rendszeren telepítettük a szükséges drivereket, és a fizikai GPU és a kapcsolódó eszközök bekerültek a konfigurációba, a „Videó” szekcióból eltávolítható a QXL adapter, hogy a rendszer kizárólag a valós grafikus kártyát használja. Ezzel együtt a „Megjelenítő” eszköz is törölhető, mivel a kép ezután közvetlenül a dedikált GPU-n jelenik meg.

A start és revert scriptek működése

Start script (GPU átadása a vendégnek)

Info
Frissítés, 2025.10.29: NVIDIA kártyák esetén bizonyos esetekben az nvidia-persistenced folyamat nem engedi el az átadáskor a GPU-t, ezért ilyenkor a start scriptbe célszerű ennek leállítását, majd a revert scriptben az újraindítását megadni. A script kiegészítésre került a parancsokkal.

A start.sh script a vendég gép indulása előtt fut le. Célja, hogy előkészítse a terepet a GPU átadásához. Lépésről lépésre tipikusan a következőket végzi:

  1. Display manager leállítása: A Linux grafikus bejelentkező felületét (pl. SDDM, GDM, LightDM) le kell állítani. Ezzel kiléptetünk minden felhasználót a grafikus felületről és felszabadítjuk a GPU-t a desktop használat alól. Például: systemctl stop display-manager.service. (GDM használata esetén szükség lehet egy killall gdm-x-session parancsra is, mert a GDM sajátosságai miatt egy futó X session túlélheti a service leállítását – ezt a saját scriptünkben vegyük figyelembe, ha GNOME-ot használunk.)
  2. Virtuális konzolok leválasztása: A Linux terminálok (tty1, tty2, stb.) alapértelmezetten a GPU-n jelennek meg. Hogy a kernel ne tartsa “fogva” a kártyát, le kell választani a konzol drivert. Ezt a /sys/class/vtconsole/vtcon* alatt tudjuk megtenni, tipikusan:echo 0 > /sys/class/vtconsole/vtcon0/bind echo 0 > /sys/class/vtconsole/vtcon1/bind Ezzel a szöveges konzolok lecsatlakoznak a kártyáról.
  3. Eszköz leválasztása a host kernel driverétől: Egy kis késleltetés után ( sleep 1 tipikusan) jön a kulcslépés: a GPU PCI-eszközt le kell választani a host driverről. Ezt megtehetjük virsh nodedev-detach paranccsal, vagy manuálisan az unbind interfészen keresztül. A lényeg, hogy ilyenkor a Linux elengedi az eszközt. Fontos, hogy a GPU-hoz általában tartozik egy audiokodek is (pl. HDMI hang, ugyanazon kártya 0000:01:00.1 bus címen). Azt is le kell választani ugyanígy, különben a kártya nem kerül teljesen szabad állapotba. Használjuk az lspci -nnk kimenet alapján az eszközazonosítókat. Példa:virsh nodedev-detach pci_0000_01_00_0 virsh nodedev-detach pci_0000_01_00_1 (Itt a 01:00.0 a VGA és 01:00.1 a hang eszköz.) A libvirt dokumentáció megjegyzi, hogy hook scriptben nem ajánlott libvirt parancsot hívni, mert deadlockot okozhat. Alternatív megoldásként echo-zni is lehet a PCI eszközt a vfio-driverhez (driver override). A mi esetünkben azonban sok egy GPU-s leírás ezt a virsh detach módszert használja. Legyünk óvatosak, és ha gond adódna, inkább a driver binding mechanizmust használjuk. Mindenesetre a cél, hogy a /sys/bus/pci/devices/<BDF>/driver ne mutasson már pl. az nvidia driverre.
  4. VFIO-PCI driver betöltése: Miután az eszköz “árván” maradt (nincs driverhez kötve), betöltjük a VFIO modulokat: modprobe vfio-pci. Ha a vfio-pci modul a kártyánk azonosítóját a paraméterei között találja (ezt lehet konfigurálni modprobe.d-ben), akkor magához ragadja az eszközt. Így innentől a libvirt/QEMU már a VFIO-n keresztül fér hozzá a GPU-hoz. A script végére akár tehetünk egy echo "VFIO binding done" jellegű logot, hogy lássuk, sikerült.

Ezzel a start script lefutott, a host oldal teljesen lemondott a GPU-ról, és készen áll a QEMU arra, hogy elinduljon a vendég rendszer közvetlenül a hardveren. A libvirt ezután elindítja a VM-et, amelynek konfigurációjában már felvettük a fizikai GPU-t és hang eszközt (PCI passthrough device-ként).

Revert script (GPU visszaadása a hostnak)

A revert.sh script a vendég gép leállítása után fut le. Feladata ennek megfelelően az, hogy mindent visszacsináljon, és a host újra teljes értékűen használhassa a videokártyát. A főbb lépések:

  1. GPU eszközök visszacsatolása a hosthoz: Itt a virsh nodedev-reattach pci_0000_01_00_X parancsokat használhatjuk, hogy a korábban leválasztott VGA és audio eszközöket visszaadjuk a host kernelnek. Ha sikerül, a PCI eszköz újra megjelenik a Linux számára és megpróbálja a korábbi driverhez kötni.
  2. GPU driver modulok betöltése: Előfordulhat, hogy a visszatérés pillanatában az adott GPU driver (pl. nvidia vagy amdgpu) már nincs a memóriában, vagy nincs teljesen felkészülve. Ezért érdemes kézzel betölteni. Nvidia esetén tipikusan:modprobe nvidia modprobe nvidia_drm modprobe nvidia_modeset modprobe nvidia_uvm – ezzel az összes szükséges modult visszatöltjük. AMD kártyánál az amdgpu modult kell betölteni (ha nem töltődne magától).
  3. Display manager újraindítása: Végül visszahozzuk a grafikus felületet: pl. systemctl start display-manager.service. Ekkor a login képernyő vagy az automatikus bejelentkezés után a desktop felület újra megjelenik a monitoron. Ha minden jól ment, néhány másodperccel a vendég leállása után a monitorunk életre kell és ott folytathatjuk a munkát a Linuxon, ahol abbahagytuk.

A fenti folyamatban lényegében az történik, hogy a host rendszert “vakon” futtatjuk a vendég futása alatt. Emiatt erősen ajánlott valamilyen távoli elérés a hosthoz a tesztelés idejére (pl. SSH-n keresztül egy laptopról), mert a grafikát leállítva nem fogjuk látni, mi történik a háttérben. SSH-n figyelemmel kísérhetjük a script futását, naplóüzeneteket. Különösen az első beállításnál lehetnek hibák, amiket így könnyebb debugolni. Ha bárhol elakad a folyamat, az SSH konzolon közbe tudunk avatkozni.

Info
A futó virtuális gépeket bármikor listázhatod ssh elérésen keresztül a sudo virsh list paranccsal amennyiben nincs kimenet a képernyőn,majd leállíthatod a sudo virsh destroy gépnév paranccsal

Script sablonok:

start.sh

#!/bin/bash

set -xuo pipefail


# --- ÁLLÍTSD BE A SAJÁT PCI AZONOSÍTÓIDAT ---

PCIS=("0000:01:00.0" "0000:01:00.1")   # VGA + HDMI-audio példa RTX 3060-hoz

NODES=()                                # ide számoljuk ki a virsh nodedev neveket


# KDE alatt a display manager jellemzően SDDM

DM="sddm.service"  # ha nem SDDM-et használsz: display-manager.service


# VFIO modulok

VFIO_MODS=(vfio-pci vfio vfio_iommu_type1 vfio_virqfd)


# --- Segéd: PCI -> virsh nodedev név ---

to_node() {

 local p="$1"; echo "pci_${p//[:.]/_}"

}


# 0) Ellenőrzés: privileged?

if [[ $EUID -ne 0 ]]; then

 echo "Ezt rootként futtasd (sudo)"; exit 1

fi


# 1) DM leállítás

systemctl stop "$DM" || true

# Ha GDM-et használsz, erre is rásegíthetsz:

#killall gdm-x-session 2>/dev/null || true


# 2) VT konzolok unbind (ha léteznek)

[[ -e /sys/class/vtconsole/vtcon0/bind ]] && echo 0 > /sys/class/vtconsole/vtcon0/bind || true

[[ -e /sys/class/vtconsole/vtcon1/bind ]] && echo 0 > /sys/class/vtconsole/vtcon1/bind || true


sleep 2  # kis várakozás, hogy biztosan elengedjen mindent


# 3) NVIDIA Persistance folyamat leállítása (Csak NVIDIA)

systemctl stop nvidia-persistenced.service


# 4) NVIDIA modulok eltávolítása, hogy a kártya felszabaduljon

modprobe -r nvidia_drm nvidia_modeset nvidia_uvm nvidia 2>/dev/null || true


# 5) VFIO modulok betöltése

for m in "${VFIO_MODS[@]}"; do modprobe "$m"; done


# 6) GPU unbind virsh-sel a host drivertől → VFIO

for p in "${PCIS[@]}"; do

 node="$(to_node "$p")"

 NODES+=("$node")

 virsh nodedev-detach "$node" || true

done


# Biztonsági háló: ha valami még fogja, próbáld sysfs-en át VFIO-hoz kötni

for p in "${PCIS[@]}"; do

 if [[ -e "/sys/bus/pci/devices/$p/driver/unbind" ]]; then

   echo "$p" > "/sys/bus/pci/devices/$p/driver/unbind" || true

 fi

 if [[ -e "/sys/bus/pci/drivers/vfio-pci/bind" ]]; then

   echo "$p" > /sys/bus/pci/drivers/vfio-pci/bind || true

 fi

done


echo "KÉSZ: a GPU-t a VFIO kezeli. VM indulása..."

revert.sh

#!/bin/bash

set -xuo pipefail


# --- ÁLLÍTSD BE A SAJÁT PCI AZONOSÍTÓIDAT ---

PCIS=("0000:01:00.0" "0000:01:00.1")

DM="sddm.service"  # vagy display-manager.service


to_node() { local p="$1"; echo "pci_${p//[:.]/_}"; }


if [[ $EUID -ne 0 ]]; then

 echo "Ezt rootként futtasd (sudo)"; exit 1

fi


# 1) GPU vissza-reattach a hosthoz

for p in "${PCIS[@]}"; do

 node="$(to_node "$p")"

 virsh nodedev-reattach "$node" || true

done


# 2) NVIDIA modulok visszatöltése

modprobe nvidia || true

modprobe nvidia_modeset || true

modprobe nvidia_uvm || true

modprobe nvidia_drm || true


# 3) NVIDIA Persistance folyamat újraindítása (Csak NVIDIA)

systemctl start nvidia-persistenced.service

# 4) VT konzolok rebind

[[ -e /sys/class/vtconsole/vtcon0/bind ]] && echo 1 > /sys/class/vtconsole/vtcon0/bind || true

# ha van vtcon1:

[[ -e /sys/class/vtconsole/vtcon1/bind ]] && echo 1 > /sys/class/vtconsole/vtcon1/bind || true


# 5) X konfiguráció friss infó (nem létfontosságú)

nvidia-xconfig --query-gpu-info > /dev/null 2>&1 || true

# 6) Display manager indítás

systemctl start "$DM" || true

echo "KÉSZ: a GPU visszaadva a hostnak, a kijelző elindult."

Megjegyzés: Saját rendszeredhez igazítsd a scriptet. A fenti lépések iránymutatók, de pl. az eszköz-azonosítók, modulnevek disztró és hardverfüggők lehetnek. Ha AMD kártyát használsz, az Nvidia modulok helyett az amdgpu-t töltsd vissza. Ha nem EFI módban bootolsz, az efifb lépések kihagyhatók stb. Egyszer érdemes végigpróbálni a folyamatot manuálisan (SSH-n bejelentkezve leállítani a display managert, unbindolni a kártyát és betölteni a vfio-t, majd vissza), hogy lásd, minden komponens működik. Ha egyszer sikerül összehangolni, onnantól a folyamat automatizáltan megy minden VM indításnál/leállításnál.

Hibaelhárítás

Még gondos beállítás mellett is előfordulhat, hogy valami nem működik elsőre. Az alábbiakban a leggyakoribb hibák röviden összefoglalva:

Fekete képernyő a virtuális gép indításakor

Ha a monitor „No Signal”-t mutat, valószínűleg a vendég rendszer még a virtuális GPU-t használja, nem a fizikai kártyát. Ellenőrizd, hogy a QXL/SPICE videóeszköz el van-e távolítva a konfigurációból, és csak a dedikált GPU maradt aktív. Ha a start script nem futott le rendesen, a host még foghatja a kártyát – ezt a naplókban ( journalctl -xe; dmesg) láthatod. Tarts fenn SSH-kapcsolatot a hosthoz indítás közben, így könnyen kiderül, hol akad el a folyamat. Ha a virsh start parancs lefagy, valószínűleg a VFIO nem tudta lefoglalni az eszközt. Ilyenkor a /var/log/libvirt/qemu/<vm>.log naplóban érdemes hibát keresni.

Ha a Windowsban Code 43 hibát látsz, rejtsd el a hypervisort a vendég XML-ben a <features> szekcióban a kvm hidden és vendor_id beállításokkal. AMD kártyáknál inkább reset bug okoz fekete képernyőt, amit sokszor csak egy host újraindítás old meg.

A host képe nem tér vissza leállítás után

Ha a VM bezárása után a Linux kijelzője fekete marad, a revert script valószínűleg nem adta vissza a GPU-t. Jelentkezz be SSH-n, és ellenőrizd a display-manager állapotát. Ha nem fut, indítsd újra. Ha fut, de nincs kép, próbáld újratölteni a GPU driver modulokat, például:

$ sudo modprobe -r nvidia_drm nvidia_modeset nvidia_uvm nvidia
sudo modprobe nvidia_drm nvidia_modeset nvidia_uvm nvidia

Ezután ismét indítsd el a grafikus felületet. AMD esetén, ha továbbra sincs kép, valószínűleg reset bugról van szó, amit csak újraindítás old meg.

Hangproblémák a vendégnél

Ha a GPU-val együtt a HDMI-hang eszközt is átadtad, akkor a vendég rendszer hangja közvetlenül a monitoron keresztül szólal meg – feltéve, hogy a kijelző rendelkezik beépített hangszóróval. Ha viszont inkább a host gép saját hangrendszerén szeretnéd hallani a vendég hangját (például fejhallgatón vagy beépített hangszórón), adhatsz a virtuális géphez egy emulált hangkártyát, például Intel HDA eszközt, és beállíthatod, hogy a QEMU a hangot PulseAudio passthrough segítségével továbbítsa a hostra.

Alacsony késleltetésű, játékra is alkalmas megoldásként a Scream (IVSHMEM) használható, amely megosztott memórián keresztül továbbítja a hangot a vendégből a hostra. Ez gyorsabb, kevesebb késleltetéssel, de valamivel összetettebb a konfigurálása.

Mivel a GPU átadásakor a host grafikus felülete leáll, a hangszolgáltatásokat célszerű a háttérben, grafikus session nélkül futtatni. Ehhez engedélyezni kell, hogy a felhasználó szolgáltatásai kijelentkezés után is aktívak maradjanak:

$ loginctl enable-linger felhasznalonev

Így a hangátviteli folyamatok (például PulseAudio vagy Scream) a grafikus felület leállítása után is működni fognak, és a vendég rendszer hangja folyamatosan hallható marad a host kimenetén.

Egyéb tippek és tanácsok

A GPU passthrough teljesítményének további javításához érdemes néhány bevált finomhangolási módszert is bevetni. Nagyobb terhelés esetén célszerű meghatározni, hogy a host és a vendég rendszer mely CPU-magokat használhatja. A Linux kernel isolcpus paraméterével vagy cgroups segítségével kijelölhetők olyan magok, amelyeket a host alig használ, így a vendég rendszer kvázi kizárólagos hozzáférést kap ezekhez. A libvirt XML konfigurációban a vCPU beállításánál pontosan megadható, hogy a vendég mely fizikai magokat használja, amivel csökkenthető a kontextusváltások száma és javítható a stabilitás. HyperThreading vagy SMT esetén érdemes ügyelni arra, hogy a logikailag összetartozó szálakat lehetőleg ugyanannak a rendszernek (hostnak vagy vendégnek) osszuk ki, mert ezek keverése néha teljesítményvesztést okozhat.

A memóriahatékonyság növelésére hasznos eszköz a Huge Pages technológia, amely a RAM-ot nagyobb, 2 MB vagy akár 1 GB méretű lapokban kezeli, csökkentve a lapozótábla méretét és a TLB hibák számát. A Linuxban alapértelmezetten működik a Transparent Huge Pages funkció, de explicit hugepage-allokálással némileg tovább gyorsítható a vendég memóriaelérése. Ezt a libvirt konfigurációban a memoryBacking és hugepages paraméterek hozzáadásával lehet engedélyezni. Fontos azonban, hogy az így lefoglalt memória fixen a vendéghez kötődik, és nem szabadítható fel más folyamatok számára. A teljesítményjavulás a legtöbb esetben mérsékelt, jellemzően néhány százalék, de alacsony késleltetésű környezetekben számottevőbb lehet.

A vendég rendszerben mindig ajánlott a VirtIO meghajtók használata, akár lemez-, akár hálózati eszközökről van szó. Ezek a paravirtualizált meghajtók lényegesen hatékonyabbak, mint az emulált IDE, SATA vagy régebbi hálózati adapterek. Windows vendég esetén mindenképpen telepíteni kell a Red Hat VirtIO drivercsomagot, és a lemezképet VirtIO SCSI vagy VirtIO Block eszközként érdemes hozzárendelni, nem pedig SATA interfészen, mivel ez érzékelhetően javítja az I/O teljesítményt és a válaszidőt.

A Windows vendégben a Hyper-V kompatibilitás, az úgynevezett “enlightenments” opciók bekapcsolása szintén növelheti a hatékonyságot. A libvirt XML-ben található hyperv szekcióban érdemes aktiválni a relaxed, vapic és spinlocks beállításokat, valamint megadni a vendor_id és hidden paramétereket, hogy a Windows jobban optimalizálja a működését a virtualizált környezetben. A korábbi, például Zen2 processzorokon jelentkező kékhalál-problémák modern kernelekben már javítva lettek, de érdemes figyelni a közösségi fórumokat, ha hasonlót tapasztalunk.

A grafikus driver beállításai is hatással lehetnek a stabilitásra. Nvidia kártyák esetében több felhasználó számolt be arról, hogy a Windows „Hardware-accelerated GPU scheduling” opciójának kikapcsolása VFIO alatt megbízhatóbb működést eredményez, valamint javasolt a Power Management módot „Prefer Maximum Performance” értékre állítani, hogy a kártya ne próbáljon túl agresszíven energiatakarékoskodni. AMD GPU-knál figyelni kell, hogy a Radeon szoftver nem jelez-e hibát vagy timeoutot; ha igen, egyes esetekben workaround lehet a Timeout Detection and Recovery kikapcsolása, bár ez haladó beavatkozás, és nem minden esetben ajánlott.

A host rendszer finomhangolása szintén sokat számíthat. Mivel a host és a vendég párhuzamosan fut, a host energiagazdálkodása és ütemezése közvetlenül befolyásolhatja a teljesítményt. Ha alacsony késleltetés a cél, érdemes megfontolni a host CPU mély alvó állapotainak letiltását, például az intel_idle.max_cstate=1 kernelparaméterrel, vagy a cpupower segítségével a performance üzemmódra váltani. A grafikus kompozitor ideiglenes letiltása a GPU váltás előtt is segíthet, különösen integrált GPU esetén, ahol akár a Looking Glass megoldással valós idejű kijelzőátvitel is elérhető.

A frissítések kezelése tudatos odafigyelést igényel. Az új kernel-, QEMU- és libvirt-verziók gyakran hoznak VFIO-val kapcsolatos fejlesztéseket és hibajavításokat, de néha regressziókat is. Érdemes figyelemmel kísérni a changelogokat, valamint a VFIO-közösségi fórumokat, például a Redditen, a Level1Techs-en vagy az Arch Linux közösségében. Ha a rendszer stabilan működik, nem feltétlenül szükséges azonnal minden frissítést telepíteni; a legfontosabb a működő és kiegyensúlyozott konfiguráció megőrzése.

A GPU passthrough hátrányai és korlátai

Nehézkes beállítás és karbantartás

A GPU passthrough, főleg egyetlen videokártyával, korántsem egyszerű technológia. Számos kézi beállítást igényel: BIOS opciók, kernelparaméterek, scriptek, Windows-driverek módosítása. Ezért inkább tapasztalt, kísérletező kedvű felhasználóknak való. A karbantartás is körülményes, mert egy frissítés – új kernel vagy videokártya-driver – könnyen felboríthatja a működést, és újrahangolást igényelhet. A libvirt és a QEMU frissítései is hozhatnak apró változásokat a konfigurációban. Rolling release rendszereknél, mint az Arch vagy a Tumbleweed, ez különösen gyakori. Bár a VFIO-rendszer általában stabil, mindig érdemes figyelni a változásokra.

A hibakeresés sem egyszerű: ha valami nem működik, ritkán van egyértelmű válasz. A passthrough erősen függ a hardvertől és a firmware-től, így előfordulhat, hogy napokig keresed a hibát, mire kiderül, hogy például az alaplap BIOS-a rosszul kezeli az IOMMU-csoportokat, vagy a monitor EDID-adatai okoznak problémát. Ezek ritka, de valós hibák.

Teljesítményveszteség és késleltetés

A passthrough-os rendszerek közel natív teljesítményt adnak, de némi veszteség mindig van. Maga a virtuális gép is igénybe veszi a processzort és a memóriát, a virtualizáció miatt pedig kicsit megnő a késleltetés. A grafikus teljesítmény általában azonos, de néha előfordul, hogy a dinamikus órajelemelés lassabban reagál, vagy a képkocka-idők kismértékben ingadoznak. Ezek a különbségek legtöbbször alig észrevehetők, de a rendszer erőforrás-megosztása miatt előfordulhat, hogy például a host-rendszer háttérműveletei hatással vannak a játékra.

Megfelelő beállításokkal a teljesítmény jellemzően a natív Windows 95–98 százaléka. A legszembetűnőbb eltérés az enyhén megnövekedett bemeneti késleltetés. Ha valaki versenyszerűen játszana, célszerű minden optimalizálást bevetni: processzormagok rögzítése, nagy lapok használata, teljesítménycentrikus üzemmód és más finomhangolások.

Az anti-cheat rendszerek korlátai

Az online játékok védelmi rendszerei a virtualizáció egyik legnagyobb akadályát jelentik. A legtöbb modern többjátékos cím kernel-szintű védelmet használ, például a Riot Vanguard, az Easy Anti-Cheat vagy a BattlEye. Ezek mélyen a rendszerbe épülnek, és automatikusan blokkolják a játék indítását, ha virtuális gépet érzékelnek.

A Valorant például el sem indul GPU passthrough-val futó Windows alatt, mivel a Riot hivatalosan is tiltja a virtualizált környezeteket. A hibaüzenet szerint a játék „nem támogatott virtuális környezetben fut”, és kilép. Hasonlóan járnak el más rendszerek is: az EAC-val védett játékok, mint az Apex Legends, a Fortnite vagy a Rust, felismerik a hypervisort és megszakítják a futást. A BattlEye-védelemmel ellátott játékok, például a Rainbow Six Siege, korábban még működtek VM-ben, de később ezeket is letiltották.

Bizonyos játékok, mint a GTA Online, technikailag ugyan elindulhatnak, de a fejlesztők felhasználási feltételei tiltják a „nem hivatalos környezetben” futtatást, ami akár tiltáshoz is vezethet. Mindez azért van, mert a csalók gyakran használnak virtualizációt a védelem megkerülésére, ezért az anti-cheat fejlesztők inkább teljesen kizárják a VM-eket.

Összességében, ha a célod az online, versenyalapú játék, a GPU passthrough jelenleg nem ajánlott. Ilyen esetekre a dual-boot vagy egy külön fizikai Windows gép a biztosabb megoldás. A passthrough inkább offline vagy egyjátékos játékokhoz, valamint olyan alkalmazásokhoz ideális, mint a videószerkesztés, 3D-modellezés vagy szoftverfejlesztés, ahol nincs ilyen korlátozás.

Teljesítménymérések – mennyire hatékony a virtuális gép?

A mérések célja az volt, hogy megvizsgáljuk, mennyire közelíti meg a Windows 11 virtuális gép a natív rendszer teljesítményét egy single GPU passthrough konfigurációban. Az összehasonlítás három környezetben történt: az EndeavourOS host Linux alatt, natív Windows 11-en, valamint a KVM-alapú Windows 11 virtuális gépben.

A szekvenciális írás és olvasás során a különbségek elhanyagolhatók voltak. A Linux és a natív Windows egyaránt körülbelül 993 MiB/s írási és 3005 MiB/s olvasási sebességet ért el, míg a virtuális gépben a mért értékek gyakorlatilag azonosak voltak, sőt olvasásban kis mértékű előny is mutatkozott. A véletlenszerű 4K írásnál és olvasásnál már nagyobb eltérés látszik: Az olvasási műveleteknél Windows 11 VM itt a natív Windows értékeinek körülbelül 98 százaléka. Az írási műveletek kapcsán azonban jelentősen elmaradt a VM teljesítménye a Natív windowséhoz képest, mely során az írási teljesítmény kevesebb mint felét sikerült elérni. Ez nem mindig van ígz, de alapesetben normális, hiszen a virtualizált I/O réteg mindig jár némi overheaddel jár, még optimalizált VirtIO driverek mellett is.

A CPU-tesztben a különbség meglepően kicsi: míg a natív Windows és a Linux nagyjából 24 ezer műveletet teljesített másodpercenként, a Windows 11 VM a normalizált értékek szerint elérte a 27 ezer ops/s-t tíz szálon, ami gyakorlatilag a natív teljesítmény szintjén van. Ez azt mutatja, hogy a processzormagok közvetlen átadása (host-passthrough) valóban hatékonyan működik, és a hypervisor overhead alig észrevehető.

A játékos méréseknél – a MangoHud és a CapFrameX adatai alapján – a különbség továbbra is minimális. A natív Windows 60 FPS-t hozott átlagosan, míg a virtuális gép 68–72 FPS körül mozgott, a frametime 14 milliszekundum körül alakult, a GPU terhelés pedig 30 százalék körül maradt. Ez valós körülmények között szinte megkülönböztethetetlen teljesítményt jelent, különösen, ha figyelembe vesszük, hogy a rendszer közben Linux alatt fut, és a GPU-t a VFIO rétegen keresztül használja.

Összességében a mérések alapján kijelenthető, hogy egy jól beállított single GPU passthrough konfigurációban a Windows 11 virtuális gép teljesítménye gyakorlatilag megegyezik a natív futtatással. A CPU és I/O terhelésnél a különbség 5–10 százalékos tartományban marad (kivéve az írási teljesítményben), játékok esetében pedig a különbség a gyakorlatban alig érzékelhető. Ez a technológia tehát nemcsak kísérleti szinten működik, hanem valóban alkalmas mindennapi használatra – akár fejlesztésre, akár játékra.

Konkluzió, avagy kinek ajánljuk?

Ez a megoldás leginkább azoknak szól, akik szeretnék egyetlen gépen kihasználni a Linux stabilitását és a Windows hardveres előnyeit. Ideális fejlesztőknek, haladó felhasználóknak és technológiáért lelkesedőknek, akik főként Linuxon dolgoznak, de időnként szükségük van Windowsra olyan feladatokhoz, amelyekhez natív grafikus gyorsítás vagy speciális szoftverek kellenek. Ilyen lehet például a grafikai munka, videóvágás, 3D modellezés, zeneszerkesztés, illetve olyan alkalmazások futtatása, amelyek kizárólag Windows alatt érhetők el – például az Adobe csomag, CAD programok vagy például a 3D modellező szoftverek.

Gamerek számára is jó lehetőség, hiszen lehetővé teszi, hogy Linuxról váltva Windows alatt játsszanak a teljesítmény szinte natív szintű megtartásával. Ugyanakkor az online és kompetitív játékok anti-cheat rendszerei miatt előfordulhatnak korlátozások, így ez a módszer inkább az egyjátékos vagy offline játékokhoz ajánlott.

Nem javasolt azoknak, akik egyszerű, garantált működésű megoldást keresnek minden helyzetre. Ha valaki csak játszani szeretne, vagy nem akar időt szánni a rendszer finomhangolására és esetenkénti hibakeresésre, számára a dual-boot vagy egy külön Windows-gép továbbra is megbízhatóbb választás.

Elakadtál a megvalósításban? Keresd fel a Discord csoportunk Community Techsupport szobáját további segítségnyújtásért. Csatlakozz most!

Gábor a Pingvinbázis alapítója és főszerkesztője, több mint 20 éves tapasztalattal rendelkezik a Linux rendszerek és az Open Source szoftverek területén. Jártas a Python, és a PHP nyelvben, valamint a BASH scriptelésben is.