Aller au contenu
English
Virtualisation medium

Passthrough PCI avec VFIO : donner un périphérique réel à une VM

40 min de lecture

Logo KVM

Le passthrough donne un périphérique physique à une machine virtuelle, qui le pilote directement. Une carte graphique, une carte réseau, un contrôleur de stockage : l'invité voit le vrai matériel, sans couche d'émulation. C'est ce qui permet de faire tourner un jeu, un calcul GPU ou un pare-feu virtuel avec les performances du matériel. Le prix à payer est que l'hôte perd ce périphérique, et que tout dépend d'une condition matérielle qui se vérifie avant toute chose.

  • Vérifier si votre machine peut faire du passthrough, avant d'essayer
  • Lire les groupes IOMMU et comprendre ce qu'ils imposent
  • Détacher un périphérique de son pilote hôte au profit de vfio-pci
  • Déclarer le périphérique dans le XML de la machine
  • Reconnaître les cas où le passthrough ne vaut pas sa complexité
  • KVM/libvirt installé (guide installation)
  • Un accès au firmware de la machine, pour y activer l'IOMMU
  • La possibilité de redémarrer l'hôte, cette activation l'exigeant

Le passthrough repose sur l'IOMMU, l'unité qui traduit les adresses mémoire entre un périphérique et le système. Sans elle, un périphérique donné à une VM pourrait lire toute la mémoire de l'hôte : le noyau refuse donc, et il a raison.

Trois contrôles, du plus rapide au plus parlant.

Fenêtre de terminal
virt-host-validate qemu | grep -i iommu

Sur une machine qui ne peut pas, la réponse est sans ambiguïté :

QEMU: Checking for device assignment IOMMU support : WARN
(No ACPI DMAR table found, IOMMU either disabled in BIOS or not supported
by this hardware platform)

La table DMAR est publiée par le firmware quand l'IOMMU est activée. Son absence signifie que la fonction est désactivée dans le BIOS, ou que le matériel ne la propose pas.

Fenêtre de terminal
ls /sys/kernel/iommu_groups/ | wc -l

Un zéro ici confirme le diagnostic précédent. Sur une machine correctement configurée, cette commande rend plusieurs dizaines de groupes.

C'est celui que je préfère, parce qu'il interroge exactement ce que libvirt utilisera :

Fenêtre de terminal
virsh nodedev-dumpxml pci_0000_00_02_0 | grep -A2 iommuGroup

Sur un hôte capable, chaque périphérique porte son groupe :

<iommuGroup number='2'>
<address domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</iommuGroup>

Sur la machine qui a servi à écrire ce guide, aucun des 16 périphériques PCI n'en porte : le bloc est simplement absent de leur description. C'est le signal le plus net qu'il n'y a rien à tenter tant que le firmware n'a pas été repris.

Deux gestes, dans cet ordre, et un redémarrage entre les deux :

  1. Dans le firmware, activer Intel VT-d ou AMD-Vi, selon le fabricant. L'intitulé varie d'une carte mère à l'autre : IOMMU, Directed I/O, parfois SR-IOV.
  2. Ajouter le paramètre au noyau, dans la ligne GRUB_CMDLINE_LINUX_DEFAULT de /etc/default/grub :
Fenêtre de terminal
intel_iommu=on # processeurs Intel
amd_iommu=on # processeurs AMD

Puis sudo update-grub sur Debian et Ubuntu, sudo grub2-mkconfig -o /boot/grub2/grub.cfg sur RHEL et dérivés, et redémarrer.

Les groupes IOMMU décident de ce que vous pouvez donner

Section intitulée « Les groupes IOMMU décident de ce que vous pouvez donner »

C'est la contrainte que personne n'anticipe, et elle est matérielle. Les périphériques sont regroupés par le chipset selon leur isolation réelle, et un groupe se donne entier. Si votre carte graphique partage son groupe avec le contrôleur USB, donner la carte donne aussi l'USB.

Fenêtre de terminal
for g in /sys/kernel/iommu_groups/*/devices/*; do
echo "groupe ${g#/sys/kernel/iommu_groups/} : $(lspci -nns "${g##*/}" 2>/dev/null)"
done | sort -V

Trois situations courantes :

Ce que le groupe contientCe que cela implique
Le périphérique seulCas idéal, rien d'autre à céder
Le périphérique et sa fonction audioNormal sur un GPU : on donne les deux, c'est voulu
Le périphérique et d'autres cartesIl faut tout donner, ou renoncer

Une fois l'IOMMU active et le groupe vérifié, le périphérique doit quitter son pilote hôte au profit de vfio-pci, le pilote générique qui le tient à disposition de QEMU.

Fenêtre de terminal
virsh nodedev-detach pci_0000_01_00_0

libvirt fait alors tout le travail : il retire le pilote en place et attache vfio-pci. La commande inverse, virsh nodedev-reattach, rend le périphérique à l'hôte.

La déclaration dans la machine se fait par un bloc <hostdev> :

<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</source>
</hostdev>

L'attribut managed='yes' est celui qui change la vie : libvirt détache le périphérique au démarrage de la VM et le rend à l'hôte à l'arrêt, sans que vous ayez à enchaîner les nodedev-detach à la main.

C'est la question à se poser avant d'y passer une soirée. Le passthrough se justifie pour trois besoins, et rarement au-delà :

  • une carte graphique pour du calcul, du rendu ou du jeu, que rien n'émule ;
  • une carte réseau dont on veut la latence ou les fonctions propres, dans un pare-feu virtuel par exemple ;
  • un contrôleur de stockage passé entier à une VM de sauvegarde.

Pour tout le reste, virtio fait mieux : un disque virtio-blk ou une carte virtio-net offrent d'excellentes performances sans immobiliser du matériel, sans contrainte de groupe, et sans empêcher la migration de la machine. Une VM à laquelle un périphérique physique est attaché ne se déplace pas.

Vérifiez ce qui est acquis, en insistant sur la partie diagnostic : c'est elle qui décide si le passthrough est à votre portée, et c'est là que la plupart des tentatives s'arrêtent, faute d'IOMMU active.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  • Le passthrough exige l'IOMMU : sans elle, le noyau refuse, et il protège la mémoire de l'hôte en le faisant.
  • Le contrôle le plus fiable est l'absence ou la présence du bloc <iommuGroup> dans virsh nodedev-dumpxml. Sur la machine de ce guide, 0 périphérique sur 16 en portait.
  • Les groupes IOMMU sont imposés par le matériel, et un groupe se donne entier : la carte graphique peut entraîner le contrôleur USB avec elle.
  • L'hôte perd le périphérique tant que la VM tourne, d'où les configurations à deux cartes graphiques.
  • managed='yes' confie à libvirt le détachement et la restitution, ce qui évite d'enchaîner les commandes à la main.
  • Une VM avec un périphérique physique ne migre pas : pour tout ce que virtio sait faire, virtio reste préférable.
  • Dépannage réseau KVM : Quand une carte passée en direct fait disparaître le réseau de l'hôte.
  • Examen final : Vérifier ce qui est acquis sur l'ensemble du parcours.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn