Corriger « IOMMU non activé » sur Proxmox pour le passthrough PCI (VT-d/AMD‑Vi) en toute sécurité

Cet article vous a aidé ?

Vous êtes devant Proxmox, vous essayez de passer une GPU, un HBA ou une NIC dans une VM, et il vous sert la douche froide classique : « IOMMU non activé ». Vous avez activé « quelque chose » dans le BIOS, vous avez redémarré deux fois, et maintenant vous vous demandez si la machine vous fait une mauvaise blague.

Ce problème n’est presque jamais mystique. C’est généralement l’une des cinq choses : bascules firmware, mauvais fichier de chargeur de démarrage, paramètres noyau manquants, modules VFIO absents, ou une carte mère qui groupe les périphériques comme si elle voulait vous empêcher d’avoir des loisirs. Nous allons le corriger en toute sécurité, avec des preuves à chaque étape, et des options de retour arrière pour ne pas briqué un hôte distant à 2 h du matin.

Ce qu’est réellement l’IOMMU (et pourquoi Proxmox s’en soucie)

Une IOMMU (Intel VT-d, AMD‑Vi) est une unité de gestion mémoire pour les périphériques. Les CPU ont une MMU qui traduit les adresses mémoire virtuelles en adresses physiques pour les processus. L’IOMMU fait le même type de traduction pour le DMA (Direct Memory Access) des périphériques PCIe : NIC, HBA, GPU, contrôleurs USB, etc.

Le passthrough PCI dépend de cela parce que lorsque vous confiez un périphérique réel à une VM, il faut que l’hôte fasse respecter « ce périphérique ne peut faire du DMA que dans la mémoire de cette VM ». Sans cela, un périphérique pourrait écrire n’importe où dans la mémoire de l’hôte ou d’une autre VM. Au-delà de la sécurité, c’est aussi une question de stabilité : des DMA intempestifs au mauvais endroit produisent des panics du noyau d’un style très créatif.

Donc Proxmox vérifie la présence de l’IOMMU. S’il ne la voit pas, il refuse de faire semblant que tout est correct. Ce n’est pas Proxmox qui est pointilleux. C’est Proxmox qui empêche votre contrôleur de stockage de devenir accidentellement un générateur d’art abstrait.

Un mantra de fiabilité utile vient de John Allspaw, idée paraphrasée : La fiabilité vient du fait de concevoir pour l’échec et d’apprendre de celui-ci, pas de prétendre que les échecs n’arriveront pas. C’est la posture ici : faire des changements, les vérifier, garder un retour arrière.

Autre chose : « IOMMU non activé » est un message à propos de l’hôte. Ce n’est pas encore une question de configuration de la VM. Ne perdez pas de temps à éditer des fichiers de conf de VM tant que l’hôte n’a pas prouvé que l’IOMMU est activée et fonctionnelle.

Faits et historique intéressants (pourquoi tout ceci est chaotique)

  • Fait 1 : La marque IOMMU d’Intel est VT-d ; VT-x concerne la virtualisation CPU. Les gens les confondent constamment, y compris dans les menus BIOS des constructeurs.
  • Fait 2 : L’implémentation IOMMU d’AMD est souvent appelée AMD‑Vi, et le commutateur BIOS est parfois simplement étiqueté « IOMMU ».
  • Fait 3 : Les premiers passthrough PCI sous Linux s’appuyaient sur l’ancien mécanisme « pciback » avant que VFIO ne devienne la norme. VFIO a gagné parce que c’est plus sain et plus sûr.
  • Fait 4 : Les frontières des groupes IOMMU proviennent des tables ACPI et de la topologie PCIe. Deux CPU identiques avec deux cartes mères différentes peuvent se comporter de façon très différente.
  • Fait 5 : « ACS » (Access Control Services) est une fonctionnalité PCIe qui aide à isoler les périphériques derrière des switches/bridges. Certaines cartes grand public l’omettent ou l’implémentent partiellement.
  • Fait 6 : Le noyau Linux supporte le remapping DMA depuis longtemps, mais les paramètres par défaut et heuristiques ont changé selon les versions — surtout autour des compromis performance vs sécurité.
  • Fait 7 : Les GPU NVIDIA grand public ont historiquement résisté à la virtualisation de diverses manières ; les pilotes modernes sont meilleurs, mais le folklore persiste car les gens gardent des cicatrices.
  • Fait 8 : Le « remappage d’interruptions » fait partie de l’histoire : il aide à garder les interruptions des périphériques correctement isolées. Son absence peut bloquer certains setups avancés de passthrough.
  • Fait 9 : Proxmox rend cela accessible, mais sous le capot c’est toujours Linux : paramètres de démarrage, initramfs, modules, sysfs, et la gotcha occasionnelle du firmware.

Voilà le contexte. Maintenant la partie pratique : faites prouver à l’hôte qu’il peut faire IOMMU, puis qu’il peut isoler le périphérique qui vous intéresse, puis passez-le.

Procédure de diagnostic rapide

Si vous êtes d’astreinte, vous ne voulez pas de philosophie. Vous voulez la voie la plus rapide pour savoir « est-ce le BIOS, le chargeur de démarrage, le noyau ou la topologie matérielle ? » Voici l’ordre qui gagne le plus souvent.

