diff -urN linux-2.4.20/arch/alpha/kernel/setup.c linux-2.4.20-initrdfix/arch/alpha/kernel/setup.c --- linux-2.4.20/arch/alpha/kernel/setup.c 2002-08-02 20:39:42.000000000 -0400 +++ linux-2.4.20-initrdfix/arch/alpha/kernel/setup.c 2003-06-18 13:53:12.000000000 -0400 @@ -243,6 +243,27 @@ 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(PAGE_ALIGN(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(KERN_INFO "initrd moved to %p\n", start); + return start; +} +#endif + #ifndef CONFIG_DISCONTIGMEM static void __init setup_memory(void *kernel_end) @@ -371,11 +392,11 @@ (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 -urN linux-2.4.20/arch/alpha/mm/init.c linux-2.4.20-initrdfix/arch/alpha/mm/init.c --- linux-2.4.20/arch/alpha/mm/init.c 2002-08-02 20:39:42.000000000 -0400 +++ linux-2.4.20-initrdfix/arch/alpha/mm/init.c 2003-06-18 13:53:09.000000000 -0400 @@ -368,18 +368,23 @@ #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 (KERN_INFO "Freeing unused kernel memory: %ldk freed\n", (&__init_end - &__init_begin) >> 10); } @@ -388,14 +393,9 @@ 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 (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - __start) >> 10); + free_reserved_mem((void *)start, (void *)end); + printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", + (end - start) >> 10); } #endif diff -urN linux-2.4.20/arch/alpha/mm/numa.c linux-2.4.20-initrdfix/arch/alpha/mm/numa.c --- linux-2.4.20/arch/alpha/mm/numa.c 2002-08-02 20:39:42.000000000 -0400 +++ linux-2.4.20-initrdfix/arch/alpha/mm/numa.c 2003-06-18 13:53:09.000000000 -0400 @@ -249,16 +249,18 @@ #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),