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(-)
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) {