Première étape : confirmer CPU et l’état du firmware

  • Le CPU/la plate-forme prend-il en charge VT-d/AMD‑Vi ?
  • Est-ce activé dans le BIOS/UEFI (pas seulement « virtualisation » mais IOMMU/VT-d spécifiquement) ?
  • Avez-vous redémarré après le changement ? (Un redémarrage chaud compte souvent, mais certaines cartes exigent un cycle d’alimentation complet.)

Deuxième étape : vérifier que le noyau a reçu les bons paramètres

  • Vérifiez la ligne de commande de démarrage réelle dans /proc/cmdline.
  • Ne faites pas confiance au fichier que vous avez édité tant que vous ne le voyez pas reflété dans le noyau en cours d’exécution.

Troisième étape : confirmer que le noyau a bien initialisé l’IOMMU

  • Cherchez les lignes DMAR/IOMMU dans dmesg.
  • Vérifiez que /sys/kernel/iommu_groups existe et est peuplé.

Quatrième étape : vérifier le groupement avant d’accuser VFIO

  • Un mauvais groupement IOMMU est un problème de topologie/firmware, pas de VFIO.
  • Sachez ce que vous êtes prêt à faire : déplacer la carte dans un autre slot, ou accepter les risques d’ACS override.

Cinquième étape : seulement ensuite lier le périphérique à vfio-pci

  • Identifiez le périphérique par son vendor:device ID.
  • Lieuz-le dans l’initramfs pour que le pilote hôte ne l’attrape pas en premier.

Cet ordre évite l’erreur classique : passer une heure sur le binding VFIO alors que l’IOMMU est encore désactivée au niveau firmware.

Sécurité pré-vol : ne vous laissez pas coincer

Activer l’IOMMU est généralement sans danger. La partie dangereuse est la façon dont les gens le font : éditer le mauvais fichier de démarrage, ajouter des paramètres agressifs, redémarrer un hôte distant sans accès hors-bande, puis découvrir qu’il ne revient pas.

Avant de toucher quoi que ce soit :

  • Confirmez que vous avez un accès console (IPMI/iDRAC/iLO, KVM-over-IP, ou au moins quelqu’un qui peut brancher un écran).
  • Planifiez une fenêtre de redémarrage. Vous touchez au noyau/firmware ; vous redémarrez.
  • Faites une copie des fichiers de configuration que vous changez, et conservez une entrée de démarrage connue comme bonne si possible.
  • Connaissez votre mode de démarrage : GRUB vs systemd-boot. Proxmox peut être l’un ou l’autre selon la méthode d’installation et la disposition du stockage.

Blague courte #1 : Si vous activez l’IOMMU sur une machine distante sans console, vous ne faites pas de SRE — vous faites de l’art performance.

Tâches pratiques : commandes, sorties, décisions (12+)

Ces tâches sont ordonnées comme je les exécuterais sur un hôte Proxmox en production. Chacune indique ce que cela signifie et la décision suivante.

Tâche 1 : confirmer les extensions de virtualisation du CPU (vérification de base)

cr0x@server:~$ lscpu | egrep -i 'Vendor ID|Model name|Virtualization|Flags'
Vendor ID:                       GenuineIntel
Model name:                      Intel(R) Xeon(R) CPU E-2278G @ 3.40GHz
Virtualization:                  VT-x
Flags:                           ... vmx ...

Ce que cela signifie : VT-x (Intel) ou SVM (AMD) est la virtualisation CPU. Cette sortie ne confirme pas VT-d/AMD‑Vi, mais elle indique que vous n’êtes pas sur du matériel antique.

Décision : Poursuivre. Si vous ne voyez pas vmx (Intel) ou svm (AMD), vous êtes peut-être en mauvais mode BIOS, ou la virtualisation est désactivée complètement.

Tâche 2 : identifier Intel ou AMD (pour choisir les paramètres noyau)

cr0x@server:~$ lscpu | awk -F: '/Vendor ID/ {print $2}'
 GenuineIntel

Ce que cela signifie : Intel utilise intel_iommu=on ; AMD utilise amd_iommu=on. Oui, il existe d’autres modes, mais commencez simple.

Décision : Choisissez le paramètre correct pour votre plateforme. Un mauvais paramètre n’agit généralement pas, ce qui explique pourquoi vous êtes parfois sûr de l’avoir activé.

Tâche 3 : confirmer le mode de démarrage et le chargeur (GRUB vs systemd-boot)

cr0x@server:~$ proxmox-boot-tool status
Re-executing '/usr/sbin/proxmox-boot-tool' in new private mount namespace..
System currently booted with uefi
Found 1 ESP(s) configured:
  /dev/disk/by-uuid/9A1B-2C3D mounted on /boot/efi
Configured with: systemd-boot

Ce que cela signifie : Cet hôte utilise systemd-boot. Éditer /etc/default/grub serait une belle perte de temps.

Décision : Si vous voyez systemd-boot, éditez généralement /etc/kernel/cmdline et exécutez proxmox-boot-tool refresh. Si c’est GRUB, éditez /etc/default/grub et lancez update-grub.

Tâche 4 : vérifier la ligne de commande du noyau actuelle (la source de vérité)

cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12-4-pve root=/dev/mapper/pve-root ro quiet

Ce que cela signifie : Aucun paramètre IOMMU n’est actuellement en vigueur.

Décision : Ajoutez les paramètres corrects et redémarrez. Ne passez pas à VFIO tant que cela n’a pas changé.

Tâche 5A (systemd-boot) : définir les paramètres du noyau en toute sécurité

