Uubu.org

Systèmes d'information: une approche OpenSource

2 PC en 1

2 PC en 1: Assigner du matériel à une machine virtuelle

Le 25 janvier 2020 , Aucun commentaire pour cet article


2 PC en 1: Assignation de matériel dans une machine virtuelle

 

Dans cet article je vais expliquer comment créer 2 environnements sur un seul PC: Actuellement mon PC fait tourner Fedora, cependant je souhaite avoir en parallèle un Windows 10 pour ma femme. J'ai donc cherché une manière simple pour avoir 2 environnements distincts.

Note: J'utilise un CPU Intel, certains module et options sont spécifique à Intel. Les liens externes à la fin de l'article indiquent l'équivalent AMD.

 

1. Le matériel

J'ai récupéré une carte graphique d'un ancien pc, un écran y est connecté sur le bureau de ma femme. J'ai également ajouté un disque dur ssd 256Go, ainsi qu'un clavier/souris sans fil, qui seront dédiés à la machine virtuelle.

 

2. Trouver le matériel et configurer l'hôte

 

2.1. La carte graphique

Avant toute chose, IOMMU doit être activé, pour celà, ajouter dans grub l'option kernel intel_iommu=on et redémarrer.

On peut donc valider que IOMMU est activé avec la commande:

> dmesg | grep -i -e DMAR -e IOMMU

[    0.520131] DMAR: IOMMU enabled
[    0.782222] DMAR: Host address width 46
[    0.782223] DMAR: DRHD base: 0x000000b5ffc000 flags: 0x0
[    0.782227] DMAR: dmar0: reg_base_addr b5ffc000 ver 1:0 cap 8d2078c106f0466 ecap f020df
[    0.782228] DMAR: DRHD base: 0x000000d8ffc000 flags: 0x0
[    0.782230] DMAR: dmar1: reg_base_addr d8ffc000 ver 1:0 cap 8d2078c106f0466 ecap f020df
[    0.782231] DMAR: DRHD base: 0x000000fbffc000 flags: 0x0
[    0.782233] DMAR: dmar2: reg_base_addr fbffc000 ver 1:0 cap 8d2078c106f0466 ecap f020df
[    0.782234] DMAR: DRHD base: 0x00000092ffc000 flags: 0x1
[    0.782236] DMAR: dmar3: reg_base_addr 92ffc000 ver 1:0 cap 8d2078c106f0466 ecap f020df
[    0.782237] DMAR: RMRR base: 0x0000003dbf3000 end: 0x0000003dbf5fff

...

 

VFIO

vfio est le pilote qui va nous permettre d'assigner notre carte graphique à notre VM. Pour commencer, identifions la carte graphique:

> lspci | grep VGA

17:00.0 VGA compatible controller: NVIDIA Corporation GM107 [GeForce GTX 750 Ti] (rev a2)
65:00.0 VGA compatible controller: NVIDIA Corporation GP106 [GeForce GTX 1060 6GB] (rev a1)

 

La carte graphique à assigner à la VM est la GTX 570, regardons cette carte plus en détail en utilisant le slot pci (en gras ci-dessus):

> lspci -vn -s 17:00.0

17:00.0 0300: 10de:1380 (rev a2)
        Subsystem: 1458:3667
        Flags: bus master, fast devsel, latency 0, IRQ 108, NUMA node 0
        Memory at b4000000 (32-bit, non-prefetchable) [size=16M]
        Memory at dfe0000000 (64-bit, prefetchable) [size=256M]
        Memory at dff0000000 (64-bit, prefetchable) [size=32M]
        I/O ports at 7000 [size=128]
        Expansion ROM at b5000000 [disabled] [size=512K]
        Capabilities:
        Kernel driver in use: nouveau
        Kernel modules: nouveau

On peut voir que par défaut, le pilote graphique nouveau est utilisé.

En recherchant sur le slot: 17:00 on trouve un périphérique audio de la carte:

> lspci -s 17:00

17:00.0 VGA compatible controller: NVIDIA Corporation GM107 [GeForce GTX 750 Ti] (rev a2)
17:00.1 Audio device: NVIDIA Corporation Device 0fbc (rev a1)

 

On peut valider que ces 2 périphériques sont bien présents dans le même groupe IOMMU:

