Hello.

There is problem in PCI device allocation algorithm (pci_setup()).
Algorithm allocates PCI BAR sorted by size and this allows
mixed allocation of prefetchable and non-prefetchable PCI MEM BAR.
This leads to wrong config of PCI root port (see "Type 1 Configuration Space Registers (Root Ports)").

Tested with version xen 4.11.1 + "export 
OVMF_UPSTREAM_REVISION=ef529e6ab7c31290a33045bb1f1837447cc0eb56"
(embeded commit OVMF does not work (crashed even in Win10.iso and uncompilable 
with newer gcc)).

Attached also testing patch.

Thanks, Martin Cerveny

---------------------------------------------------------------------

Verifiable in crash of OVMF (UEFI firmware) [OVMF DEBUG]:

ASSERT_EFI_ERROR (Status = Not Found)
ASSERT 
/root/rpmbuild/BUILD/xen-4.11.1/tools/firmware/ovmf-dir-remote/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c(513):
 !EFI_ERROR (Status)

---------------------------------------------------------------------

Summary of errored output:

[xl dmesg]
(d1) [  395.698273] pci dev 0b:0 bar 14 size 010000000: 0e0000008
(d1) [  395.714836] pci dev 0b:0 bar 18 size 002000000: 0f0000000
(d1) [  395.715369] pci dev 02:0 bar 14 size 001000000: 0f2000008
(d1) [  395.716049] pci dev 0b:0 bar 10 size 001000000: 0f3000000
(d1) [  395.716479] pci dev 04:0 bar 30 size 000040000: 0f4000000
(d1) [  395.716908] pci dev 0b:0 bar 30 size 000010000: 0f4040000

- *008 == prefetchable MEM BAR (PCI_BASE_ADDRESS_MEM_PREFETCH)

[OVMF DEBUG]:
InitRootBridge: populated root bus 0, with room for 0 subordinate bus(es)
RootBridge: PciRoot(0x0)
  Support/Attr: 7007F / 7007F
    DmaAbove4G: No
NoExtConfSpace: Yes
     AllocAttr: 0 ()
           Bus: 0 - 0 Translation=0
            Io: C000 - C2EF Translation=0
           Mem: F0000000 - F40550FF Translation=0
    MemAbove4G: FFFFFFFFFFFFFFFF - 0 Translation=0
          PMem: E0000000 - F2FFFFFF Translation=0
   PMemAbove4G: FFFFFFFFFFFFFFFF - 0 Translation=0

- check overlap of Mem an PMem!
- check code 
tools/firmware/ovmf-dir-remote/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
    //
    // Add all the Mem/PMem aperture to GCD
    // Mem/PMem shouldn't overlap with each other
    // Root bridge which needs to combine MEM and PMEM should only report
    // the MEM aperture in Mem
    //

---------------------------------------------------------------------

Summary of OK/expected output:

[xl dmesg]
(d2) [ 1833.077182] pci dev 0b:0 bar 14 size 010000000: 0e0000008
(d2) [ 1833.077798] pci dev 02:0 bar 14 size 001000000: 0f0000008
(d2) [ 1833.103301] pci dev 0b:0 bar 18 size 002000000: 0f2000000
(d2) [ 1833.103882] pci dev 0b:0 bar 10 size 001000000: 0f4000000
(d2) [ 1833.104164] pci dev 04:0 bar 30 size 000040000: 0f5000000
(d2) [ 1833.104429] pci dev 0b:0 bar 30 size 000010000: 0f5040000

[OVMF DEBUG]
RootBridge: PciRoot(0x0)
  Support/Attr: 7007F / 7007F
    DmaAbove4G: No
NoExtConfSpace: Yes
     AllocAttr: 0 ()
           Bus: 0 - 0 Translation=0
            Io: C000 - C2EF Translation=0
           Mem: F2000000 - F50550FF Translation=0
    MemAbove4G: FFFFFFFFFFFFFFFF - 0 Translation=0
          PMem: E0000000 - F0FFFFFF Translation=0
   PMemAbove4G: FFFFFFFFFFFFFFFF - 0 Translation=0

---------------------------------------------------------------------
From b8d8f9f5ada9568f672f4ce9d68fe0f66cae44f5 Mon Sep 17 00:00:00 2001
From: Martin Cerveny <m.cerv...@computer.org>
Date: Sun, 31 Mar 2019 09:26:05 +0200
Subject: [PATCH] pci: Merge allocation of prefetchable MEM BAR

Fragmented allocation of NON-prefetchable (MMIO) and prefetchable PCI MEM BAR
not supported - see "Type 1 Configuration Space Registers (Root Ports)".
---
 tools/firmware/hvmloader/pci.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/tools/firmware/hvmloader/pci.c b/tools/firmware/hvmloader/pci.c
index 0b708bf578..42a3dd5e62 100644
--- a/tools/firmware/hvmloader/pci.c
+++ b/tools/firmware/hvmloader/pci.c
@@ -97,7 +97,7 @@ void pci_setup(void)
         uint32_t bar_reg;
         uint64_t bar_sz;
     } *bars = (struct bars *)scratch_start;
-    unsigned int i, nr_bars = 0;
+    unsigned int i, nr_bars = 0, nr_bars_pref = 0;
     uint64_t mmio_hole_size = 0;
 
     const char *s;
@@ -253,9 +253,19 @@ void pci_setup(void)
             if ( bar_sz == 0 )
                 continue;
 
-            for ( i = 0; i < nr_bars; i++ )
-                if ( bars[i].bar_sz < bar_sz )
-                    break;
+           if (((bar_data & PCI_BASE_ADDRESS_SPACE) ==
+                 PCI_BASE_ADDRESS_SPACE_MEMORY) &&
+                ((bar_data & PCI_BASE_ADDRESS_MEM_PREFETCH) ==
+                PCI_BASE_ADDRESS_MEM_PREFETCH)) {
+                for ( i = 0; i < nr_bars_pref; i++ )
+                   if ( bars[i].bar_sz < bar_sz )
+                       break;
+                nr_bars_pref++;
+            }
+            else
+                for ( i = nr_bars_pref; i < nr_bars; i++ )
+                    if ( bars[i].bar_sz < bar_sz )
+                       break;
 
             if ( i != nr_bars )
                 memmove(&bars[i+1], &bars[i], (nr_bars-i) * sizeof(*bars));
-- 
2.20.1

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Reply via email to