* [PATCH qemu-server] cpu config: expose CPU 'level' property required for certain host/guest configurations
@ 2026-05-18 12:40 Fiona Ebner
2026-05-18 14:00 ` David Riley
2026-05-18 15:59 ` applied: " Thomas Lamprecht
0 siblings, 2 replies; 3+ messages in thread
From: Fiona Ebner @ 2026-05-18 12:40 UTC (permalink / raw)
To: pve-devel
As reported in the community forum in 2024 [0] already, with somewhat
recent Intel CPUs, Windows guests with Hyper-V enabled will fail to
boot with certain CPU types like 'host' or 'max'. A workaround is
using 'level=30' in the '-cpu' QEMU commandline. The 'level' property
is currently not exposed, so users were forced to use custom 'args',
which means they lose other CPU configuration made by Proxmox VE.
Expose the 'level' setting, so it can be done without custom args.
While the problem is not new, it will become more common, since
virtualization-based security is being adapted more broadly.
[0]: https://forum.proxmox.com/threads/131950/post-642093
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
src/PVE/QemuServer/CPUConfig.pm | 18 ++++++++++++++++++
src/test/cfg2cmd/cpu-level.conf | 6 ++++++
src/test/cfg2cmd/cpu-level.conf.cmd | 26 ++++++++++++++++++++++++++
3 files changed, 50 insertions(+)
create mode 100644 src/test/cfg2cmd/cpu-level.conf
create mode 100644 src/test/cfg2cmd/cpu-level.conf.cmd
diff --git a/src/PVE/QemuServer/CPUConfig.pm b/src/PVE/QemuServer/CPUConfig.pm
index 2c30a5db..39d1767f 100644
--- a/src/PVE/QemuServer/CPUConfig.pm
+++ b/src/PVE/QemuServer/CPUConfig.pm
@@ -355,6 +355,16 @@ my $cpu_fmt = {
. " note that doing so will break live migration to CPUs with other values.",
optional => 1,
},
+ 'level' => {
+ type => 'integer',
+ minimum => 0,
+ maximum => 4294967295, # It's a uint32_t in QEMU
+ description =>
+ "The CPUID topology level. Limits the topology presented by the virtual CPU, in "
+ . " particular, limits the set of CPUID leaves. Only applies when the vCPU architecture"
+ . " is x86_64.",
+ optional => 1,
+ },
};
PVE::JSONSchema::register_standard_option('pve-qm-custom-cpu-model', $cpu_fmt);
@@ -910,6 +920,14 @@ sub get_cpu_options(
my $cpu_str = $cputype;
+ if (defined(my $level = $cpu->{level} // $custom_cpu->{level})) {
+ if ($arch eq 'x86_64') {
+ $cpu_str .= ",level=${level}";
+ } else {
+ warn "CPU 'level' property is ignored for architecture '$arch'\n";
+ }
+ }
+
# will be resolved in parameter order
my $resolved_flags = resolve_cpu_flags(
$pve_flags,
diff --git a/src/test/cfg2cmd/cpu-level.conf b/src/test/cfg2cmd/cpu-level.conf
new file mode 100644
index 00000000..1ce1e6a9
--- /dev/null
+++ b/src/test/cfg2cmd/cpu-level.conf
@@ -0,0 +1,6 @@
+# TEST: Test for a configuration where the 'level' option and some flags are set for a CPU
+cpu: host,level=30,flags=+md-clear;+pdpe1gb;-hv-tlbflush
+memory: 768
+numa: 0
+ostype: win11
+sockets: 1
diff --git a/src/test/cfg2cmd/cpu-level.conf.cmd b/src/test/cfg2cmd/cpu-level.conf.cmd
new file mode 100644
index 00000000..d276a6de
--- /dev/null
+++ b/src/test/cfg2cmd/cpu-level.conf.cmd
@@ -0,0 +1,26 @@
+/usr/bin/kvm \
+ -id 8006 \
+ -name vm8006 \
+ -no-shutdown \
+ -chardev 'socket,id=qmp,path=/var/run/qemu-server/8006.qmp,server=on,wait=off' \
+ -mon 'chardev=qmp,mode=control' \
+ -chardev 'socket,id=qmp-event,path=/var/run/qmeventd.sock,reconnect-ms=5000' \
+ -mon 'chardev=qmp-event,mode=control' \
+ -pidfile /var/run/qemu-server/8006.pid \
+ -daemonize \
+ -smp '1,sockets=1,cores=1,maxcpus=1' \
+ -nodefaults \
+ -boot 'menu=on,strict=on,reboot-timeout=1000,splash=/usr/share/qemu-server/bootsplash.jpg' \
+ -vnc 'unix:/var/run/qemu-server/8006.vnc,password=on' \
+ -global 'kvm-pit.lost_tick_policy=discard' \
+ -cpu 'host,level=30,-cet-ibt,-cet-ss,-hv-tlbflush,hv_ipi,hv_relaxed,hv_reset,hv_runtime,hv_spinlocks=0x1fff,hv_stimer,hv_synic,hv_time,hv_vapic,hv_vpindex,+kvm_pv_eoi,+kvm_pv_unhalt,+md-clear,+pdpe1gb' \
+ -m 768 \
+ -device 'pci-bridge,id=pci.1,chassis_nr=1,bus=pci.0,addr=0x1e' \
+ -device 'pci-bridge,id=pci.2,chassis_nr=2,bus=pci.0,addr=0x1f' \
+ -device 'piix3-usb-uhci,id=uhci,bus=pci.0,addr=0x1.0x2' \
+ -device 'usb-tablet,id=tablet,bus=uhci.0,port=1' \
+ -device 'VGA,id=vga,bus=pci.0,addr=0x2,edid=off' \
+ -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3' \
+ -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
+ -rtc 'driftfix=slew,base=localtime' \
+ -machine 'hpet=off,type=pc-i440fx-5.1+pve0'
--
2.47.3
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH qemu-server] cpu config: expose CPU 'level' property required for certain host/guest configurations
2026-05-18 12:40 [PATCH qemu-server] cpu config: expose CPU 'level' property required for certain host/guest configurations Fiona Ebner
@ 2026-05-18 14:00 ` David Riley
2026-05-18 15:59 ` applied: " Thomas Lamprecht
1 sibling, 0 replies; 3+ messages in thread
From: David Riley @ 2026-05-18 14:00 UTC (permalink / raw)
To: Fiona Ebner, pve-devel
Thanks for sending in this patch.
I was able to apply the series without issues. I tested the new
`level=30` option by adding it to my <vmid>.conf for a Windows Server
Guest.
Checked the output from `qm showcmd <vmid>` and was able to verify
that the option was set correctly and the default Hyper-V
Enlightenments were also still present as expected.
Tested-by: David Riley <d.riley@proxmox.com>
Reviewed-by: David Riley <d.riley@proxmox.com>
On 5/18/26 2:40 PM, Fiona Ebner wrote:
> As reported in the community forum in 2024 [0] already, with somewhat
> recent Intel CPUs, Windows guests with Hyper-V enabled will fail to
> boot with certain CPU types like 'host' or 'max'. A workaround is
> using 'level=30' in the '-cpu' QEMU commandline. The 'level' property
> is currently not exposed, so users were forced to use custom 'args',
> which means they lose other CPU configuration made by Proxmox VE.
> Expose the 'level' setting, so it can be done without custom args.
>
> While the problem is not new, it will become more common, since
> virtualization-based security is being adapted more broadly.
>
> [0]: https://forum.proxmox.com/threads/131950/post-642093
>
> Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
> ---
> src/PVE/QemuServer/CPUConfig.pm | 18 ++++++++++++++++++
> src/test/cfg2cmd/cpu-level.conf | 6 ++++++
> src/test/cfg2cmd/cpu-level.conf.cmd | 26 ++++++++++++++++++++++++++
> 3 files changed, 50 insertions(+)
> create mode 100644 src/test/cfg2cmd/cpu-level.conf
> create mode 100644 src/test/cfg2cmd/cpu-level.conf.cmd
>
>
> [snip]
^ permalink raw reply [flat|nested] 3+ messages in thread
* applied: [PATCH qemu-server] cpu config: expose CPU 'level' property required for certain host/guest configurations
2026-05-18 12:40 [PATCH qemu-server] cpu config: expose CPU 'level' property required for certain host/guest configurations Fiona Ebner
2026-05-18 14:00 ` David Riley
@ 2026-05-18 15:59 ` Thomas Lamprecht
1 sibling, 0 replies; 3+ messages in thread
From: Thomas Lamprecht @ 2026-05-18 15:59 UTC (permalink / raw)
To: pve-devel, Fiona Ebner
On Mon, 18 May 2026 14:40:09 +0200, Fiona Ebner wrote:
> As reported in the community forum in 2024 [0] already, with somewhat
> recent Intel CPUs, Windows guests with Hyper-V enabled will fail to
> boot with certain CPU types like 'host' or 'max'. A workaround is
> using 'level=30' in the '-cpu' QEMU commandline. The 'level' property
> is currently not exposed, so users were forced to use custom 'args',
> which means they lose other CPU configuration made by Proxmox VE.
> Expose the 'level' setting, so it can be done without custom args.
>
> [...]
Applied, thanks!
[1/1] cpu config: expose CPU 'level' property required for certain host/guest configurations
commit: 82f0c412a2d16dc4b6ed6301f6181efe8df74de0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-05-18 16:00 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-18 12:40 [PATCH qemu-server] cpu config: expose CPU 'level' property required for certain host/guest configurations Fiona Ebner
2026-05-18 14:00 ` David Riley
2026-05-18 15:59 ` applied: " Thomas Lamprecht
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox