|
|
7fdf80 |
From 71c39f0fb0b9a3e9856cebc58ef3812752fd07cc Mon Sep 17 00:00:00 2001
|
|
|
7fdf80 |
From: Laszlo Ersek <lersek@redhat.com>
|
|
|
7fdf80 |
Date: Tue, 4 Jun 2019 11:06:45 +0200
|
|
|
7fdf80 |
Subject: [PATCH 3/3] OvmfPkg/PlatformPei: set 32-bit UC area at PciBase /
|
|
|
7fdf80 |
PciExBarBase (pc/q35)
|
|
|
7fdf80 |
MIME-Version: 1.0
|
|
|
7fdf80 |
Content-Type: text/plain; charset=UTF-8
|
|
|
7fdf80 |
Content-Transfer-Encoding: 8bit
|
|
|
7fdf80 |
|
|
|
7fdf80 |
Message-id: <20190604090645.2847-4-lersek@redhat.com>
|
|
|
7fdf80 |
Patchwork-id: 88483
|
|
|
7fdf80 |
O-Subject: [RHEL-8.1.0 edk2 PATCH v2 3/3] OvmfPkg/PlatformPei: set 32-bit UC
|
|
|
7fdf80 |
area at PciBase / PciExBarBase (pc/q35)
|
|
|
7fdf80 |
Bugzilla: 1666941
|
|
|
7fdf80 |
Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
|
|
|
7fdf80 |
Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
|
|
7fdf80 |
|
|
|
7fdf80 |
(This is a replacement for commit 39b9a5ffe661 ("OvmfPkg/PlatformPei: fix
|
|
|
7fdf80 |
MTRR for low-RAM sizes that have many bits clear", 2019-05-16).)
|
|
|
7fdf80 |
|
|
|
7fdf80 |
Reintroduce the same logic as seen in commit 39b9a5ffe661 for the pc
|
|
|
7fdf80 |
(i440fx) board type.
|
|
|
7fdf80 |
|
|
|
7fdf80 |
For q35, the same approach doesn't work any longer, given that (a) we'd
|
|
|
7fdf80 |
like to keep the PCIEXBAR in the platform DSC a fixed-at-build PCD, and
|
|
|
7fdf80 |
(b) QEMU expects the PCIEXBAR to reside at a lower address than the 32-bit
|
|
|
7fdf80 |
PCI MMIO aperture.
|
|
|
7fdf80 |
|
|
|
7fdf80 |
Therefore, introduce a helper function for determining the 32-bit
|
|
|
7fdf80 |
"uncacheable" (MMIO) area base address:
|
|
|
7fdf80 |
|
|
|
7fdf80 |
- On q35, this function behaves statically. Furthermore, the MTRR setup
|
|
|
7fdf80 |
exploits that the range [0xB000_0000, 0xFFFF_FFFF] can be marked UC with
|
|
|
7fdf80 |
just two variable MTRRs (one at 0xB000_0000 (size 256MB), another at
|
|
|
7fdf80 |
0xC000_0000 (size 1GB)).
|
|
|
7fdf80 |
|
|
|
7fdf80 |
- On pc (i440fx), the function behaves dynamically, implementing the same
|
|
|
7fdf80 |
logic as commit 39b9a5ffe661 did. The PciBase value is adjusted to the
|
|
|
7fdf80 |
value calculated, similarly to commit 39b9a5ffe661. A further
|
|
|
7fdf80 |
simplification is that we show that the UC32 area size truncation to a
|
|
|
7fdf80 |
whole power of two automatically guarantees a >=2GB base address.
|
|
|
7fdf80 |
|
|
|
7fdf80 |
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
|
|
7fdf80 |
Cc: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
7fdf80 |
Cc: Jordan Justen <jordan.l.justen@intel.com>
|
|
|
7fdf80 |
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1859
|
|
|
7fdf80 |
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
7fdf80 |
Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com>
|
|
|
7fdf80 |
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
|
|
7fdf80 |
(cherry picked from commit 49edde15230a5bfd6746225eb95535eaa2ec1ba4)
|
|
|
7fdf80 |
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
7fdf80 |
---
|
|
|
7fdf80 |
OvmfPkg/PlatformPei/MemDetect.c | 59 ++++++++++++++++++++++++++++++++++++++---
|
|
|
7fdf80 |
OvmfPkg/PlatformPei/Platform.c | 5 +++-
|
|
|
7fdf80 |
OvmfPkg/PlatformPei/Platform.h | 7 +++++
|
|
|
7fdf80 |
3 files changed, 66 insertions(+), 5 deletions(-)
|
|
|
7fdf80 |
|
|
|
7fdf80 |
diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetect.c
|
|
|
7fdf80 |
index 2f9e835..0c38b70 100644
|
|
|
7fdf80 |
--- a/OvmfPkg/PlatformPei/MemDetect.c
|
|
|
7fdf80 |
+++ b/OvmfPkg/PlatformPei/MemDetect.c
|
|
|
7fdf80 |
@@ -20,6 +20,7 @@ Module Name:
|
|
|
7fdf80 |
// The package level header files this module uses
|
|
|
7fdf80 |
//
|
|
|
7fdf80 |
#include <IndustryStandard/E820.h>
|
|
|
7fdf80 |
+#include <IndustryStandard/I440FxPiix4.h>
|
|
|
7fdf80 |
#include <IndustryStandard/Q35MchIch9.h>
|
|
|
7fdf80 |
#include <PiPei.h>
|
|
|
7fdf80 |
|
|
|
7fdf80 |
@@ -48,6 +49,8 @@ STATIC UINT32 mS3AcpiReservedMemorySize;
|
|
|
7fdf80 |
|
|
|
7fdf80 |
STATIC UINT16 mQ35TsegMbytes;
|
|
|
7fdf80 |
|
|
|
7fdf80 |
+UINT32 mQemuUc32Base;
|
|
|
7fdf80 |
+
|
|
|
7fdf80 |
VOID
|
|
|
7fdf80 |
Q35TsegMbytesInitialization (
|
|
|
7fdf80 |
VOID
|
|
|
7fdf80 |
@@ -104,6 +107,54 @@ Q35TsegMbytesInitialization (
|
|
|
7fdf80 |
}
|
|
|
7fdf80 |
|
|
|
7fdf80 |
|
|
|
7fdf80 |
+VOID
|
|
|
7fdf80 |
+QemuUc32BaseInitialization (
|
|
|
7fdf80 |
+ VOID
|
|
|
7fdf80 |
+ )
|
|
|
7fdf80 |
+{
|
|
|
7fdf80 |
+ UINT32 LowerMemorySize;
|
|
|
7fdf80 |
+ UINT32 Uc32Size;
|
|
|
7fdf80 |
+
|
|
|
7fdf80 |
+ if (mXen) {
|
|
|
7fdf80 |
+ return;
|
|
|
7fdf80 |
+ }
|
|
|
7fdf80 |
+
|
|
|
7fdf80 |
+ if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
|
|
|
7fdf80 |
+ //
|
|
|
7fdf80 |
+ // On q35, the 32-bit area that we'll mark as UC, through variable MTRRs,
|
|
|
7fdf80 |
+ // starts at PcdPciExpressBaseAddress. The platform DSC is responsible for
|
|
|
7fdf80 |
+ // setting PcdPciExpressBaseAddress such that describing the
|
|
|
7fdf80 |
+ // [PcdPciExpressBaseAddress, 4GB) range require a very small number of
|
|
|
7fdf80 |
+ // variable MTRRs (preferably 1 or 2).
|
|
|
7fdf80 |
+ //
|
|
|
7fdf80 |
+ ASSERT (FixedPcdGet64 (PcdPciExpressBaseAddress) <= MAX_UINT32);
|
|
|
7fdf80 |
+ mQemuUc32Base = (UINT32)FixedPcdGet64 (PcdPciExpressBaseAddress);
|
|
|
7fdf80 |
+ return;
|
|
|
7fdf80 |
+ }
|
|
|
7fdf80 |
+
|
|
|
7fdf80 |
+ ASSERT (mHostBridgeDevId == INTEL_82441_DEVICE_ID);
|
|
|
7fdf80 |
+ //
|
|
|
7fdf80 |
+ // On i440fx, start with the [LowerMemorySize, 4GB) range. Make sure one
|
|
|
7fdf80 |
+ // variable MTRR suffices by truncating the size to a whole power of two,
|
|
|
7fdf80 |
+ // while keeping the end affixed to 4GB. This will round the base up.
|
|
|
7fdf80 |
+ //
|
|
|
7fdf80 |
+ LowerMemorySize = GetSystemMemorySizeBelow4gb ();
|
|
|
7fdf80 |
+ Uc32Size = GetPowerOfTwo32 ((UINT32)(SIZE_4GB - LowerMemorySize));
|
|
|
7fdf80 |
+ mQemuUc32Base = (UINT32)(SIZE_4GB - Uc32Size);
|
|
|
7fdf80 |
+ //
|
|
|
7fdf80 |
+ // Assuming that LowerMemorySize is at least 1 byte, Uc32Size is at most 2GB.
|
|
|
7fdf80 |
+ // Therefore mQemuUc32Base is at least 2GB.
|
|
|
7fdf80 |
+ //
|
|
|
7fdf80 |
+ ASSERT (mQemuUc32Base >= BASE_2GB);
|
|
|
7fdf80 |
+
|
|
|
7fdf80 |
+ if (mQemuUc32Base != LowerMemorySize) {
|
|
|
7fdf80 |
+ DEBUG ((DEBUG_VERBOSE, "%a: rounded UC32 base from 0x%x up to 0x%x, for "
|
|
|
7fdf80 |
+ "an UC32 size of 0x%x\n", __FUNCTION__, LowerMemorySize, mQemuUc32Base,
|
|
|
7fdf80 |
+ Uc32Size));
|
|
|
7fdf80 |
+ }
|
|
|
7fdf80 |
+}
|
|
|
7fdf80 |
+
|
|
|
7fdf80 |
+
|
|
|
7fdf80 |
/**
|
|
|
7fdf80 |
Iterate over the RAM entries in QEMU's fw_cfg E820 RAM map that start outside
|
|
|
7fdf80 |
of the 32-bit address range.
|
|
|
7fdf80 |
@@ -694,11 +745,11 @@ QemuInitializeRam (
|
|
|
7fdf80 |
ASSERT_EFI_ERROR (Status);
|
|
|
7fdf80 |
|
|
|
7fdf80 |
//
|
|
|
7fdf80 |
- // Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB as
|
|
|
7fdf80 |
- // uncacheable
|
|
|
7fdf80 |
+ // Set the memory range from the start of the 32-bit MMIO area (32-bit PCI
|
|
|
7fdf80 |
+ // MMIO aperture on i440fx, PCIEXBAR on q35) to 4GB as uncacheable.
|
|
|
7fdf80 |
//
|
|
|
7fdf80 |
- Status = MtrrSetMemoryAttribute (LowerMemorySize,
|
|
|
7fdf80 |
- SIZE_4GB - LowerMemorySize, CacheUncacheable);
|
|
|
7fdf80 |
+ Status = MtrrSetMemoryAttribute (mQemuUc32Base, SIZE_4GB - mQemuUc32Base,
|
|
|
7fdf80 |
+ CacheUncacheable);
|
|
|
7fdf80 |
ASSERT_EFI_ERROR (Status);
|
|
|
7fdf80 |
}
|
|
|
7fdf80 |
}
|
|
|
7fdf80 |
diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c
|
|
|
7fdf80 |
index 64b8034..de19f5c 100644
|
|
|
7fdf80 |
--- a/OvmfPkg/PlatformPei/Platform.c
|
|
|
7fdf80 |
+++ b/OvmfPkg/PlatformPei/Platform.c
|
|
|
7fdf80 |
@@ -197,7 +197,8 @@ MemMapInitialization (
|
|
|
7fdf80 |
ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB);
|
|
|
7fdf80 |
PciBase = (UINT32)(PciExBarBase + SIZE_256MB);
|
|
|
7fdf80 |
} else {
|
|
|
7fdf80 |
- PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam;
|
|
|
7fdf80 |
+ ASSERT (TopOfLowRam <= mQemuUc32Base);
|
|
|
7fdf80 |
+ PciBase = mQemuUc32Base;
|
|
|
7fdf80 |
}
|
|
|
7fdf80 |
|
|
|
7fdf80 |
//
|
|
|
7fdf80 |
@@ -656,6 +657,8 @@ InitializePlatform (
|
|
|
7fdf80 |
|
|
|
7fdf80 |
PublishPeiMemory ();
|
|
|
7fdf80 |
|
|
|
7fdf80 |
+ QemuUc32BaseInitialization ();
|
|
|
7fdf80 |
+
|
|
|
7fdf80 |
InitializeRamRegions ();
|
|
|
7fdf80 |
|
|
|
7fdf80 |
if (mXen) {
|
|
|
7fdf80 |
diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h
|
|
|
7fdf80 |
index b12a5c1..2b486ce 100644
|
|
|
7fdf80 |
--- a/OvmfPkg/PlatformPei/Platform.h
|
|
|
7fdf80 |
+++ b/OvmfPkg/PlatformPei/Platform.h
|
|
|
7fdf80 |
@@ -69,6 +69,11 @@ GetSystemMemorySizeBelow4gb (
|
|
|
7fdf80 |
);
|
|
|
7fdf80 |
|
|
|
7fdf80 |
VOID
|
|
|
7fdf80 |
+QemuUc32BaseInitialization (
|
|
|
7fdf80 |
+ VOID
|
|
|
7fdf80 |
+ );
|
|
|
7fdf80 |
+
|
|
|
7fdf80 |
+VOID
|
|
|
7fdf80 |
InitializeRamRegions (
|
|
|
7fdf80 |
VOID
|
|
|
7fdf80 |
);
|
|
|
7fdf80 |
@@ -120,4 +125,6 @@ extern UINT32 mMaxCpuCount;
|
|
|
7fdf80 |
|
|
|
7fdf80 |
extern UINT16 mHostBridgeDevId;
|
|
|
7fdf80 |
|
|
|
7fdf80 |
+extern UINT32 mQemuUc32Base;
|
|
|
7fdf80 |
+
|
|
|
7fdf80 |
#endif // _PLATFORM_PEI_H_INCLUDED_
|
|
|
7fdf80 |
--
|
|
|
7fdf80 |
1.8.3.1
|
|
|
7fdf80 |
|