cr0x@server:~$ sudo cp -a /etc/kernel/cmdline /etc/kernel/cmdline.bak
cr0x@server:~$ echo "root=/dev/mapper/pve-root ro quiet intel_iommu=on iommu=pt" | sudo tee /etc/kernel/cmdline
root=/dev/mapper/pve-root ro quiet intel_iommu=on iommu=pt

Ce que cela signifie : Vous avez défini les paramètres pour Intel. iommu=pt utilise le mode pass-through pour les périphériques hôte (souvent de meilleures performances, tout en gardant l’isolation pour VFIO).

Décision : Rafraîchissez les entrées de démarrage et l’intégration initramfs via les outils Proxmox.

Tâche 6A (systemd-boot) : appliquer et synchroniser la configuration de démarrage

cr0x@server:~$ sudo proxmox-boot-tool refresh
Re-executing '/usr/sbin/proxmox-boot-tool' in new private mount namespace..
Running hook script 'proxmox-auto-removal'..
Copying kernel and creating EFI boot entry
Refreshing /dev/disk/by-uuid/9A1B-2C3D
Success.

Ce que cela signifie : Votre nouvelle cmdline du noyau est maintenant dans l’environnement de démarrage UEFI que Proxmox utilise.

Décision : Redémarrez quand vous avez accès à la console.

Tâche 5B (alternative GRUB) : définir les paramètres du noyau

cr0x@server:~$ sudo cp -a /etc/default/grub /etc/default/grub.bak
cr0x@server:~$ sudo sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 intel_iommu=on iommu=pt"/' /etc/default/grub
cr0x@server:~$ grep GRUB_CMDLINE_LINUX_DEFAULT /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"

Ce que cela signifie : Les paramètres seront intégrés dans la configuration générée par GRUB ensuite.

Décision : Lancez update-grub et redémarrez.

Tâche 6B (alternative GRUB) : régénérer la config GRUB

cr0x@server:~$ sudo update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.8.12-4-pve
Found initrd image: /boot/initrd.img-6.8.12-4-pve
done

Ce que cela signifie : La configuration GRUB est mise à jour. Toujours pas active tant que vous n’avez pas redémarré.

Décision : Redémarrez avec la console prête.

Tâche 7 : redémarrer et vérifier que la cmdline a réellement changé

cr0x@server:~$ sudo reboot
cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12-4-pve root=/dev/mapper/pve-root ro quiet intel_iommu=on iommu=pt

Ce que cela signifie : Vous ne devinez plus. Le noyau en cours d’exécution a les paramètres IOMMU.

Décision : Vérifiez maintenant les journaux du noyau pour confirmer l’initialisation.

Tâche 8 : confirmer que l’IOMMU est initialisée dans dmesg (DMAR Intel ou IOMMU AMD)

cr0x@server:~$ dmesg | egrep -i 'DMAR|IOMMU|AMD-Vi|Interrupt Remapping' | head -n 20
[    0.000000] DMAR: IOMMU enabled
[    0.000000] DMAR: Host address width 39
[    0.123456] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
[    0.234567] DMAR: Interrupt remapping enabled

Ce que cela signifie : Voilà le résultat décisif. Si vous ne voyez pas « IOMMU enabled » (ou les équivalents AMD), vous n’avez pas encore terminé.

Décision : Si absent, revenez en arrière : paramètres firmware, mauvais paramètre de démarrage, ou limitation de la plateforme.

Tâche 9 : vérifier que les groupes IOMMU existent dans sysfs

cr0x@server:~$ ls -1 /sys/kernel/iommu_groups | head
0
1
10
11
12
13
14
15
16
17

Ce que cela signifie : Des groupes existent. Cela suggère fortement que l’IOMMU est opérationnelle.

Décision : Passez à l’identification de votre périphérique et à la vérification de son isolation.

Tâche 10 : lister les périphériques PCI et trouver celui que vous voulez passer

cr0x@server:~$ lspci -nn
00:00.0 Host bridge [0600]: Intel Corporation Device [8086:3ec2]
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
01:00.1 Audio device [0403]: NVIDIA Corporation TU104 HD Audio Controller [10de:10f8]
03:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]

Ce que cela signifie : Le GPU est à 01:00.0 et sa fonction audio à 01:00.1. Pour les GPU, on passe généralement les deux fonctions ensemble.

Décision : Notez les adresses BDF et les vendor:device IDs. Vous en aurez besoin pour le binding VFIO et la config VM.

Tâche 11 : voir quel pilote noyau possède actuellement le périphérique

cr0x@server:~$ lspci -nnk -s 01:00.0
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
        Subsystem: Hewlett-Packard Company Device [103c:12a3]
        Kernel driver in use: nouveau
        Kernel modules: nouveau

Ce que cela signifie : Le pilote hôte nouveau a pris le GPU. Il s’opposera à VFIO.

Décision : Prévoyez de lier ce périphérique à vfio-pci tôt (initramfs) et blacklisterez les pilotes conflictuels si nécessaire.

Tâche 12 : charger les modules VFIO (et les rendre persistants)

cr0x@server:~$ printf "vfio\nvfio_iommu_type1\nvfio_pci\nvfio_virqfd\n" | sudo tee /etc/modules-load.d/vfio.conf
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
cr0x@server:~$ sudo modprobe vfio_pci
cr0x@server:~$ lsmod | egrep '^vfio'
vfio_pci               16384  0
vfio_iommu_type1       45056  0
vfio                   65536  2 vfio_pci,vfio_iommu_type1