> shopt -s nullglob; for g in /sys/kernel/iommu_groups/*; do echo "IOMMU Group ${g##*/}:"; for d in $g/devices/*; do echo -e " $(lspci -nns ${d##*/})"; done; done;

[...]

IOMMU Group 31:
        17:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM107 [GeForce GTX 750 Ti] [10de:1380] (rev a2)
        17:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:0fbc] (rev a1)

[...]

 

Nous allons donc forcer le système à utiliser vfio pour ces 2 périphériques. ci-dessus en gras les identifiant vendor:device qui vont nous servir à les identifer:

 

Créer un fichier /etc/modules-load.d/vfio.conf, afin de charger les pilote vfio au démarrage:

vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd

 

Créer un fichier /etc/modprobe.d/vfio.conf, en spécifiant les identifiant vendor:device nos 2 périphériques :

options vfio-pci ids=10de:1380,10de:0fbc disable_vga=1

 

enfin, le pilote graphique étant chargé assez tôt dans la séquence de boot, il est nécessaire de passer les informations au kernel au boot:

rd.driver.pre=vfio-pci vfio-pci.ids=10de:1380,10de:0fbc

 

Rédémarrer le système.

 

On peut donc vérifier que le pilote est utilisé avec:

> lspci -vn -s 17:00.0

17:00.0 0300: 10de:1380 (rev a2)
        Subsystem: 1458:3667
        Flags: bus master, fast devsel, latency 0, IRQ 108, NUMA node 0
        Memory at b4000000 (32-bit, non-prefetchable) [size=16M]
        Memory at dfe0000000 (64-bit, prefetchable) [size=256M]
        Memory at dff0000000 (64-bit, prefetchable) [size=32M]
        I/O ports at 7000 [size=128]
        Expansion ROM at b5000000 [disabled] [size=512K]
        Capabilities:
        Kernel driver in use: vfio-pci
        Kernel modules: nouveau

Ok, notre carte graphique est prête, passons aux autres périphériques.

 

2.2. Disque dur

On pourrait faire de même pour le disque dur, cependant, celà va déconnecter tous les disques connectés au contrôleurs sata d'un coup. Une possibilité serait d'utiliser une carte PCI avec des ports SATA, tous les disques dur branchés sur cette carte seront donc déconnectés de l'hôte et pourrons être utilisés dans la VM.

Comme je souhaite assigner qu'un seul disque, /dev/sdp, je l'utiliserai directement comme périphérique raw

 

2.3 Clavier/Souris

Comme j'ai un combo clavier/souris sans fil, donc je ne vois qu'un seul périphérique:

> lsusb

[...]

Bus 001 Device 005: ID 046d:c52b Logitech, Inc. Unifying Receiver

[...]

 

Je vais simplement changer les permissions sur ce périphérique, afin que l'utilisateur qui va lancer la VM puisse y accéder. Mon compte utilisateur étant déjà membre du groupe qemu, donc:

> chown root:qemu /dev/bus/usb/001/005

 

Tout est prêt pour lancer la VM

 

3. la configuration de QEMU

Commençons par les paramètres classiques:

qemu-system-x86_64 -name Windows10 -machine q35,accel=kvm -smp 2,cores=1,threads=2,sockets=1,maxcpus=2 -numa node,nodeid=0 -numa cpu,node-id=0,socket-id=0 -cpu host,+x2apic,+kvm-asyncpf,+kvm-hint-dedicated,+kvm-mmu,+kvm-nopiodelay,+kvm-pv-eoi,+kvm-pv-ipi,+kvm-pv-tlb-flush,+kvm-pv-unhalt,+kvm-steal-time,+kvmclock,+kvmclock-stable-bit,+kvm_pv_eoi,+kvm_pv_unhalt,+kvm_nopiodelay,kvm=off,-hypervisor -m 4G,slots=1,maxmem=8G -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE.fd -drive if=pflash,format=raw,file=/var/lib/VMMGR/UEFI/Windows10/OVMF_VARS.fd -global isa-debugcon.iobase=0x402 -debugcon file:/var/lib/VMMGR/UEFI/Windows10/OVMF_LOG.log -daemonize -no-user-config -nodefaults -msg timestamp=on --mem-prealloc -boot menu=on,strict=off,splash=/var/lib/VMMGR/UEFI/splash640.bmp,splash-time=2000 -global PIIX4_PM.disable_s3=1 -global PIIX4_PM.disable_s4=1 -device pci-bridge,id=pci.0,chassis_nr=1 -device qemu-xhci,p3=15 -device virtio-tablet-pci -drive if=none,id=DVD,readonly=on -device ide-cd,drive=DVD -device i6300esb,id=watchdog0 -watchdog-action none -device virtio-balloon-pci,id=balloon0 -object rng-random,id=rng0,filename=/dev/random -device virtio-rng-pci,rng=rng0,max-bytes=1234,period=2000 -overcommit cpu-pm=on -overcommit mem-lock=off -rtc base=localtime,clock=vm,driftfix=none -global kvm-pit.lost_tick_policy=discard -device vmgenid -display none -netdev tap,id=virtio-tap1,script=/var/lib/VMMGR/TAPSCRIPTS/tapup-swvpl-main,downscript=/var/lib/VMMGR/TAPSCRIPTS/tapdown-swvpl-main,vhost=on,queues=8 -device virtio-net-pci,netdev=virtio-tap1,mac=52:54:00:00:00:09,id=drive-virtio-tap1,tx=bh,host_tso6=on,host_tso4=on,guest_tso6=on,guest_tso4=on,gso=on,rx_queue_size=1024,tx_queue_size=1024,mq=on,vectors=12,ctrl_vq=on,page-per-vq=on,disable-legacy=on,disable-modern=off,x-disable-pcie=off,x-pcie-lnksta-dllla=on,x-pcie-extcap-init=on,x-pcie-pm-init=on,x-pcie-deverr-init=on,x-pcie-lnkctl-init=on,event_idx=on,iommu_platform=on,ats=on,host_ecn=off,guest_ecn=on,host_mtu=1500,host_ufo=off,guest_ufo=off,guest_announce=on,speed=1024,duplex=full,status=on,ctrl_vlan=off,multifunction=on,ctrl_mac_addr=off,ctrl_rx=on,ctrl_rx_extra=on,guest_csum=off,csum=on,ctrl_guest_offloads=on,notify_on_empty=on,mrg_rxbuf=on,ioeventfd=on -monitor telnet:swvpl-main:3000,server,nowait

 

Ici je passe les détails sur les paramètres. Noter que j'utilise un script perso dont le lien est en fin d'article pour me simplifier la vie.

Ensuite on déclare notre carte graphique, en spécifiant les 2 slots PCI:

-device ioh3420,bus=pcie.0,addr=1c.0,multifunction=on,port=1,chassis=1,id=root.1 -device vfio-pci,host=17:00.0,bus=root.1,addr=00.0,multifunction=on,x-vga=off -device vfio-pci,host=17:00.1,bus=root.1,addr=00.1

Ensuite on déclare le disque:

-drive file=/dev/sdp,format=raw,if=none,cache=none,id=hd0 -device ich9-ahci,id=ahci0 -device ide-drive,drive=hd0,bus=ahci0.0

et enfin le périphérique USB (mon combo clavier/souris):

-device usb-host,hostbus=1,hostaddr=5

 

Voilà, grâce à ces options, le disque dur est vu sans pilote virtio, le reste fonctionne nativement dans la VM, il suffira de télécharger les pilotes NVIDIA une fois Windows10 installé.

Note: La VM proposée ici a besoin de 3 pilotes Virtio: un pour le périphérique balloon, un pour le générateur aléatoire, et un pour la carte réseau. Comme les pilotes Virtio ne sont pas signés, il faut utiliser le mode test pour pouvoir les utiliser. On peut toutefois ne pas utiliser balloon et rng, et pour la carte réseau, utiliser soit une 2ème carte pci, soit d'un adaptateur usb-ethernet en utilisant les informations ci-dessus pour l'assigner à la VM. Cela permettra de se passer intégralement des pilotes virtio.

 

Liens utiles:

Article très complet sur le pci-passthrough:

https://wiki.archlinux.org/index.php/PCI_passthrough_via_OVMF

Mon script de gestion de VM:

https://github.com/uubufr/VMMgr

Aucun commentaire pour cet article

Note: Les commentaires sont temporaiment désactivés, merci de contacter l'auteur par mail