summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2023-01-17 13:16:28 +0100
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-01-17 16:36:59 +0000
commitc0a0b9bc3534b71ad90c022b0cab10910697de69 (patch)
treed2d951a301e48ddab73646e83f808f0562b6caeb
parent328076cfdf4560aed3ae83bfb0f013e8da827ed5 (diff)
downloadedk2-c0a0b9bc3534b71ad90c022b0cab10910697de69.tar.gz
edk2-c0a0b9bc3534b71ad90c022b0cab10910697de69.tar.bz2
edk2-c0a0b9bc3534b71ad90c022b0cab10910697de69.zip
OvmfPkg/PlatformInitLib: Add PlatformReservationConflictCB
Add PlatformReservationConflictCB() callback function for use with PlatformScanE820(). It checks whenever the 64bit PCI MMIO window overlaps with a reservation from qemu. If so move down the MMIO window to resolve the conflict. Write any actions done (moving mmio window) to the firmware log with INFO loglevel. This happens on (virtual) AMD machines with 1TB address space, because the AMD IOMMU uses an address window just below 1TB. Bugzilla: https://bugzilla.tianocore.org/show_bug.cgi?id=4251 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
-rw-r--r--OvmfPkg/Library/PlatformInitLib/MemDetect.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
index c24105c329..6c30566db9 100644
--- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c
+++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
@@ -217,6 +217,51 @@ PlatformAddHobCB (
}
/**
+ Check whenever the 64bit PCI MMIO window overlaps with a reservation
+ from qemu. If so move down the MMIO window to resolve the conflict.
+
+ This happens on (virtual) AMD machines with 1TB address space,
+ because the AMD IOMMU uses an address window just below 1TB.
+**/
+STATIC
+VOID
+PlatformReservationConflictCB (
+ IN EFI_E820_ENTRY64 *E820Entry,
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
+ )
+{
+ UINT64 IntersectionBase;
+ UINT64 IntersectionEnd;
+ UINT64 NewBase;
+
+ IntersectionBase = MAX (
+ E820Entry->BaseAddr,
+ PlatformInfoHob->PcdPciMmio64Base
+ );
+ IntersectionEnd = MIN (
+ E820Entry->BaseAddr + E820Entry->Length,
+ PlatformInfoHob->PcdPciMmio64Base +
+ PlatformInfoHob->PcdPciMmio64Size
+ );
+
+ if (IntersectionBase >= IntersectionEnd) {
+ return; // no overlap
+ }
+
+ NewBase = E820Entry->BaseAddr - PlatformInfoHob->PcdPciMmio64Size;
+ NewBase = NewBase & ~(PlatformInfoHob->PcdPciMmio64Size - 1);
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: move mmio: 0x%Lx => %Lx\n",
+ __FUNCTION__,
+ PlatformInfoHob->PcdPciMmio64Base,
+ NewBase
+ ));
+ PlatformInfoHob->PcdPciMmio64Base = NewBase;
+}
+
+/**
Iterate over the entries in QEMU's fw_cfg E820 RAM map, call the
passed callback for each entry.
@@ -653,6 +698,7 @@ PlatformDynamicMmioWindow (
DEBUG ((DEBUG_INFO, "%a: MMIO Space 0x%Lx (%Ld GB)\n", __func__, MmioSpace, RShiftU64 (MmioSpace, 30)));
PlatformInfoHob->PcdPciMmio64Size = MmioSpace;
PlatformInfoHob->PcdPciMmio64Base = AddrSpace - MmioSpace;
+ PlatformScanE820 (PlatformReservationConflictCB, PlatformInfoHob);
} else {
DEBUG ((DEBUG_INFO, "%a: using classic mmio window\n", __func__));
}