Ce que cela signifie : VFIO est disponible maintenant et sera chargé au démarrage à l’avenir.

Décision : Ensuite, liez les vendor:device IDs à vfio-pci, puis reconstruisez l’initramfs pour que le binding se fasse avant que les pilotes GPU hôtes ne s’attachent.

Tâche 13 : lier des vendor:device IDs spécifiques à vfio-pci

cr0x@server:~$ echo "options vfio-pci ids=10de:1eb1,10de:10f8 disable_vga=1" | sudo tee /etc/modprobe.d/vfio.conf
options vfio-pci ids=10de:1eb1,10de:10f8 disable_vga=1

Ce que cela signifie : Au démarrage, vfio-pci devrait revendiquer ces IDs.

Décision : Si c’est votre seul GPU et que vous comptez sur la console locale, marquez une pause et réfléchissez. Passer le seul adaptateur d’affichage peut rendre l’hôte « sans tête » de façon surprenante.

Tâche 14 : blacklist des pilotes GPU conflictuels (uniquement si nécessaire)

cr0x@server:~$ printf "blacklist nouveau\noptions nouveau modeset=0\n" | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0

Ce que cela signifie : Empêche le pilote NVIDIA open-source de se lier en premier. La même logique s’applique à d’autres périphériques (par ex. ixgbe pour certaines NIC), mais blacklister un pilote de NIC peut couper votre propre câble réseau. Ne le faites pas à la légère.

Décision : Reconstruisez l’initramfs et redémarrez pour assurer le binding précoce.

Tâche 15 : reconstruire l’initramfs (pour que le binding VFIO arrive tôt)

cr0x@server:~$ sudo update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-6.8.12-4-pve

Ce que cela signifie : La sélection des pilotes au démarrage respectera maintenant votre config VFIO plus tôt.

Décision : Redémarrez et vérifiez que le périphérique est revendiqué par vfio-pci.

Tâche 16 : vérifier que le périphérique est maintenant lié à vfio-pci

cr0x@server:~$ sudo reboot
cr0x@server:~$ lspci -nnk -s 01:00.0
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
        Subsystem: Hewlett-Packard Company Device [103c:12a3]
        Kernel driver in use: vfio-pci
        Kernel modules: nouveau

Ce que cela signifie : Parfait. L’hôte voit la carte, mais vfio-pci en est propriétaire. La ligne « Kernel modules » peut toujours lister des modules possibles ; ce qui compte est « driver in use ».

Décision : Vérifiez maintenant l’appartenance aux groupes IOMMU pour vous assurer que vous pouvez la passer en toute sécurité.

Tâche 17 : lister les groupes IOMMU avec les périphériques (la vérité topologique)

