Les groupes IOMMU sont un piège : comment obtenir un passthrough GPU/NVMe propre sans douleur

Cet article vous a aidé ?

Vous n’avez pas acheté un GPU pour le voir rester derrière un hyperviseur à ne rien faire. Vous n’avez pas acheté un disque NVMe pour le faire passer via un contrôleur émulé comme si c’était 2009. Vous vouliez des performances quasi-natives dans une VM, et à la place vous vous heurtez à un mur étiqueté IOMMU group 12.

Le piège, c’est que les groupes IOMMU donnent l’impression d’un simple problème de case à cocher—jusqu’à ce qu’ils deviennent un problème de topologie, de firmware et de spécificités de plateforme. La bonne nouvelle : il existe un chemin propre, et il consiste surtout à refuser de deviner.

Ce que sont vraiment les groupes IOMMU (et pourquoi ils font mal)

Un groupe IOMMU est la manière dont le noyau dit : « ces périphériques PCIe ne peuvent pas être isolés les uns des autres en toute sécurité, donc ils sont traités comme un même domaine de sécurité. » Si vous passez un périphérique du groupe à une VM, vous faites implicitement confiance à tout le reste du groupe pour ne pas effectuer de DMA intempestifs vers l’hôte ou la VM.

La partie « ne peut pas être isolé » est la clef. La frontière du groupe n’est pas définie par vos impressions, l’étiquette du slot sur la carte mère, ni le prix du GPU. Elle est définie par la topologie PCIe et le comportement d’Access Control Services (ACS) des switches/bridges entre le périphérique et le port racine CPU. Si ACS n’offre pas une isolation correcte (ou n’est pas annoncée), le noyau ne fera pas semblant.

La conséquence pratique

Un passthrough propre signifie que le périphérique visé—GPU ou NVMe—se retrouve dans un groupe IOMMU sans rien d’autre d’important pour vous. Idéalement : le GPU et sa fonction audio ensemble, éventuellement un contrôleur USB si vous l’avez délibérément placé là, et c’est tout. Quand votre GPU partage un groupe avec votre contrôleur SATA, une carte réseau et la moitié du chipset, vous ne faites pas du « GPU passthrough ». Vous faites du « hope-as-a-service ».

Deux mauvais modèles mentaux qui causent la plupart des problèmes

  • « Les groupes IOMMU sont déterminés par l’OS. » L’OS rapporte ce que le matériel et le firmware exposent. Vous ne pouvez pas reconfigurer un switch en aval qui n’annonce pas ACS.
  • « S’il démarre, c’est sûr. » La sécurité ici, c’est l’isolation DMA et le remapping des interruptions sous charge, réinitialisations à chaud et récupération d’erreurs. Démarrer prouve presque rien.

Le tranchant : le patch ACS override

Sur de nombreuses plateformes grand public, des gens « corrigent » des groupements IOMMU disgracieux en forçant le comportement ACS via le paramètre noyau pcie_acs_override. Ça peut scinder les groupes d’une manière qui paraît parfaite.

Mais c’est un mensonge que vous racontez au noyau. Ça peut être un mensonge utile dans un homelab. En production ou en environnement multi-tenant, c’est une concession de sécurité. Vous demandez au noyau d’assumer une isolation que le fabric peut ne pas réellement appliquer.

N’utilisez ACS override que si vous acceptez le risque : hôte mono-utilisateur, invités de confiance, pas d’hébergement partagé et vous comprenez l’impact potentiel. Sinon : changez la plateforme, changez le slot ou changez de plan.

Blague n°1 : ACS override, c’est comme mettre un panneau « Interdit d’entrer » sur une porte sans serrure. Ça améliore l’ambiance, pas la sécurité.

Faits intéressants et contexte historique

  • VT-d et AMD-Vi n’ont pas été conçus pour les joueurs. VT-d d’Intel et IOMMU d’AMD (AMD-Vi) viennent d’un besoin de virtualiser l’E/S en toute sécurité dans les serveurs et environnements multi-tenant.
  • Le DMA était à l’origine le « trust me bro ».  Les périphériques PCI classiques pouvaient faire du DMA vers la mémoire hôte sans beaucoup de contraintes ; l’IOMMU existe principalement pour empêcher un périphérique d’écrire partout.
  • ACS est une fonctionnalité du fabric PCIe, pas une fonctionnalité Linux. Linux ne peut grouper qu’en fonction de ce que la hiérarchie PCIe rapporte comme isolable.
  • Le remapping des interruptions fait aussi partie de l’histoire de la sécurité. Même avec l’isolation DMA, un routage/remapping d’interruptions cassé peut devenir un problème de stabilité et de sécurité sous charge.
  • Les GPU sont devenus des périphériques « bizarres » en passthrough à cause du comportement de reset. Beaucoup de GPU n’ont pas été conçus pour un reset propre par fonction (FLR) depuis un invité ; certains nécessitent des resets de bus, d’autres ne se réinitialisent pas correctement du tout.
  • Le NVMe est généralement plus simple que les GPU… jusqu’à ce que ce ne soit pas le cas. Les contrôleurs NVMe se comportent souvent bien avec FLR et la gestion des namespaces, mais la gestion d’alimentation et les bizarreries ASPM peuvent encore poser problème.
  • SR-IOV a normalisé l’idée de partager des périphériques en toute sécurité. Les fournisseurs réseau et stockage ont fortement poussé SR-IOV ; la virtualisation GPU (vGPU) a suivi une voie différente, souvent verrouillée par les vendeurs.
  • Les cartes grand public ont été optimisées pour le coût, pas pour l’isolation. Beaucoup de chipsets desktop placent plusieurs fonctions derrière des bridges ou switches partagés qui n’exposent pas ACS comme les plateformes serveurs.

