diff options
author | Laszlo Ersek <lersek@redhat.com> | 2017-07-04 14:50:43 +0200 |
---|---|---|
committer | Laszlo Ersek <lersek@redhat.com> | 2017-07-05 22:29:28 +0200 |
commit | d5e064447f8c2bcd4477631bf6fcd8fde7aae51b (patch) | |
tree | 89984a613ee8f1421a7a56f9f9ea0c93735e4f3b | |
parent | 6812bb7bb5a66f6877bed67fa61ed67679611f67 (diff) | |
download | edk2-d5e064447f8c2bcd4477631bf6fcd8fde7aae51b.tar.gz edk2-d5e064447f8c2bcd4477631bf6fcd8fde7aae51b.tar.bz2 edk2-d5e064447f8c2bcd4477631bf6fcd8fde7aae51b.zip |
OvmfPkg/PlatformPei: honor extended TSEG in PcdQ35TsegMbytes if available
Recognize an extended TSEG when available in
Q35TsegMbytesInitialization(), and set both PcdQ35TsegMbytes (for
OvmfPkg/SmmAccess) and "mQ35TsegMbytes" (for PlatformPei's own use)
accordingly. The new logic interfaces with the QEMU feature added in QEMU
commit 2f295167e0c4 ("q35/mch: implement extended TSEG sizes",
2017-06-08).
At this point we have to explicitly restrict Q35TsegMbytesInitialization()
to the Q35 board, but that's OK, because Q35TsegMbytesInitialization() is
only called when PcdSmmSmramRequire is set, and for that Q35 is already an
enforced requirement.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Suggested-by: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
-rw-r--r-- | OvmfPkg/PlatformPei/MemDetect.c | 52 | ||||
-rw-r--r-- | OvmfPkg/PlatformPei/Platform.c | 10 | ||||
-rw-r--r-- | OvmfPkg/PlatformPei/Platform.h | 2 |
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_
|