[OpenBIOS] [PATCH] pci: fix setup of 64-bit BARs

Mark Cave-Ayland mark.cave-ayland at ilande.co.uk
Sat Mar 11 15:38:39 CET 2017

The current PCI implementation is designed for a 32-bit PCI bus. When
a 64-bit BAR is encountered during PCI bus enumeration, currently we
treat the MSB BAR the same as a standard 32-bit BAR, attempting to guess
its size by setting to 0xffffffff and reading back the response which
returns back an invalid size of 0 and fails.

This has the effect of setting the MSB BAR to 0xffffffff meaning that
64-bit BARs are mapped at the top of PCI memory in the wrong location.

Handle this case by ignoring the MSB BAR when we detect a 64-bit BAR
leaving it at its default value of zero. This solves the issue by
ensuring that all 64-bit BARs are mapped within 32-bit PCI space which
is fine for the PPC/SPARC64 machines we care about.

Most noticeably this solves the issue of virtio modern devices (which
use 64-bit BARs under QEMU) causing a kernel panic upon startup on
qemu-system-sparc64 because they are mapped at the wrong address by OpenBIOS.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
 drivers/pci.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/pci.c b/drivers/pci.c
index c998280..2e09d0a 100644
--- a/drivers/pci.c
+++ b/drivers/pci.c
@@ -1202,9 +1202,9 @@ ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar,
                  unsigned long *mem_base, unsigned long *io_base)
-        uint32_t omask;
+        uint32_t omask, mask;
         uint16_t cmd;
-        int reg;
+        int reg, flags, space_code;
         pci_addr config_addr;
         ob_pci_configure_irq(addr, config);
@@ -1216,6 +1216,14 @@ ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar,
                 ob_pci_configure_bar(addr, config, reg, config_addr,
                                      &omask, mem_base,
+                /* Ignore 64-bit BAR MSBs (always map in 32-bit space) */
+                pci_decode_pci_addr(config->assigned[reg],
+                                    &flags, &space_code, &mask);
+                if (space_code == MEMORY_SPACE_64) {
+                    reg++;
+                }
         if (rom_bar) {

More information about the OpenBIOS mailing list