Une idée paraphrasée à garder sur votre mur : paraphrased idea « L’espoir n’est pas une stratégie » — attribuée à de nombreux opérateurs au fil des ans, et la version SRE est « mesurez, puis changez. »

Concevoir un passthrough propre : choisissez les batailles gagnables

1) Commencez par la topologie, pas par des flags noyau

Avant de toucher GRUB, découvrez ce que vous avez réellement acheté : quels slots sont des ports racine CPU, lesquels sont des lanes chipset, lesquels partagent un switch en aval et lesquels partagent un bridge avec « tout le reste ». Les schémas marketing omettent des vérités. Vous devez voir l’arbre PCIe.

2) Privilégiez les lanes attachées au CPU pour les périphériques de passthrough

Les GPU et les NVMe hautes performances se comportent mieux lorsqu’ils sont sur des ports racine CPU. Les périphériques attachés au chipset partagent souvent bande passante et frontières d’isolation, et ont plus de chances de finir dans d’énormes groupes IOMMU avec d’autres contrôleurs.

3) Ne faites pas passer le périphérique depuis lequel vous démarrez

Oui, vous pouvez le faire. Oui, vous pouvez y parvenir. Et oui, c’est un générateur d’incidents lorsque des mises à jour de firmware, des changements d’initramfs ou des changements d’énumération apparaissent. Gardez le boot de l’hôte sur quelque chose de banal : un petit SSD SATA, une paire en miroir ou un M.2 dédié que vous ne donnez jamais aux invités.

4) GPU : prévoyez les resets et la propriété de l’affichage

Les échecs de passthrough GPU ne sont souvent pas des « problèmes IOMMU ». Ce sont des problèmes de reset, de ROM ou de propriété du pilote.

  • Reset : Si le GPU ne peut pas se réinitialiser proprement entre arrêts/démarrages de VM, vous aurez le redoutable « ça marche une fois après le boot ».
  • ROM : Certaines configurations nécessitent un fichier ROM GPU ; d’autres cassent si vous en imposez un.
  • Propriété par l’hôte : Si l’hôte charge un pilote et saisit la framebuffer du GPU tôt, le détacher plus tard peut être délicat.

5) NVMe : choisissez entre passthrough et stockage virtualisé selon le domaine de défaillance

Le passthrough NVMe est excellent pour des charges sensibles à la latence, des VM de jeu ou des appliances mono-locataire. Mais cela change qui peut récupérer des erreurs.

Si le contrôleur NVMe se bloque et que l’invité en est propriétaire, l’hôte ne peut pas forcément le récupérer sans démonter la VM. Si vous avez besoin de HA côté hôte, de snapshots, de réplication ou d’une récupération prévisible, un disque virtuel sur une couche de stockage hôte bien pensée gagne souvent—même si c’est un peu plus lent.

6) La seule posture de sécurité sensée : traiter les invités en passthrough comme de confiance

VFIO + IOMMU assure une forte isolation quand la plateforme le supporte correctement, mais le passthrough donne à l’invité plus de contrôle sur du matériel réel. Si votre invité n’est pas de confiance, reconsidérez. Si votre plateforme nécessite ACS override, ne prétendez pas construire un système multi-tenant durci.

Tâches pratiques : commandes, sorties, décisions

Vous diagnostiquerez cela le plus rapidement en le traitant comme n’importe quel autre problème ops : observez, changez une chose, observez à nouveau. Ci‑dessous des tâches concrètes à exécuter sur un hôte Linux KVM (y compris les environnements type Proxmox) avec des notes sur l’interprétation des sorties et la décision à prendre.

Task 1: Verify IOMMU is enabled (kernel boot and dmesg)

cr0x@server:~$ dmesg | egrep -i 'iommu|dmar|amd-vi' | head -n 30
[    0.000000] ACPI: DMAR 0x0000000079B2B000 0000A8 (v01 INTEL  SKL      00000001 INTL 00000001)
[    0.000000] DMAR: IOMMU enabled
[    0.000000] DMAR: Host address width 39
[    0.000000] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
[    0.000000] DMAR: Queued invalidation will be enabled to support x2apic and Intr-remapping.
[    0.000000] DMAR: Enabled IRQ remapping in x2apic mode

