summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--OvmfPkg/PlatformPei/MemDetect.c52
-rw-r--r--OvmfPkg/PlatformPei/Platform.c10
-rw-r--r--OvmfPkg/PlatformPei/Platform.h2
3 files changed, 58 insertions, 6 deletions
diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c
index 886d236226..97f3fa5afc 100644
--- a/OvmfPkg/PlatformPei/MemDetect.c
+++ b/OvmfPkg/PlatformPei/MemDetect.c
@@ -19,16 +19,19 @@ Module Name:
//
// The package level header files this module uses
//
+#include <IndustryStandard/Q35MchIch9.h>
#include <PiPei.h>
//
// The Library classes this module consumes
//
+#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/IoLib.h>
#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
#include <Library/PeimEntryPoint.h>
#include <Library/ResourcePublicationLib.h>
#include <Library/MtrrLib.h>
@@ -49,7 +52,54 @@ Q35TsegMbytesInitialization (
VOID
)
{
- mQ35TsegMbytes = PcdGet16 (PcdQ35TsegMbytes);
+ UINT16 ExtendedTsegMbytes;
+ RETURN_STATUS PcdStatus;
+
+ if (mHostBridgeDevId != INTEL_Q35_MCH_DEVICE_ID) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
+ "only DID=0x%04x (Q35) is supported\n",
+ __FUNCTION__,
+ mHostBridgeDevId,
+ INTEL_Q35_MCH_DEVICE_ID
+ ));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+
+ //
+ // Check if QEMU offers an extended TSEG.
+ //
+ // This can be seen from writing MCH_EXT_TSEG_MB_QUERY to the MCH_EXT_TSEG_MB
+ // register, and reading back the register.
+ //
+ // On a QEMU machine type that does not offer an extended TSEG, the initial
+ // write overwrites whatever value a malicious guest OS may have placed in
+ // the (unimplemented) register, before entering S3 or rebooting.
+ // Subsequently, the read returns MCH_EXT_TSEG_MB_QUERY unchanged.
+ //
+ // On a QEMU machine type that offers an extended TSEG, the initial write
+ // triggers an update to the register. Subsequently, the value read back
+ // (which is guaranteed to differ from MCH_EXT_TSEG_MB_QUERY) tells us the
+ // number of megabytes.
+ //
+ PciWrite16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB), MCH_EXT_TSEG_MB_QUERY);
+ ExtendedTsegMbytes = PciRead16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB));
+ if (ExtendedTsegMbytes == MCH_EXT_TSEG_MB_QUERY) {
+ mQ35TsegMbytes = PcdGet16 (PcdQ35TsegMbytes);
+ return;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: QEMU offers an extended TSEG (%d MB)\n",
+ __FUNCTION__,
+ ExtendedTsegMbytes
+ ));
+ PcdStatus = PcdSet16S (PcdQ35TsegMbytes, ExtendedTsegMbytes);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ mQ35TsegMbytes = ExtendedTsegMbytes;
}
diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c
index b8a28450d6..98cfaaa28e 100644
--- a/OvmfPkg/PlatformPei/Platform.c
+++ b/OvmfPkg/PlatformPei/Platform.c
@@ -645,6 +645,11 @@ InitializePlatform (
AddressWidthInitialization ();
MaxCpuCountInitialization ();
+ //
+ // Query Host Bridge DID
+ //
+ mHostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
+
if (FeaturePcdGet (PcdSmmSmramRequire)) {
Q35TsegMbytesInitialization ();
}
@@ -658,11 +663,6 @@ InitializePlatform (
InitializeXen ();
}
- //
- // Query Host Bridge DID
- //
- mHostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
-
if (mBootMode != BOOT_ON_S3_RESUME) {
if (!FeaturePcdGet (PcdSmmSmramRequire)) {
ReserveEmuVariableNvStore ();
diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h
index d2d627b221..ae855531c1 100644
--- a/OvmfPkg/PlatformPei/Platform.h
+++ b/OvmfPkg/PlatformPei/Platform.h
@@ -108,4 +108,6 @@ extern UINT8 mPhysMemAddressWidth;
extern UINT32 mMaxCpuCount;
+extern UINT16 mHostBridgeDevId;
+
#endif // _PLATFORM_PEI_H_INCLUDED_