cr0x@server:~$ for g in /sys/kernel/iommu_groups/*; do \
  echo "IOMMU Group ${g##*/}"; \
  for d in "$g"/devices/*; do echo "  $(lspci -nn -s ${d##*/})"; done; \
done | sed -n '1,40p'
IOMMU Group 1
  00:01.0 PCI bridge [0604]: Intel Corporation Device [8086:1901]
IOMMU Group 2
  01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104GL [Quadro RTX 4000] [10de:1eb1]
  01:00.1 Audio device [0403]: NVIDIA Corporation TU104 HD Audio Controller [10de:10f8]
IOMMU Group 3
  03:00.0 Non-Volatile memory controller [0108]: Samsung Electronics Co Ltd NVMe SSD Controller [144d:a808]

Ce que cela signifie : Les fonctions du GPU sont isolées dans leur propre groupe. C’est ce que vous voulez. Si votre GPU partage un groupe avec, par exemple, un contrôleur SATA ou un contrôleur USB dont vous avez besoin pour l’hôte, vous avez un problème.

Décision : Si l’isolation est bonne, procédez à la config de la VM. Sinon, vous êtes en territoire « permutation de slot / mise à jour BIOS / décision ACS override ».

Tâche 18 : vérifier que KVM est réellement utilisable (ne sautez pas ceci sur des plateformes étranges)

cr0x@server:~$ lsmod | egrep 'kvm|vfio'
kvm_intel             380928  0
kvm                  1032192  1 kvm_intel
vfio_pci               16384  0
vfio_iommu_type1       45056  0
vfio                   65536  2 vfio_pci,vfio_iommu_type1

Ce que cela signifie : La virtualisation est présente (kvm_intel ou kvm_amd) et la pile VFIO est chargée.

Décision : Si KVM n’est pas chargé, vous résolvez un problème différent (virtualisation BIOS désactivée ou complexité de virtualisation imbriquée). Ne le confondez pas avec IOMMU.

Tâche 19 : vérifier que Proxmox voit IOMMU d’une manière utilisateur

cr0x@server:~$ pvesh get /nodes/$(hostname)/hardware/pci --noborder | head -n 20
┌─────────┬───────────────────────────────────────────────────────────┬────────────┬────────────┬─────────────┬───────────────┐
│ class   │ device                                                    │ id         │ iommugroup │ subsystem_id │ subsystem_name │
╞═════════╪═══════════════════════════════════════════════════════════╪════════════╪════════════╪═════════════╪═══════════════╡
│ 0x0300  │ NVIDIA Corporation TU104GL [Quadro RTX 4000]              │ 0000:01:00 │ 2          │ 103c:12a3    │ Hewlett-Packard│
└─────────┴───────────────────────────────────────────────────────────┴────────────┴────────────┴─────────────┴───────────────┘

Ce que cela signifie : Proxmox peut mapper les périphériques aux groupes IOMMU. C’est un fort indicateur que votre travail précédent est correct.

Décision : Configurez le passthrough sur la VM. Si Proxmox affiche encore « IOMMU non activé » à ce stade, vous regardez probablement un état UI obsolète, un mauvais nœud, ou vous l’avez activé sur le mauvais hôte.

GRUB vs systemd-boot sur Proxmox : choisissez le bon levier

C’est le piège le plus courant que je vois en environnement réel : quelqu’un édite GRUB, mais le système boot via systemd-boot ; ou il édite /etc/kernel/cmdline, mais le système est basé sur GRUB. Les deux approches sont du « travail Linux valide » qui ne change absolument rien sur l’hôte en cours d’exécution.

Comment le déterminer rapidement

  • systemd-boot (commun avec racine ZFS, UEFI) : proxmox-boot-tool status affiche « Configured with: systemd-boot ». Vous éditez /etc/kernel/cmdline et lancez proxmox-boot-tool refresh.
  • GRUB : efibootmgr -v montre souvent GRUB, et proxmox-boot-tool peut ne pas être utilisé. Vous éditez /etc/default/grub puis exécutez update-grub.

Paramètres noyau généralement sûrs comme valeurs par défaut

  • Intel : intel_iommu=on iommu=pt
  • AMD : amd_iommu=on iommu=pt

Paramètres que les gens ajoutent parce qu’ils les ont vus en ligne (et pourquoi être prudent)

  • pcie_acs_override=downstream,multifunction : peut scinder artificiellement les groupes ; réduit aussi les garanties d’isolation. À n’utiliser que si vous comprenez le risque et l’acceptez.
  • intel_iommu=on,igfx_off : peut aider avec des quirks d’iGPU sur certains systèmes, mais ne le faites pas en mode cargo-cult.
  • iommu=soft : pas ce que vous voulez pour le passthrough ; c’est un mode de repli et peut contrecarrer votre objectif.

L’état d’esprit correct : ajoutez le minimum de paramètres pour activer l’IOMMU. Vérifiez. Puis résolvez le groupement. Puis le binding. Tout le reste est du assaisonnement, pas le plat principal.

Lier des périphériques à VFIO (sans voler votre disque de démarrage)

Quand l’IOMMU fonctionne, VFIO est le mécanisme qui rend le passthrough gérable. L’idée centrale est simple : dire à l’hôte d’attacher un périphérique à vfio-pci au lieu de son pilote habituel, pour que QEMU puisse le prendre pour la VM.

La méthode sûre : lier par vendor:device ID, pas par « ce qui est en 01:00.0 »

Lier par adresse PCI peut fonctionner, mais lier par ID est typiquement plus robuste au travers des redémarrages et des changements topologiques. C’est aussi plus dangereux si vous êtes négligent : si vous liez par erreur votre contrôleur de stockage, vous aurez un redémarrage très instructif.

Ce qu’il faut passer ensemble

  • GPU : généralement fonction VGA + fonction audio HDMI/DP.
  • HBA : tout le contrôleur. Ne passez pas des disques individuels d’un contrôleur que vous utilisez aussi sur l’hôte sauf si vous aimez les cas limites.
  • Contrôleurs USB : un contrôleur entier est souvent préférable au passthrough par périphérique, surtout pour les dongles et les appareils à faible latence.
  • NIC : peuvent être excellentes, mais réfléchissez à l’accès de gestion. Si vous passez la seule NIC, vous risquez de couper votre session SSH en vol.

Quand blacklister des pilotes

Si le pilote hôte attrape le périphérique avant VFIO, le binding peut échouer. Le blacklistage aide, mais c’est un outil grossier. Blacklister un pilote de GPU sur un serveur sans tête est acceptable. Blacklister un pilote de NIC sur un hôte distant est la façon rapide d’apprendre si vous avez réellement IPMI.

Blague courte #2 : Blacklister le pilote de votre seule NIC est un moyen rapide d’atteindre la conformité « air-gapped ».

Groupes IOMMU : comment les lire et que faire des mauvais groupements

Les groupes IOMMU sont la frontière de sécurité. Les périphériques dans le même groupe ne peuvent pas être isolés en toute sécurité les uns des autres pour le passthrough. Concrètement, cela signifie : si vous passez un périphérique d’un groupe à une VM, vous devez en général passer tous les périphériques de ce groupe, ou accepter un risque accru.

À quoi ressemble un « mauvais groupement »

Un cauchemar courant : le GPU partage un groupe IOMMU avec un contrôleur SATA, un contrôleur USB, ou un bridge PCI qui héberge aussi des périphériques dont vous avez besoin. Proxmox refusera souvent le passthrough ou affichera des avertissements. Ce n’est pas du théâtre : c’est la réalité des capacités d’isolation de la plateforme.

Trois leviers qui fonctionnent réellement (classés par justesse)

  1. Déplacez la carte vers un autre slot PCIe. Slot différent, ports descendants différents, groupement différent. C’est le correctif gratuit le plus efficace.
  2. Mettez à jour le BIOS/UEFI. Les fabricants corrigent parfois des problèmes ACS/DMAR. Parfois non, mais ça vaut le coup avant les hacks.
  3. Paramètre kernel ACS override. Cela peut scinder les groupes par la force. Cela peut aussi donner une fausse impression d’isolation. À utiliser seulement si vous acceptez le modèle de risque (typiquement un homelab ; rarement un environnement régulé).

Ce que je fais en production

En production où la frontière VM compte, j’évite l’ACS override. Si la carte mère ne groupe pas correctement les périphériques, je choisis du matériel différent, ou je redesigne : SR-IOV pour les NIC si possible, ou un service au niveau hôte au lieu du passthrough.

Si vous faites un poste de travail dans une VM sur une seule machine et que vous êtes prêt à échanger isolation stricte contre fonctionnalité, l’ACS override peut être acceptable. Ne prétendez pas que c’est « la même sécurité ». Ce n’est pas le cas.

Trois mini-récits d’entreprise issus du terrain

1) Incident causé par une mauvaise hypothèse : « virtualisation activée » signifiait VT-d activé

Une équipe a déployé un nouveau cluster Proxmox pour un labo qui hébergeait une pile d’appliances VM. L’une de ces appliances avait besoin d’un NIC double-port en passthrough pour le timing de paquets et une exigence fournisseur. L’ingénieur qui a fait le build a activé « Intel Virtualization Technology » dans le BIOS, vérifié que KVM se chargeait, et a passé à autre chose.

Pendant la bascule, le passthrough a échoué avec « IOMMU non activé ». L’équipe a supposé que c’était une régression Proxmox parce que le noyau avait récemment été mis à jour. Ils ont cherché dans les configs VFIO pendant une heure, reconstruit initramfs deux fois, et blacklisté un pilote inutile. Pendant ce temps, l’ancien environnement était déjà drainé et éteint car le plan était « switch propre ».

La correction était embarrassante de simplicité : le BIOS avait deux commutateurs distincts — VT-x et VT-d. VT-x était activé ; VT-d était désactivé par défaut. La machine a redémarré, DMAR est apparu dans dmesg, et tout a fonctionné.

La leçon n’était pas « lisez le manuel ». La leçon était : vérifiez toujours l’état du noyau en cours d’exécution (/proc/cmdline, dmesg, /sys/kernel/iommu_groups) avant de toucher VFIO. Les hypothèses sont confortables. La production ne l’est pas.

2) Optimisation qui a mal tourné : ACS override comme raccourci

