diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 988c00a..5c1d0b7 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -130,7 +130,7 @@ void __init e820_add_region(u64 start, u64 size, int type)
 	__e820_add_region(&e820, start, size, type);
 }
 
-static void __init e820_print_type(u32 type)
+static void e820_print_type(u32 type)
 {
 	switch (type) {
 	case E820_RAM:
@@ -704,6 +704,91 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn)
 			break;
 	}
 }
+
+int save_mem_chk_map(struct mementry *mem_chk_map)
+{
+	int i;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+
+		if (i > MEMCHKMAX)
+			break;
+
+		mem_chk_map[i].addr = ei->addr;
+		mem_chk_map[i].size = ei->size;
+		mem_chk_map[i].type = ei->type;
+	}
+
+	/* return number or e820 regions for amount comparison */
+	return e820.nr_map;
+}
+
+static void print_mem_chk_map(int mem_chk_entries, struct mementry *mem_chk_map)
+{
+	int i;
+
+	for (i = 0; i < mem_chk_entries; i++) {
+		struct e820entry *ei = &e820.map[i];
+
+		printk(KERN_INFO "e820: Check memory region: [mem %#018Lx-%#018Lx] ",
+		       (unsigned long long) ei->addr,
+		       (unsigned long long) (ei->addr + ei->size - 1));
+		e820_print_type(ei->type);
+		printk(KERN_CONT "\n");
+
+		/* Don't print over the maximum amount of check entries */
+		if (i > MEMCHKMAX)
+			continue;
+
+		if (mem_chk_map[i].addr != ei->addr ||
+		    mem_chk_map[i].size != ei->size ||
+		    mem_chk_map[i].type != ei->type) {
+			printk(KERN_INFO "               Old region: [mem %#018Lx-%#018Lx] ",
+			       (unsigned long long) mem_chk_map[i].addr,
+			       (unsigned long long)
+			       (mem_chk_map[i].addr + mem_chk_map[i].size - 1));
+			e820_print_type(mem_chk_map[i].type);
+			printk(KERN_CONT "\n");
+		}
+	}
+}
+
+bool check_mem_map(int mem_chk_entries, struct mementry *mem_chk_map)
+{
+	int i;
+	bool ret = true;
+
+	if (mem_chk_entries != e820.nr_map) {
+		pr_err("PM: memory check entry number %d:%d\n",
+			mem_chk_entries, e820.nr_map);
+		ret = false;
+		goto Print_map;
+	}
+
+	for (i = 0; i < mem_chk_entries; i++) {
+		struct e820entry *ei = &e820.map[i];
+
+		if (i > MEMCHKMAX)
+			break;
+
+		/* check regions not E820_RAM or E820_RESERVED_KERN */
+		if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN) {
+			if (mem_chk_map[i].addr != ei->addr ||
+			    mem_chk_map[i].size != ei->size ||
+			    mem_chk_map[i].type != ei->type) {
+				ret = false;
+				goto Print_map;
+			}
+		}
+	}
+
+Print_map:
+	if (!ret)
+		print_mem_chk_map(mem_chk_entries, mem_chk_map);
+
+	return ret;
+}
 #endif
 
 #ifdef CONFIG_ACPI
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 24d63e8..49b43d4 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -309,6 +309,22 @@ struct platform_hibernation_ops {
 };
 
 #ifdef CONFIG_HIBERNATION
+#define MEMCHKMAX 128   /* number of entries in memory check map */
+struct mementry {
+	__u64 addr;     /* start of memory segment */
+	__u64 size;     /* size of memory segment */
+	__u32 type;     /* type of memory segment */
+} __attribute__((packed));
+
+/* arch/x86/kernel/e820.c */
+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_32)
+extern int save_mem_chk_map(struct mementry *);
+extern bool check_mem_map(int, struct mementry *);
+#else
+static int save_mem_chk_map(struct mementry *m) {return 0}
+static bool check_mem_map(int n, struct mementry *m) {return true}
+#endif /* CONFIG_X86_64 || CONFIG_X86_32 */
+
 /* kernel/power/snapshot.c */
 extern void __register_nosave_region(unsigned long b, unsigned long e, int km);
 static inline void __init register_nosave_region(unsigned long b, unsigned long e)
@@ -333,6 +349,8 @@ extern struct pbe *restore_pblist;
 #else /* CONFIG_HIBERNATION */
 static inline void register_nosave_region(unsigned long b, unsigned long e) {}
 static inline void register_nosave_region_late(unsigned long b, unsigned long e) {}
+static int save_mem_chk_map(struct mementry *m) {return 0}
+static bool check_mem_map(int n, struct mementry *m) {return true}
 static inline int swsusp_page_is_forbidden(struct page *p) { return 0; }
 static inline void swsusp_set_page_free(struct page *p) {}
 static inline void swsusp_unset_page_free(struct page *p) {}
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 5d49dca..83730fc 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -12,6 +12,8 @@ struct swsusp_info {
 	unsigned long		image_pages;
 	unsigned long		pages;
 	unsigned long		size;
+	int                     mem_chk_entries;
+	struct mementry         mem_chk_map[MEMCHKMAX];
 } __aligned(PAGE_SIZE);
 
 #ifdef CONFIG_HIBERNATION
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index c4b8093..9d4f5f9 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -1925,6 +1925,7 @@ static int init_header(struct swsusp_info *info)
 	info->pages = snapshot_get_image_size();
 	info->size = info->pages;
 	info->size <<= PAGE_SHIFT;
+	info->mem_chk_entries = save_mem_chk_map(info->mem_chk_map);
 	return init_header_complete(info);
 }
 
@@ -2066,6 +2067,8 @@ static int check_header(struct swsusp_info *info)
 	reason = check_image_kernel(info);
 	if (!reason && info->num_physpages != get_num_physpages())
 		reason = "memory size";
+	if (!reason && !check_mem_map(info->mem_chk_entries, info->mem_chk_map))
+		reason = "memory map changed";
 	if (reason) {
 		printk(KERN_ERR "PM: Image mismatch: %s\n", reason);
 		return -EPERM;
