Deux réglages faits une fois puis oubliés

Proxmox VE 9 fait deux choses utiles pour vous sans qu’on le lui demande. Il donne à un invité Fisher-Price OS (Windows) les fonctions paravirtuelles dont il a besoin pour tourner correctement sur KVM, et il charge un microcode CPU à jour au démarrage.

Les deux sont automatiques. Les deux dépendent aussi d’une décision prise une fois, il y a peut-être des années, et jamais revue depuis.

La première dépend du OS Type choisi à la création de la VM. Prenez une des entrées Microsoft Windows et Proxmox ajoute les enlightenments Hyper-V à chaque démarrage. Laissez Other, ce qui arrive facilement quand on importe un disque ou qu’on clone quelque chose d’ancien, et l’invité n’en reçoit aucun. Il démarre, il tourne, il est plus lent, et rien ne vous le dit.

La seconde dépend de la façon dont l’hôte est arrivé en version 9. L’installateur 9.0 active le composant firmware de Debian et installe le paquet de microcode adapté à votre CPU. Un hôte mis à niveau depuis la 8.x garde les dépôts qu’il avait, et sur la plupart d’entre eux, cela veut dire aucun paquet de microcode. Sur un hôte AMD Zen 5 avec un noyau 6.17.9 ou plus récent, ce n’est pas un trou théorique : les invités qui utilisent les types de CPU EPYC ne démarrent plus.

Deux réglages par défaut, deux choix oubliésUne VM : selon son OS TypeOS Type, choisi une foisMicrosoft WindowsOther ou Linuxflags hv_ ajoutésà chaque démarrageaucun flaget aucun avertissementUn hôte : selon son chemin vers la 9Hôte Proxmox VE 9installateur 9.xmis à niveau de 8.xpaquet de microcodeinstalléaucun paquetpve8to9 avertit seulement
Les deux réglages par défaut tiennent à un choix fait bien avant que quoi que ce soit ne tourne mal. Dans chaque cas, le chemin de droite est celui contre lequel rien ne vous prévient.

La suite prend chacun à son tour : ce que c’est, la règle exacte que Proxmox applique, comment l’activer là où il manque, et comment prouver que ça a pris. Les règles viennent du code de qemu-server et de pve-manager sur un hôte 9.2 en production, pas de mémoire, parce que deux d’entre elles ne sont pas ce que la plupart des gens devineraient.

Ce qu’est vraiment un enlightenment

Un système d’exploitation invité écrit pour du vrai matériel dépense beaucoup d’efforts sur des choses inutiles dans une VM. Il programme ses timers à travers des puces émulées, tourne en boucle sur des verrous tenus par un vCPU qui n’est même pas ordonnancé, et déclenche des watchdogs quand l’hôte lui vole quelques millisecondes.

La paravirtualisation règle ça en faisant savoir à l’invité qu’il est un invité, et en le laissant parler directement à l’hyperviseur. Linux le fait avec les interfaces propres à KVM. Le Fisher-Price OS (Windows) ne parle qu’un seul dialecte paravirtuel, celui d’Hyper-V, alors KVM implémente ce dialecte et annonce à l’invité qu’il tourne sur un hyperviseur compatible Hyper-V. Chaque morceau de ce dialecte s’appelle un enlightenment.

Rien de tout ça n’est actif tant que quelque chose ne le demande pas. La documentation de QEMU est claire là-dessus : « No Hyper-V enlightenments are enabled by default by either KVM or QEMU »1. Sur Proxmox, ce qui le demande, c’est qemu-server, et il ne le demande que si le type d’OS est une des entrées Microsoft Windows.

Vous pouvez voir la différence sur n’importe quel hôte. Voici une VM Linux sur mon nœud 9.2, ostype: l26, type de CPU host :

# qm showcmd 101 --pretty | grep -- -cpu
  -cpu host,+kvm_pv_eoi,+kvm_pv_unhalt \

Deux flags KVM pour la gestion paravirtuelle des interruptions et des spinlocks propre à Linux, et aucun flag hv_. Correct pour Linux. Faux pour un invité qui ne comprend que Hyper-V.

Ce que fait chaque enlightenment, d’après les descriptions de QEMU1 :

FlagCe que l’invité reçoitCe que ça économise
hv_timehorloge de référence Hyper-V et page TSClectures d’horodatage sans sortie de VM
hv_relaxedconsigne de désactiver les délais du watchdogfaux dépassements quand un vCPU est désordonnancé
hv_vapicpage d’assistance VP pour l’APICfin d’interruption sans sortie de VM
hv_spinlocksspinlocks paravirtuels, nombre d’essais avant de prévenir l’hôtetourner sur un verrou dont le détenteur ne tourne pas
hv_vpindexson propre index de processeur virtuelprérequis des quatre suivants
hv_runtimele temps réel d’exécution de chaque vCPUune vue honnête du temps volé
hv_synic, hv_stimercontrôleur d’interruptions et timers synthétiquesmatériel de timer émulé
hv_ipienvoyer des IPI à plusieurs vCPU en un seul hypercallune sortie APIC par CPU cible
hv_resetréinitialisation via l’hyperviseur
hv_evmcsVMCS enlightened, Intel uniquementvirtualisation imbriquée plus rapide
hv_tlbflushinvalidation de TLB paravirtuelleattendre des vCPU qui ne tournent pas

Le type d’OS est l’interrupteur

La règle tient dans une seule fonction, get_hyperv_enlightenments, dans le CPUConfig.pm de qemu-server2. Le type d’OS est d’abord converti en numéro de version : win11 devient 11, win10 devient 10, w2k8 et wvista deviennent tous deux 6, et les types XP et 2003 deviennent 5. Linux, Other et tout le reste deviennent 0.

Ensuite les portes s’appliquent dans l’ordre.

