Proxmox Intel iGPU passthrough
2024-08-31T00:00:00Z | 5 minutes de lecture | Mise à jour le 2024-08-31T00:00:00Z
Tuto afin d’utiliser un GPU intégré au CPU dans une machine virtuelle Linux d’une machine Proxmox
Contexte
Mon MSI GS30-2M-Shadow que j’avais démonté afin de m’en servir comme serveur maison à rendu l’âme récemment (la batterie a gonflé et a dû endommager la carte mère…).
J’ai alors acheté un NAB6
sur lequel j’ai installé Proxmox au lieu d’un Ubuntu en baremetal.
Du coup, je n’ai plus accès au décodage matériel du CPU sur mon hôte
(machine virtuelle Ubuntu) me servant pour mon serveur Jellyfin.
J’ai alors entrepris de transmettre le iGPU “UHD Graphics” à ma VM pour pouvoir effectuer les tâches de traitement vidéos.
Proxmox
Configuration du Serveur
Sur la machine physique, il faut faire en sorte que cette dernière ne prend
plus en charge notre iGPU.
Pour cela, on va modifier les données du noyau de démarrage afin d’exclure notre matériel.
Afin de s’assurer de la faisabilité de la chose, on vérifie qu’on a bien un contrôleur graphique détecté :
lspci -nnv | grep VGA
00:02.0 VGA compatible controller [0300]: Intel Corporation Alder Lake-P GT1 [UHD Graphics] [8086:46a3] (rev 0c) (prog-if 00 [VGA controller])
[!NOTE] Il existe différentes méthodes pour arriver au même résultat.
J’utilise ici la méthode qui effectue le moins de modification sur le système.
On peut alors modifier le fichier /etc/default/grub
en remplaçant la ligne
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
par :
GRUB_CMDLINE_LINUX_DEFAULT="quiet 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=radeon,nouveau,nvidia,nvidiafb,nvidia-gpu,snd_hda_intel,snd_hda_codec_hdmi,i915"
On met à jour le noyau de démarrage afin que cette modification soit prise en compte :
update-grub
Ensuite, on va activer des modules nécessaires au PCI Passthrough en ajoutant
les modules suivants au fichier /etc/modules
:
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
Et on fait en sorte que cela soit pris en compte :
update-initramfs -u -k all
[!TIP] Au sein d’un rôle passthrough qui s’applique sur mon serveur Proxmox :
tasks/main.yml
:- name: Allow passthrough and Blacklists known graphics drivers # to prevent proxmox from utilizing the iGPU ansible.builtin.lineinfile: path: /etc/default/grub regexp: '^GRUB_CMDLINE_LINUX_DEFAULT=' # Use C1 instead of C1E c-state, turn off hyperthreading, disable all optional CPU mitigations, turn on intel IOMMU, pass thru gpu line: 'GRUB_CMDLINE_LINUX_DEFAULT="quiet 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=radeon,nouveau,nvidia,nvidiafb,nvidia-gpu,snd_hda_intel,snd_hda_codec_hdmi,i915"' mode: '644' state: present create: false notify: - Update grub - name: Add vfio modules to allow PCI passthrough ansible.builtin.blockinfile: path: /etc/modules block: | vfio vfio_pci vfio_virqfd vfio_iommu_type1 notify: - Update initramfs
handlers/main.yml
:- name: Update grub ansible.builtin.command: update-grub - name: Update initramfs ansible.builtin.command: update-initramfs -u -k all
Ainsi, on redémarre la machine (que j’ai fait via la WebUI de Proxmox).
On vérifie que le passthrough est bien actif :
dmesg | grep -e DMAR -e IOMMU
Dans les résultats de la commande, vous devriez avoir la ligne suivante :
[ 0.060254] DMAR: IOMMU enabled
Configuration de l’hôte
Votre VM doit être de type q35
. Si ce n’est pas le cas, effectué le
changement et vérifier que votre VM démarre bien de cette manière.
[!IMPORTANT] J’étais aussi dans le cas ou ma VM était de type
Default (i440fx)
.En modifiant son type, j’ai perdu le réseau dessus.
Pour une raison que j’ignore, le nom de mon interface réseau a été modifié par ce changement. J’ai donc édité ma configuration Netplan via le VNC de Proxmox.
On ajoute donc un périphérique PCI (dans le menu “Hardware”, “Add”, “PCI Device”) en sélectionnant notre périphérique graphique :
Et on lui attribue les paramètres suivants :
Ce blog impliquant souvent des drames, cet article n’en fait pas exeption.
En démarrant ma VM avec ces paramètres, la VM ne voulait plus démarrer…
J’ai trouvé la solution en mettant le paramètre Display à none (none)
.
Cela implique que le VNC de Proxmox n’est plus utilisable mais cela ne me pose
pas de problème car j’utilise ma VM via SSH.
Hôte Proxmox (VM)
Vérification
Sur ma VM (Ubuntu 24.04), je vois bien mon périphérique :
lspci -nnv | grep VGA
01:00.0 VGA compatible controller [0300]: Intel Corporation Alder Lake-P GT1 [UHD Graphics] [8086:46a3] (rev 0c) (prog-if 00 [VGA controller])
Pour vérifier que le décodage hardware est possible, on vérifie la présence du
driver renderD128
:
cd /dev/dri
ls -la
Utilisation sur Jellyfin (Docker)
Mon service Jellyfin étant sur Docker, je dois effectuer des modifications afin que le conteneur ait accès au matériel.
Sur mon hôte Docker (donc ma VM Proxmox Ubuntu), j’ai besoin de connaitre
l’ID du groupe render
.
getent group render | cut -d ':' -f3
Dans mon cas, render
est dans le groupe d’ID 993
.
Cela va me permettre de faire en sorte que l’utilisateur du conteneur puisse utiliser le périphérique.
J’édite alors mon Docker Compose pour Jellyfin :
|
|
Une fois le conteneur recréé, je vais sur le tableau de bord de Jellyfin et active le transcodage selon les paramètres suivants :
Pour le choix des cases à cocher, j’ai trouvé des recommandations sur Internet
mais je ne suis pas sûr que cela soit les bons réglages.
Ne prenez donc pas cela comme étant la seule et bonne méthode.
Pour tester cela, j’ai alors lancé un film qui faisait que mon CPU était très sollicité. Et ce n’est plus le cas ! Donc ma configuration a bien fonctionné.
Mot de la fin
On a donc vu ici comment j’ai fait pour “envoyé un périphérique PCI” sur une VM.
Bien qu’ici, on le fait pour un iGPU, le principe peut-être repris pour autre chose.