Un autre environnement voulait maximiser la densité. Ils avaient des hôtes avec des cartes mères plutot grand public. Ils devaient passer plusieurs périphériques par hôte : un GPU pour des charges type VDI et un contrôleur USB pour des dongles de licence. Le groupement était mauvais : plusieurs root ports et endpoints atterrissaient dans un énorme groupe IOMMU.

Quelqu’un a trouvé le paramètre ACS override et l’a présenté comme un « correctif propre ». Il a effectivement scindé les groupes. Proxmox a cessé de se plaindre. Le déploiement a repris, et les tableaux de bord étaient verts.

Quelques semaines plus tard, ils ont commencé à observer des problèmes rares mais méchants : des VMs se bloquaient parfois sous forte I/O. L’hôte ne plantait pas, mais la VM affectée devenait non réactive, et les resets échouaient parfois. Il n’y avait pas de coupable unique. Juste des timeouts VFIO épars et du bruit PCIe AER occasionnel.

Ils ont finalement annulé l’ACS override et repensé le design : ont déplacé les charges critiques vers des serveurs avec meilleure isolation PCIe et ont utilisé la redirection USB réseau quand c’était acceptable. L’« optimisation » n’était pas liée à la performance ; c’était liée au planning. Elle a acheté du temps et de la stabilité de coût.

La morale : ACS override n’est pas un plat gratuit. C’est un compromis que vous devriez documenter comme un risque, pas une « solution finale ».

3) Pratique ennuyeuse mais correcte qui a sauvé la mise : redémarrage par étapes et entrées de démarrage de retour

Une entreprise axée stockage faisait tourner des hôtes Proxmox avec HBAs pour ZFS et un passthrough NIC dédié pour une VM pare-feu. Ils devaient activer l’IOMMU sur un sous-ensemble d’hôtes pour supporter une nouvelle carte PCIe. Ils l’ont fait lentement et correctement : un hôte à la fois, hors heures, avec console hors-bande vérifiée.

Ils ont aussi conservé un plan de retour en arrière presque offensivement peu glamour. Avant de changer les paramètres de démarrage, ils ont copié le fichier de config pertinent, noté la /proc/cmdline actuelle, et assuré qu’il existait une entrée de démarrage connue bonne. Sur les hôtes systemd-boot, ils ont vérifié proxmox-boot-tool status et ont exécuté explicitement proxmox-boot-tool refresh. Pas de « je pense que ça synchronise automatiquement ».

Sur le troisième hôte, l’activation de l’IOMMU a mis au jour un bug firmware : la machine a booté, mais l’énumération PCIe a changé et un nom d’interface NIC a bougé. Leur VM pare-feu ne démarrait plus car sa config référençait un mapping d’interface désormais absent. Comme le changement était progressif, seul un segment du site a été affecté, et le retour arrière a été simple.

Ils ont corrigé en fiabilisant le nommage des interfaces (par MAC) puis ont poursuivi hôte par hôte. La pratique qui les a sauvés n’était pas du génie — c’était faire un changement à la fois et avoir un moyen de revenir. Le gain de fiabilité venait de l’ennui.

