aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.h17
-rw-r--r--src/pciinit.c49
2 files changed, 59 insertions, 7 deletions
diff --git a/src/config.h b/src/config.h
index 238a2866..a7a6ccc6 100644
--- a/src/config.h
+++ b/src/config.h
@@ -161,7 +161,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 b635e44b..a65c58da 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) {