diff -urN 2.2.16-VM-bigmem/arch/alpha/kernel/setup.c 2.2.16-VM-bigmem-initrd/arch/alpha/kernel/setup.c --- 2.2.16-VM-bigmem/arch/alpha/kernel/setup.c Sat Jun 17 02:30:43 2000 +++ 2.2.16-VM-bigmem-initrd/arch/alpha/kernel/setup.c Sat Jun 17 03:22:55 2000 @@ -298,8 +298,27 @@ if (initrd_end > *memory_end_p) { printk("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx)\ndisabling initrd\n", - initrd_end, (unsigned long) memory_end_p); + initrd_end, *memory_end_p); initrd_start = initrd_end = 0; + } else { + /* move initrd from the middle of the RAM to the + start of the RAM so we won't risk to rewrite + initrd while allocating the memory at boot time */ + unsigned long memory_start; + + memory_start = *memory_start_p; + /* + * Alloc initrd in a page aligned region, + * the memory between memory_start and + * the end of the page would be wasted anyway... + */ + memory_start = PAGE_ALIGN(memory_start); + memmove((char *) memory_start, + (char *) initrd_start, INITRD_SIZE); + initrd_start = memory_start; + initrd_end = initrd_start + INITRD_SIZE; + *memory_start_p = PAGE_ALIGN(initrd_end); + initrd_below_start_ok = 1; } } #endif diff -urN 2.2.16-VM-bigmem/arch/i386/kernel/setup.c 2.2.16-VM-bigmem-initrd/arch/i386/kernel/setup.c --- 2.2.16-VM-bigmem/arch/i386/kernel/setup.c Sat Jun 17 03:03:33 2000 +++ 2.2.16-VM-bigmem-initrd/arch/i386/kernel/setup.c Sat Jun 17 03:23:05 2000 @@ -430,6 +430,28 @@ "(0x%08lx > 0x%08lx)\ndisabling initrd\n", initrd_end,memory_end); initrd_start = 0; + } else if (initrd_start < memory_start) { + printk("initrd starts before the start of memory " + "(0x%08lx < 0x%08lx)\ndisabling initrd\n", + initrd_start,memory_start); + initrd_start = 0; + } else { + /* + * Move initrd from the middle of the RAM to the + * start of the RAM so we won't risk to rewrite + * initrd while allocating the memory at boot time. + * Alloc initrd in a page aligned region, + * the memory between memory_start and + * the end of the page would be wasted anyway... + */ + memory_start = PAGE_ALIGN(memory_start); + memmove((char *) memory_start, + (char *) initrd_start, INITRD_SIZE); + initrd_start = memory_start; + initrd_end = initrd_start + INITRD_SIZE; + memory_start = PAGE_ALIGN(initrd_end); + *memory_start_p = memory_start; + initrd_below_start_ok = 1; } } #endif diff -urN 2.2.16-VM-bigmem/drivers/block/rd.c 2.2.16-VM-bigmem-initrd/drivers/block/rd.c --- 2.2.16-VM-bigmem/drivers/block/rd.c Sat Jun 17 03:03:33 2000 +++ 2.2.16-VM-bigmem-initrd/drivers/block/rd.c Sat Jun 17 03:14:52 2000 @@ -236,7 +236,18 @@ unsigned long i; if (--initrd_users) return 0; - for (i = initrd_start; i < initrd_end; i += PAGE_SIZE) +#if defined(__i386__) || defined(__alpha__) + /* + * On i386 and alpha the robust initrd memmove make sure + * nothing is allocated between the end of of initrd + * and the start of the next page, so we can free also the + * last page of initrd even if it doesn't finish page aligned. + */ + initrd_end = PAGE_ALIGN(initrd_end); +#else + initrd_end &= PAGE_MASK; +#endif + for (i = PAGE_ALIGN(initrd_start); i < initrd_end; i += PAGE_SIZE) free_page(i); initrd_start = 0; return 0;