Virtuozzo QEMU development (svt-core@virtuozzo.com)
 help / color / mirror / Atom feed
* [PATCH hci-8.0/hci-8.1] i386: hide la57 at fresh start on vz machine types up to vz10.0.0 #VSTOR-152405
@ 2026-10-29 17:42 Denis V. Lunev
  2026-10-29 17:46 ` no-reply
  0 siblings, 1 reply; 2+ messages in thread
From: Denis V. Lunev @ 2026-10-29 17:42 UTC (permalink / raw)
  To: andrey.drobyshev; +Cc: svt-core, den

From: Denis V. Lunev <den@openvz.org>

The vz10 OVMF enables 5-level paging whenever the CPU has la57, so on
AMD EPYC 9004/9005 hosts with "-cpu host" Windows boots its LA57
kernel. That kernel bugchecks with UNSUPPORTED_PROCESSOR on the Intel
only ARCH_CAPABILITIES MSR, which pc-q35-vz10.0.0 and older still show
to AMD guests (x-arch-cap-always-on). There is no IDT yet, so the guest
triple-faults and reboots in a loop (ASUP-3871). The vz9 OVMF never
used 5-level paging, so these guests did not see this before.

Add x-no-la57-on-start and turn it on in pc_vz_10_0_compat, which
covers vz10.0.0 and every older vz machine type. On a fresh start a
"-cpu host" guest loses la57 unless la57=on is given explicitly. The
bit is reported in filtered-features, so libvirt writes la57=off into
the live definition and migration, save and snapshots carry it.

An incoming QEMU keeps la57: a guest from an older node may already run
with CR4.LA57 set. A hotplugged vCPU follows the boot vCPUs. Named CPU
models are not touched, la57 is part of their definition.

Signed-off-by: Denis V. Lunev <den@openvz.org>
---
The patch applies to hci-8.0 without changes; the base given below is
hci-dev, on top of "i386: keep CPU features of guests from older nodes
on vz machine types".

Customer case ASUP-3871, bug VSTOR-152405. New VMs get vz10.0.0 only
because nova pins it instead of using the q35 alias; that is
VSTOR-152413. pc-q35-vz10.1.0 already hides ARCH_CAPABILITIES on AMD and
is not touched here.

Testing, hci-8.0 build, bg-sdc2-e19-07 (EPYC 9355, VHI 8.0.0 packages):
- -cpu host, fresh start: la57 hidden and listed in
  unavailable-features on vz10.0.0 and vz9.2.0; kept with la57=on,
  on vz10.1.0 and with EPYC-Genoa.
- live migration from stock qemu-kvm 10.1.0-20.vz10.16 to the patched
  binary: completes, la57 kept on the destination.
- vCPU hotplug follows the boot vCPU, after a fresh start and after an
  incoming migration.
- Windows Server 2025 GA ISO (26100.1742) with the nova command line of
  the customer VM, pc-q35-vz10.0.0, -cpu host and the Hyper-V
  enlightenments: OVMF stays in 4-level paging and Setup starts. Stock
  qemu-kvm triple-faults there with bugcheck 0x5D (MSR 0x10a).
- Not tested: libvirt writing la57=off into the live XML and carrying
  it to the destination. That follows from virCPUx86UpdateLive for
  host-passthrough with check='none' and does not depend on the libvirt
  relaxations dropped in libvirt.ovz PR 392.

 hw/i386/pc.c         |  5 +++++
 hw/i386/pc_piix.c    |  2 +-
 hw/i386/pc_q35.c     |  2 +-
 include/hw/i386/pc.h |  3 +++
 target/i386/cpu.c    | 27 +++++++++++++++++++++++++++
 target/i386/cpu.h    |  6 ++++++
 6 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 9b6b51bd5f7..2834982dab4 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -548,6 +548,11 @@ GlobalProperty pc_vz_compat[] = {
 };
 const size_t pc_vz_compat_len = G_N_ELEMENTS(pc_vz_compat);
 
+GlobalProperty pc_vz_10_0_compat[] = {
+    { TYPE_X86_CPU, "x-no-la57-on-start", "on" },
+};
+const size_t pc_vz_10_0_compat_len = G_N_ELEMENTS(pc_vz_10_0_compat);
+
 GlobalProperty pc_vz_9_2_compat[] = {
     { TYPE_X86_CPU, "x-tsx-compat", "on" },
     { TYPE_X86_CPU, "x-spec-ctrl-compat", "on" },
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index b1b595078eb..ab29ea0cd12 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -1057,7 +1057,7 @@ DEFINE_I440FX_RHEL_MACHINE(7, 2, 0);
 /*  maj min mic         basemt      isdefault                              */
 #define VZ_PC_MT(X) \
     X(10, 1, 0, MT_VER_SYM(10, 0, 0), true)                                 \
-    X(10, 0, 0, MT_VER_SYM(10, 0, 0), false)                                \
+    X(10, 0, 0, MT_VER_SYM(10, 0, 0), false, pc_vz_10_0_compat)             \
     X(7, 16, 0, MT_VER_SYM(7, 6, 0),  false, pc_vz_9_2_compat,              \
                                              hw_compat_vz_9_1,              \
                                              hw_compat_vz_7_16,             \
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 019239bec6a..51539f22399 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -973,7 +973,7 @@ DEFINE_Q35_RHEL_MACHINE(7, 3, 0);
 /*  maj min mic         basemt      isdefault                              */
 #define VZ_Q35_MT(X)                                                        \
     X(10, 1, 0, MT_VER_SYM(10, 2, 0), true)                                 \
-    X(10, 0, 0, MT_VER_SYM(10, 0, 0), false)                                \
+    X(10, 0, 0, MT_VER_SYM(10, 0, 0), false, pc_vz_10_0_compat)             \
     X(9, 2,  0, MT_VER_SYM(9, 6, 0),  false, pc_vz_9_2_compat)              \
     X(9, 1,  0, MT_VER_SYM(9, 4, 0),  false, hw_compat_vz_9_1)              \
     X(9, 0,  0, MT_VER_SYM(9, 2, 0),  false)                                \
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index bd73426644e..021b139b872 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -364,6 +364,9 @@ extern const size_t pc_rhel_7_2_compat_len;
 extern GlobalProperty pc_vz_compat[];
 extern const size_t pc_vz_compat_len;
 
+extern GlobalProperty pc_vz_10_0_compat[];
+extern const size_t pc_vz_10_0_compat_len;
+
 extern GlobalProperty pc_vz_9_2_compat[];
 extern const size_t pc_vz_9_2_compat_len;
 
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 29e7b4b7e15..8d2ce279a72 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -40,6 +40,7 @@
 #ifndef CONFIG_USER_ONLY
 #include "confidential-guest.h"
 #include "system/reset.h"
+#include "system/runstate.h"
 #include "qapi/qapi-commands-machine.h"
 #include "system/address-spaces.h"
 #include "hw/boards.h"
@@ -9107,6 +9108,27 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
     }
 }
 
+/*
+ * Reported as filtered, so that libvirt records la57=off in the live
+ * definition and passes it on to migration, save and snapshots.
+ */
+static bool x86_cpu_hide_la57(X86CPU *cpu)
+{
+    CPUX86State *env = &cpu->env;
+
+    if (!cpu->no_la57_on_start || !X86_CPU_GET_CLASS(cpu)->max_features ||
+        !kvm_enabled() ||
+        !(env->features[FEAT_7_0_ECX] & CPUID_7_0_ECX_LA57) ||
+        (env->user_features[FEAT_7_0_ECX] & CPUID_7_0_ECX_LA57)) {
+        return false;
+    }
+    if (DEVICE(cpu)->hotplugged) {
+        return first_cpu && !(X86_CPU(first_cpu)->env.features[FEAT_7_0_ECX] &
+                              CPUID_7_0_ECX_LA57);
+    }
+    return !runstate_check(RUN_STATE_INMIGRATE);
+}
+
 /* Requested features that a vz compat property keeps despite the host */
 static uint64_t x86_cpu_compat_kept_features(X86CPU *cpu, FeatureWord w)
 {
@@ -9404,6 +9426,10 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
         }
     }
 
+    if (x86_cpu_hide_la57(cpu)) {
+        mark_unavailable_features(cpu, FEAT_7_0_ECX, CPUID_7_0_ECX_LA57, NULL);
+    }
+
     /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
      * CPUID[1].EDX.
      */
@@ -10120,6 +10146,7 @@ static const Property x86_cpu_properties[] = {
                      bus_lock_detect_compat, false),
     DEFINE_PROP_BOOL("x-v-vmsave-vmload-compat", X86CPU,
                      v_vmsave_vmload_compat, false),
+    DEFINE_PROP_BOOL("x-no-la57-on-start", X86CPU, no_la57_on_start, false),
     DEFINE_PROP_BOOL("x-svm-features-compat", X86CPU,
                      svm_features_compat, false),
 };
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 97e38013e46..5c1a692aca3 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -2342,6 +2342,12 @@ struct ArchCPU {
     bool v_vmsave_vmload_compat;
     bool svm_features_compat;
 
+    /*
+     * Virtuozzo machine types up to vz10.0.0: hide la57 from "-cpu host"
+     * when the VM starts fresh, keep it on incoming migration.
+     */
+    bool no_la57_on_start;
+
     /* Number of physical address bits supported */
     uint32_t phys_bits;
 

base-commit: 02f55118bcb0533ce4c6544458c30803d96bea4a
-- 
2.53.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-29 17:46 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-29 17:42 [PATCH hci-8.0/hci-8.1] i386: hide la57 at fresh start on vz machine types up to vz10.0.0 #VSTOR-152405 Denis V. Lunev
2026-10-29 17:46 ` no-reply

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox