[edk2-devel] [PATCH 2/2] OvmfPkg/PlatformInitLib: check 64bit mmio window for resource conflicts

Gerd Hoffmann posted 2 patches 3 years, 1 month ago
There is a newer version of this series
[edk2-devel] [PATCH 2/2] OvmfPkg/PlatformInitLib: check 64bit mmio window for resource conflicts
Posted by Gerd Hoffmann 3 years, 1 month ago
Add new operation mode to PlatformScanOrAdd64BitE820Ram() which checks
whenever any reservations from the qemu e820 table overlap with the mmio
window.  Should that be the case move it to avoid the conflict.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 OvmfPkg/Library/PlatformInitLib/MemDetect.c | 47 ++++++++++++++++++---
 1 file changed, 41 insertions(+), 6 deletions(-)

diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
index 1255d6300fdd..4f5a04832a4e 100644
--- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c
+++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
@@ -126,6 +126,12 @@ PlatformQemuUc32BaseInitialization (
                           entries that start at or above 4GB.
                           It also produces HOBs for reserved entries.
 
+  @param[in out] PlatformInfoHob  If Lowmemory PlatformInfoHob is not NULL,
+                                  then PlatformScanOrAdd64BitE820Ram() checks
+                                  the 64bit PCI MMIO window against conflicts
+                                  with e820 reservations from qemu.  If needed
+                                  the MMIO window will be moved down.
+
   @param[out] LowMemory  If Lowmemory is not NULL, then Lowmemory MaxAddress
                          holds the amout of emory below 4G on output.
 
@@ -147,9 +153,10 @@ PlatformQemuUc32BaseInitialization (
 STATIC
 EFI_STATUS
 PlatformScanOrAdd64BitE820Ram (
-  IN BOOLEAN  AddHighHob,
-  OUT UINT64  *LowMemory OPTIONAL,
-  OUT UINT64  *MaxAddress OPTIONAL
+  IN BOOLEAN                    AddHighHob,
+  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob OPTIONAL,
+  OUT UINT64                    *LowMemory OPTIONAL,
+  OUT UINT64                    *MaxAddress OPTIONAL
   )
 {
   EFI_STATUS            Status;
@@ -249,6 +256,33 @@ PlatformScanOrAdd64BitE820Ram (
           E820Entry.Length
           );
       }
+
+      if (PlatformInfoHob) {
+        UINT64  IntersectionBase = MAX (
+                                     E820Entry.BaseAddr,
+                                     PlatformInfoHob->PcdPciMmio64Base
+                                     );
+        UINT64  IntersectionEnd = MIN (
+                                    E820Entry.BaseAddr + E820Entry.Length,
+                                    PlatformInfoHob->PcdPciMmio64Base +
+                                    PlatformInfoHob->PcdPciMmio64Size
+                                    );
+
+        if (IntersectionBase < IntersectionEnd) {
+          // have overlap, so move mmio window down from end of address space
+          UINT64  NewBase = (PlatformInfoHob->PcdPciMmio64Base -
+                             PlatformInfoHob->PcdPciMmio64Size);
+
+          DEBUG ((
+            DEBUG_INFO,
+            "%a: move mmio: 0x%Lx => %Lx\n",
+            __FUNCTION__,
+            PlatformInfoHob->PcdPciMmio64Base,
+            NewBase
+            ));
+          PlatformInfoHob->PcdPciMmio64Base = NewBase;
+        }
+      }
     }
   }
 
@@ -340,7 +374,7 @@ PlatformGetSystemMemorySizeBelow4gb (
     return (UINT32)GetHighestSystemMemoryAddressFromPvhMemmap (TRUE);
   }
 
-  Status = PlatformScanOrAdd64BitE820Ram (FALSE, &LowerMemorySize, NULL);
+  Status = PlatformScanOrAdd64BitE820Ram (FALSE, NULL, &LowerMemorySize, NULL);
   if ((Status == EFI_SUCCESS) && (LowerMemorySize > 0)) {
     return (UINT32)LowerMemorySize;
   }
