}\r
}\r
\r
+/**\r
+ Check whenever the 64bit PCI MMIO window overlaps with a reservation\r
+ from qemu. If so move down the MMIO window to resolve the conflict.\r
+\r
+ This happens on (virtual) AMD machines with 1TB address space,\r
+ because the AMD IOMMU uses an address window just below 1TB.\r
+**/\r
+STATIC\r
+VOID\r
+PlatformReservationConflictCB (\r
+ IN EFI_E820_ENTRY64 *E820Entry,\r
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
+ )\r
+{\r
+ UINT64 IntersectionBase;\r
+ UINT64 IntersectionEnd;\r
+ UINT64 NewBase;\r
+\r
+ IntersectionBase = MAX (\r
+ E820Entry->BaseAddr,\r
+ PlatformInfoHob->PcdPciMmio64Base\r
+ );\r
+ IntersectionEnd = MIN (\r
+ E820Entry->BaseAddr + E820Entry->Length,\r
+ PlatformInfoHob->PcdPciMmio64Base +\r
+ PlatformInfoHob->PcdPciMmio64Size\r
+ );\r
+\r
+ if (IntersectionBase >= IntersectionEnd) {\r
+ return; // no overlap\r
+ }\r
+\r
+ NewBase = E820Entry->BaseAddr - PlatformInfoHob->PcdPciMmio64Size;\r
+ NewBase = NewBase & ~(PlatformInfoHob->PcdPciMmio64Size - 1);\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a: move mmio: 0x%Lx => %Lx\n",\r
+ __FUNCTION__,\r
+ PlatformInfoHob->PcdPciMmio64Base,\r
+ NewBase\r
+ ));\r
+ PlatformInfoHob->PcdPciMmio64Base = NewBase;\r
+}\r
+\r
/**\r
Iterate over the entries in QEMU's fw_cfg E820 RAM map, call the\r
passed callback for each entry.\r
DEBUG ((DEBUG_INFO, "%a: MMIO Space 0x%Lx (%Ld GB)\n", __func__, MmioSpace, RShiftU64 (MmioSpace, 30)));\r
PlatformInfoHob->PcdPciMmio64Size = MmioSpace;\r
PlatformInfoHob->PcdPciMmio64Base = AddrSpace - MmioSpace;\r
+ PlatformScanE820 (PlatformReservationConflictCB, PlatformInfoHob);\r
} else {\r
DEBUG ((DEBUG_INFO, "%a: using classic mmio window\n", __func__));\r
}\r