Les flags hv_ qu'ajoute qemu-server, porte par porteDu type d'OS aux flags hv_, dans l'ordre du codeVersion du type d'OS inférieure à 6 ?ouiarrêt : rien d'ajoutéFirmware OVMF et version inférieure à 8 ?ouiarrêt : rien d'ajoutémachine 2.3, puis 2.6 ou ultérieureajoutespinlocks vapic time reset vpindex runtimeversion 7 ou plusajouterelaxed synic stimer ipihôte Intel, version 11, machine 11.0+pve2ajouteevmcs
L’ordre dans lequel qemu-server les applique. Une version inférieure à 6 s’arrête à la première porte, et un invité UEFI antérieur au type 8.x s’arrête à la seconde, sans rien du tout d’ajouté.

Lire une règle, c’est une chose. L’exécuter, c’est mieux. J’ai donc chargé le CPUConfig.pm installé sur deux hôtes 9.2, mon nœud AMD Ryzen pour les lignes AMD et un nœud Intel Celeron N5100 pour les lignes Intel, et appelé cette fonction avec chaque combinaison :

Type d’OSFirmwareVersion de machineHôteEnlightenments ajoutés
l26 ou othertoustoutestousaucun
wxp (5)SeaBIOS11.0tousaucun
w2k8 (Vista/2008)SeaBIOS11.0tousspinlocks, vapic, time, reset, vpindex, runtime
win7SeaBIOS11.0tousles six ci-dessus plus relaxed, synic, stimer, ipi
win7OVMF11.0tousaucun
win10OVMF11.0+pve2Intelles dix, sans evmcs
win11OVMF11.0+pve1Intelles dix, sans evmcs
win11OVMF11.0+pve2Intelles dix plus evmcs
win11SeaBIOS11.0+pve2AMDles dix, sans evmcs

Trois choses là-dedans méritent d’être sues avant de toucher à l’interface.

Un invité UEFI avec un type d’OS antérieur à 8.x n’a rien. Le code sort tôt quand le firmware est OVMF et la version inférieure à 8. Un invité 7/2008r2 que vous avez passé en UEFI a perdu en silence tous les enlightenments qu’il avait.

hv_evmcs exige trois choses à la fois. Un hôte Intel, le type d’OS 11/2022/2025, et une version de machine 11.0+pve2 ou ultérieure. Un invité 10/2016/2019 ne l’obtient jamais par défaut, aussi récente que soit sa version de machine.

Le fabricant de l’hôte est lu au démarrage de la VM. Le test appelle read_cpuinfo sur le nœud qui démarre la VM, pas sur celui où elle a été créée. Dans un cluster mêlant Intel et AMD, la même VM reçoit hv_evmcs sur un nœud et pas sur l’autre, et c’est décidé à nouveau à chaque démarrage à froid.

Les anciennes portes sur la version de machine (2.3, 2.6, 2.12, 3.1) ne concernent que les VM épinglées sur des machines du lointain passé de QEMU. Tout ce que vous créeriez aujourd’hui les franchit.

Choisissez donc le type d’OS le plus proche de l’invité, pas le plus récent de la liste. Un invité 10/2016/2019 va sur 10/2016/2019. La documentation de Proxmox donne une seconde raison pour laquelle le type compte au-delà de ces flags : il règle aussi, par exemple, si l’horloge RTC virtuelle tourne en heure locale3.

Pourquoi vos anciennes VM ratent le correctif de juillet

hv_evmcs par défaut, c’est nouveau. C’est arrivé dans qemu-server 9.2.0 le 15 juillet 2026, pour « mitigate guest freezes and 100% CPU usage seen on certain Intel CPUs with Windows guests that use Virtualization-Based Security (VBS) »4, et c’est lié à la version de machine 11.0+pve2.

Ce lien est le piège, parce que Proxmox épingle la version de machine de toute VM au type d’OS Microsoft Windows au moment de sa création. La documentation en donne la raison : « Windows is sensitive to changes in the virtual hardware - even between cold boots »3. C’est une décision saine. Elle veut aussi dire qu’une VM créée en juin 2026 est sur 11.0+pve1 ou plus ancien, et qu’elle y restera jusqu’à ce que quelqu’un la déplace.

Quelqu’un va-t-il la déplacer pour vous ? Non. Le nouveau réglage par défaut s’applique aux nouvelles VM et à celles que vous montez de version volontairement, et à rien d’autre.

Si vous avez des hôtes Intel qui font tourner des invités 11/2022/2025 avec VBS activé, et que certains se sont figés à 100 % de CPU, c’est la première chose à vérifier :

qm config <vmid> | grep -E '^(ostype|machine):'

Un ostype: win11 avec une ligne machine: inférieure à pc-q35-11.0+pve2 doit être monté de version pour recevoir le correctif. Le monter change le matériel virtuel que voit l’invité, c’est-à-dire exactement ce contre quoi l’épinglage protège. Faites-le donc dans une fenêtre de maintenance, après une sauvegarde ou un snapshot, via Hardware → Machine → Edit, cochez Advanced et choisissez la version.

Si la ligne commence par pc-i440fx-, la version est le moindre des problèmes : cet invité ne devrait pas être sur i440fx du tout, pour les raisons données dans Toujours Q35, jamais i440fx, et L’activer, et prouver que ça a pris plus bas s’en occupe.

Deux réglages par défaut voisins sont arrivés dans les mêmes quelques mois, et ils valent d’être connus pendant que vous y êtes. qemu-server 9.1.12 a désactivé les flags cet-ibt et cet-ss pour le type 11/2022/2025, parce qu’avec QEMU 11.0 et les noyaux 7.x qui les exposent, les invités avec VBS ne démarraient plus4. Et 9.1.14 a exposé la propriété CPU level, que la documentation décrit comme « a known workaround for Hyper-V boot failures of Windows guests on recent Intel hosts when the CPU type is host or max »3.

