|
@@ -14,6 +14,7 @@
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/mm.h>
|
|
|
#include <linux/bootmem.h>
|
|
|
+#include <linux/memblock.h>
|
|
|
#include <linux/gfp.h>
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/init.h>
|
|
@@ -79,6 +80,34 @@ static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __read_mostly;
|
|
|
physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES] __read_mostly;
|
|
|
int npmem_ranges __read_mostly;
|
|
|
|
|
|
+/*
|
|
|
+ * get_memblock() allocates pages via memblock.
|
|
|
+ * We can't use memblock_find_in_range(0, KERNEL_INITIAL_SIZE) here since it
|
|
|
+ * doesn't allocate from bottom to top which is needed because we only created
|
|
|
+ * the initial mapping up to KERNEL_INITIAL_SIZE in the assembly bootup code.
|
|
|
+ */
|
|
|
+static void * __init get_memblock(unsigned long size)
|
|
|
+{
|
|
|
+ static phys_addr_t search_addr __initdata;
|
|
|
+ phys_addr_t phys;
|
|
|
+
|
|
|
+ if (!search_addr)
|
|
|
+ search_addr = PAGE_ALIGN(__pa((unsigned long) &_end));
|
|
|
+ search_addr = ALIGN(search_addr, size);
|
|
|
+ while (!memblock_is_region_memory(search_addr, size) ||
|
|
|
+ memblock_is_region_reserved(search_addr, size)) {
|
|
|
+ search_addr += size;
|
|
|
+ }
|
|
|
+ phys = search_addr;
|
|
|
+
|
|
|
+ if (phys)
|
|
|
+ memblock_reserve(phys, size);
|
|
|
+ else
|
|
|
+ panic("get_memblock() failed.\n");
|
|
|
+
|
|
|
+ return __va(phys);
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_64BIT
|
|
|
#define MAX_MEM (~0UL)
|
|
|
#else /* !CONFIG_64BIT */
|
|
@@ -118,11 +147,7 @@ static void __init mem_limit_func(void)
|
|
|
|
|
|
static void __init setup_bootmem(void)
|
|
|
{
|
|
|
- unsigned long bootmap_size;
|
|
|
unsigned long mem_max;
|
|
|
- unsigned long bootmap_pages;
|
|
|
- unsigned long bootmap_start_pfn;
|
|
|
- unsigned long bootmap_pfn;
|
|
|
#ifndef CONFIG_DISCONTIGMEM
|
|
|
physmem_range_t pmem_holes[MAX_PHYSMEM_RANGES - 1];
|
|
|
int npmem_holes;
|
|
@@ -178,33 +203,29 @@ static void __init setup_bootmem(void)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- if (npmem_ranges > 1) {
|
|
|
-
|
|
|
- /* Print the memory ranges */
|
|
|
+ /* Print the memory ranges */
|
|
|
+ pr_info("Memory Ranges:\n");
|
|
|
|
|
|
- printk(KERN_INFO "Memory Ranges:\n");
|
|
|
+ for (i = 0; i < npmem_ranges; i++) {
|
|
|
+ struct resource *res = &sysram_resources[i];
|
|
|
+ unsigned long start;
|
|
|
+ unsigned long size;
|
|
|
|
|
|
- for (i = 0; i < npmem_ranges; i++) {
|
|
|
- unsigned long start;
|
|
|
- unsigned long size;
|
|
|
+ size = (pmem_ranges[i].pages << PAGE_SHIFT);
|
|
|
+ start = (pmem_ranges[i].start_pfn << PAGE_SHIFT);
|
|
|
+ pr_info("%2d) Start 0x%016lx End 0x%016lx Size %6ld MB\n",
|
|
|
+ i, start, start + (size - 1), size >> 20);
|
|
|
|
|
|
- size = (pmem_ranges[i].pages << PAGE_SHIFT);
|
|
|
- start = (pmem_ranges[i].start_pfn << PAGE_SHIFT);
|
|
|
- printk(KERN_INFO "%2d) Start 0x%016lx End 0x%016lx Size %6ld MB\n",
|
|
|
- i,start, start + (size - 1), size >> 20);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- sysram_resource_count = npmem_ranges;
|
|
|
- for (i = 0; i < sysram_resource_count; i++) {
|
|
|
- struct resource *res = &sysram_resources[i];
|
|
|
+ /* request memory resource */
|
|
|
res->name = "System RAM";
|
|
|
- res->start = pmem_ranges[i].start_pfn << PAGE_SHIFT;
|
|
|
- res->end = res->start + (pmem_ranges[i].pages << PAGE_SHIFT)-1;
|
|
|
+ res->start = start;
|
|
|
+ res->end = start + size - 1;
|
|
|
res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
|
|
|
request_resource(&iomem_resource, res);
|
|
|
}
|
|
|
|
|
|
+ sysram_resource_count = npmem_ranges;
|
|
|
+
|
|
|
/*
|
|
|
* For 32 bit kernels we limit the amount of memory we can
|
|
|
* support, in order to preserve enough kernel address space
|
|
@@ -263,16 +284,9 @@ static void __init setup_bootmem(void)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- bootmap_pages = 0;
|
|
|
- for (i = 0; i < npmem_ranges; i++)
|
|
|
- bootmap_pages += bootmem_bootmap_pages(pmem_ranges[i].pages);
|
|
|
-
|
|
|
- bootmap_start_pfn = PAGE_ALIGN(__pa((unsigned long) &_end)) >> PAGE_SHIFT;
|
|
|
-
|
|
|
#ifdef CONFIG_DISCONTIGMEM
|
|
|
for (i = 0; i < MAX_PHYSMEM_RANGES; i++) {
|
|
|
memset(NODE_DATA(i), 0, sizeof(pg_data_t));
|
|
|
- NODE_DATA(i)->bdata = &bootmem_node_data[i];
|
|
|
}
|
|
|
memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
|
|
|
|
|
@@ -284,28 +298,24 @@ static void __init setup_bootmem(void)
|
|
|
|
|
|
/*
|
|
|
* Initialize and free the full range of memory in each range.
|
|
|
- * Note that the only writing these routines do are to the bootmap,
|
|
|
- * and we've made sure to locate the bootmap properly so that they
|
|
|
- * won't be writing over anything important.
|
|
|
*/
|
|
|
|
|
|
- bootmap_pfn = bootmap_start_pfn;
|
|
|
max_pfn = 0;
|
|
|
for (i = 0; i < npmem_ranges; i++) {
|
|
|
unsigned long start_pfn;
|
|
|
unsigned long npages;
|
|
|
+ unsigned long start;
|
|
|
+ unsigned long size;
|
|
|
|
|
|
start_pfn = pmem_ranges[i].start_pfn;
|
|
|
npages = pmem_ranges[i].pages;
|
|
|
|
|
|
- bootmap_size = init_bootmem_node(NODE_DATA(i),
|
|
|
- bootmap_pfn,
|
|
|
- start_pfn,
|
|
|
- (start_pfn + npages) );
|
|
|
- free_bootmem_node(NODE_DATA(i),
|
|
|
- (start_pfn << PAGE_SHIFT),
|
|
|
- (npages << PAGE_SHIFT) );
|
|
|
- bootmap_pfn += (bootmap_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
|
+ start = start_pfn << PAGE_SHIFT;
|
|
|
+ size = npages << PAGE_SHIFT;
|
|
|
+
|
|
|
+ /* add system RAM memblock */
|
|
|
+ memblock_add(start, size);
|
|
|
+
|
|
|
if ((start_pfn + npages) > max_pfn)
|
|
|
max_pfn = start_pfn + npages;
|
|
|
}
|
|
@@ -317,32 +327,22 @@ static void __init setup_bootmem(void)
|
|
|
*/
|
|
|
max_low_pfn = max_pfn;
|
|
|
|
|
|
- /* bootmap sizing messed up? */
|
|
|
- BUG_ON((bootmap_pfn - bootmap_start_pfn) != bootmap_pages);
|
|
|
-
|
|
|
/* reserve PAGE0 pdc memory, kernel text/data/bss & bootmap */
|
|
|
|
|
|
#define PDC_CONSOLE_IO_IODC_SIZE 32768
|
|
|
|
|
|
- reserve_bootmem_node(NODE_DATA(0), 0UL,
|
|
|
- (unsigned long)(PAGE0->mem_free +
|
|
|
- PDC_CONSOLE_IO_IODC_SIZE), BOOTMEM_DEFAULT);
|
|
|
- reserve_bootmem_node(NODE_DATA(0), __pa(KERNEL_BINARY_TEXT_START),
|
|
|
- (unsigned long)(_end - KERNEL_BINARY_TEXT_START),
|
|
|
- BOOTMEM_DEFAULT);
|
|
|
- reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
|
|
|
- ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT),
|
|
|
- BOOTMEM_DEFAULT);
|
|
|
+ memblock_reserve(0UL, (unsigned long)(PAGE0->mem_free +
|
|
|
+ PDC_CONSOLE_IO_IODC_SIZE));
|
|
|
+ memblock_reserve(__pa(KERNEL_BINARY_TEXT_START),
|
|
|
+ (unsigned long)(_end - KERNEL_BINARY_TEXT_START));
|
|
|
|
|
|
#ifndef CONFIG_DISCONTIGMEM
|
|
|
|
|
|
/* reserve the holes */
|
|
|
|
|
|
for (i = 0; i < npmem_holes; i++) {
|
|
|
- reserve_bootmem_node(NODE_DATA(0),
|
|
|
- (pmem_holes[i].start_pfn << PAGE_SHIFT),
|
|
|
- (pmem_holes[i].pages << PAGE_SHIFT),
|
|
|
- BOOTMEM_DEFAULT);
|
|
|
+ memblock_reserve((pmem_holes[i].start_pfn << PAGE_SHIFT),
|
|
|
+ (pmem_holes[i].pages << PAGE_SHIFT));
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -360,8 +360,7 @@ static void __init setup_bootmem(void)
|
|
|
initrd_below_start_ok = 1;
|
|
|
printk(KERN_INFO "initrd: reserving %08lx-%08lx (mem_max %08lx)\n", __pa(initrd_start), __pa(initrd_start) + initrd_reserve, mem_max);
|
|
|
|
|
|
- reserve_bootmem_node(NODE_DATA(0), __pa(initrd_start),
|
|
|
- initrd_reserve, BOOTMEM_DEFAULT);
|
|
|
+ memblock_reserve(__pa(initrd_start), initrd_reserve);
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
@@ -439,7 +438,7 @@ static void __init map_pages(unsigned long start_vaddr,
|
|
|
*/
|
|
|
|
|
|
if (!pmd) {
|
|
|
- pmd = (pmd_t *) alloc_bootmem_low_pages_node(NODE_DATA(0), PAGE_SIZE << PMD_ORDER);
|
|
|
+ pmd = (pmd_t *) get_memblock(PAGE_SIZE << PMD_ORDER);
|
|
|
pmd = (pmd_t *) __pa(pmd);
|
|
|
}
|
|
|
|
|
@@ -458,8 +457,7 @@ static void __init map_pages(unsigned long start_vaddr,
|
|
|
|
|
|
pg_table = (pte_t *)pmd_address(*pmd);
|
|
|
if (!pg_table) {
|
|
|
- pg_table = (pte_t *)
|
|
|
- alloc_bootmem_low_pages_node(NODE_DATA(0), PAGE_SIZE);
|
|
|
+ pg_table = (pte_t *) get_memblock(PAGE_SIZE);
|
|
|
pg_table = (pte_t *) __pa(pg_table);
|
|
|
}
|
|
|
|
|
@@ -737,7 +735,7 @@ static void __init pagetable_init(void)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
|
|
|
+ empty_zero_page = get_memblock(PAGE_SIZE);
|
|
|
}
|
|
|
|
|
|
static void __init gateway_init(void)
|