diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c index 83a7b6726b..c28d7601f8 100644 --- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c +++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c @@ -491,6 +491,42 @@ PlatformGetFirstNonAddress ( return FirstNonAddress; } +/* + * Use CPUID to figure physical address width. Does *not* work + * reliable on qemu. For historical reasons qemu returns phys-bits=40 + * even in case the host machine supports less than that. + * + * qemu has a cpu property (host-phys-bits={on,off}) to change that + * and make sure guest phys-bits are not larger than host phys-bits., + * but it is off by default. Exception: microvm machine type + * hard-wires that property to on. + */ +VOID +EFIAPI +PlatformAddressWidthFromCpuid ( + IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob + ) +{ + UINT32 RegEax; + + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PlatformInfoHob->PhysMemAddressWidth = (UINT8)RegEax; + } else { + PlatformInfoHob->PhysMemAddressWidth = 36; + } + + PlatformInfoHob->FirstNonAddress = LShiftU64 (1, PlatformInfoHob->PhysMemAddressWidth); + + DEBUG (( + DEBUG_INFO, + "%a: cpuid: phys-bits is %d\n", + __FUNCTION__, + PlatformInfoHob->PhysMemAddressWidth + )); +} + /** Initialize the PhysMemAddressWidth field in PlatformInfoHob based on guest RAM size. **/ @@ -503,6 +539,11 @@ PlatformAddressWidthInitialization ( UINT64 FirstNonAddress; UINT8 PhysMemAddressWidth; + if (PlatformInfoHob->HostBridgeDevId == 0xffff /* microvm */) { + PlatformAddressWidthFromCpuid (PlatformInfoHob); + return; + } + // // As guest-physical memory size grows, the permanent PEI RAM requirements // are dominated by the identity-mapping page tables built by the DXE IPL. diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index f006755d5f..009db67ee6 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -357,12 +357,12 @@ InitializePlatform ( S3Verification (); BootModeInitialization (&mPlatformInfoHob); - AddressWidthInitialization (&mPlatformInfoHob); // // Query Host Bridge DID // mPlatformInfoHob.HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID); + AddressWidthInitialization (&mPlatformInfoHob); MaxCpuCountInitialization (&mPlatformInfoHob);