diff options
Diffstat (limited to 'arch/i386/kernel/setup.c')
| -rw-r--r-- | arch/i386/kernel/setup.c | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index b6f2d5995836..55ce1b114cdf 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -1166,9 +1166,10 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat /* * Request address space for all standard resources */ -static void __init register_memory(unsigned long max_low_pfn) +static void __init register_memory(void) { - unsigned long low_mem_size; + unsigned long gapstart, gapsize; + unsigned long long last; int i; if (efi_enabled) @@ -1183,10 +1184,46 @@ static void __init register_memory(unsigned long max_low_pfn) for (i = 0; i < STANDARD_IO_RESOURCES; i++) request_resource(&ioport_resource, &standard_io_resources[i]); - /* Tell the PCI layer not to allocate too close to the RAM area.. */ - low_mem_size = ((max_low_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff; - if (low_mem_size > pci_mem_start) - pci_mem_start = low_mem_size; + /* + * Search for the bigest gap in the low 32 bits of the e820 + * memory space. + */ + last = 0x100000000ull; + gapstart = 0x10000000; + gapsize = 0x400000; + i = e820.nr_map; + while (--i >= 0) { + unsigned long long start = e820.map[i].addr; + unsigned long long end = start + e820.map[i].size; + + /* + * Since "last" is at most 4GB, we know we'll + * fit in 32 bits if this condition is true + */ + if (last > end) { + unsigned long gap = last - end; + + if (gap > gapsize) { + gapsize = gap; + gapstart = end; + } + } + if (start < last) + last = start; + } + + /* + * Start allocating dynamic PCI memory a bit into the gap, + * aligned up to the nearest megabyte. + * + * Question: should we try to pad it up a bit (do something + * like " + (gapsize >> 3)" in there too?). We now have the + * technology. + */ + pci_mem_start = (gapstart + 0xfffff) & ~0xfffff; + + printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n", + pci_mem_start, gapstart, gapsize); } /* Use inline assembly to define this because the nops are defined @@ -1432,7 +1469,7 @@ void __init setup_arch(char **cmdline_p) get_smp_config(); #endif - register_memory(max_low_pfn); + register_memory(); #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) |