Le côté QEMU, version par version

qemu-server construit la ligne de commande. pve-qemu-kvm est le QEMU qui l’exécute, et le correctif de juillet a besoin des deux.

La version de machine 11.0+pve2 ne peut être choisie que si un binaire QEMU 11.0 est installé, parce que qemu-server refuse toute version de machine plus récente que le QEMU qu’il trouve sur l’hôte5. Le +pve2 est le compteur de révision de qemu-server, pas celui de QEMU, donc n’importe quel build 11.0 le satisfait. Le jour de la sortie de la 9.2.0, la paire se présentait ainsi :

PaquetVersionSortieCe qu’il apporte
qemu-server9.2.015 juillet 2026le défaut hv-evmcs et la machine 11.0+pve2
pve-qemu-kvm11.0.2-11er juillet 2026QEMU 11.0.2, le plus récent ce jour-là
pve-qemu-kvm, minimum11.0.0-15 mai 2026le premier build QEMU 11.0

apt va-t-il s’assurer que vous avez les deux ? Non. qemu-server 9.2.0 ne déclare rien de plus fort que pve-qemu-kvm (>= 7.1~)6, donc un nœud dont QEMU est resté bloqué en 10.x prend le nouveau qemu-server sans broncher, puis ne peut pas proposer la version de machine dont dépend le correctif. Vérifiez les deux, sur chaque nœud. Voici mon hôte 9.2 aujourd’hui, bien au-delà des deux :

# pveversion -v | grep -E '^(qemu-server|pve-qemu-kvm):'
pve-qemu-kvm: 11.0.3-4
qemu-server: 9.2.11

Chaque version de QEMU depuis que Proxmox VE 9.0 est sorti sur la 10.0.27 a apporté ses propres correctifs pour les invités Fisher-Price OS (Windows). Voici ceux qui touchent l’invité, d’après le changelog du paquet Proxmox8 et les changelogs amont de QEMU9 :

QEMUBuild ProxmoxCe qu’il a corrigé pour l’invité
10.010.0.2-1, 17 juin 2025le bug « PCI Label Id », sans conséquence en anglais mais capable de figer les installations localisées
10.110.1.2-3, 17 novembre 2025une régression du presse-papiers VNC qui cassait le pointeur de la souris
10.110.1.2-5, 22 décembre 2025les sauvegardes d’une VM avec un disque TPM qui restaient bloquées, un correctif io_uring
11.011.0.0-1, 5 mai 2026une régression de l’export FUSE qu’utilise swtpm pour l’état du TPM
11.011.0.2-1, 1er juillet 2026les enlightenments Hyper-V reconnus comme flags CPUID, pour qu’un modèle de CPU personnalisé puisse les porter

QEMU 11.0 a aussi cassé quelque chose : il s’est mis à exposer cet-ibt et cet-ss, ce qui a empêché les invités VBS de démarrer et a conduit qemu-server 9.1.12 à les désactiver, comme vu plus haut.

Les correctifs de l’agent invité dans ces mêmes versions sont une autre affaire. QEMU 10.1, 10.2 et 11.0 ont chacun corrigé une partie de la gestion VSS et du gel du système de fichiers de l’agent invité, dont le « Access denied Event ID 8194 » que la 11.0 a guéri9. Rien de tout cela n’arrive avec pve-qemu-kvm. L’agent de cet invité est livré sur l’ISO des pilotes virtio-win10, donc il ne change que lorsque vous mettez à jour l’agent dans la VM.

Les deux flags que vous pouvez poser à la main

Proxmox ne vous laisse pas ajouter n’importe quel flag CPU à une VM. Hardware → Processors → Edit, cochez Advanced, et Extra CPU Flags propose une liste fixe, définie dans CPUFlags.pm11. Deux entrées de cette liste sont des enlightenments, et ce sont les deux que Proxmox ne pose pas par défaut, ou ne posait pas jusqu’en juillet.

FlagLa description de ProxmoxQuand le poser
hv-tlbflush« Improve performance in overcommitted Windows guests. May lead to guest bluescreens on old CPUs. »Facultatif. Essayez d’abord sur une VM et surveillez-la.
hv-evmcs« Improve performance for nested virtualization. Only supported on Intel CPUs. »Hyper-V imbriqué, WSL2 ou VBS dans l’invité, sur Intel. Déjà actif pour 11/2022/2025 en 11.0+pve2.

Les deux sont devenus optionnels dans qemu-server 6.0-6 le 23 juillet 2019, décrits dans le changelog comme « sometimes problematic »4. hv-tlbflush est resté ainsi pendant sept ans. C’est un bon indice du nombre de tests qu’il demande avant de le déployer sur un cluster.

La note de QEMU sur hv-evmcs dit qu’il est réservé à Intel, et que « some virtualization features (e.g. Posted Interrupts) are disabled when hv-evmcs is enabled »1. L’activer à la main sur un invité qui ne fait pas de virtualisation imbriquée ne vous apporte rien et vous coûte ça.

L’activer, et prouver que ça a pris

Pour une nouvelle VM : Create VM → OS, mettez Type sur Microsoft Windows et Version sur la correspondance la plus proche.

Pour une VM existante : Options → OS Type → Edit, choisissez la version, OK. Proxmox épingle la version de machine quand vous passez une VM existante à un type Microsoft Windows, comme il le fait à la création4, alors attendez-vous à ce que la ligne machine: de la configuration change aussi.

Et mettez-la sur q35. Un invité avec enlightenments n’a rien à faire sur pc-i440fx. C’est le chipset sans bus PCIe, et les raisons vont bien au-delà du passthrough ; elles sont toutes dans Toujours Q35, jamais i440fx.

