aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt2
-rw-r--r--arch/x86_64/kernel/e820.c21
-rw-r--r--arch/x86_64/kernel/setup.c27
-rw-r--r--include/asm-x86_64/e820.h1
4 files changed, 50 insertions, 1 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 0dc848bf0b56bb..12b7d938a897f2 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 17579a1a174bda..293cd71a266aa2 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 64c4534b930c74..ff9620b800c07d 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 e682edc24a6807..8dcc32665240fb 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__*/