aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-08-14 04:45:41 -0400
committerDavid S. Miller <davem@davemloft.net>2008-08-14 04:45:41 -0400
commitf2b6079464fc73cf12f08248180a618f05033a70 (patch)
tree840e53b1a0b7a61d1875206a8fc520714541b6d8
parentc918dcce92f76bb9903e4d049f4780bad384c207 (diff)
sparc64: Fix cmdline_memory_size handling bugs.
First, lmb_enforce_memory_limit() interprets it's argument (mostly, heh) as a size limit not an address limit. So pass the raw cmdline_memory_size value into it. And we don't need to check it against zero, lmb_enforce_memory_limit() does that for us. Next, free_initmem() needs special handling when the kernel command line trims the available memory. The problem case is if the trimmed out memory is where the kernel image itself resides. When that memory is trimmed out, we don't add those physical ram areas to the sparsemem active ranges, amongst other things. Which means that this free_initmem() code will free up invalid page structs, resulting in either crashes or hangs. Just quick fix this by not freeing initmem at all if "mem=" was given on the boot command line. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/mm/init.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 64d8e7623e0d..b4aeb0f696dc 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1726,8 +1726,7 @@ void __init paging_init(void)
1726 1726
1727 find_ramdisk(phys_base); 1727 find_ramdisk(phys_base);
1728 1728
1729 if (cmdline_memory_size) 1729 lmb_enforce_memory_limit(cmdline_memory_size);
1730 lmb_enforce_memory_limit(phys_base + cmdline_memory_size);
1731 1730
1732 lmb_analyze(); 1731 lmb_analyze();
1733 lmb_dump_all(); 1732 lmb_dump_all();
@@ -1964,6 +1963,15 @@ void __init mem_init(void)
1964void free_initmem(void) 1963void free_initmem(void)
1965{ 1964{
1966 unsigned long addr, initend; 1965 unsigned long addr, initend;
1966 int do_free = 1;
1967
1968 /* If the physical memory maps were trimmed by kernel command
1969 * line options, don't even try freeing this initmem stuff up.
1970 * The kernel image could have been in the trimmed out region
1971 * and if so the freeing below will free invalid page structs.
1972 */
1973 if (cmdline_memory_size)
1974 do_free = 0;
1967 1975
1968 /* 1976 /*
1969 * The init section is aligned to 8k in vmlinux.lds. Page align for >8k pagesizes. 1977 * The init section is aligned to 8k in vmlinux.lds. Page align for >8k pagesizes.
@@ -1978,13 +1986,16 @@ void free_initmem(void)
1978 ((unsigned long) __va(kern_base)) - 1986 ((unsigned long) __va(kern_base)) -
1979 ((unsigned long) KERNBASE)); 1987 ((unsigned long) KERNBASE));
1980 memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE); 1988 memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
1981 p = virt_to_page(page);
1982 1989
1983 ClearPageReserved(p); 1990 if (do_free) {
1984 init_page_count(p); 1991 p = virt_to_page(page);
1985 __free_page(p); 1992
1986 num_physpages++; 1993 ClearPageReserved(p);
1987 totalram_pages++; 1994 init_page_count(p);
1995 __free_page(p);
1996 num_physpages++;
1997 totalram_pages++;
1998 }
1988 } 1999 }
1989} 2000}
1990 2001