From: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
To: svt-core@virtuozzo.com
Cc: andrey.drobyshev@virtuozzo.com, den@openvz.org
Subject: [PATCH edk2.vzspecs hci-8.1] edk2-build.vz: build firmwares from OvmfPkgX64.dsc #VSTOR-152672 #VSTOR-152405
Date: Mon, 2 Nov 2026 17:25:32 +0200 [thread overview]
Message-ID: <20261102152532.61807-1-andrey.drobyshev@virtuozzo.com> (raw)
Our x86_64 firmwares are built from OvmfPkgIa32X64.dsc, i.e. 32-bit PEI
and 64-bit DXE, with PcdUse5LevelPageTable=TRUE on the 4MB images. The
mixed-arch platform is a historical artifact:
* edk2-build.vz was cloned from edk2-build.rhel-9 of rhel9-20230524 in
Jan 2024, back when RHEL still built its secure-boot image from
OvmfPkgIa32X64.dsc. Our PIIX builds were derived from that section;
* RHEL moved the secure-boot build to OvmfPkgX64.dsc with the
edk2-stable202311 rebase (rhel9-20231122-1). We imported that
version in Jun 2024 but never carried the switch over into
edk2-build.vz;
* RHEL 10 later enabled PcdUse5LevelPageTable on top of its X64
builds. Our vz10 config picked the PCD up in Mar 2026 while staying
on OvmfPkgIa32X64.dsc.
That combination is wrong. In a 32-bit PEI the PCD is the only policy:
DxeIpl enables 5-level paging on every CPU that has la57, regardless of
the guest size. The 64-bit PEI instead runs PlatformSetupPagingLevel()
(OvmfPkg/Library/PlatformInitLib/MemDetect.c, under MDE_CPU_X64), which
picks the paging level per guest:
* whatever "-fw_cfg name=opt/org.tianocore/PagingLevel" says (never
set in VZ downstream);
* OR 4-level paging while the guest address space stays below the
threshold (1TiB edk2 upstream, 16TiB VZ downstream);
* OR 5-level paging above the threshold.
Handing a small guest over in 5-level paging mode buys nothing, as 4-level
already covers 64TiB of firmware address space, and changes what the OS
sees at ExitBootServices. This might lead to problems e.g. on Windows:
it boots its LA57 kernel (ntkrla57.exe), which bugchecks on AMD guests that
are exposed to the ARCH_CAPABILITIES MSR (VSTOR-152405) and breaks Windows
Setup. We should simply never do 5-level paging on small guests.
So switch all four 4MB builds (q35 SMM, PIIX no-SMM, and both debug
variants) to OvmfPkgX64.dsc, arch X64, keeping the la57 PCD, which is
exactly the RHEL 10 configuration. Output file names, the VARS layout
and the firmware descriptors don't change.
The 2MB PIIX build stays on OvmfPkgIa32X64.dsc. It is the legacy image
for old VMs; it never had the la57 PCD and therefore always runs 4-level
paging.
NOTE: OvmfPkgX64.dsc also compiles in the confidential-computing code
which OvmfPkgIa32X64.dsc stubs out (CcExitLib, TdxDxe, MemEncrypt
libraries); it is inert on ordinary guests and is what RHEL ships.
Fixes: fb4eb03891fe ("Add VZ build config edk2-build.vz")
Fixes: 5236bf9a1655 ("Add debug builds to edk2-build.vz")
Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
edk2-build.vz | 51 +++++++++++++++++++++++++++++++++------------------
1 file changed, 33 insertions(+), 18 deletions(-)
diff --git a/edk2-build.vz b/edk2-build.vz
index a25b8f3..1be0961 100644
--- a/edk2-build.vz
+++ b/edk2-build.vz
@@ -31,8 +31,23 @@ SECURE_BOOT_ENABLE = TRUE
SMM_REQUIRE = FALSE
[pcds.la57]
-# Enables LA57 (5-level page tables, 57-bit virtual address space, 128 PB)
-# We enable it for 4MB builds to support large-memory configurations
+# Allow 5-level paging in the firmware, following RHEL downstream.
+#
+# Only use together with OvmfPkgX64.dsc (64-bit PEI). Its PEI picks the
+# paging level per guest:
+#
+# * whatever is set via "-fw_cfg name=opt/org.tianocore/PagingLevel"
+# setting (not used in VZ downstream);
+# * OR 4-level paging below the address space threshold (1TiB edk2
+# upstream, 16TiB VZ downstream);
+# * OR 5-level paging above that threshold.
+#
+# The 32-bit PEI of OvmfPkgIa32X64.dsc has no such policy and forces
+# 5-level paging on every la57 guest, which makes Windows boot its LA57
+# kernel. That is wrong and might lead to problems, particularly on AMD
+# guests.
+#
+# See VSTOR-152405, VSTOR-152672
PcdUse5LevelPageTable = TRUE
[pcds.nx.compat.x64]
@@ -48,15 +63,15 @@ DEBUG_PRINT_ERROR_LEVEL = 0x8040004F
# stateful ovmf builds (with vars in flash)
[build.ovmf.4m.sb.smm]
-desc = ovmf build (32/64-bit, 4MB, q35 only, needs smm, secure boot)
-conf = OvmfPkg/OvmfPkgIa32X64.dsc
-arch = IA32 X64
+desc = ovmf build (64-bit, 4MB, q35 only, needs smm, secure boot)
+conf = OvmfPkg/OvmfPkgX64.dsc
+arch = X64
opts = ovmf.common
ovmf.4m
ovmf.sb.smm
pcds = nx.compat.x64
la57
-plat = Ovmf3264
+plat = OvmfX64
dest = RHEL-10/ovmf
cpy1 = FV/OVMF_CODE.fd OVMF_CODE.secboot.fd
cpy2 = FV/OVMF_VARS.fd OVMF_VARS.secboot.fd
@@ -68,16 +83,16 @@ cpy4 = X64/EnrollDefaultKeys.efi
[build.ovmf.4m.sb.nosmm]
# PSBM-143808
-desc = ovmf build (32/64-bit, 4MB, piix, secure boot, no smm)
-conf = OvmfPkg/OvmfPkgIa32X64.dsc
-arch = IA32 X64
+desc = ovmf build (64-bit, 4MB, piix, secure boot, no smm)
+conf = OvmfPkg/OvmfPkgX64.dsc
+arch = X64
opts = ovmf.common
ovmf.noshell
ovmf.4m
ovmf.sb.nosmm
pcds = nx.compat.x64
la57
-plat = Ovmf3264
+plat = OvmfX64
dest = RHEL-10/ovmf
cpy1 = FV/OVMF_CODE.fd OVMF_CODE_4M.fd
cpy2 = FV/OVMF_VARS.fd OVMF_VARS_4M.fd
@@ -125,9 +140,9 @@ cpy2 = FV/OVMF_VARS.fd OVMF_VARS.fd
# Same as 4m.sb.smm Q35 build, but with debug output enabled
[build.ovmf.debug.4m.sb.smm]
-desc = ovmf debug build (32/64-bit, 4MB, q35 only, needs smm, secure boot)
-conf = OvmfPkg/OvmfPkgIa32X64.dsc
-arch = IA32 X64
+desc = ovmf debug build (64-bit, 4MB, q35 only, needs smm, secure boot)
+conf = OvmfPkg/OvmfPkgX64.dsc
+arch = X64
tgts = DEBUG
opts = ovmf.common
ovmf.4m
@@ -135,7 +150,7 @@ opts = ovmf.common
ovmf.verbose
pcds = nx.compat.x64
la57
-plat = Ovmf3264
+plat = OvmfX64
dest = RHEL-10/ovmf
cpy1 = FV/OVMF_CODE.fd OVMF_CODE.secboot.fd.debug
cpy2 = FV/OVMF_VARS.fd OVMF_VARS.secboot.fd
@@ -145,9 +160,9 @@ cpy2 = FV/OVMF_VARS.fd OVMF_VARS.secboot.fd
[build.ovmf.debug.4m.sb.nosmm]
# PSBM-143808
-desc = ovmf debug build (32/64-bit, 4MB, piix, secure boot, no smm)
-conf = OvmfPkg/OvmfPkgIa32X64.dsc
-arch = IA32 X64
+desc = ovmf debug build (64-bit, 4MB, piix, secure boot, no smm)
+conf = OvmfPkg/OvmfPkgX64.dsc
+arch = X64
tgts = DEBUG
opts = ovmf.common
ovmf.noshell
@@ -156,7 +171,7 @@ opts = ovmf.common
ovmf.verbose
pcds = nx.compat.x64
la57
-plat = Ovmf3264
+plat = OvmfX64
dest = RHEL-10/ovmf
cpy1 = FV/OVMF_CODE.fd OVMF_CODE_4M.fd.debug
cpy2 = FV/OVMF_VARS.fd OVMF_VARS_4M.fd
--
2.47.1
next reply other threads:[~2026-11-02 15:25 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 15:25 Andrey Drobyshev [this message]
2026-11-02 15:44 ` Denis V. Lunev
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=20261102152532.61807-1-andrey.drobyshev@virtuozzo.com \
--to=andrey.drobyshev@virtuozzo.com \
--cc=den@openvz.org \
--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