Windows sur le même disque en tant qu'hôte invité dans KVM

A $DAYJOB, on me fournit comme outil de travail un ordinateur portable qui tourne sous Windows 10. Je sais bien que cette version est devenue presque utilisable au quotidien et que Microsoft est en pleine transformation mais étant un aspirant crypto anarchiste en voie d’ossification avec des habitudes tenaces, je préfère quand même utiliser un système libre. Idéalement, j’aimerais pouvoir installer OpenBSD mais le matériel n’est pas supporté, en tous cas ça ne démarre pas. Mon choix suivant serait Debian mais pour profiter de SecureBoot, il y a quelques manipulations à faire et devant rendre mon ancien poste rapidement, je me suis donc tourné vers Ubuntu.

L’ordinateur étant la propriété de mon employeur et moi-même étant dans la position d’une éventuelle utilisation du système d’origine, il faut pouvoir installer les deux systèmes côte à côte pour pouvoir démarrer l’un ou l’autre, ce qu’on appelle communément le dual boot. C’est donc une pratique courante et bien documentée. Mais plutôt que de basculer d’un système à l’autre, pourquoi ne pas également utiliser Windows dans Linux ? Le premier est déjà installé, l’éditeur nous autorise à le faire, c’est techniquement possible grâce à la virtualisation. Il existe plusieurs solutions de virtualisation ou paravirtualisation sous Linux, citons par exemple VirtualBox ou Xen. Mais nous allons utiliser KVM qui est intégré au noyau et qui permet des performances proches de celles du matériel physique si on utilise les pilotes para virtualisés virtio. Avec libvirt et virt-manager, on a une solution presque facilement utilisable. Evidemment, faire tourner deux systèmes d’exploitation ça demande des ressources processeur et surtout mémoire. Concernant le processeur, il en faut un qui supporte le jeu d’instructions VT chez Intel ou AMD-V chez son concurrent principal. Pour la ram, ça dépendra surtout de la mémoire allouée à la machine virtuelle, avec 4Gio alloués, on peut fonctionner avec une machine en comportant 8 mais c’est quand même mieux avec 16. Pour le disque, ça va aussi beaucoup plus vite avec un SSD.

On a donc au préalable installé un ubuntu. S’agissant d’un ordinateur moderne, le disque utilise une table de partitionnement GPT et le système est configuré pour utiliser UEFI. On a donc une partition de démarrage EFI (/dev/sda1), des partitions windows (/dev/sda[234]), du swap pour linux (/dev/sda5) et une partition qui contient l’installation d’ubuntu (/dev/sda6) :

➜  ~ sudo fdisk -l /dev/sda                                 
Disque /dev/sda : 477 GiB, 512110190592 octets, 1000215216 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : gpt
Identifiant de disque : C957E3B5-C756-4C42-B27E-54DF29F001F7

Périphérique     Début        Fin  Secteurs Taille Type
/dev/sda1         2048    1026047   1024000   500M Système EFI
/dev/sda2      1026048    1288191    262144   128M Réservé Microsoft
/dev/sda3      1288192  507095039 505806848 241,2G Données de base Microsoft
/dev/sda4    998184960 1000212479   2027520   990M Environnement de récupération Windows
/dev/sda5    507095040  539095039  32000000  15,3G Partition d'échange Linux
/dev/sda6    539095040  739094527 199999488  95,4G Système de fichiers Linux

Les entrées de la table de partitions ne sont pas dans l'ordre du disque.
 

Je crois que KVM est installé par défaut dans Ubuntu (au moins la 18.04 aka bionic), je ne me souviens pas l’avoir installé (c’est le paquet qemu-kvm) mais on a également besoin des paquets libvirt-daemon et virt-manager. Windows est configuré pour démarrer en UEFI, il nous faut donc également le paque ovmf. On peut maintenant créer une nouvelle machine virtuelle dans virt-manager qui va pointer sur notre installation de Windows.

Création Le disque existe déjà… on peut donc simplement l’importer et cliquer sur suivant.

Etape 2 Il faut spécifier le disque complet et pas la partition Windows. J’imagine que le type de système d’exploitation implique le choix de certains paramètres de la machine virtuelle par défaut.

Etape 3 Sur ma machine avec un processeur à 2 cœurs avec SMT (ou HyperThreading™) et 16Gio de mémoire, c’est bien supporté.

Etape 4 Le nom de la machine virtuelle est suggéré par virt-manager. J’en avais déjà une qui s’appelait win10, il a donc proposé win10-2… Il ne faut pas oublier de cocher la case “Personnaliser la configuration avant l’installation”. Pour le réseau, j’ai choisi d’utiliser l’interface réseau ethernet de mon poste en mode source “Pont”, de cette manière, la machine virtuelle aura sa propre adresse IP sur le réseau local fourni par le serveur DHCP de l’entreprise. Par contre, l’inconvénient du pilote macvtap est qu’il ne permet pas à l’hôte et à l’inviter de se voir sur le réseau en mode pont.

Etape 5 Ici, il faut changer le microprogramme pour utiliser l’UEFI fourni par OVMF.

Etape 6 J’ai changé le bus du disque émulé en SATA, je ne suis pas certain que ça a un vrai impact sur les performances. Idéalement, il faudrait utiliser Virtio mais windows ne démarre pas en bare metal sur ce nouveau poste si le pilote disque virtio est installé (mais ça marchait sur l’ancien), je ne sais pas si c’est lié à la version du pilote, au disque ou encore autre chose.

On peut maintenant cliquer sur “Commencer l’installation”, ce qui devrait afficher le logo suivant :

Etape 7 Là, il faut vite appuyer sur la touche “Echap” en s’assurant que la fenêtre de la machine virtuelle a bien le focus.

Etape 8 On arrive alors dans le programme de configuration du microprogramme. Pour s’assurer que c’est bien Windows qui démarre, on va ajouter une entrée au menu de démarrage et le positionner en première position. Il faut donc choisir l’option “Boot Maintenance Manager”.

Etape 9 Maintenant, l’option “Boot Options”.

Etape 10 “Add Boot Option”.

Etape 11 Ce truc c’est normalement le disque dur.

Etape 12 Là c’est la partition EFI qui contient les fichiers de démarrage de chaque système installé.

Etape 13 On voit les différentes options de démarrage, on en veut ajouter une pour Windows qui se trouve dans le dossier “Microsoft”.

Etape 14 Tout au fond à droite, dans “Boot”.

Etape 15 Voilà le fichier qu’on cherche, c’est “bootmgfw.efi”.

Etape 16 Il faut lui donner un petit nom, au hasard “windows”.

Etape 17 Oui, c’est bon je suis sûr.

Etape 18 Maintenant, on change l’ordre.

Etape 19 Il est tout en bas pour l’instant mais si on tape sur la touche “Entrée” et puis sur “+” plein de fois…

Etape 20 …il se retrouve en haut.

Etape 21 Ok, c’est bon. On peut sortir de l’outil et voilà, windows doit normalement démarrer.

Etape 22

Pour un affichage de qualité, il faut utiliser Spice avec les pilotes QXL dans la machine virtuelle. C’est fourni dans un installeur. Ça permet également le copier/coller entre l’hôte et la machine virtuelle, mais ça passe par le réseau. J’ai donc défini une deuxième interface cette fois en mode NAT. Je démarre également la machine virtuelle en même temps que le système mais sinon sudo virsh start win10 && virt-viewer -f win10 &!.

Pour éviter de passer par ces étapes, vous pouvez utiliser le fichier de définition win10.xml. Il faudra éditer l’“uuid” et les adresses mac, je ne sais pas ce qui se passe sinon, et l’importer avec sudo virsh define win10.xml.