L’assistant ne vous en empêchera pas, et pour la plupart des types Microsoft Windows c’est là qu’il vous mettra. La documentation de Proxmox elle-même appelle Intel 440FX « the default »3, et les valeurs par défaut par OS de l’interface ne la remplacent que pour une seule entrée : 11/2022/2025 reçoit machine: 'q35' et bios: 'ovmf'12. Tous les autres types Microsoft Windows héritent des valeurs génériques, qui ne fixent aucune machine. Un invité 10/2016/2019 créé en cliquant sur Next atterrit donc sur i440fx, avec enlightenments et sur le mauvais chipset en même temps.

Type d’OS choisi dans l’assistantMachine obtenueFirmware obtenu
11/2022/2025q35OVMF
10/2016/2019 et tous les types Microsoft Windows plus anciensi440fxSeaBIOS
Other, Linuxi440fxSeaBIOS

Changez-le dans l’onglet System avant de terminer l’assistant. Pour une VM qui existe déjà, changer de chipset est une modification du matériel virtuel plus lourde qu’une montée de version de machine, donc les mêmes règles de fenêtre de maintenance et de sauvegarde s’appliquent, et l’article sur q35 couvre ce qu’en fait l’invité.

Ensuite, arrêtez-la proprement. Les enlightenments sont des arguments de la ligne de commande QEMU, et cette ligne n’est construite qu’au démarrage du processus QEMU. Un redémarrage depuis l’invité garde le même processus, donc il garde les anciens flags. Éteignez, attendez stopped, puis Start.

Prouvez-le depuis l’hôte, parce que c’est là qu’est la réponse :

qm showcmd <vmid> --pretty | grep -o "hv_[a-z_]*[=0-9a-fx]*" | sort -u

Cela affiche ce que qemu-server passera à QEMU au prochain démarrage. Un invité 11/2022/2025 en 11.0+pve2 sur Intel doit en lister onze : hv_evmcs, hv_ipi, hv_relaxed, hv_reset, hv_runtime, hv_spinlocks=0x1fff, hv_stimer, hv_synic, hv_time, hv_vapic et hv_vpindex. Le même invité sur AMD en liste dix. Un résultat vide veut dire que le type d’OS n’est pas un type Microsoft Windows, ou que c’est un type antérieur à 8.x sur UEFI.

Si un invité ne démarre plus après le changement, remettez le type d’OS sur Other le temps d’un démarrage pour mettre les enlightenments hors de cause, ou non. Il tourne sans eux. Il tourne juste moins bien.

Le microcode : ce qu’il corrige et d’où il vient

Le second réglage par défaut se trouve sous l’hyperviseur, pas au-dessus.

Le microcode CPU est le firmware du fabricant pour le processeur lui-même. Ses mises à jour corrigent des vulnérabilités de sécurité et de graves bugs du CPU, et le guide d’administration de Proxmox fait la remarque qui compte pour quiconque s’inquiète du coût en vitesse : « a patched microcode is usually still more performant than an unpatched microcode where the kernel itself has to do mitigations »13.

Il peut venir de trois endroits, et ils sont indépendants.

SourceAppliquéFourni parSur mon hôte 9.2 aujourd’hui
Mise à jour du BIOS/UEFI de la carteà chaque mise sous tension, persistantle fabricant de la carte ou du serveurce que portait le dernier BIOS
Debian non-free-firmwaretôt au démarrage, depuis l’initramfsDebianintel-microcode 3.20251111.1~deb13u1, amd64-microcode 3.20250311.1
Dépôt Proxmox VEtôt au démarrage, depuis l’initramfsProxmoxamd64-microcode 3.20251202.1~bpo13+1, pas de paquet Intel

La voie du BIOS est celle que Proxmox dit recommandée13. Le chargement précoce est le filet de sécurité pour quand le fabricant de la carte a cessé de publier des mises à jour de BIOS, ce qui, sur tout ce qui a quelques années, est en général le cas.

La troisième ligne m’a surpris. Proxmox fournit dans son propre dépôt un amd64-microcode plus récent que celui de Debian dans trixie14, avec la même priorité de pin, donc apt choisit celui de Proxmox. Sur un hôte AMD avec le dépôt Proxmox configuré, c’est la version que vous finirez par faire tourner, et comme le montre la section suivante, c’est la version qui compte.

Où le microcode est appliqué pendant un démarrageUn démarrage, de gauche à droiteMise sous tensionmicrocode du BIOSChargeurcharge l'initramfsLe noyau démarremise à jour précoceHôte en marcheinvités lancésChargement tardifbloquépersistant,fabricant de cartedepuis l'initramfs,Debian ou Proxmoxblacklist dans/etc/modprobe.d
Le chargement précoce a lieu avant que le noyau ait lancé quoi que ce soit d’autre. Le chargement tardif sur un système en marche est la voie que Debian bloque, et elle reste bloquée.

Le chargement précoce est ce que ce billet met en place. Le microcode va dans l’initramfs et le noyau l’applique tout au début du démarrage, avant que quoi que ce soit d’autre ne tourne.

Le chargement tardif l’applique à un système en marche. La documentation du noyau a une section intitulée « Why is late loading dangerous? » et, depuis la 5.19, il n’est plus activé par défaut15. Debian le bloque aussi. Voici le fichier sur mon hôte, mot pour mot :

# cat /etc/modprobe.d/amd64-microcode-blacklist.conf
# The microcode module attempts to apply a microcode update when
# it autoloads.  This is not always safe, so we block it by default.
blacklist microcode

N’y touchez pas. L’hôte ci-dessus l’a en place et montre quand même une mise à jour précoce réussie, donc il ne gêne rien.

Les deux voies demandent un redémarrage. Il n’y a pas moyen d’y couper.

