[SeaBIOS] [PATCH 2/2] shadow: Batch PCI config writes

Kevin O'Connor kevin at koconnor.net
Tue Apr 5 18:51:56 CEST 2016


Enabling and disabling shadow ram on QEMU is slow.  Batch the PCI
writes to reduce the number of memory changes QEMU must implement.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 src/fw/shadow.c | 55 ++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 38 insertions(+), 17 deletions(-)

diff --git a/src/fw/shadow.c b/src/fw/shadow.c
index f766bb5..cd02d3a 100644
--- a/src/fw/shadow.c
+++ b/src/fw/shadow.c
@@ -21,27 +21,39 @@
 // On the emulators, the bios at 0xf0000 is also at 0xffff0000
 #define BIOS_SRC_OFFSET 0xfff00000
 
+union pamdata_u {
+    u8 data8[8];
+    u32 data32[2];
+};
+
 // Enable shadowing and copy bios.
 static void
 __make_bios_writable_intel(u16 bdf, u32 pam0)
 {
+    // Read in current PAM settings from pci config space
+    union pamdata_u pamdata;
+    pamdata.data32[0] = pci_config_readl(bdf, ALIGN_DOWN(pam0, 4));
+    pamdata.data32[1] = pci_config_readl(bdf, ALIGN_DOWN(pam0, 4) + 4);
+    u8 *pam = &pamdata.data8[pam0 & 0x03];
+
     // Make ram from 0xc0000-0xf0000 writable
     int i;
-    for (i=0; i<6; i++) {
-        u32 pam = pam0 + 1 + i;
-        pci_config_writeb(bdf, pam, 0x33);
-    }
+    for (i=0; i<6; i++)
+        pam[i + 1] = 0x33;
 
     // Make ram from 0xf0000-0x100000 writable
-    int reg = pci_config_readb(bdf, pam0);
-    pci_config_writeb(bdf, pam0, 0x30);
-    if (reg & 0x10)
-        // Ram already present.
-        return;
-
-    // Copy bios.
-    memcpy(VSYMBOL(code32flat_start), VSYMBOL(code32flat_start) + BIOS_SRC_OFFSET
-           , SYMBOL(code32flat_end) - SYMBOL(code32flat_start));
+    int ram_present = pam[0] & 0x10;
+    pam[0] = 0x30;
+
+    // Write PAM settings back to pci config space
+    pci_config_writel(bdf, ALIGN_DOWN(pam0, 4), pamdata.data32[0]);
+    pci_config_writel(bdf, ALIGN_DOWN(pam0, 4) + 4, pamdata.data32[1]);
+
+    if (!ram_present)
+        // Copy bios.
+        memcpy(VSYMBOL(code32flat_start)
+               , VSYMBOL(code32flat_start) + BIOS_SRC_OFFSET
+               , SYMBOL(code32flat_end) - SYMBOL(code32flat_start));
 }
 
 static void
@@ -68,6 +80,12 @@ make_bios_readonly_intel(u16 bdf, u32 pam0)
     // Flush any pending writes before locking memory.
     wbinvd();
 
+    // Read in current PAM settings from pci config space
+    union pamdata_u pamdata;
+    pamdata.data32[0] = pci_config_readl(bdf, ALIGN_DOWN(pam0, 4));
+    pamdata.data32[1] = pci_config_readl(bdf, ALIGN_DOWN(pam0, 4) + 4);
+    u8 *pam = &pamdata.data8[pam0 & 0x03];
+
     // Write protect roms from 0xc0000-0xf0000
     u32 romlast = BUILD_BIOS_ADDR, rommax = BUILD_BIOS_ADDR;
     if (CONFIG_WRITABLE_UPPERMEMORY)
@@ -77,17 +95,20 @@ make_bios_readonly_intel(u16 bdf, u32 pam0)
     int i;
     for (i=0; i<6; i++) {
         u32 mem = BUILD_ROM_START + i * 32*1024;
-        u32 pam = pam0 + 1 + i;
         if (romlast < mem + 16*1024 || rommax < mem + 32*1024) {
             if (romlast >= mem && rommax >= mem + 16*1024)
-                pci_config_writeb(bdf, pam, 0x31);
+                pam[i + 1] = 0x31;
             break;
         }
-        pci_config_writeb(bdf, pam, 0x11);
+        pam[i + 1] = 0x11;
     }
 
     // Write protect 0xf0000-0x100000
-    pci_config_writeb(bdf, pam0, 0x10);
+    pam[0] = 0x10;
+
+    // Write PAM settings back to pci config space
+    pci_config_writel(bdf, ALIGN_DOWN(pam0, 4), pamdata.data32[0]);
+    pci_config_writel(bdf, ALIGN_DOWN(pam0, 4) + 4, pamdata.data32[1]);
 }
 
 static int ShadowBDF = -1;
-- 
2.5.5




More information about the SeaBIOS mailing list