Erreurs courantes : symptôme → cause racine → correctif

1) Symptom : l’UI Proxmox indique « IOMMU non activé » après avoir « activé la virtualisation » dans le BIOS

Cause racine : VT-x/SVM activé, mais VT-d/AMD‑Vi (IOMMU) toujours désactivé, ou nécessite un cycle d’alimentation.

Correctif : Activez VT-d (Intel) ou IOMMU/AMD‑Vi (AMD) explicitement dans le firmware. Puis cold boot si nécessaire. Confirmez avec dmesg | egrep -i 'DMAR|AMD-Vi'.

2) Symptom : vous avez édité GRUB, mais /proc/cmdline ne change jamais

Cause racine : L’hôte utilise systemd-boot, pas GRUB (commun sur UEFI + racine ZFS).

Correctif : Éditez /etc/kernel/cmdline, lancez proxmox-boot-tool refresh, redémarrez, re-vérifiez /proc/cmdline.

3) Symptom : /proc/cmdline contient intel_iommu=on, mais dmesg n’affiche aucune ligne DMAR

Cause racine : Le firmware désactive encore VT-d, ou la plateforme ne le supporte pas, ou les tables DMAR sont corrompues/cachées par des réglages BIOS (parfois « Above 4G decoding » et réglages PCIe associés interagissent).

Correctif : Revérifiez les options firmware, mettez à jour le BIOS, essayez d’activer « Above 4G decoding » sur certaines plateformes (surtout pour plusieurs GPU), et vérifiez les logs au démarrage.

4) Symptom : IOMMU activée, mais votre GPU partage un groupe avec la moitié de la machine

Cause racine : Mauvais support ACS / topologie PCIe sur la carte mère. Commun sur les cartes grand public.

Correctif : Déplacez la carte dans un autre slot, mettez à jour le BIOS, ou acceptez le risque ACS override. Si c’est de la production avec des besoins stricts d’isolation : changez le matériel.

5) Symptom : la VM ne démarre pas ; « device is in use » ou « cannot bind to vfio »

Cause racine : Le pilote hôte possède encore le périphérique (nouveau/nvidia/amdgpu, ou un pilote stockage/NIC), ou le binding n’était pas dans initramfs.

Correctif : Liez avec /etc/modprobe.d/vfio.conf, reconstruisez initramfs, redémarrez, confirmez Kernel driver in use: vfio-pci.

6) Symptom : l’hôte boot, mais la console locale est morte après le binding VFIO

Cause racine : Vous avez lié le seul GPU à VFIO. L’hôte n’a plus rien pour afficher.

Correctif : Utilisez un iGPU pour la console de l’hôte, ajoutez un GPU bon marché pour l’hôte, ou acceptez d’être headless + gestion distante.

7) Symptom : le passthrough fonctionne, mais la performance est étrange (pics de latence)

Cause racine : Remappage d’interruptions désactivé, quirks MSI/MSI-X, gestion d’énergie, ou mauvais affinité CPU/NUMA. Ce n’est pas strictement « IOMMU non activé », mais souvent découvert juste après.

Correctif : Confirmez le remappage d’interruptions dans dmesg, vérifiez la localité NUMA, envisagez d’épingler les vCPU, et évitez de passer des périphériques entre nœuds NUMA si possible.

8) Symptom : après activation de l’IOMMU, les noms d’interfaces réseau ont changé et des VMs ont perdu la connectivité

Cause racine : L’énumération PCI a changé ; le nommage prévisible des interfaces a bougé ; la configuration de bridge fait référence aux anciens noms.

Correctif : Utilisez un nommage stable (par MAC dans la configuration réseau Proxmox), vérifiez /etc/network/interfaces, et traitez l’activation IOMMU comme un « redémarrage susceptible de changer l’énumération ».

Listes de contrôle / plan étape par étape

Étape par étape : activer l’IOMMU en toute sécurité sur un hôte Proxmox

  1. Obtenez un accès console (IPMI/iDRAC/iLO). Si vous ne pouvez pas, arrêtez-vous.
  2. Identifiez la plateforme : Intel vs AMD (lscpu).
  3. Activez le réglage firmware : VT-d (Intel) ou IOMMU/AMD‑Vi (AMD). Sauvegardez, redémarrez. Si cela n’apparaît toujours pas ensuite, faites un cold boot.
  4. Identifiez le chargeur : proxmox-boot-tool status.
  5. Ajoutez les paramètres noyau : Intel intel_iommu=on iommu=pt ou AMD amd_iommu=on iommu=pt.
  6. Appliquez les changements de chargeur : systemd-boot proxmox-boot-tool refresh ; GRUB update-grub.
  7. Redémarrez.
  8. Vérifiez :
    • /proc/cmdline contient vos paramètres
    • dmesg montre DMAR/IOMMU enabled
    • /sys/kernel/iommu_groups peuplé

Étape par étape : préparer un périphérique pour le passthrough

  1. Identifiez le périphérique : lspci -nn et capturez les vendor:device IDs.
  2. Vérifiez le groupe : énumérez les groupes IOMMU ; assurez-vous que le périphérique n’est pas collé à des périphériques critiques de l’hôte.
  3. Chargez les modules VFIO de façon persistante (/etc/modules-load.d/vfio.conf).
  4. Lieuz les IDs à vfio-pci (/etc/modprobe.d/vfio.conf).
  5. Blacklistez le pilote hôte seulement si nécessaire (évitez de blacklister les pilotes NIC/stockage à moins d’en être sûr).
  6. Reconstruisez l’initramfs et redémarrez.
  7. Vérifiez le binding : lspci -nnk montre Kernel driver in use: vfio-pci.
  8. Ce n’est qu’ensuite que vous attachez le périphérique à la VM dans Proxmox.

