diff options
| author | Ivan Kokshaysky <ink@jurassic.park.msu.ru> | 2002-11-18 22:18:19 -0800 |
|---|---|---|
| committer | Richard Henderson <rth@are.twiddle.net> | 2002-11-18 22:18:19 -0800 |
| commit | 248aa132a75fe75e54e607b9d2853eee7159ded4 (patch) | |
| tree | 15c971acfa67ddf2237bcbe22c3b75bb38de689c | |
| parent | fdea9fc98bc266f5992b35c01737e5e6f70ffdd1 (diff) | |
[PATCH] alpha: initrd vs. "mem=" fix
As the aboot always puts initrd image near the top of physical memory,
initrd is not accessible if we limit memory size with "mem=" argument.
Fixed by moving the image to the "low" memory if needed.
Also, some of these routines will be used by marvel (in non-NUMA config)
and up1500.
Ivan.
| -rw-r--r-- | arch/alpha/kernel/setup.c | 31 | ||||
| -rw-r--r-- | arch/alpha/mm/init.c | 33 | ||||
| -rw-r--r-- | arch/alpha/mm/numa.c | 12 |
3 files changed, 49 insertions, 27 deletions
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 7f07f5e5dad7..6c9e86da2a95 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c @@ -251,6 +251,27 @@ get_mem_size_limit(char *s) return end >> PAGE_SHIFT; /* Return the PFN of the limit. */ } +#ifdef CONFIG_BLK_DEV_INITRD +void * __init +move_initrd(unsigned long mem_limit) +{ + void *start; + unsigned long size; + + size = initrd_end - initrd_start; + start = __alloc_bootmem(size, PAGE_SIZE, 0); + if (!start || __pa(start) + size > mem_limit) { + initrd_start = initrd_end = 0; + return NULL; + } + memmove(start, (void *)initrd_start, size); + initrd_start = (unsigned long)start; + initrd_end = initrd_start + size; + printk("initrd moved to %p\n", start); + return start; +} +#endif + #ifndef CONFIG_DISCONTIGMEM static void __init setup_memory(void *kernel_end) @@ -379,11 +400,11 @@ setup_memory(void *kernel_end) (void *) initrd_start, INITRD_SIZE); if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%p)\ndisabling initrd\n", - initrd_end, - phys_to_virt(PFN_PHYS(max_low_pfn))); - initrd_start = initrd_end = 0; + if (!move_initrd(PFN_PHYS(max_low_pfn))) + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%p)\ndisabling initrd\n", + initrd_end, + phys_to_virt(PFN_PHYS(max_low_pfn))); } else { reserve_bootmem(virt_to_phys((void *)initrd_start), INITRD_SIZE); diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index 2233f32d7923..a33c2289db41 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -357,18 +357,23 @@ mem_init(void) #endif /* CONFIG_DISCONTIGMEM */ void -free_initmem (void) +free_reserved_mem(void *start, void *end) { - extern char __init_begin, __init_end; - unsigned long addr; - - addr = (unsigned long)(&__init_begin); - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); - free_page(addr); + void *__start = start; + for (; __start < end; __start += PAGE_SIZE) { + ClearPageReserved(virt_to_page(__start)); + set_page_count(virt_to_page(__start), 1); + free_page((long)__start); totalram_pages++; } +} + +void +free_initmem(void) +{ + extern char __init_begin, __init_end; + + free_reserved_mem(&__init_begin, &__init_end); printk ("Freeing unused kernel memory: %ldk freed\n", (&__init_end - &__init_begin) >> 10); } @@ -377,13 +382,7 @@ free_initmem (void) void free_initrd_mem(unsigned long start, unsigned long end) { - unsigned long __start = start; - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); - free_page(start); - totalram_pages++; - } - printk ("Freeing initrd memory: %ldk freed\n", (end - __start) >> 10); + free_reserved_mem((void *)start, (void *)end); + printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); } #endif diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c index 5071c14da059..1375e90f809d 100644 --- a/arch/alpha/mm/numa.c +++ b/arch/alpha/mm/numa.c @@ -249,16 +249,18 @@ setup_memory(void *kernel_end) #ifdef CONFIG_BLK_DEV_INITRD initrd_start = INITRD_START; if (initrd_start) { + extern void *move_initrd(unsigned long); + initrd_end = initrd_start+INITRD_SIZE; printk("Initial ramdisk at: 0x%p (%lu bytes)\n", (void *) initrd_start, INITRD_SIZE); if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%p)\ndisabling initrd\n", - initrd_end, - phys_to_virt(PFN_PHYS(max_low_pfn))); - initrd_start = initrd_end = 0; + if (!move_initrd(PFN_PHYS(max_low_pfn))) + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%p)\ndisabling initrd\n", + initrd_end, + phys_to_virt(PFN_PHYS(max_low_pfn))); } else { reserve_bootmem_node(NODE_DATA(KVADDR_TO_NID(initrd_start)), virt_to_phys((void *)initrd_start), |