Et c’est x86 uniquement. Le guide de Proxmox le dit sans détour : « There is no equivalent operating-system-level microcode package for arm64 »13.

Pourquoi un hôte mis à niveau n’en a pas

Le « non-free » de non-free-firmware concerne la licence, pas l’argent ni un abonnement Proxmox. Le wiki de Debian l’explique : le côté noyau est du logiciel libre, mais les données de mise à jour du fabricant sont opaques, « and its contents are unknown to Debian »16. C’est pour ça qu’elles vivent dans leur propre composant, et qu’un système Debian ne les reçoit pas tant que le composant n’est pas activé.

L’installateur de Proxmox VE 9.0 l’active. Les notes de version disent que l’ISO va « Install the microcode package matching the current platform », et que « installations now have the non-free-firmware repository enabled »7. Une mise à niveau ne fait ni l’un ni l’autre, parce qu’elle garde les lignes de dépôt que vous aviez en 8.x.

Installation 9.x neuveMis à niveau depuis la 8.x
non-free-firmwareactivé par l’installateurce qu’avait la 8.x, souvent absent
Paquet de microcodeinstallé pour le CPU détectéaucun, tant que vous n’ajoutez pas le composant
Ce qui vous prévientrien de nécessairepve8to9, par un FAIL et un WARN, et seulement si vous le lancez
Mises à jour suivantesapt full-upgrade et un redémarragepareil, une fois le paquet en place

Le vérificateur le signale bel et bien, plus fort que je ne m’y attendais. Le voici sur mon nœud Intel, qui vient de la 8.x :

# pve8to9 | grep -i -B1 -A2 microcode
PASS: Legacy file '/etc/sysctl.conf' is not present.
INFO: Checking if matching CPU microcode package is installed.
FAIL: unable to determine installed intel-microcode version.
WARN: The matching CPU microcode package 'intel-microcode' could not be found! Consider installing it to receive the latest security and bug fixes for your CPU.
	apt install intel-microcode
SKIP: NOTE: Expensive checks, like CT cgroupv2 compat, not performed without '--full' parameter

Le FAIL est un effet de bord : la recherche de version journalise un échec pour tout paquet non installé, avant que la vérification du microcode n’arrive à son propre avertissement17. Quoi qu’il en soit, pve8to9 est un vérificateur, pas une barrière. Il ne lance pas la mise à niveau et ne peut pas l’arrêter, donc la mise à niveau passe droit devant.

Est-ce que ça compte en pratique ? Voici deux cas où oui, et le premier est le mien.

Ce nœud Intel est un Celeron N5100. Sa liste de sources portait déjà non-free-firmware, donc le paquet était à une commande, et jusqu’au 27 octobre 2026 personne ne l’avait lancée. Le noyau l’avait remarqué, même si personne d’autre ne l’avait fait :

# dmesg | grep -i microcode
[    0.000000] x86/CPU: Running old microcode
[    0.497219] microcode: Current revision: 0x0000001d
# lscpu | grep -i 'old microcode'
Vulnerability Old microcode:             Vulnerable

Le noyau garde « a table of released microcode », et un CPU qui a démarré sur quoi que ce soit de plus ancien « will say “Vulnerable” »18. Ancien à quel point ? Les notes de version d’Intel répondent pour cette puce19 :

RévisionVersion IntelSur cet hôte
0x1dmicrocode-20210608ce que le firmware de la carte charge aujourd’hui
0x2400001fmicrocode-20220207
0x24000023microcode-20220510sortie six mois avant que le BIOS de cette carte soit compilé
0x24000024microcode-20230214
0x24000026microcode-20240312dans le intel-microcode 3.20251111.1~deb13u1 de Debian

Le BIOS est en version 5.19, daté du 8 novembre 2022, et il charge toujours le premier microcode qu’Intel a publié pour cette puce, alors que deux plus récents étaient déjà sortis quand il a été compilé. C’est exactement le cas pour lequel le chargement précoce existe : quatre mises à jour qui attendaient dans un paquet que l’hôte voyait déjà. Je l’ai installé en écrivant ce billet, et ce que ça a fait se trouve sous L’activer, parce que ça montre un piège.

Le second cas est celui d’AMD. Les processeurs Zen 5 ont un bug dans l’instruction RDSEED20. Les notes de version 9.1 de Proxmox consignent ce qui se passe ensuite : les noyaux à partir de 6.17.9, « without active microcode update will disable the RDSEED32 CPU-bit, and will fail to run Qemu guests with a CPU type that exposes that bit (for example EPYC or EPYC-v4) »21. Le correctif est amd64-microcode 3.20251202.1~bpo13+1 ou plus récent, qui est la version du dépôt Proxmox et pas celle de Debian.

Il y a un second piège dans celui-là. Sur les cartes Zen 5 dont le BIOS est antérieur au correctif de la vulnérabilité Entrysign d’AMD, le noyau refuse le nouveau microcode et journalise No sha256 digest for patch ID, et le conseil de Proxmox est une mise à jour du BIOS21. Sur ce matériel, la voie du système ne marche donc qu’une fois que le fabricant de la carte a fait sa part.

L’activer

Notez d’abord où vous en êtes. Sur l’hôte, en root :

pveversion
grep -m1 vendor_id /proc/cpuinfo                 # GenuineIntel or AuthenticAMD
grep microcode /proc/cpuinfo | uniq              # revision running now
dpkg -l intel-microcode amd64-microcode 2>/dev/null | grep ^ii
dmesg | grep -i microcode
lscpu > /root/lscpu-before.txt                   # vulnerabilities and mitigations

Si dpkg montre déjà le paquet correspondant en ii, l’hôte est prêt et vous pouvez passer directement à la vérification du résultat.

