Patchwork [v2,4/8] seabios: pciinit: make pci bar assigner preferchable memory aware.

login
register
mail settings
Submitter Isaku Yamahata
Date June 22, 2010, 8:57 a.m.
Message ID <b7ed5501402cb89c9c099475b65921908b2b5062.1277196704.git.yamahata@valinux.co.jp>
Download mbox | patch
Permalink /patch/56439/
State New
Headers show

Comments

Isaku Yamahata - June 22, 2010, 8:57 a.m.
Make pci bar assigner preferchable memory aware.
This is needed for PCI bridge support because memory space and
prefetchable memory space is filtered independently based on
memory base/limit and prefetchable memory base/limit of pci bridge.
On bus 0, such a distinction isn't necessary so keep existing behavior
by checking bus=0.

With this patch, pci mem assignment area has been decreased.
To make seabios behave as before for compatible reason,
define CONFIG_OLD_PCIMEM_ASSIGNMENT.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

---
changes v1 -> v2.
- introduced BUILD_PCI{MEM, PERFMEM}_{START, SIZE, END}
- added range overlap check of pci mem/perfmem area.
---
 src/config.h  |   17 +++++++++++++++++
 src/pciinit.c |   49 ++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 59 insertions(+), 7 deletions(-)

Patch

diff --git a/src/config.h b/src/config.h
index ad569c6..b1e17de 100644
--- a/src/config.h
+++ b/src/config.h
@@ -151,7 +151,24 @@ 
 // 32KB for shadow ram copying (works around emulator deficiencies)
 #define BUILD_BIOS_TMP_ADDR       0x30000
 #define BUILD_MAX_HIGHMEM         0xe0000000
+
+// Support old pci mem assignment behaviour
+//#define CONFIG_OLD_PCIMEM_ASSIGNMENT    1
+#if CONFIG_OLD_PCIMEM_ASSIGNMENT
+#define BUILD_PCIMEM_START        0xf0000000
+#define BUILD_PCIMEM_SIZE         (BUILD_PCIMEM_END - BUILD_PCIMEM_START)
+#define BUILD_PCIMEM_END          0xfec00000    /* IOAPIC is mapped at */
+#define BUILD_PCIPREFMEM_START    0
+#define BUILD_PCIPREFMEM_SIZE     0
+#define BUILD_PCIPREFMEM_END      0
+#else
 #define BUILD_PCIMEM_START        0xf0000000
+#define BUILD_PCIMEM_SIZE         0x08000000    /* half- of pci window */
+#define BUILD_PCIMEM_END          (BUILD_PCIMEM_START + BUILD_PCIMEM_SIZE)
+#define BUILD_PCIPREFMEM_START    BUILD_PCIMEM_END
+#define BUILD_PCIPREFMEM_SIZE     (BUILD_PCIPREFMEM_END - BUILD_PCIPREFMEM_START)
+#define BUILD_PCIPREFMEM_END      0xfec00000    /* IOAPIC is mapped at */
+#endif
 
 #define BUILD_APIC_ADDR           0xfee00000
 #define BUILD_IOAPIC_ADDR         0xfec00000
diff --git a/src/pciinit.c b/src/pciinit.c
index b635e44..a65c58d 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -16,6 +16,7 @@ 
 
 static u32 pci_bios_io_addr;
 static u32 pci_bios_mem_addr;
+static u32 pci_bios_prefmem_addr;
 /* host irqs corresponding to PCI irqs A-D */
 static u8 pci_irqs[4] = {
     10, 10, 11, 11
@@ -66,21 +67,54 @@  static int pci_bios_allocate_region(u16 bdf, int region_num)
     u32 val = pci_config_readl(bdf, ofs);
     pci_config_writel(bdf, ofs, old);
 
+    u32 size = (~(val & mask)) + 1;
     if (val != 0) {
-        u32 size = (~(val & mask)) + 1;
-        if (val & PCI_BASE_ADDRESS_SPACE_IO)
+        if (val & PCI_BASE_ADDRESS_SPACE_IO) {
             paddr = &pci_bios_io_addr;
-        else
+            if (ALIGN(*paddr, size) + size >= 64 * 1024) {
+                dprintf(1,
+                        "io region of (bdf 0x%x bar %d) can't be mapped.\n",
+                        bdf, region_num);
+                size = 0;
+            }
+        } else if ((val & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
+                 /* keep behaviour on bus = 0 */
+                 pci_bdf_to_bus(bdf) != 0 &&
+                 /* If pci_bios_prefmem_addr == 0, keep old behaviour */
+                 pci_bios_prefmem_addr != 0) {
+            paddr = &pci_bios_prefmem_addr;
+            if (ALIGN(*paddr, size) + size >= BUILD_PCIPREFMEM_END) {
+                dprintf(1,
+                        "prefmem region of (bdf 0x%x bar %d) can't be mapped. "
+                        "decrease BUILD_PCIMEM_SIZE and recompile. size %x\n",
+                        bdf, region_num, BUILD_PCIPREFMEM_SIZE);
+                size = 0;
+            }
+        } else {
             paddr = &pci_bios_mem_addr;
-        *paddr = ALIGN(*paddr, size);
-        pci_set_io_region_addr(bdf, region_num, *paddr);
-        *paddr += size;
+            if (ALIGN(*paddr, size) + size >= BUILD_PCIMEM_END) {
+                dprintf(1,
+                        "mem region of (bdf 0x%x bar %d) can't be mapped. "
+                        "increase BUILD_PCIMEM_SIZE and recompile. size %x\n",
+                        bdf, region_num, BUILD_PCIMEM_SIZE);
+                size = 0;
+            }
+        }
+        if (size > 0) {
+            *paddr = ALIGN(*paddr, size);
+            pci_set_io_region_addr(bdf, region_num, *paddr);
+            *paddr += size;
+        }
     }
 
     int is_64bit = !(val & PCI_BASE_ADDRESS_SPACE_IO) &&
         (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64;
     if (is_64bit) {
-        pci_config_writel(bdf, ofs + 4, 0);
+        if (size > 0) {
+            pci_config_writel(bdf, ofs + 4, 0);
+        } else {
+            pci_config_writel(bdf, ofs + 4, ~0);
+        }
     }
     return is_64bit;
 }
@@ -220,6 +254,7 @@  pci_setup(void)
 
     pci_bios_io_addr = 0xc000;
     pci_bios_mem_addr = BUILD_PCIMEM_START;
+    pci_bios_prefmem_addr = BUILD_PCIPREFMEM_START;
 
     int bdf, max;
     foreachpci(bdf, max) {