Journal VGA Passthrough par vfio sur libvirt / qemu / kvm sous Debian Jessie : ca fonctionne !

35
12
avr.
2014

Bonjour à tous,

Beaucoup de progrès ont été fait ces derniers mois sur VFIO (https://www.kernel.org/doc/Documentation/vfio.txt) dans les dernières versions du noyau linux.

Il devient maintenant possible d'attribuer un ou plusieurs GPU à une machine virtuelle sans pour autant avoir à patcher et à recompiler qemu. C'est stable et de plus en plus facile.

En effet la procédure que j'ai suivie fonctionne sur une Debian Jessie out of the box… ou presque \_0< !

Oui… il faut tout de même encore recompiler son noyau 3.13 pour y ajouter une seule et unique option de configuration : CONFIG VFIO_PCI_VGA qui doit être placé à y. Je pense que les équipes Debian ne vont pas tarder à l'activer par défaut ;)

Donc si votre plateforme supporte l'IOMMU et que la virtualisation vous intéresse c'est le moment de s'amuser un peu :).

Voici la procédure en question : https://bbs.archlinux.org/viewtopic.php?pid=1268413#p1268413

Ce qui donne grosso modo :

Recompiler un noyau avec CONFIG_VFIO_PCI_VGA=y.

Configurer les adresses pci à exclure lors du démarrage de l'hôte avec pci-stub dans le chargement des modules initrd pour éviter qu'un driver linux soit chargé lors du démarrage pour les cartes qui seront dédiés aux machines virtuelles.

Configurer une démarrage auto de vfio-bind avec un nouveau service dans system-d et les ids des cartes à lui passer.

Pour de meilleurs performances mettre les disques et interfaces réseau en virtio.

Faire un fichier de configuration pour libvirt pour la plateforme.

Pour ce qui est de virtio, l'iso est à télécharger chez Redhat (http://alt.fedoraproject.org/pub/alt/virtio-win/latest/images/). Les pilotes doivent être fourni à l'installation des invités pour que le matériel soit reconnu. Le montage de l'iso est aussi dans le fichier xml d'exemple ci dessous.

Que dire de plus, sinon que la machine pour laquelle le xml a été fait est est un Phenom X6 1055T sur une Gigabite 990FXA-UD3. J'ai pu lui passer une Nvidia GTX 275 et une Ati HD 3870 qui fonctionnent toutes les deux dans l'invité sous windows 7 avec l'accélération graphique sans freeze ou autre soucis. Elles encaissent de multiples reboot sans avoir à faire de bidouilles du type éjection du périphérique dans l'invité. Le xml en exemple concerne la Ati HD-3870.

Bref le bonheur tout fonctionne à merveille.

Pour ceux que ça intéresse voici le fichier xml que j'utilise pour libvirt / qemu. C'est lui qui m'a posé le plus de problème en somme :

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  <name>windows7</name>
  <uuid>c9c5bd4a-5055-4a60-0bd4-411b8495b1ed</uuid>
  <memory unit='KiB'>6291456</memory>
  <currentMemory unit='KiB'>6291456</currentMemory>
  <memoryBacking>
    <nosharepages/>
    <locked/>
  </memoryBacking>
  <vcpu placement='static'>4</vcpu>
  <os>
    <type arch='x86_64' machine='pc-q35-1.7'>hvm</type>
    <boot dev='cdrom'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <cpu>
    <topology sockets='1' cores='4' threads='1'/>
  </cpu>
  <clock offset='localtime'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type='block' device='disk'>
      <driver name='qemu' type='raw'/>
      <source dev='/dev/disk/by-id/XXXX ou /dev/sdXXXX'/>
      <target dev='vda' bus='virtio'/>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x04' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw'/>
      <source file='/media/medias/Windows7_Professionnel_N_ISO_64bit.iso'/>
      <target dev='hda' bus='ide'/>
      <readonly/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw'/>
      <source file='/media/medias/virtio-win-0.1-74.iso'/>
      <target dev='hdc' bus='ide'/>
      <readonly/>
      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
    </disk>
    <controller type='pci' index='0' model='pcie-root'/>
    <controller type='pci' index='1' model='dmi-to-pci-bridge'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </controller>
    <controller type='pci' index='2' model='pci-bridge'>
      <address type='pci' domain='0x0000' bus='0x01' slot='0x01' function='0x0'/>
    </controller>
    <controller type='ide' index='0'>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x1'/>
    </controller>
    <controller type='usb' index='0'>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x01' function='0x2'/>
    </controller>
    <controller type='virtio-serial' index='0'>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x08' function='0x0'/>
    </controller>
    <controller type='sata' index='0'>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
    </controller>
    <interface type='bridge'>
      <mac address='52:54:00:a3:0a:7e'/>
      <source bridge='br0'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target type='serial' port='0'/>
    </console>
    <channel type='spicevmc'>
      <target type='virtio' name='com.redhat.spice.0'/>
      <address type='virtio-serial' controller='0' bus='0' port='1'/>
    </channel>
    <sound model='ich6'>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x07' function='0x0'/>
    </sound>
    <hostdev mode='subsystem' type='pci' managed='yes'>
      <source>
        <address domain='0x0000' bus='0x00' slot='0x12' function='0x0'/>
      </source>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x02' function='0x0'/>
    </hostdev>
    <hostdev mode='subsystem' type='pci' managed='yes'>
      <source>
        <address domain='0x0000' bus='0x00' slot='0x12' function='0x2'/>
      </source>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x06' function='0x0'/>
    </hostdev>
    <memballoon model='virtio'>
      <address type='pci' domain='0x0000' bus='0x02' slot='0x05' function='0x0'/>
    </memballoon>
  </devices>
  <seclabel type='none'/>
  <qemu:commandline>
    <qemu:arg value='-device'/>
    <qemu:arg value='vfio-pci,host=01:00.0,bus=pcie.0,addr=07.0,multifunction=on,x-vga=on'/>
    <qemu:arg value='-device'/>
    <qemu:arg value='vfio-pci,host=01:00.1,bus=pcie.0,addr=07.1'/>
    <qemu:arg value='-vga'/>
    <qemu:arg value='none'/>
    <qemu:arg value='-cpu'/>
    <qemu:arg value='qemu64'/>
  </qemu:commandline>
</domain>

Bon week end à tous :)
Christophe.

  • # virsh & quelques commandes

    Posté par . Évalué à 3. Dernière modification le 13/04/14 à 08:20.

    pour ceux qui se demandent quoi faire avec ce fichier XML, on peut créer/importer ceux-ci via la commande virsh.

    On peut générer ces fichiers depuis une ligne de commande qemu par exemple, puis compléter la configuration de la machine via "virt-manager", et re dumper le fichier XML, parce que les arguments qemu sont complexes à spécifier à la main.

    Par exemple :
    créer un de ces fichiers depuis un domaine existant
    $ virsh dumpxml "domain" > domain.xml
    depuis votre ligne de commande qemu préférée
    $ virsh domxml-from-native qemu "qemu-args"
    recréer la ligne de commande qemu après modifications dans virt-manager
    $ virsh domxml-to-native "domain" (marche pas toujours)

    voila. pour le cpu, je force systématiquement kvm32 ou kvm64, ça marche mieux avec ma mageia, mais j'en suis pas à faire du "passthrough" pour utiliser directement une CG depuis la machine virtuelle.

    • [^] # Re: virsh & quelques commandes

      Posté par . Évalué à 3.

      j'me réponds pour m'compléter (parce que je peux pas éditer):

      virt-manager, c'est le clickodrome où on utilise ces domaines. C'est sympa, en tout cas, plus que qemu en ligne de commande, même si on connait toutes les options, ça rend la chose plus accessible. Mais il faut savoir une chose important : il y a 2 modes concernant le driver qemu :

      Soit on lance en mode session (qemu se lance alors en user),
      $ virt-manager -c qemu:///session

      soit en mode system, et là, il vaut mieux connaitre SELinux, ou autre joyeusetées dans ce genre.

      virt-manager permet aussi de gérer plusieurs serveurs en un seul endroit

      $ virt-manager -c qemu+ssh://user@machine/session

      faut faire gaffe à ça.

      • [^] # Re: virsh & quelques commandes

        Posté par . Évalué à -8.

        virt-manager, c'est le clickodrome

        clickodrome qui crashe sans arrêt depuis des années et qui est tellement rigide qu'avec vmware player on a l'impression d'être le roi du monde.

        • [^] # Re: virsh & quelques commandes

          Posté par . Évalué à 5.

          clickodrome qui crashe sans arrêt depuis des années et qui est tellement rigide qu'avec vmware player on a l'impression d'être le roi du monde.

          N'importe quoi. Ça fait le boulot, c'est simple à configurer, rien à redire.
          Mais il faut toujours un troll comme toi, pour pourrir le boulot des autres en venant prôner un logiciel privateur.

          Triste sir.

          "Gentoo" is an ancient african word, meaning "Read the F*ckin' Manual". "Gentoo" also means "I am what I am because you all are freaky n3rdz"

          • [^] # Re: virsh & quelques commandes

            Posté par . Évalué à 2.

            clickodrome qui crashe sans arrêt depuis des années et qui est tellement rigide qu'avec vmware player on a l'impression d'être le roi du monde.

            N'importe quoi. Ça fait le boulot, c'est simple à configurer, rien à redire.

            Tout à fait d'accord, j'ai utilisé Virt-manager tous les jours au boulo pendant plus de 6 mois pour gérer parfois 6 ou 7 VM (Debian, RedHat, Mint, CentOS, …) et je n'ai jamais subi un seul crash !

            Sinon merci pour ce journal, j'ai hâte d'avoir un CPU avec des instructions IOMMU pour pouvoir enfin avoir des VM avec l'accélération graphique matérielle \o/

            Sinon une petite question :

            Configurer les adresses pci à exclure lors du démarrage de l'hôte avec pci-stub dans le chargement des modules initrd pour éviter qu'un driver linux soit chargé lors du démarrage pour les cartes qui seront dédiés aux machines virtuelles.

            Cela veut il dire que l'on ne peut plus avoir accès à un périphérique sur le Linux hôte si on décide que ce périphérique sera passé à une VM ?

            kentoc'h mervel eget bezan saotred

            • [^] # Re: virsh & quelques commandes

              Posté par . Évalué à 3.

              Cela veut il dire que l'on ne peut plus avoir accès à un périphérique sur le Linux hôte si on décide que ce périphérique sera passé à une VM ?

              Ben oui, sinon imagine le merdier quand les deux OS vont aller jouer avec la carte graphique …

              • [^] # Re: virsh & quelques commandes

                Posté par (page perso) . Évalué à 4.

                On pourrait penser que le périphérique n'est indisponible pour l'hôte que lorsqu'on lance un invité qui l'utilise.
                Pas trop de problème pour un port parallèle ou un contrôleur USB (il faut que l'hôte cesse de l'utiliser). Mais pour une carte graphique c'est plus compliqué.
                La solution actuelle d'interdire l'hôte d'utiliser ces périphériques est la plus simple.
                À l'avenir je suppose que ce sera différent.

            • [^] # Re: virsh & quelques commandes

              Posté par . Évalué à 2.

              Pas de problème de stabilité de mon coté non plus. Il n'aime pas que l'on redémarre libvirt-bin quand il est connecté et affiche un message d'erreur pour dire qu'il a été déconnecté… bref c'est normal et c'est le seul message d'erreur que j'ai eu.
              Vu la configuration un peu exotique avec 3 gpu dans la machine et tous les tests que j'ai pu faire avec l'iommu vfio les pci assign etc je dirai même que l'ensemble est étonnamment stable pour des utilisations aussi expérimentales. Pas un crash système que ce soit invité ou hôte.

              Pas un crash du "clickodorme" non plus qui est effectivement très pratique pour ajouter les périphériques qui n'ont pas besoin d'avoir des options exotiques.
              Il faut aussi dire que les commandes de lancement de qemu générées par l'outil peuvent prendre 6 ou 7 lignes dans un terminal. C'est bien plus agréable d'éditer un fichier de configuration.

              Pour ce qui est du pci-stub oinkoink_daotter et Kerro ont tout juste à propos des drivers. Cf ma réponse plus bas à propos de partager une carte entre hôte et vm.

              J'ai hâte d'avoir un CPU avec des instructions IOMMU pour pouvoir enfin avoir des VM avec l'accélération graphique matérielle \o/

              AMD a quelques plateformes bon marché qui prennent en charge l'IOMMU. Coté Intel ils réservent ça plutôt au haut de gamme.
              Après sur le marché de l'occasion il y a vraiment de quoi faire, le 1055T m'a couté 50€ il y a environ deux ans.

          • [^] # Re: virsh & quelques commandes

            Posté par . Évalué à 2.

            Putain quand je lis ça je me dis que je dois avoir du matériel très exotique ou être l'homme le plus malchanceux de la planète. CentOS, Fedora, Ubuntu, Debian, chaque fois que j'utilise virt-manager, je mange des crashs à répétition, surtout si j'essaie de modifier du matériel dans l'assistant de création de la VM.

            Et bordel c'est pas une question de logiciel propriétaire, même VirtualBox est plus stable !

            • [^] # Re: virsh & quelques commandes

              Posté par . Évalué à 1.

              Putain quand je lis ça je me dis que je dois avoir du matériel très exotique

              Avec les processeurs que j'utilisais il y avait toujours les instructions VT-x (flag vmx dans /proc/cpuinfo pour les processeurs Intel)

              ou être l'homme le plus malchanceux de la planète

              Il peut y avoir un bug d'interface chaise clavier ;-)

              kentoc'h mervel eget bezan saotred

              • [^] # Re: virsh & quelques commandes

                Posté par . Évalué à 2.

                Du tout, pour avoir bossé sur Hyper-V, Vmware, VirtualBox, KVM (avec les lignes de commandes et le bridge à monter à la mano), je sais à peu près ce que je fais. Tu me cites VT-x, tu confonds peut-être KVM avec virt-manager…
                Je n'ai jamais critiqué KVM, mon problème c'est virt-manager (l'interface graphique pour libvirt).

                • [^] # Re: virsh & quelques commandes

                  Posté par . Évalué à 1.

                  tu confonds peut-être KVM avec virt-manager…

                  Non non c'est juste que j'utilisais virt-manager avec (pour paramétrer) KVM donc j'ai fais un lien entre les deux.

                  kentoc'h mervel eget bezan saotred

            • [^] # Re: virsh & quelques commandes

              Posté par (page perso) . Évalué à 2.

              Si c'est sur une même machine, on peut penser qu'elle a un problème.
              Si c'est sur des machines différentes, je pense que tu bricoles trop tes distributions :-)

              Pour ma part j'utilise KVM depuis… heu… des années (7 ans ?) et j'ai eu un seul problème avec (c'est Nicolas PARPANDET qui a trouvé l'explication) : il y avait un problème de compatibilité avec les processeurs AMD sur une distribution 64-bits et une carte-mère précise. À part ça, zéro (jamais) pépin, même à l'arrache.

              Par contre avec VirtualBox j'ai parfois des soucis. Je m'en sert pour faire des trucs rapidos sur des hôtes Windows et des fois je le secoue un peu trop fort.

              • [^] # Re: virsh & quelques commandes

                Posté par (page perso) . Évalué à 3.

                Par contre avec VirtualBox j'ai parfois des soucis. Je m'en sert pour faire des trucs rapidos sur des hôtes Windows et des fois je le secoue un peu trop fort.

                J'ai eu plus de soucis avec VirtualBox sous Windows que sous Linux (tout en l'utilisant plus sous Linux).

                « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

              • [^] # Re: virsh & quelques commandes

                Posté par . Évalué à 4.

                Attention à ne pas confondre KVM avec virt-manager, ou même libvirt.
                KVM marche plutôt bien, c'est virt-manager que je critique.

                • [^] # Re: virsh & quelques commandes

                  Posté par (page perso) . Évalué à 2.

                  Ah exact.
                  Du coup je n'ai aucun retour d'expérience vu que j'utilise QEMU/KVM via ligne de commande ou scripts (je n'ai pas saisi l'intérêt de rajouter une couche de complexité pour obtenir moins de souplesse, sans pour autant allégé les connaissances nécessaires).

  • # Reboot de la carte entre Host et Slave

    Posté par (page perso) . Évalué à 2.

    Je me suis toujours demandé s’il était possible de faire rebooter la carte entre l'host (ici un Linux) et l'esclave (ici un Windows) SANS rebooter le système host.

    Exemple d'utilisation, j'ai une machine avec un CPU Intel contenant un GPU Intel intégré, suffisant pour les besoins de bureautique. J'ai aussi un GPU Nvidia et un GPU AMD dans la machine.

    90% du temps, je "travaille", ce qui implique que je développe sous Linux et que je teste mon code openGL/openCL sur mes différents GPUs.

    Le serveur X tourne sur le GPU Intel intégré, et je pourrais utiliser virtualgl pour envoyer des commandes à mes GPU AMD et nvidia.

    De temps à autre, je joue. Sous wine, en utilisant virtualgl pour addresser le GPU qui va bien (en fonction du jeu).

    Dans de rares occurrences, je veux pouvoir faire cela sous Windows aussi, avec la carte NVIDIA et l'ATI. a) pour tester mon code et b) pour jouer.

    Solution a) Je reboot tout, c'est lourd. Solution b) Je peux seulement "désactiver" les GPU NVIDIA et ATI et booter la VM dessus. Comme cela je garde ma session "bureautique" qui tourne sur le GPU intégré Intel, mais je peux booter un Windows à performance "native" sur les deux autres GPU.

    • [^] # Re: Reboot de la carte entre Host et Slave

      Posté par . Évalué à 2.

      en compilant le module en "module" (m dans la config) et pas en dure (y dans la config) dans le noyau
      tu dois pouvoir le charger à la demande, et le decharger quand tu n'en as pas besoin.

      cela correspondrait à ce que tu veux faire,

      apres faut voir si le systeme le permet.

      • [^] # Re: Reboot de la carte entre Host et Slave

        Posté par . Évalué à 1. Dernière modification le 16/04/14 à 11:13.

        En gardant les GPU gérés par le module vfio il est possible d'avoir plusieurs vms qui s'adressent aux mêmes GPU. Pas en même temps bien entendu mais pour avoir des vms dédiées à certaines activités cela peut avoir un intérêt.
        Par contre au niveau de l'hôte une fois que les modules fglrx se sont lancés - dans le cas de ma carte ATI - c'est terminé. Même en virant le module je n'ai pas pu réutiliser la carte avec vfio.
        C'est pour cela que l'on doit mettre les cartes en pci-stub au lancement, pour qu'aucun pilote graphique ne se charge.
        Donc rien ne t’empêche de les partager entre vms. Mais pas avec l'hôte d'après mon expérience. En tout cas pour le moment.

      • [^] # Re: Reboot de la carte entre Host et Slave

        Posté par . Évalué à 2.

        Normalement ya même pas besoin de compiler en module, les attributs unbind et bind du sysfs te permettent dissocier un périphérique d'un driver.

        Par contre comme Christophe K. a l'air de dire que décharger le module ne suffit pas, cette solution ne marchera pas plus (ça fait la même chose), c'est donc que la carte garde un état foireux. Dans ce cas-là il faudrait voir si on peut demander au bus PCI de couper l'alim de la carte, pour la hard-rebooter.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.