summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kokshaysky <ink@jurassic.park.msu.ru>2002-11-18 22:18:19 -0800
committerRichard Henderson <rth@are.twiddle.net>2002-11-18 22:18:19 -0800
commit248aa132a75fe75e54e607b9d2853eee7159ded4 (patch)
tree15c971acfa67ddf2237bcbe22c3b75bb38de689c
parentfdea9fc98bc266f5992b35c01737e5e6f70ffdd1 (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.c31
-rw-r--r--arch/alpha/mm/init.c33
-rw-r--r--arch/alpha/mm/numa.c12
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),