@@ -412,7 +446,7 @@ PlatformGetFirstNonAddress (
   // Otherwise, get the flat size of the memory above 4GB from the CMOS (which
   // can only express a size smaller than 1TB), and add it to 4GB.
   //
-  Status = PlatformScanOrAdd64BitE820Ram (FALSE, NULL, &FirstNonAddress);
+  Status = PlatformScanOrAdd64BitE820Ram (FALSE, NULL, NULL, &FirstNonAddress);
   if (EFI_ERROR (Status)) {
     FirstNonAddress = BASE_4GB + PlatformGetSystemMemorySizeAbove4gb ();
   }
@@ -648,6 +682,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;
+    PlatformScanOrAdd64BitE820Ram (FALSE, PlatformInfoHob, NULL, NULL);
   } else {
     DEBUG ((DEBUG_INFO, "%a: using classic mmio window\n", __func__));
   }
@@ -960,7 +995,7 @@ PlatformQemuInitializeRam (
     // entries. Otherwise, create a single memory HOB with the flat >=4GB
     // memory size read from the CMOS.
     //
-    Status = PlatformScanOrAdd64BitE820Ram (TRUE, NULL, NULL);
+    Status = PlatformScanOrAdd64BitE820Ram (TRUE, NULL, NULL, NULL);
     if (EFI_ERROR (Status)) {
       UpperMemorySize = PlatformGetSystemMemorySizeAbove4gb ();
       if (UpperMemorySize != 0) {
-- 
2.39.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#98125): https://edk2.groups.io/g/devel/message/98125
Mute This Topic: https://groups.io/mt/96093486/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH 2/2] OvmfPkg/PlatformInitLib: check 64bit mmio window for resource conflicts
Posted by Pedro Falcato 3 years, 1 month ago
On Fri, Jan 6, 2023 at 2:04 PM Gerd Hoffmann <kraxel@redhat.com> wrote:

> Add new operation mode to PlatformScanOrAdd64BitE820Ram() which checks
> whenever any reservations from the qemu e820 table overlap with the mmio
> window.  Should that be the case move it to avoid the conflict.
>
Hi,

In what case could this happen? Does QEMU ever place e820 entries inside
the PCI MMIO window? Why?
(In fact, when does QEMU even add a reservation in the e820? I've never
seen one.)
Just checking for QemuOpenBoardPkg.

Thanks,
Pedro


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#98140): https://edk2.groups.io/g/devel/message/98140
Mute This Topic: https://groups.io/mt/96093486/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-


Re: [edk2-devel] [PATCH 2/2] OvmfPkg/PlatformInitLib: check 64bit mmio window for resource conflicts
Posted by Gerd Hoffmann 3 years, 1 month ago
On Fri, Jan 06, 2023 at 08:39:38PM +0000, Pedro Falcato wrote:
> On Fri, Jan 6, 2023 at 2:04 PM Gerd Hoffmann <kraxel@redhat.com> wrote:
> 
> > Add new operation mode to PlatformScanOrAdd64BitE820Ram() which checks
> > whenever any reservations from the qemu e820 table overlap with the mmio
> > window.  Should that be the case move it to avoid the conflict.
> >
> Hi,
> 
> In what case could this happen? Does QEMU ever place e820 entries inside
> the PCI MMIO window? Why?

Well, the *firmware* picks where it places the PCI MMIO window.  So it's
not qemu creating a conflict ;)

> (In fact, when does QEMU even add a reservation in the e820? I've never
> seen one.)

New enough qemu adds a reservation just below 1TB when running on AMD
processors (or emulating one with tcg).  That window is used by the
iommu.

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#98172): https://edk2.groups.io/g/devel/message/98172
Mute This Topic: https://groups.io/mt/96093486/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-