Skip to contentSkip to conversation

FAILED: patch "[PATCH] x86/e820: Fix handling of subpage regions when calculating" failed to apply to 5.4-stable tree

PATCH In review [email protected] 3 participants 3 messages Apr 17, 2025 – Apr 18, 2025

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.4.y
git checkout FETCH_HEAD
git cherry-pick -x f2f29da9f0d4367f6ff35e0d9d021257bb53e273
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025041757-drum-wispy-ef78@gregkh' --subject-prefix 'PATCH 5.4.y' HEAD^..

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From f2f29da9f0d4367f6ff35e0d9d021257bb53e273 Mon Sep 17 00:00:00 2001
From: Myrrh Periwinkle <[email protected]>
Date: Sun, 6 Apr 2025 11:45:22 +0700
Subject: [PATCH] x86/e820: Fix handling of subpage regions when calculating
nosave ranges in e820__register_nosave_regions()

While debugging kexec/hibernation hangs and crashes, it turned out that the current implementation of e820__register_nosave_regions() suffers from multiple serious issues:

- The end of last region is tracked by PFN, causing it to find holes that aren't there if two consecutive subpage regions are present

- The nosave PFN ranges derived from holes are rounded out (instead of rounded in) which makes it inconsistent with how explicitly reserved regions are handled

Fix this by:

- Treating reserved regions as if they were holes, to ensure consistent handling (rounding out nosave PFN ranges is more correct as the kernel does not use partial pages)

- Tracking the end of the last RAM region by address instead of pages to detect holes more precisely

These bugs appear to have been introduced about ~18 years ago with the very first version of e820_mark_nosave_regions(), and its flawed assumptions were carried forward uninterrupted through various waves of rewrites and renames.

[ mingo: Added Git archeology details, for kicks and giggles. ]

Fixes e8eff5ac294e ("[PATCH] Make swsusp avoid memory holes and reserved memory regions on x86_64")
Cc Rafael J. Wysocki <[email protected]>
Cc Ard Biesheuvel <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Kees Cook <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc David Woodhouse <[email protected]>
Cc Len Brown <[email protected]>
arch/x86/kernel/e820.c +8 -9
index 57120f0749cc..9d8dd8deb2a7 100644
@@ -753,22 +753,21 @@ void __init e820__memory_setup_extended(u64 phys_addr, u32 data_len)
 void __init e820__register_nosave_regions(unsigned long limit_pfn)
 {
 	int i;
-	unsigned long pfn = 0;
+	u64 last_addr = 0;
 
 	for (i = 0; i < e820_table->nr_entries; i++) {
 		struct e820_entry *entry = &e820_table->entries[i];
 
-		if (pfn < PFN_UP(entry->addr))
-			register_nosave_region(pfn, PFN_UP(entry->addr));
-
-		pfn = PFN_DOWN(entry->addr + entry->size);
-
 		if (entry->type != E820_TYPE_RAM)
-			register_nosave_region(PFN_UP(entry->addr), pfn);
+			continue;
 
-		if (pfn >= limit_pfn)
-			break;
+		if (last_addr < entry->addr)
+			register_nosave_region(PFN_DOWN(last_addr), PFN_UP(entry->addr));
+
+		last_addr = entry->addr + entry->size;
 	}
+
+	register_nosave_region(PFN_DOWN(last_addr), limit_pfn);
 }
 
 #ifdef CONFIG_ACPI
#1 lore raw

PATCH 1/1 x86/e820: Fix handling of subpage regions when calculating nosave ranges in e820__register_nosave_regions()

While debugging kexec/hibernation hangs and crashes, it turned out that the current implementation of e820__register_nosave_regions() suffers from multiple serious issues:

- The end of last region is tracked by PFN, causing it to find holes that aren't there if two consecutive subpage regions are present

- The nosave PFN ranges derived from holes are rounded out (instead of rounded in) which makes it inconsistent with how explicitly reserved regions are handled

Fix this by:

- Treating reserved regions as if they were holes, to ensure consistent handling (rounding out nosave PFN ranges is more correct as the kernel does not use partial pages)

- Tracking the end of the last RAM region by address instead of pages to detect holes more precisely

These bugs appear to have been introduced about ~18 years ago with the very first version of e820_mark_nosave_regions(), and its flawed assumptions were carried forward uninterrupted through various waves of rewrites and renames.