Sens : Vous voulez voir « IOMMU enabled » (Intel : DMAR) ou « AMD-Vi: Enabled. » Des points bonus pour « IRQ remapping enabled. »

Décision : Si vous ne voyez pas IOMMU activé, corrigez les réglages firmware (VT-d/AMD-Vi) et les paramètres noyau avant tout.

Task 2: Confirm kernel command line (catch wrong flags)

cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12 root=ZFS=rpool/ROOT/default ro quiet intel_iommu=on iommu=pt

Sens : intel_iommu=on ou amd_iommu=on active l’IOMMU ; iommu=pt améliore souvent les performances de l’hôte en utilisant des mappings passthrough pour les périphériques non-VFIO.

Décision : Gardez iommu=pt pour les performances sauf si vous déboguez quelque chose d’exotique ; c’est généralement correct.

Task 3: List IOMMU groups and spot the “monster group”

cr0x@server:~$ for g in /sys/kernel/iommu_groups/*; do echo "IOMMU Group $(basename "$g")"; for d in "$g"/devices/*; do echo -n "  "; lspci -nns "$(basename "$d")"; done; done | sed -n '1,80p'
IOMMU Group 0
  00:00.0 Host bridge [0600]: Intel Corporation Device [8086:1237]
IOMMU Group 1
  00:01.0 PCI bridge [0604]: Intel Corporation Device [8086:460d]
IOMMU Group 12
  01:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2684] (rev a1)
  01:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:22bc] (rev a1)
IOMMU Group 13
  02:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]

Sens : C’est la vérité. Votre GPU a généralement deux fonctions (graphique + audio) et devrait être dans le même groupe. Un contrôleur NVMe idéalement est seul ou avec des voisins inoffensifs que vous n’utilisez pas.

Décision : Si votre périphérique cible partage un groupe avec des périphériques critiques de l’hôte (contrôleur SATA, NIC nécessaire, contrôleur USB utilisé pour l’entrée hôte), arrêtez-vous et re‑concevez : slot différent, carte mère différente ou acceptez le risque ACS override.

Task 4: See the PCIe tree (find the bridge causing group merging)

cr0x@server:~$ lspci -tv
-+-[0000:00]-+-00.0  Intel Corporation Device 1237
 |           +-01.0-[01]----00.0  NVIDIA Corporation Device 2684
 |           |            \-00.1  NVIDIA Corporation Device 22bc
 |           +-03.0-[02]----00.0  Samsung Electronics Co Ltd NVMe SSD Controller a808
 |           \-14.0  Intel Corporation Device 7ae0

Sens : Vous cherchez où votre périphérique est connecté : ports racine CPU vs bridges chipset. L’arbre vous aide à corréler un « mauvais grouping » avec un bridge en amont particulier.

Décision : Si le GPU/NVMe est derrière un switch/bridge partagé en aval, essayez un autre slot physique qui mappe à un port racine différent.

Task 5: Identify your GPU/NVMe device IDs for vfio-pci binding

cr0x@server:~$ lspci -nn | egrep -i 'vga|audio|nvme'
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation Device [10de:2684] (rev a1)
01:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:22bc] (rev a1)
02:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]

Sens : Les paires entre crochets sont vendor:device IDs. Vous liez ces IDs à vfio-pci pour empêcher les pilotes hôtes de les utiliser.

Décision : Capturez toutes les fonctions que vous prévoyez de passer (GPU + audio ; parfois un GPU a aussi un contrôleur USB‑C).

Task 6: Check which driver currently owns the device

cr0x@server:~$ lspci -k -s 01:00.0
01:00.0 VGA compatible controller: NVIDIA Corporation Device 2684 (rev a1)
	Subsystem: Gigabyte Technology Co., Ltd Device 4101
	Kernel driver in use: nvidia
	Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia

Sens : Si l’hôte utilise nvidia ou nouveau, le passthrough sera plus difficile. Pour un VFIO propre, vous voulez Kernel driver in use: vfio-pci.

Décision : Si un pilote non‑VFIO est lié, vous devez binder tôt via initramfs/config modprobe ou blacklister le pilote.

Task 7: Bind devices to vfio-pci (modprobe config) and rebuild initramfs

cr0x@server:~$ sudo tee /etc/modprobe.d/vfio.conf >/dev/null <<'EOF'
options vfio-pci ids=10de:2684,10de:22bc,144d:a808 disable_vga=1
EOF
cr0x@server:~$ sudo tee /etc/modprobe.d/blacklist-gpu.conf >/dev/null <<'EOF'
blacklist nouveau
blacklist nvidia
blacklist nvidiafb
EOF
cr0x@server:~$ sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-6.8.12

Sens : Cela force vfio-pci à réclamer ces IDs de périphérique au démarrage, avant les autres pilotes.

Décision : Redémarrez après ce changement. Si vous ne pouvez pas redémarrer, n’effectuez pas de « rebind live » à moins d’aimer déboguer un hôte sans interface depuis le sol.

Task 8: After reboot, confirm vfio-pci owns the devices

cr0x@server:~$ lspci -k -s 01:00.0
01:00.0 VGA compatible controller: NVIDIA Corporation Device 2684 (rev a1)
	Subsystem: Gigabyte Technology Co., Ltd Device 4101
	Kernel driver in use: vfio-pci
	Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia

Sens : Des modules peuvent exister, mais « driver in use » doit être vfio-pci.

Décision : Si ça se lie toujours à un pilote GPU, votre initramfs n’a pas inclus les réglages vfio assez tôt, ou la pile GPU de la distribution force son usage. Corrigez cela avant de toucher QEMU.

Task 9: Check VFIO and IOMMU faults in the kernel log

cr0x@server:~$ sudo dmesg -T | egrep -i 'vfio|iommu|dmar|fault' | tail -n 30
[Tue Feb  4 10:10:02 2026] vfio-pci 0000:01:00.0: enabling device (0000 -> 0003)
[Tue Feb  4 10:10:02 2026] vfio-pci 0000:02:00.0: enabling device (0000 -> 0002)
[Tue Feb  4 10:12:17 2026] DMAR: [DMA Read] Request device [02:00.0] fault addr 0x7f1c9000 [fault reason 0x02] Present bit in context entry is clear

Sens : VFIO « enabling device » est normal. Les fautes DMAR/IOMMU ne le sont pas. « Present bit in context entry is clear » indique souvent un problème de mapping ou un périphérique défaillant.

Décision : Si vous voyez des fautes IOMMU récurrentes sous charge, suspectez un firmware bogué, un remapping d’interruption cassé ou un périphérique incompatible avec la plateforme. Ne colmatez pas ça à la va‑vite.

Task 10: Validate interrupt remapping (stability and security)

cr0x@server:~$ dmesg | egrep -i 'interrupt remapping|irq remapping|x2apic' | head
[    0.000000] DMAR: Queued invalidation will be enabled to support x2apic and Intr-remapping.
[    0.000000] DMAR: Enabled IRQ remapping in x2apic mode

Sens : Vous voulez le remapping IRQ activé, surtout si vous tenez à la robustesse et à l’isolation.

Décision : S’il est désactivé, vérifiez les réglages du BIOS (souvent liés à « Above 4G decoding », « SR-IOV » ou « Intel VT-d ») et les paramètres du noyau. Sur certaines plateformes, activer x2APIC aide.

Task 11: Check for ACS override usage (know when you’re lying to yourself)

cr0x@server:~$ cat /proc/cmdline | tr ' ' '\n' | egrep 'pcie_acs_override|acs'
pcie_acs_override=downstream,multifunction

Sens : C’est le « group splitter ». Il peut rendre les groupes propres sans que le matériel n’assure réellement l’isolation.

Décision : Si c’est présent sur un hôte avec invités non fiables ou exigences de conformité, retirez‑le et corrigez le matériel/la topologie à la place.

Task 12: Check PCIe link speed/width (performance bottleneck hiding in plain sight)

cr0x@server:~$ sudo lspci -s 02:00.0 -vv | egrep -i 'LnkCap|LnkSta'
LnkCap: Port #0, Speed 16GT/s, Width x4, ASPM L1, Exit Latency L1 <8us
LnkSta: Speed 8GT/s (downgraded), Width x2 (downgraded)

Sens : Votre NVMe est capable de PCIe Gen4 x4, mais fonctionne en Gen3 x2. Ce n’est pas un problème de virtualisation. C’est un problème de slot, BIOS, riser ou intégrité du signal.

Décision : Corrigez l’entraînement du lien avant de benchmarker quoi que ce soit. Changez de slot, retirez les risers, mettez à jour le BIOS ou forcez la génération PCIe dans le firmware si possible.

Task 13: Check IOMMU group membership of a single device (surgical view)

cr0x@server:~$ dev=0000:02:00.0; readlink -f /sys/bus/pci/devices/$dev/iommu_group
/sys/kernel/iommu_groups/13

Sens : Cela vous dit exactement à quel groupe le périphérique appartient, utile pour les scripts et le suivi des changements.

Décision : Si cela change après des mises à jour BIOS ou des déplacements de slot, mettez à jour vos docs de provisioning et les configs VM. N’assumez pas la stabilité.

Task 14: Attach via QEMU/Libvirt and verify guest sees the real device

cr0x@server:~$ sudo virsh domblklist win11-gpu
 Target   Source
------------------------------------------------
 vda      /var/lib/libvirt/images/win11.qcow2

cr0x@server:~$ sudo virsh dumpxml win11-gpu | egrep -n 'hostdev|address|vfio' | head -n 40
132:    
133:      
134:        
135:

Sens : La définition VM inclut une assignation de périphérique hôte PCI. C’est votre passthrough.

Décision : Si l’invité voit un contrôleur de stockage générique au lieu du modèle NVMe, vous n’avez pas réellement passé le contrôleur — vous avez passé un disque virtuel.

Task 15: Measure latency and I/O inside the guest vs host (find virtualization overhead)

cr0x@server:~$ sudo fio --name=randread --filename=/dev/nvme0n1 --ioengine=io_uring --direct=1 --bs=4k --iodepth=32 --numjobs=1 --runtime=15 --time_based --rw=randread
randread: (groupid=0, jobs=1): err= 0: pid=24111: Tue Feb  4 10:21:12 2026
  read: IOPS=182k, BW=712MiB/s (747MB/s)(10.4GiB/15001msec)
    slat (nsec): min=820, max=12514, avg=1790.12, stdev=402.21
    clat (usec): min=49, max=412, avg=173.40, stdev=21.11

Sens : C’est la référence côté hôte. Comparez des runs similaires dans l’invité sur le NVMe passé. Les écarts importants suggèrent de la modulation d’interruption, des problèmes de gestion de l’alimentation ou d’affectation CPU—pas seulement VFIO.

Décision : Si la latence invité est beaucoup plus mauvaise que l’hôte, vérifiez la topologie CPU, les C‑states et si la VM utilise correctement MSI/MSI‑X.

Task 16: Check if your NVMe supports reset sanely (avoid “works once”)

cr0x@server:~$ sudo nvme id-ctrl /dev/nvme0 | egrep -i 'frmw|oacs|oncs|vwc|lpa' | head
oacs    : 0x17
oncs    : 0x5f
vwc     : 0x1
lpa     : 0x3

Sens : Les capacités varient ; vous vérifiez principalement que le contrôleur n’est pas une curiosité bon marché qui se comporte étrangement lors des resets/événements d’alimentation.

Décision : Si la stabilité de passthrough est mauvaise, passez à un contrôleur plutôt orienté entreprise ou au moins un modèle reconnu pour se comporter en virtualisation.

Méthode de diagnostic rapide

Voici la routine « j’ai 20 minutes et un VP qui plane au-dessus ». L’objectif est d’identifier si votre goulot est l’isolation, la propriété, le reset ou la simple bande passante PCIe.

Première étape : topologie et isolation (ne déboguez pas des fantômes)

  1. Vérifiez les groupes IOMMU et confirmez que le périphérique ciblé n’est pas collé à des périphériques critiques de l’hôte.
  2. Vérifiez l’arbre PCIe pour voir sur quel bridge/port racine le périphérique pend.
  3. Vérifiez ACS override et décidez si vous acceptez le profil de risque.

Deuxième étape : propriété du pilote et binding (la partie ennuyeuse qui casse tout)

  1. Confirmez que vfio-pci est utilisé pour chaque fonction que vous passez.
  2. Parcourez dmesg à la recherche d’erreurs VFIO, de fautes DMAR et du statut de remapping d’interruptions.
  3. Vérifiez la config VM inclut réellement des hostdev, et que vous ne benchmarkez pas un disque virtuel par erreur.

Troisième étape : performance et stabilité (là où « ça marche » devient « utilisable »)

  1. Vérifiez la largeur/vitesse du lien pour des rétrogradations (un périphérique Gen4 fonctionnant en Gen3 x1 est classique).
  2. Lancez un court test fio sur l’hôte et l’invité pour comparer latence et IOPS.
  3. Cherchez des symptômes liés au reset « ça marche une fois » après un stop/start de VM.

Si vous faites cela dans l’ordre, vous évitez la perte de temps la plus courante : tweaker les flags QEMU pour un problème qui est en réalité une décision de routage de la carte mère.

Trois mini-récits d’entreprise du terrain

Mini-récit 1 : L’incident causé par une mauvaise hypothèse

Une société de taille moyenne a construit un « pool GPU » interne pour des charges CI : compilation, tests et quelques exécutions CUDA. Ils ont acheté des stations grand public, mis quelques GPU dans chacune et exécuté KVM avec VFIO. Au début, tout semblait propre. Un GPU par VM. Tout le monde content.

Puis une mise à jour du noyau est passée et le groupement IOMMU a changé subtilement sur un sous‑ensemble d’hôtes. Même modèle de carte mère, révisions de firmware différentes. Sur ces hôtes, un GPU s’est retrouvé groupé avec un contrôleur USB qui hébergeait aussi la clé KVM hors‑bande utilisée par la maintenance distante. Personne ne l’a remarqué car la VM démarrât toujours.

Lors d’un recyclage de VM, VFIO a pris tout le groupe IOMMU. L’hôte n’a pas planté, mais il a perdu l’accès d’entrée à distance. Ce n’aurait pas été fatal—sauf que ces « stations » étaient dans une salle fermée sans vrai BMC, et le seul chemin d’accès à distance passait par ce contrôleur USB. Deux personnes ont passé une soirée à coordonner un redémarrage physique à travers des fuseaux horaires.

La mauvaise hypothèse n’était pas « IOMMU existe ». C’était « les groupes IOMMU sont stables et identiques sur un hardware identique. » Ils ne le sont pas. Le firmware, le câblage du slot et même de mineures modifications d’énumération PCIe peuvent déplacer le fromage.

La correction a été douloureusement ordinaire : standardiser les versions BIOS, verrouiller les SKU hardware et ajouter une validation pré‑déploiement qui vérifie l’appartenance au groupe avant de provisionner une VM GPU. Ils ont aussi arrêté d’attacher leur unique chemin de management distant à un contrôleur qui pouvait être arraché à l’hôte.

Mini-récit 2 : L’optimisation qui a mal tourné

Une autre organisation voulait du stockage très basse latence dans une VM Windows qui hébergeait un outil de traitement de données au modèle de licence capricieux. Ils ont passé un NVMe directement à la VM. Les performances étaient spectaculaires. Les benchmarks faisaient envie.

Puis la réalité est arrivée : la VM plantait parfois sous des rafales d’écriture, et quand elle plantait, le contrôleur NVMe restait parfois bloqué. L’hôte voyait un périphérique présent mais qui n’achevait plus les commandes. Un redémarrage chaud ne le remettait pas forcément en état. Parfois, il fallait un cycle d’alimentation complet du châssis.

Ils avaient optimisé pour le mauvais indicateur. Ils ont optimisé la performance en régime permanent, pas le comportement de récupération. La partie « mal tournée » n’était pas que le passthrough soit mauvais ; c’était que le domaine de défaillance avait migré dans l’OS invité et sa pile de pilotes, et le hardware ne se réinitialisait pas de manière fiable sur leur plateforme.

La solution finale a été de cesser de prétendre avoir besoin du NVMe brut pour cette charge. Ils ont migré la VM sur un disque virtuel géré par la couche de stockage hôte avec cache d’écriture configuré de manière sensée et snapshots périodiques. Ils ont gardé un seul NVMe de passthrough dédié pour un petit sous‑ensemble de tâches qui en avaient vraiment besoin, avec des contrôleurs connus et un parcours de reset testé.

Ils ont perdu un peu de gloire au benchmark et gagné un système réparable sans qu’un technicien doive aller au datacenter appuyer sur le bouton d’alimentation.

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une équipe de services financiers exécutait quelques VM poste de travail hautement critiques pour l’ingénierie et la visualisation. Ils avaient une gestion du changement stricte, impopulaire jusqu’à ce que ce soit la seule chose entre vous et le chaos. Leur runbook exigeait de capturer la topologie PCIe et les listings de groupes IOMMU comme artefacts chaque fois que le firmware changeait.

Un trimestre, une mise à jour fournisseur « a amélioré la compatibilité PCIe ». En staging, rien n’a cassé. Mais leur diff d’artefacts montrait que le groupe d’un GPU incluait maintenant un nouveau voisin : une fonction bridge PCIe auparavant cachée. Ça ne posait pas de problème en bare metal, mais ça posait problème pour VFIO car le bridge amenait d’autres périphériques.

Parce qu’ils ont remarqué avant le déploiement, ils ont stoppé. Ils ont testé des slots alternatifs, trouvé un slot qui gardait le GPU isolé, et mis à jour leur standard physique de montage : « Le GPU doit être en slot X ; le passthrough NVMe doit être sur le port M.2 CPU Y. »

Quand le déploiement en production est arrivé, c’était ennuyeux. Aucune surprise. L’équipe a eu presque l’air déçue.

Blague n°2 : La gestion du changement, c’est comme passer la soie dentaire—personne n’a envie de le faire, et les conséquences de sauter l’étape sont coûteuses et étranges.

Erreurs fréquentes : symptômes → cause racine → correction

1) La VM ne démarre pas : « Device is in use » / « cannot reset »

Symptômes : Erreurs QEMU concernant le reset du périphérique, ou « device is in use ». La VM démarre seulement une fois par boot.

Cause racine : Le pilote hôte a saisi le périphérique en premier, ou le périphérique ne supporte pas proprement FLR, ou il manque un chemin de reset de bus approprié.

Correction : Binder sur vfio-pci dans l’initramfs ; évitez la framebuffer hôte ; envisagez un modèle de GPU différent ; assurez‑vous que le périphérique est seul dans son groupe ; pour les GPU avec bugs de reset, testez les quirks de reset spécifiques au vendeur ou changez de matériel.

2) Le passthrough GPU fonctionne, mais les performances sont catastrophiques

Symptômes : FPS bas, stuttering, forte charge CPU, ou l’invité se comporte comme s’il utilisait un adaptateur d’affichage basique.

Cause racine : Le GPU n’est pas réellement passé (utilisation de virtio-gpu), lien PCIe rétrogradé, pilote invité manquant, ou problèmes d’ordonnancement/affectation CPU.

Correction : Vérifiez que l’invité voit le modèle GPU ; vérifiez le statut du lien avec lspci -vv ; installez les bons pilotes invités ; pincez les vCPU sur des cœurs physiques et évitez l’overcommit pour des charges sensibles à la latence.

3) Les benchmarks NVMe en passthrough sont excellents puis corrompent ou disparaissent

Symptômes : Erreurs I/O dans l’invité, resets NVMe, le périphérique disparaît jusqu’au reboot/cycle d’alimentation.

Cause racine : Bizarreries du firmware du contrôleur en virtualisation, problèmes de gestion d’alimentation/ASPM, reset cassé ou instabilité de la plateforme.

Correction : Désactivez ASPM pour ce lien si nécessaire ; mettez à jour BIOS/firmware NVMe ; essayez un autre contrôleur ; si vous avez besoin de fiabilité, passez aux disques virtuels gérés par l’hôte.

4) Après activation de l’IOMMU, le réseau hôte casse ou devient instable

Symptômes : Perte de paquets, resets NIC, pics de latence étranges.

Cause racine : Certains pilotes/plateformes se comportent différemment avec le remapping DMA ; remapping d’interruptions problématique ; BIOS bogué.

Correction : Assurez‑vous que le remapping IRQ est activé ; mettez à jour le BIOS ; testez un noyau différent ; envisagez iommu=pt ; si c’est un bug de plateforme, ne vous acharnez pas—remplacez la carte.

5) « Le groupe IOMMU est énorme, je vais tout passer »

Symptômes : L’hôte perd le stockage/NIC/USB ; pannes soudaines quand la VM démarre.

Cause racine : Passage de tout un groupe contenant des périphériques critiques de l’hôte.

Correction : Ne faites pas ça. Déplacez le périphérique de passthrough vers un slot/port racine différent ou changez de plateforme. Si vous devez, re‑concevez l’hôte pour que ces périphériques « critiques » ne soient pas requis par l’hôte (NIC séparée, disque de boot séparé, contrôleur USB séparé).

6) ACS override « corrige » les groupes mais introduit des problèmes inquiétants plus tard

Symptômes : Fautes DMA/IOMMU rares, instabilité étrange, panique lors d’un audit de sécurité.

Cause racine : Forcer la séparation des groupes sans garanties d’isolation matérielle ACS.

Correction : Retirez l’override dans des environnements sérieux ; migrez vers du matériel avec ACS correct ; utilisez des chipsets serveur/workstation connus pour leurs groupements raisonnables.

Listes de vérification / plan étape par étape

Étape par étape : obtenir un passthrough GPU propre

  1. Configuration firmware : Activez VT-d/AMD-Vi. Activez « Above 4G decoding » si vous avez des GPU modernes et plusieurs périphériques.
  2. Flags de boot : Ajoutez intel_iommu=on ou amd_iommu=on ; pensez à iommu=pt pour les performances hôte.
  3. Cartographiez les groupes : Énumérez les groupes IOMMU et confirmez que le GPU (et son audio) sont isolés des périphériques critiques de l’hôte.
  4. Choisissez le bon slot : Favorisez les ports racine CPU. Si un slot passe par des bridges/switches chipset, il crée souvent des groupes désordonnés.
  5. Liez tôt : Configurez les IDs vfio-pci et blacklistez les pilotes GPU conflictuels ; reconstruisez l’initramfs.
  6. Confirmez la propriété : Après reboot, assurez‑vous de Kernel driver in use: vfio-pci.
  7. Config VM : Passez toutes les fonctions GPU nécessaires (graphique + audio ; parfois contrôleur USB‑C).
  8. Test de stabilité : Démarrez/arrêtez la VM plusieurs fois. Si ça ne marche qu’une fois, vous avez un problème de reset à résoudre avant de considérer la tâche « terminée ».

Étape par étape : obtenir un passthrough NVMe propre

  1. Décidez du domaine de défaillance : Si l’invité prend en charge la récupération, le passthrough est correct. Si l’hôte doit récupérer et snapshotter, préférez les disques virtuels.
  2. Isolez le contrôleur : Assurez‑vous que le groupe IOMMU du NVMe n’inclut pas le stockage de boot de l’hôte ou une NIC dont vous avez besoin.
  3. Vérifiez le statut du lien : Confirmez la génération et la largeur PCIe attendues. Corrigez toute rétrogradation d’abord.
  4. Liez à vfio-pci : Comme pour les GPU, faites‑le tôt et de façon cohérente.
  5. Vérification invité : Confirmez que l’invité voit le vrai contrôleur NVMe et que les pilotes sont corrects.
  6. Test de charge : Lancez des tests I/O courts et brutaux. Surveillez dmesg de l’hôte pour les resets ou fautes DMAR.
  7. Gestion d’alimentation : Si vous avez des problèmes de stabilité, testez des modifications ASPM et des mises à jour de firmware.

Checklist opérationnelle : éviter les régressions

  • Enregistrez la topologie PCIe (lspci -tv) et les groupes IOMMU comme artefacts par hôte.
  • Standardisez les versions BIOS/UEFI au sein d’un cluster.
  • Après des mises à jour firmware, revalidez l’appartenance aux groupes et le binding des périphériques avant de remettre en production.
  • Gardez le stockage de boot de l’hôte séparé des périphériques de passthrough.
  • Maintenez une voie de rollback pour le noyau et l’initramfs.

FAQ

1) Pourquoi ne puis‑je pas passer qu’un seul périphérique d’un groupe IOMMU ?

Parce que la frontière du groupe est la frontière de sécurité du noyau pour l’isolation DMA. Si les périphériques ne peuvent pas être isolés, passer un seul d’entre eux risque de permettre aux autres d’accéder par DMA à la mauvaise mémoire.

2) Les groupes IOMMU sont‑ils identiques aux lanes ou aux slots PCIe ?

Non. Les groupes sont façonnés par la hiérarchie PCIe et les capacités ACS. Un seul slot physique peut être derrière un bridge qui fusionne des domaines d’isolation.

3) L’ACS override est‑il sûr ?

Il peut être acceptable pour des configurations monoposte et de confiance. Ce n’est pas une hypothèse sûre pour des environnements multi‑tenant ou sensibles à la sécurité parce qu’il peut prétendre à une isolation que le matériel n’applique pas.

4) Mon GPU partage un groupe avec sa fonction audio. Est‑ce un problème ?

Non, c’est normal. Vous passez généralement les deux fonctions ensemble. Le problème survient lorsque le groupe inclut des périphériques critiques et sans rapport avec l’hôte.

5) Pourquoi le passthrough GPU ne fonctionne‑t‑il qu’une seule fois après le reboot ?

Souvent un problème de reset : le GPU ne supporte pas proprement FLR ou la plateforme ne peut pas le réinitialiser correctement après l’arrêt de la VM. Le binding, les quirks ROM et le comportement des pilotes vendeurs peuvent aussi contribuer.

6) NVMe passthrough vs virtio-blk sur ZFS/LVM : lequel est « meilleur » ?

Pour la latence brute et le contrôle direct, le passthrough NVMe gagne souvent. Pour la sécurité opérationnelle—snapshots, réplication, récupération côté hôte—les disques virtuels sur une couche de stockage gérée par l’hôte gagnent généralement.

7) Activer iommu=pt affaiblit‑il l’isolation ?

Cela applique typiquement des mappings passthrough pour les périphériques appartenant à l’hôte afin de réduire la surcharge, tandis que les périphériques VFIO utilisent toujours des mappings stricts. C’est largement utilisé ; validez dans votre environnement.

8) Quel est le moyen le plus rapide pour savoir si un problème de performance est lié au PCIe ?

Vérifiez LnkSta avec lspci -vv. Si le lien est rétrogradé en vitesse ou en largeur, corrigez cela avant de toucher au tuning VM.

9) Dois‑je passer tout le disque NVMe ou utiliser des namespaces ?

Si vous avez besoin d’une séparation stricte et que votre stack le supporte, les namespaces peuvent aider—mais vous traitez toujours un seul contrôleur et ses bizarreries. Pour la simplicité et moins de surprises, le passthrough du contrôleur entier est courant.

10) Puis‑je faire un passthrough propre sur du matériel grand public ?

Parfois, oui—surtout si la carte a un bon comportement ACS et des slots attachés au CPU. Mais vous misez sur la chance de la topologie. Si la disponibilité est importante, achetez du matériel conçu pour être ennuyeux.

Conclusion : prochaines étapes qui fonctionnent vraiment

Si vous voulez un passthrough GPU/NVMe propre, arrêtez de traiter les groupes IOMMU comme un obstacle à argumenter. Ce sont un sérum de vérité matériel.

Faites ceci ensuite :

  1. Inventoriez votre groupement et l’arbre PCIe actuel. Sauvegardez‑les. Traitez‑les comme de la configuration, parce que ça en est.
  2. Déplacez le périphérique vers un slot/port racine CPU si le groupement est moche.
  3. Binder tôt sur vfio-pci, confirmez la propriété après reboot et refusez de déboguer les pilotes invités tant que le côté hôte n’est pas propre.
  4. Mesurez la vitesse/largeur du lien et la latence avant et après, pour savoir si vous avez réellement amélioré quelque chose.
  5. Si vous comptez sur ACS override pour la « sécurité », arrêtez‑vous et redéfinissez le périmètre : soit acceptez des invités de confiance, soit achetez la bonne plateforme.

Quand le passthrough est propre, c’est un plaisir. Quand ce n’est pas le cas, c’est une carrière à interpréter des messages d’erreur. Choisissez le plaisir. Corrigez la topologie.

← Précédent
Comptes administrateurs locaux : la porte dérobée cachée sur votre propre PC
Suivant →
Moniteur externe non détecté : le pilote qui vous manque

Laisser un commentaire