Checklist de retour arrière (parce que les adultes planifient un retour)

  • Supprimez les paramètres IOMMU du noyau de GRUB ou de /etc/kernel/cmdline.
  • Enlevez ou commentez le binding VFIO ID dans /etc/modprobe.d/vfio.conf.
  • Retirez les blacklists que vous avez ajoutées.
  • Reconstruisez l’initramfs.
  • Rafraîchissez la config du chargeur (GRUB/systemd-boot).
  • Redémarrez et confirmez que le pilote d’origine possède de nouveau le périphérique.

FAQ

1) VT-x est-ce la même chose que VT-d ?

Non. VT-x est la virtualisation CPU. VT-d est l’IOMMU pour les périphériques. Vous pouvez avoir VT-x fonctionnel (KVM se charge) tandis que VT-d est désactivé et le passthrough échoue.

2) Sur AMD, que dois-je activer dans le BIOS ?

Cherchez « IOMMU » ou « AMD‑Vi ». « SVM » est la virtualisation CPU, pas le remappage DMA des périphériques. Vous voulez généralement les deux pour la virtualisation Proxmox + passthrough.

3) Ai-je besoin de iommu=pt ?

Généralement c’est un bon défaut sur les hôtes faisant du passthrough. Cela peut réduire l’overhead pour les périphériques hôtes tout en conservant l’isolation VFIO. Si vous dépannez, vous pouvez l’enlever pour simplifier, mais la plupart des configurations fonctionnent bien avec.

4) Pourquoi Proxmox dit encore « IOMMU non activé » après avoir défini les paramètres noyau ?

Parce que les paramètres noyau peuvent ne pas être appliqués (vous avez édité le mauvais fichier de chargeur), ou le firmware VT-d/AMD‑Vi est éteint, ou vous n’avez pas redémarré. Vérifiez d’abord /proc/cmdline. Si vous ne voyez pas les paramètres, rien d’autre n’a d’importance.

5) Et si les groupes IOMMU sont mauvais ?

Tentez d’abord un autre slot PCIe et une mise à jour du BIOS. Si cela échoue, décidez si vous acceptez le risque ACS override. Si vous avez besoin d’une isolation forte, ne « corrigez » pas du mauvais matériel avec un hack noyau — utilisez du matériel meilleur.

6) Puis-je passer un périphérique USB sans passer tout le contrôleur ?

Oui, via le passthrough USB au niveau QEMU. Mais pour les périphériques instables (dongles, VR, périphériques basse latence), passer tout le contrôleur USB est souvent plus fiable.

7) Dois-je désactiver le pilote GPU de l’hôte ?

Seulement si le pilote hôte se lie au GPU avant que VFIO n’ait pu le faire. L’approche la plus propre est le binding VFIO par ID dans l’initramfs. Le blacklistage aide quand le pilote est agressif, mais c’est un instrument grossier.

8) Activer l’IOMMU va-t-il casser quelque chose ?

Habituellement non. Parfois cela change l’énumération PCI ou révèle des bugs firmware. C’est pourquoi vous faites des redémarrages planifiés, vérifiez le nommage réseau et conservez des options de retour.

9) Puis-je activer l’IOMMU sans redémarrer ?

Non. C’est une initialisation matérielle/firmware et noyau au démarrage. Si quelqu’un prétend le contraire, il vous vend du vent.

10) Quelle est la différence entre passer par adresse PCI et par vendor:device ID ?

Le binding par adresse cible un chemin/slot spécifique ; le binding par ID cible un modèle de périphérique. Le binding par ID est courant et stable mais peut attraper plus de périphériques que prévu si vous avez des duplicatas. En production, soyez explicite et vérifiez avec lspci -nnk après redémarrage.

Conclusion : prochaines étapes qui font réellement avancer les choses

Si vous voyez « IOMMU non activé », ne vous éparpillez pas dans les configs de VM. Faites prouver à l’hôte que l’IOMMU est activée :

  • Vérifiez la bascule firmware : VT-d/AMD‑Vi est activée.
  • Vérifiez que les paramètres noyau sont appliqués via /proc/cmdline.
  • Vérifiez que le noyau a initialisé l’IOMMU via dmesg et /sys/kernel/iommu_groups.
  • Vérifiez l’isolation du périphérique via les groupes IOMMU avant le binding et le passthrough.

Puis faites VFIO de façon disciplinée : liez les bons IDs, reconstruisez l’initramfs, redémarrez, confirmez que vfio-pci possède le périphérique, et seulement après, attachez-le à la VM.

Enfin, décidez comme un adulte concernant le groupement : déplacez les slots et mettez à jour le firmware d’abord ; considérez l’ACS override seulement si vous acceptez les concessions. Le passthrough le plus sûr est celui que votre matériel a été conçu pour supporter.

← Précédent
MySQL vs PostgreSQL : sauvegardes et restaurations — qui vous remet en ligne le plus vite
Suivant →
Docker « too many open files » : augmenter correctement les limites (systemd + conteneur)

Laisser un commentaire