From: Marco Scardovi <scardracs@disroot.org>
To: moravec@ukf.sk
Cc: bp@alien8.de, crecklin@redhat.com, dave.hansen@linux.intel.com,
hpa@zytor.com, linux-kernel@vger.kernel.org,
linux-pm@vger.kernel.org, mingo@redhat.com, pavel@kernel.org,
rafael@kernel.org, regressions@leemhuis.info,
regressions@lists.linux.dev, scardracs@disroot.org,
tglx@kernel.org, x86@kernel.org
Subject: [PATCH v2 3/4] x86/power: Implement relaxed E820 memory map integrity check
Date: Tue, 23 Jun 2026 18:47:29 +0200 [thread overview]
Message-ID: <20260623165724.10753-4-scardracs@disroot.org> (raw)
In-Reply-To: <20260623165724.10753-1-scardracs@disroot.org>
On some UEFI platforms (such as the HP OmniBook X Flip), resuming from
hibernation fails with 'Hibernate inconsistent memory map detected!' because
the UEFI firmware makes non-deterministic allocations or shifts reserved/ACPI
memory regions dynamically across boots. This changes the CRC32 checksum
computed over the entire E820 table, even though the usable RAM layout
remains completely identical and safe to restore.
However, bypassing the E820 integrity check entirely is risky, as the
restored kernel might access shifted ACPI tables, AML operation regions,
or UEFI runtime services at stale physical addresses, leading to post-resume
crashes or corruption.
Implement a relaxed verification path if 'hibernate=relaxed_memmap' is set.
If the full E820 table checksum mismatches, perform a secondary check
comparing only the usable RAM regions. If the RAM regions differ, the resume
is aborted to prevent direct map mismatches and paging faults. If the RAM
regions match, the resume is allowed to proceed with a warning.
To support this, add a secondary 'e820_ram_checksum' field to the
x86 'restore_data_record', and increment 'RESTORE_MAGIC' to signal the
header layout change.
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Marco Scardovi <scardracs@disroot.org>
---
arch/x86/power/hibernate.c | 40 ++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/arch/x86/power/hibernate.c b/arch/x86/power/hibernate.c
index a2294c1649f6..88452769d1aa 100644
--- a/arch/x86/power/hibernate.c
+++ b/arch/x86/power/hibernate.c
@@ -61,6 +61,7 @@ struct restore_data_record {
unsigned long cr3;
unsigned long magic;
unsigned long e820_checksum;
+ unsigned long e820_ram_checksum;
};
/**
@@ -78,10 +79,32 @@ static inline u32 compute_e820_crc32(struct e820_table *table)
return ~crc32_le(~0, (unsigned char const *)table, size);
}
+/**
+ * compute_e820_ram_crc32 - calculate crc32 of usable RAM regions in e820 table
+ *
+ * @table: the e820 table to be calculated
+ *
+ * Return: the resulting checksum
+ */
+static u32 compute_e820_ram_crc32(struct e820_table *table)
+{
+ u32 crc = ~0;
+ int i;
+
+ for (i = 0; i < table->nr_entries; i++) {
+ if (table->entries[i].type == E820_TYPE_RAM) {
+ crc = crc32_le(crc, (unsigned char const *)&table->entries[i],
+ sizeof(struct e820_entry));
+ }
+ }
+
+ return ~crc;
+}
+
#ifdef CONFIG_X86_64
-#define RESTORE_MAGIC 0x23456789ABCDEF02UL
+#define RESTORE_MAGIC 0x23456789ABCDEF03UL
#else
-#define RESTORE_MAGIC 0x12345679UL
+#define RESTORE_MAGIC 0x1234567AUL
#endif
/**
@@ -122,6 +145,7 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
rdr->cr3 = restore_cr3 & ~CR3_PCID_MASK;
rdr->e820_checksum = compute_e820_crc32(e820_table_firmware);
+ rdr->e820_ram_checksum = compute_e820_ram_crc32(e820_table_firmware);
return 0;
}
@@ -144,8 +168,16 @@ int arch_hibernation_header_restore(void *addr)
restore_cr3 = rdr->cr3;
if (rdr->e820_checksum != compute_e820_crc32(e820_table_firmware)) {
- pr_crit("Hibernate inconsistent memory map detected!\n");
- return -ENODEV;
+ if (hibernate_relaxed_memmap) {
+ if (rdr->e820_ram_checksum != compute_e820_ram_crc32(e820_table_firmware)) {
+ pr_crit("Hibernate inconsistent RAM map detected!\n");
+ return -ENODEV;
+ }
+ pr_warn("Hibernate inconsistent non-RAM memory map ignored due to relaxed_memmap!\n");
+ } else {
+ pr_crit("Hibernate inconsistent memory map detected!\n");
+ return -ENODEV;
+ }
}
return 0;
--
2.54.0
next prev parent reply other threads:[~2026-06-23 16:57 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-20 8:15 [PATCH 0/1] x86/power: only verify usable RAM regions during hibernation E820 check Marco Scardovi
2026-06-20 8:15 ` [PATCH 1/1] " Marco Scardovi
2026-06-20 9:20 ` Milan Oravec
2026-06-23 12:59 ` Rafael J. Wysocki
2026-06-23 15:11 ` Milan Oravec
2026-06-23 16:47 ` [PATCH v2 0/4] PM: hibernate: Add relaxed_memmap option for x86 E820 integrity check Marco Scardovi
2026-06-23 16:47 ` [PATCH v2 1/4] PM: hibernate: Declare hibernate_relaxed_memmap Marco Scardovi
2026-06-23 16:47 ` [PATCH v2 2/4] PM: hibernate: Define and parse hibernate=relaxed_memmap parameter Marco Scardovi
2026-06-23 16:47 ` Marco Scardovi [this message]
2026-06-23 16:47 ` [PATCH v2 4/4] Documentation: Document hibernate=relaxed_memmap parameter option Marco Scardovi
2026-06-29 13:04 ` [PATCH v2 0/4] PM: hibernate: Add relaxed_memmap option for x86 E820 integrity check Milan Oravec
2026-06-29 19:53 ` Marco Scardovi
2026-06-30 6:52 ` Milan Oravec
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260623165724.10753-4-scardracs@disroot.org \
--to=scardracs@disroot.org \
--cc=bp@alien8.de \
--cc=crecklin@redhat.com \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=moravec@ukf.sk \
--cc=pavel@kernel.org \
--cc=rafael@kernel.org \
--cc=regressions@leemhuis.info \
--cc=regressions@lists.linux.dev \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®