[ mingo: Added Git archeology details, for kicks and giggles. ]

Fixes e8eff5ac294e ("[PATCH] Make swsusp avoid memory holes and reserved memory regions on x86_64")
Cc Rafael J. Wysocki <[email protected]>
Cc Ard Biesheuvel <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Kees Cook <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc David Woodhouse <[email protected]>
Cc Len Brown <[email protected]>
(cherry picked from commit f2f29da9f0d4367f6ff35e0d9d021257bb53e273)
---
 arch/x86/kernel/e820.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)
arch/x86/kernel/e820.c +8 -9
index 7da2bcd2b8eb..f826c0a60a29 100644
@@ -738,22 +738,21 @@ void __init e820__memory_setup_extended(u64 phys_addr, u32 data_len)
 void __init e820__register_nosave_regions(unsigned long limit_pfn)
 {
 	int i;
-	unsigned long pfn = 0;
+	u64 last_addr = 0;
 
 	for (i = 0; i < e820_table->nr_entries; i++) {
 		struct e820_entry *entry = &e820_table->entries[i];
 
-		if (pfn < PFN_UP(entry->addr))
-			register_nosave_region(pfn, PFN_UP(entry->addr));
-
-		pfn = PFN_DOWN(entry->addr + entry->size);
-
 		if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN)
-			register_nosave_region(PFN_UP(entry->addr), pfn);
+			continue;
 
-		if (pfn >= limit_pfn)
-			break;
+		if (last_addr < entry->addr)
+			register_nosave_region(PFN_DOWN(last_addr), PFN_UP(entry->addr));
+
+		last_addr = entry->addr + entry->size;
 	}
+
+	register_nosave_region(PFN_DOWN(last_addr), limit_pfn);
 }
 
 #ifdef CONFIG_ACPI
Signature · 1 line
2.49.0
maintainer
#2 lore raw

Re: [PATCH 5.4.y 5.10.y 5.15.y 6.1.y 6.6.y 6.12.y 6.13.y 6.14.y] x86/e820: Fix handling of subpage regions when calculating nosave ranges in e820__register_nosave_regions()

[ Sasha's backport helper bot ]

Hi,

Summary of potential issues:
⚠️ Found matching upstream commit but patch is missing proper reference to it

Found matching upstream commit: f2f29da9f0d4367f6ff35e0d9d021257bb53e273

Status in newer kernel trees:

6.14.y | Not found
6.13.y | Not found
6.12.y | Not found

6.6.y | Not found
6.1.y | Not found
5.15.y | Not found
5.10.y | Not found

Note: The patch differs from the upstream commit:
---
1: f2f29da9f0d43 ! 1: f3ea523486c43 x86/e820: Fix handling of subpage regions when calculating nosave ranges in e820__register_nosave_regions()

    @@ Commit message
         Cc: [email protected]
         Link: https://lore.kernel.org/r/[email protected]
         Closes: https://lore.kernel.org/all/Z4WFjBVHpndct7br@desktop0a/
    +    (cherry picked from commit f2f29da9f0d4367f6ff35e0d9d021257bb53e273)
    +    Signed-off-by: Myrrh Periwinkle <[email protected]>
     
      ## arch/x86/kernel/e820.c ##
     @@ arch/x86/kernel/e820.c: void __init e820__memory_setup_extended(u64 phys_addr, u32 data_len)
    @@ arch/x86/kernel/e820.c: void __init e820__memory_setup_extended(u64 phys_addr, u
     -
     -		pfn = PFN_DOWN(entry->addr + entry->size);
     -
    - 		if (entry->type != E820_TYPE_RAM)
    + 		if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN)
     -			register_nosave_region(PFN_UP(entry->addr), pfn);
     +			continue;

---

Results of testing on various branches:

| Branch                    | Patch Apply | Build Test |
|---------------------------|-------------|------------|
| stable/linux-5.4.y        |  Success    |  Success   |
| stable/linux-5.10.y       |  Success    |  Success   |
| stable/linux-5.15.y       |  Success    |  Success   |
| stable/linux-6.1.y        |  Success    |  Success   |
| stable/linux-6.6.y        |  Success    |  Success   |
| stable/linux-6.12.y       |  Success    |  Success   |
| stable/linux-6.13.y       |  Success    |  Success   |
| stable/linux-6.14.y       |  Success    |  Success   |