From: "Denis V. Lunev" <den@openvz.org>
To: andrey.drobyshev@virtuozzo.com
Cc: svt-core@virtuozzo.com, den@openvz.org
Subject: [PATCH hci-8.0/hci-8.1] i386: hide la57 at fresh start on vz machine types up to vz10.0.0 #VSTOR-152405
Date: Thu, 29 Oct 2026 18:42:21 +0100 [thread overview]
Message-ID: <20261029174221.1068858-1-den@openvz.org> (raw)
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
next reply other threads:[~2026-10-29 17:42 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-29 17:42 Denis V. Lunev [this message]
2026-10-29 17:46 ` no-reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261029174221.1068858-1-den@openvz.org \
--to=den@openvz.org \
--cc=andrey.drobyshev@virtuozzo.com \
--cc=svt-core@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox