Virtuozzo QEMU development (svt-core@virtuozzo.com)
 help / color / mirror / Atom feed
* [PATCH edk2.vzspecs hci-8.1] edk2-build.vz: build firmwares from OvmfPkgX64.dsc #VSTOR-152672 #VSTOR-152405
@ 2026-11-02 15:25 Andrey Drobyshev
  2026-11-02 15:44 ` Denis V. Lunev
  0 siblings, 1 reply; 2+ messages in thread
From: Andrey Drobyshev @ 2026-11-02 15:25 UTC (permalink / raw)
  To: svt-core; +Cc: andrey.drobyshev, den

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


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

* Re: [PATCH edk2.vzspecs hci-8.1] edk2-build.vz: build firmwares from OvmfPkgX64.dsc #VSTOR-152672 #VSTOR-152405
  2026-11-02 15:25 [PATCH edk2.vzspecs hci-8.1] edk2-build.vz: build firmwares from OvmfPkgX64.dsc #VSTOR-152672 #VSTOR-152405 Andrey Drobyshev
@ 2026-11-02 15:44 ` Denis V. Lunev
  0 siblings, 0 replies; 2+ messages in thread
From: Denis V. Lunev @ 2026-11-02 15:44 UTC (permalink / raw)
  To: Andrey Drobyshev, svt-core; +Cc: den

On 11/2/26 16:25, Andrey Drobyshev wrote:
> 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
Reviewed-by: Denis V. Lunev <den@openvz.org>

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

end of thread, other threads:[~2026-11-02 15:44 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-02 15:25 [PATCH edk2.vzspecs hci-8.1] edk2-build.vz: build firmwares from OvmfPkgX64.dsc #VSTOR-152672 #VSTOR-152405 Andrey Drobyshev
2026-11-02 15:44 ` Denis V. Lunev

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