Activez le composant. L’apt de trixie préfère le format deb822 .sources, et le guide de mise à niveau de Proxmox renvoie à apt modernize-sources pour convertir les anciens fichiers d’une ligne, en gardant les originaux en .bak22. Ajoutez ensuite non-free-firmware à la ligne Components: de la strophe principale et de la strophe de sécurité dans /etc/apt/sources.list.d/debian.sources. Voici le fichier sur mon hôte, qui vient de l’installateur :

Types: deb
URIs: http://deb.debian.org/debian/
Suites: trixie trixie-updates
Components: main contrib non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

Types: deb
URIs: http://security.debian.org/debian-security/
Suites: trixie-security
Components: main contrib non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

Les deux strophes, parce que Debian livre le microcode à stable par les deux voies. L’archive de sécurité porte intel-microcode 3.20250812.1~deb13u1 alors que l’archive principale est passée à 3.20251111.1~deb13u123, et vous voulez la plus récente des deux.

Installez celui qui correspond au CPU.

apt update
apt install intel-microcode     # Intel
apt install amd64-microcode     # AMD

Uniquement celui de votre fabricant. Ensuite, le nouveau microcode arrive avec les apt full-upgrade ordinaires, et chaque nouvelle version demande un redémarrage comme la première.

L’installer reconstruit l’initramfs, parce que c’est là que le microcode précoce doit se trouver. Le noyau le lit dans une archive non compressée en tête de l’initrd, sous kernel/x86/microcode/GenuineIntel.bin ou AuthenticAMD.bin15, et le script d’installation du paquet déclenche le trigger d’initramfs pour l’y placer24. Voici mon nœud Intel qui reçoit le paquet pendant l’écriture de ce billet :

# grep -A6 'Setting up intel-microcode' /var/log/apt/term.log
Setting up intel-microcode (3.20251111.1~deb13u1) ...
intel-microcode: microcode will be updated at next boot
Processing triggers for man-db (2.13.1-1) ...
Processing triggers for initramfs-tools (0.148.4) ...
update-initramfs: Generating /boot/initrd.img-7.0.14-24-pve
Running hook script 'zz-proxmox-boot'..
Re-executing '/etc/kernel/postinst.d/zz-proxmox-boot' in new private mount namespace..

zz-proxmox-boot est le hook de Proxmox. Sur un hôte dont les partitions EFI sont gérées par proxmox-boot-tool, il y copie la nouvelle image ; celui-ci n’en a aucune à synchroniser.

Regardez maintenant quelle image il a générée. Sans noyau précisé, update-initramfs -u ne reconstruit que la plus récente : « The default is the latest kernel version »25. Le même nœud, juste après :

# uname -r
7.0.14-23-pve
# for f in /boot/initrd.img-*; do echo "$f: $(lsinitramfs $f 2>/dev/null | grep -c GenuineIntel.bin)"; done
/boot/initrd.img-7.0.12-1-pve: 0
/boot/initrd.img-7.0.14-11-pve: 0
/boot/initrd.img-7.0.14-12-pve: 0
/boot/initrd.img-7.0.14-19-pve: 0
/boot/initrd.img-7.0.14-23-pve: 0
/boot/initrd.img-7.0.14-24-pve: 1
/boot/initrd.img-7.0.14-8-pve: 0

Une image sur sept porte le microcode, et ce n’est pas celle sur laquelle tourne l’hôte.

Prochain démarrageL’initramfs contient le microcodeRévision sur laquelle finit le CPU
7.0.14-24, l’entrée par défautouile 0x24000026 du paquet
7.0.14-23, épinglé ou entrée de secoursnonle 0x1d du BIOS
tout ce qui est plus anciennonle 0x1d du BIOS

Reconstruisez donc toutes les images après l’installation, et de nouveau après chaque mise à jour du microcode, car chacune déclenche la même reconstruction limitée au noyau le plus récent. Relancez ensuite la boucle ci-dessus pour le prouver :

update-initramfs -u -k all

Redémarrez et vérifiez. Voici mon hôte AMD 9.2 après l’installation du paquet du dépôt Proxmox :

# grep microcode /proc/cpuinfo | uniq
microcode	: 0xa500012
# dmesg | grep -i microcode
[    0.587928] microcode: Current revision: 0x0a500012
[    0.587930] microcode: Updated early from: 0x0a50000d

Updated early from est la ligne qui le prouve. Le guide d’administration de Proxmox montre encore l’ancienne formulation, microcode updated early to revision13 ; le noyau actuel affiche les deux lignes ci-dessus26. L’une ou l’autre forme veut dire que ça a marché.

L’absence de cette ligne n’est pas une panne en soi. Elle n’apparaît que lorsque le paquet contient quelque chose de plus récent à la fois que la révision intégrée au CPU et que celle chargée par le BIOS. Un paquet couvre un très grand nombre de modèles de CPU, et le guide a raison de dire que sa date ne vous apprend pas quand votre modèle a reçu quelque chose pour la dernière fois13.

Le déployer sur un cluster

Le changement de dépôt et l’installation peuvent se faire sur tous les nœuds à la fois. Rien ne change avant un redémarrage. Les redémarrages se font un nœud à la fois, et chaque nœud est sain avant que le suivant ne s’arrête.

Un redémarrage tournant pour le microcode, un nœud par passagePar nœud, puis le suivantVérifierquorum, Ceph OKMaintenanceinvités déplacésnooutfacultatifRedémarrervérifier dmesgAttendreOSD up et inLibérerunset, rapatriernœud suivant, mêmes étapes
Un nœud par passage. Les deux étapes Ceph ne concernent que les clusters hyperconvergés, et la paire noout est facultative.
ÉtapeCommandeFait quand
Cluster sainpvecm status, ceph -squorum atteint, HEALTH_OK
Vider le nœudha-manager crm-command node-maintenance enable <node>, migrer à la main les invités hors HAplus aucun invité dessus
Facultatif, Cephceph osd set nooutflag visible dans ceph -s
Redémarrer, vérifierdmesg | grep -i microcodenouvelle révision affichée
Ceph rétabliceph -stous les OSD up et in, HEALTH_OK
Libérernode-maintenance disable <node>, ceph osd unset nooutinvités HA revenus

Le mode maintenance de HA note d’où vient chaque invité HA et l’y ramène une fois le nœud sorti de maintenance27. Les invités hors HA, c’est votre affaire.

Sur noout, les avis divergent et les deux camps ont un argument. Ceph marque vite un OSD silencieux comme down, mais ne le marque out qu’après mon_osd_down_out_interval, qui vaut dix minutes par défaut28, et c’est le passage à out qui déclenche le rééquilibrage. Un redémarrage normal revient bien avant. Un serveur au POST long, avec une invite du firmware ou un contrôleur RAID lent, peut-être pas. Poser noout empêche un redémarrage lent de tourner au rééquilibrage. Le prix, c’est de penser à le retirer, et un noout oublié masque plus tard une vraie panne.

Faites tout le cluster dans la même fenêtre. Des nœuds qui tournent avec des révisions de microcode différentes, c’est exactement la situation où un invité au type de CPU host, qui voit directement les fonctions du CPU physique, peut migrer à chaud vers un nœud qui en annonce un jeu différent.

Quand une mise à jour de microcode tourne mal

C’est rare, mais ça arrive, et le guide de Proxmox le couvre correctement13.

SituationFaites ceciPourquoi
Vous soupçonnez le nouveau microcodedémarrez une fois avec dis_ucode_ldrdésactive le chargeur pour ce démarrage uniquement29
L’ancienne révision allait, la nouvelle noninstallez la version précédente et bloquez-laune purge peut laisser tourner une révision du BIOS encore plus ancienne
Quelques semaines plus tardapt-mark unhold, puis full-upgradeun correctif ailleurs peut régler le problème à version de microcode égale

Pour le démarrage ponctuel : menu GRUB (maintenez Maj s’il est masqué), E sur l’entrée Proxmox, ajoutez dis_ucode_ldr à la ligne qui commence par linux, puis Ctrl+X. Un hôte sous systemd-boot plutôt que GRUB est couvert dans le chapitre du guide d’administration sur le chargeur de démarrage.

Le retour en arrière, sur Intel :

apt list -a intel-microcode               # what versions exist
apt install intel-microcode=<version>     # pick the earlier one
apt-mark hold intel-microcode             # stop the next upgrade undoing it
reboot

Remplacez par amd64-microcode sur AMD. Rétrogradez, ne purgez jamais.

Un réglage par défaut est une promesse faite à qui a pris le chemin prévu

Aucun des deux n’est un bug. Proxmox a fait le choix raisonnable les deux fois : activer la fonction là où c’est sûr, la laisser éteinte là où ça pourrait ne pas l’être, et épingler le matériel virtuel auquel l’invité est sensible. L’installateur a été corrigé, le vérificateur de mise à niveau le signale, le changelog dit ce qui a changé et quand. Proxmox a fait sa part.

Mais un réglage par défaut est une promesse faite à celui qui a fait les choses comme le fabricant l’avait prévu. Installation neuve, bon type d’OS, VM créée après juillet. Quiconque a un parc avec un historique, et c’est le cas de tous ceux qui font tourner quelque chose de réel, est en partie hors de cette promesse, et l’écart ne s’annonce pas. Il se montre sous la forme d’un invité un peu lent, d’un gel VBS que personne ne relie à une version de machine, ou d’un nœud Zen 5 où les invités EPYC ne démarrent plus après une mise à jour du noyau.

Les notes de version décrivent ce que reçoit une installation neuve. Elles ne disent rien de ce que vos hôtes font réellement tourner, et ce sont deux questions différentes. La seule façon de répondre à la seconde est d’aller regarder : qm showcmd sur les invités, dmesg sur les hôtes, la ligne machine dans la configuration. Rien de tout ça ne prend plus d’une minute par machine.

