[PATCH 2/2][RFC] PM / hibernate: Utilize the original e820 map for consistent check

From: Chen Yu
Date: Sat Jun 17 2017 - 01:23:23 EST

Use the e820_table_ori instead of e820_table_firmware to check
the consistence of memory layout provided by BIOS, because the
e820_table_firmware might be modified by the kernel such as efi
boot stub. To be more specific, during bootup, the efi boot stub
might allocate memory via efi service for the PCI device
information structure, then e820_reserve_setup_data() reserved
these dynamically allocated structures(AKA, setup_data) in
e820_table_firmware accordingly, changing their attribute from
E820_TYPE_RAM to E820_TYPE_RESERVED_KERN. So e820_table_firmware
is not the original BIOS-provided memory layout anymore.

As a result, we might get false-positive report that the memory layout
is inconsistent across hibernation:

The suspend kernel:
[ 0.000000] e820: update [mem 0x76671018-0x76679457] usable ==> usable

The resume kernel:
[ 0.000000] e820: update [mem 0x7666f018-0x76677457] usable ==> usable
[ 15.752088] PM: Using 3 thread(s) for decompression.
[ 15.752088] PM: Loading and decompressing image data (471870 pages)...
[ 15.764971] Hibernate inconsistent memory map detected!
[ 15.770833] PM: Image mismatch: architecture specific data

Actually it is safe to restore these pages because E820_TYPE_RAM and
E820_TYPE_RESERVED_KERN are treated the same during hibernation.

Reported-by: James Ren <james.ren@xxxxxxxxx>
Reported-by: "Mejia, Leonidas A" <leonidas.a.mejia@xxxxxxxxx>
Cc: Rafael J. Wysocki <rafael@xxxxxxxxxx>
Cc: Len Brown <lenb@xxxxxxxxxx>
Cc: Matt Fleming <matt@xxxxxxxxxxxxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxxxxx>
Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Cc: linux-pm@xxxxxxxxxxxxxxx
Signed-off-by: Chen Yu <yu.c.chen@xxxxxxxxx>
arch/x86/power/hibernate_64.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c
index a6e21fe..4bf087d 100644
--- a/arch/x86/power/hibernate_64.c
+++ b/arch/x86/power/hibernate_64.c
@@ -250,7 +250,7 @@ static int get_e820_md5(struct e820_table *table, void *buf)

static void hibernation_e820_save(void *buf)
- get_e820_md5(e820_table_firmware, buf);
+ get_e820_md5(e820_table_ori, buf);

static bool hibernation_e820_mismatch(void *buf)
@@ -263,7 +263,7 @@ static bool hibernation_e820_mismatch(void *buf)
if (!memcmp(result, buf, MD5_DIGEST_SIZE))
return false;

- ret = get_e820_md5(e820_table_firmware, result);
+ ret = get_e820_md5(e820_table_ori, result);
if (ret)
return true;