OvmfPkg/PlatformInitLib: redefine low memory

Traditionally "low memory" is all memory below 4G.  The code logic dates
back to the days where OVMF has used the CMOS to figure how much memory
is installed instead of the e820 table provided by qemu.

That approach to memory detection implicitly assumes there is a single
block of memory below 4G.  Should that not be the case things fall
apart.  This happens in case OVMF runs under SVSM and SVSM caves out a
chunk of memory below 4G for itself, passing the remaining two blocks of
memory below 4G on to OVMF (via igvm memory map).

Fix that by redefining what OVMF considers "low memory".  It is the
first block of memory (with base address zero) now.  This fixes the SVSM
use case outlined above.  For other use cases nothing will change.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2026-02-05 12:02:12 +01:00 committed by mergify[bot]
parent d2e5c5781e
commit 0a0919607c

View file

@ -157,8 +157,13 @@ PlatformGetFirstNonAddressCB (
}
/**
Store the low (below 4G) memory size in
PlatformInfoHob->LowMemory
Store the low memory size in PlatformInfoHob->LowMemory.
The first memory block with base address zero is considered "low memory".
Traditionally this has been all memory below 4G. When running under SVSM
there are multiple memory blocks below 4G though, because SVSM caves out a
chunk of memory for itself. Only the first of these blocks is considered
low memory.
**/
STATIC
VOID
@ -167,21 +172,16 @@ PlatformGetLowMemoryCB (
IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
)
{
UINT64 Candidate;
if (E820Entry->Type != EfiAcpiAddressRangeMemory) {
return;
}
Candidate = E820Entry->BaseAddr + E820Entry->Length;
if (Candidate >= BASE_4GB) {
if (E820Entry->BaseAddr != 0) {
return;
}
if (PlatformInfoHob->LowMemory < Candidate) {
DEBUG ((DEBUG_INFO, "%a: LowMemory=0x%Lx\n", __func__, Candidate));
PlatformInfoHob->LowMemory = (UINT32)Candidate;
}
DEBUG ((DEBUG_INFO, "%a: LowMemory=0x%Lx\n", __func__, E820Entry->Length));
PlatformInfoHob->LowMemory = (UINT32)E820Entry->Length;
}
/**
@ -201,7 +201,9 @@ PlatformAddHobCB (
switch (E820Entry->Type) {
case EfiAcpiAddressRangeMemory:
if (Base >= BASE_4GB) {
if (End <= PlatformInfoHob->LowMemory) {
// nothing, handled by PlatformGetLowMemoryCB()
} else {
//
// Round up the start address, and round down the end address.
//