diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 0dc848bf0b56bb59b0c69eacfc3fb4d6a593fb7c..12b7d938a897f2ce0564a1a9d9bc6fa388f95afd 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -832,7 +832,7 @@ running once the system is up. mem=nopentium [BUGS=IA-32] Disable usage of 4MB pages for kernel memory. - memmap=exactmap [KNL,IA-32] Enable setting of an exact + memmap=exactmap [KNL,IA-32,X86_64] Enable setting of an exact E820 memory map, as specified by the user. Such memmap=exactmap lines can be constructed based on BIOS output or other requirements. See the memmap=nn@ss diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index 17579a1a174bda40da7f3291793ac746b9515cb0..293cd71a266aa221800c6e3246ee768cce5a71cd 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c @@ -559,6 +559,27 @@ void __init parse_memopt(char *p, char **from) end_user_pfn >>= PAGE_SHIFT; } +void __init parse_memmapopt(char *p, char **from) +{ + unsigned long long start_at, mem_size; + + mem_size = memparse(p, from); + p = *from; + if (*p == '@') { + start_at = memparse(p+1, from); + add_memory_region(start_at, mem_size, E820_RAM); + } else if (*p == '#') { + start_at = memparse(p+1, from); + add_memory_region(start_at, mem_size, E820_ACPI); + } else if (*p == '$') { + start_at = memparse(p+1, from); + add_memory_region(start_at, mem_size, E820_RESERVED); + } else { + end_user_pfn = (mem_size >> PAGE_SHIFT); + } + p = *from; +} + unsigned long pci_mem_start = 0xaeedbabe; /* diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 64c4534b930c74bc118cf1530a812401456f3d4e..ff9620b800c07d1ba203b118d4175b13878680ab 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -275,6 +275,7 @@ static __init void parse_cmdline_early (char ** cmdline_p) { char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; + int userdef = 0; /* Save unparsed command line copy for /proc/cmdline */ memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); @@ -357,6 +358,28 @@ static __init void parse_cmdline_early (char ** cmdline_p) if (!memcmp(from, "mem=", 4)) parse_memopt(from+4, &from); + if (!memcmp(from, "memmap=", 7)) { + /* exactmap option is for used defined memory */ + if (!memcmp(from+7, "exactmap", 8)) { +#ifdef CONFIG_CRASH_DUMP + /* If we are doing a crash dump, we + * still need to know the real mem + * size before original memory map is + * reset. + */ + saved_max_pfn = e820_end_of_ram(); +#endif + from += 8+7; + end_pfn_map = 0; + e820.nr_map = 0; + userdef = 1; + } + else { + parse_memmapopt(from+7, &from); + userdef = 1; + } + } + #ifdef CONFIG_NUMA if (!memcmp(from, "numa=", 5)) numa_setup(from+5); @@ -403,6 +426,10 @@ static __init void parse_cmdline_early (char ** cmdline_p) break; *(to++) = c; } + if (userdef) { + printk(KERN_INFO "user-defined physical RAM map:\n"); + e820_print_map("user"); + } *to = '\0'; *cmdline_p = command_line; } diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h index e682edc24a68072c97da7611be582f92b9000425..8dcc32665240fbaa657029e34c65274f8e234fd4 100644 --- a/include/asm-x86_64/e820.h +++ b/include/asm-x86_64/e820.h @@ -55,6 +55,7 @@ extern unsigned long e820_hole_size(unsigned long start_pfn, unsigned long end_pfn); extern void __init parse_memopt(char *p, char **end); +extern void __init parse_memmapopt(char *p, char **end); extern struct e820map e820; #endif/*!__ASSEMBLY__*/