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__*/