Cette minute, c’est le métier. Proxmox vous donne les outils pour vérifier, et de ce fait l’écart entre ce que vous supposiez et ce qui tourne est à vous de le combler, pas à eux.


  1. QEMU documentation — Hyper-V Enlightenments — « No Hyper-V enlightenments are enabled by default by either KVM or QEMU » ; descriptions flag par flag ; hv-evmcs « The feature is Intel-only » et « some virtualization features (e.g. Posted Interrupts) are disabled when hv-evmcs is enabled ». ↩︎ ↩︎ ↩︎

  2. Proxmox qemu-server — CPUConfig.pm — get_hyperv_enlightenments : les portes OVMF et de version, les gardes sur la version de machine, et le test GenuineIntel pour hv_evmcs. Exécuté ici depuis qemu-server 9.2.11. ↩︎

  3. Proxmox VE admin guide — Qemu/KVM Virtual Machines — « You can choose between the default Intel 440FX or the Q35 chipset » et « switch from the default SeaBIOS to OVMF » ; « For Windows guests, the machine version is pinned during creation, because Windows is sensitive to changes in the virtual hardware - even between cold boots » ; la propriété level et les valeurs par défaut cet-ibt/cet-ss pour ces invités. ↩︎ ↩︎ ↩︎ ↩︎

  4. Proxmox qemu-server — Debian changelog — la 9.2.0 (15 juillet 2026) active hv-evmcs pour les invités 11/2022/2025 sur Intel à partir de la machine 11.0+pve2 ; la 9.1.14 expose level ; la 9.1.12 désactive cet-ibt et cet-ss ; épinglage lors du passage à un type d’OS Microsoft Windows (janvier 2025) ; 6.0-6 (23 juillet 2019) « Make sometimes problematic ‘hv-tlbflush’ and ‘hv-evmcs’ CPU flags optional ». ↩︎ ↩︎ ↩︎ ↩︎

  5. Proxmox qemu-server — Machine.pm — can_run_pve_machine_version renvoie faux quand la version majeure.mineure de QEMU de la machine est plus récente que le binaire installé ; les révisions +pveN sont listées dans le même fichier. ↩︎

  6. Proxmox qemu-server 9.2.0 — debian/control — au commit « bump version to 9.2.0 » du 15 juillet 2026, la dépendance d’exécution est pve-qemu-kvm (>= 7.1~). ↩︎

  7. Proxmox VE Roadmap — 9.0, Installation ISO — « Install the microcode package matching the current platform… This also means that installations now have the non-free-firmware repository enabled. » ; la même version annonce « QEMU 10.0.2 » ↩︎ ↩︎

  8. Proxmox pve-qemu — Debian changelog — 10.0.2-1 (17 juin 2025) « update QEMU and downstream patches for 10.0.2 release », qui apporte le correctif amont de 10.0 ci-dessous ; 10.1.2-3 « a regression with VNC clipboard breaking mouse pointer in Windows guests » ; 10.1.2-5 le correctif io_uring pour « backup with TPM disk potentially getting stuck » ; 11.0.0-1 « regression when using fuse export for swtpm » ; 11.0.2-1 « recognize Hyper-V enlightenments in the list of supported CPUID flags ». ↩︎

  9. QEMU upstream changelogs, 10.0 — « Workaround ‘PCI Label Id’ Windows bug, which is normally harmless but on localized versions can lead to guest hangs » ; 10.1, 10.2 et 11.0 pour les correctifs VSS et de gel de l’agent invité, dont « Fix guest-fs-freeze cause “Access denied Event ID 8194” in Event Viewer ». ↩︎ ↩︎

  10. Proxmox VE wiki — Qemu-guest-agent — pour cet invité, « First you have to download the virtio-win driver iso ». ↩︎

  11. Proxmox qemu-server — CPUFlags.pm — la liste des flags par VM, avec les descriptions de hv-tlbflush et hv-evmcs citées plus haut. ↩︎

  12. Proxmox pve-manager — OSDefaults.js — l’entrée win11 fixe machine: 'q35' et bios: 'ovmf' ; les autres entrées Microsoft Windows héritent de generic, qui ne fixe aucune machine. ↩︎

  13. Proxmox VE admin guide — CPU Microcode Updates — mises à jour précoces par le système, la voie BIOS/UEFI comme recommandée, l’absence de paquet système pour arm64, la procédure dis_ucode_ldr, et la rétrogradation plutôt que la purge. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  14. Proxmox VE pve-no-subscription repository for trixie — fournit amd64-microcode 3.20251202.1~bpo13+1 et pas de intel-microcode, relevé le 27 octobre 2026. ↩︎

  15. Linux kernel documentation — The Linux Microcode Loader — « Since kernel 5.19, late loading is not enabled by default », et la section « Why is late loading dangerous? ». ↩︎ ↩︎

  16. Debian Wiki — Microcode — les données de mise à jour « opaque » fournies par le fabricant du CPU « is non-free, and its contents are unknown to Debian ». ↩︎

  17. Proxmox pve-manager — pve8to9.pm — check_cpu_microcode_package journalise l’avertissement ; la recherche $get_pkg qu’il appelle d’abord journalise « unable to determine installed $pkg version. » comme un échec pour tout paquet non installé. ↩︎

  18. Linux kernel documentation — Old Microcode — « The kernel keeps a table of released microcode. Systems that had microcode older than this at boot will say “Vulnerable”. » ↩︎

  19. Intel — Linux Processor Microcode Data Files, release notes — les lignes JSL pour 06-9c-00/01, « Celeron N4500/N4505/N5100/N5105 », des versions 20210608 à 20240312 ; 0x24000026 lu dans l’en-tête de 06-9c-00 du paquet Debian. ↩︎

  20. AMD security bulletin AMD-SB-7055 — le problème RDSEED sur les processeurs Zen 5. ↩︎

  21. Proxmox VE Roadmap — 9.1 known issues, AMD Zen5 CPU issue with RDSEED — l’échec de démarrage des invités, la version de paquet corrigée, et le message No sha256 digest sur les cartes sans le correctif BIOS Entrysign. ↩︎ ↩︎

  22. Proxmox VE wiki — Upgrade from 8 to 9 — apt modernize-sources convertit en deb822 et garde les anciens fichiers avec le suffixe .bak. ↩︎

  23. Debian packages — intel-microcode in trixie — les versions stable et sécurité, recoupées avec apt-cache policy sur l’hôte. ↩︎

  24. Debian sources — intel-microcode.postinst — dpkg-trigger --no-await update-initramfs, puis « microcode will be updated at next boot » ; amd64-microcode fait de même. ↩︎

  25. Debian manual — update-initramfs(8) — pour -k, « The default is the latest kernel version », et la valeur « all » agit « on all installed kernel versions that already have an initramfs (with -d or -u) ». ↩︎

  26. Linux kernel source — arch/x86/kernel/cpu/microcode/core.c — affiche « Current revision: 0x%08x » et « Updated early from: 0x%08x ». ↩︎

  27. Proxmox VE admin guide — High Availability, maintenance mode — les services HA sont déplacés, puis ramenés « automatically once the maintenance mode is disabled and the node is back online ». ↩︎

  28. Ceph documentation — Configuring Monitor/OSD Interaction — mon_osd_down_out_interval, « The number of seconds Ceph waits before marking a Ceph OSD Daemon down and out », 10 minutes par défaut. ↩︎

  29. Linux kernel documentation — kernel parameters — dis_ucode_ldr : « Disable the microcode loader. » ↩︎