]> xenbits.xensource.com Git - seabios.git/commitdiff
pci: add mmconfig support
authorGerd Hoffmann <kraxel@redhat.com>
Mon, 23 Mar 2020 14:59:11 +0000 (15:59 +0100)
committerGerd Hoffmann <kraxel@redhat.com>
Fri, 27 Mar 2020 07:32:45 +0000 (08:32 +0100)
Add support for pci config space access via mmconfig bar.  Enable for
qemu q35 chipset.  Main advantage is that we need only one instead of
two io operations per config space access, which translates to one
instead of two vmexits for virtualization.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20200323145911.22319-3-kraxel@redhat.com

src/fw/pciinit.c
src/hw/pci.c
src/hw/pci.h

index d5e87f00f1649416987ae77add47cb36bab1438e..d25931bb0573c0c59e6d4328d21d1b81bdb94f22 100644 (file)
@@ -480,6 +480,7 @@ static void mch_mmconfig_setup(u16 bdf)
     pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0);
     pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);
     pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower);
+    pci_enable_mmconfig(Q35_HOST_BRIDGE_PCIEXBAR_ADDR, "q35");
 }
 
 static void mch_mem_addr_setup(struct pci_device *dev, void *arg)
index 7aca1e6bfa9712124bcc8ca1981694fcf0f39ef1..d9dbf313965c2a620cc7e3ea1b16f01095a3a483 100644 (file)
 #define PORT_PCI_CMD           0x0cf8
 #define PORT_PCI_DATA          0x0cfc
 
+static u32 mmconfig;
+
+static void *mmconfig_addr(u16 bdf, u32 addr)
+{
+    return (void*)(mmconfig + ((u32)bdf << 12) + addr);
+}
+
 static u32 ioconfig_cmd(u16 bdf, u32 addr)
 {
     return 0x80000000 | (bdf << 8) | (addr & 0xfc);
@@ -21,38 +28,62 @@ static u32 ioconfig_cmd(u16 bdf, u32 addr)
 
 void pci_config_writel(u16 bdf, u32 addr, u32 val)
 {
-    outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
-    outl(val, PORT_PCI_DATA);
+    if (MODESEGMENT && mmconfig) {
+        writel(mmconfig_addr(bdf, addr), val);
+    } else {
+        outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+        outl(val, PORT_PCI_DATA);
+    }
 }
 
 void pci_config_writew(u16 bdf, u32 addr, u16 val)
 {
-    outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
-    outw(val, PORT_PCI_DATA + (addr & 2));
+    if (MODESEGMENT && mmconfig) {
+        writew(mmconfig_addr(bdf, addr), val);
+    } else {
+        outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+        outw(val, PORT_PCI_DATA + (addr & 2));
+    }
 }
 
 void pci_config_writeb(u16 bdf, u32 addr, u8 val)
 {
-    outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
-    outb(val, PORT_PCI_DATA + (addr & 3));
+    if (MODESEGMENT && mmconfig) {
+        writeb(mmconfig_addr(bdf, addr), val);
+    } else {
+        outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+        outb(val, PORT_PCI_DATA + (addr & 3));
+    }
 }
 
 u32 pci_config_readl(u16 bdf, u32 addr)
 {
-    outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
-    return inl(PORT_PCI_DATA);
+    if (MODESEGMENT && mmconfig) {
+        return readl(mmconfig_addr(bdf, addr));
+    } else {
+        outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+        return inl(PORT_PCI_DATA);
+    }
 }
 
 u16 pci_config_readw(u16 bdf, u32 addr)
 {
-    outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
-    return inw(PORT_PCI_DATA + (addr & 2));
+    if (MODESEGMENT && mmconfig) {
+        return readw(mmconfig_addr(bdf, addr));
+    } else {
+        outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+        return inw(PORT_PCI_DATA + (addr & 2));
+    }
 }
 
 u8 pci_config_readb(u16 bdf, u32 addr)
 {
-    outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
-    return inb(PORT_PCI_DATA + (addr & 3));
+    if (MODESEGMENT && mmconfig) {
+        return readb(mmconfig_addr(bdf, addr));
+    } else {
+        outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+        return inb(PORT_PCI_DATA + (addr & 3));
+    }
 }
 
 void
@@ -63,6 +94,15 @@ pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
     pci_config_writew(bdf, addr, val);
 }
 
+void
+pci_enable_mmconfig(u64 addr, const char *name)
+{
+    if (addr >= 0x100000000ll)
+        return;
+    dprintf(1, "PCIe: using %s mmconfig at 0x%llx\n", name, addr);
+    mmconfig = addr;
+}
+
 u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap)
 {
     int i;
index 2e30e28918a0589eccb1831dd188784163d3d315..01c51f705a00dd39c39b81fbebdef12e5d258009 100644 (file)
@@ -39,6 +39,7 @@ u32 pci_config_readl(u16 bdf, u32 addr);
 u16 pci_config_readw(u16 bdf, u32 addr);
 u8 pci_config_readb(u16 bdf, u32 addr);
 void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
+void pci_enable_mmconfig(u64 addr, const char *name);
 u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap);
 int pci_next(int bdf, int bus);
 int pci_probe_host(void);