Skip to contentSkip to conversation

arm64: Fix 5-level paging support in kexec/hibernate trampoline

PATCH Applied Ard Biesheuvel 4 participants 4 messages Jan 10, 2025 – Feb 4, 2025 arm64

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 arm64: Fix 5-level paging support in kexec/hibernate trampoline

From: Ard Biesheuvel <[email protected]>

Add the missing code to allocate P4D level page tables when cloning the the kernel page tables. This fixes a crash that may be observed when attempting to resume from hibernation on an LPA2 capable system with 4k pages, which therefore uses 5 levels of paging.

Presumably, kexec is equally affected.

---
 arch/arm64/mm/trans_pgd.c | 7 +++++++
 1 file changed, 7 insertions(+)
arch/arm64/mm/trans_pgd.c +7 -0
index 0f7b484cb2ff..84594f02f780 100644
@@ -162,6 +162,13 @@ static int copy_p4d(struct trans_pgd_info *info, pgd_t *dst_pgdp,
 	unsigned long next;
 	unsigned long addr = start;
 
+	if (pgd_none(READ_ONCE(*dst_pgdp))) {
+		dst_p4dp = trans_alloc(info);
+		if (!dst_p4dp)
+			return -ENOMEM;
+		pgd_populate(NULL, dst_pgdp, dst_p4dp);
+	}
+
 	dst_p4dp = p4d_offset(dst_pgdp, start);
 	src_p4dp = p4d_offset(src_pgdp, start);
 	do {
Signature · 1 line
2.47.1.688.g23fc6f90ad-goog
#1 lore raw
Quoted 19 lines · Ard Biesheuvel

From: Ard Biesheuvel <[email protected]>

Add the missing code to allocate P4D level page tables when cloning the the kernel page tables. This fixes a crash that may be observed when attempting to resume from hibernation on an LPA2 capable system with 4k pages, which therefore uses 5 levels of paging.

Presumably, kexec is equally affected.

---
 arch/arm64/mm/trans_pgd.c | 7 +++++++
 1 file changed, 7 insertions(+)
arch/arm64/mm/trans_pgd.c +0 -0
index 0f7b484cb2ff..84594f02f780 100644

arch/arm64/mm/trans_pgd.c static int copy_p4d(struct trans_pgd_info *info, pgd_t *dst_pgdp, · line 169

Quoted 8 lines
arch/arm64/mm/trans_pgd.c +5 -0
@@ -162,6 +162,13 @@ static int copy_p4d(struct trans_pgd_info *info, pgd_t *dst_pgdp,
 	unsigned long next;
 	unsigned long addr = start;
 
+	if (pgd_none(READ_ONCE(*dst_pgdp))) {
+		dst_p4dp = trans_alloc(info);
+		if (!dst_p4dp)
+			return -ENOMEM;
+		pgd_populate(NULL, dst_pgdp, dst_p4dp);

Just wondering would not dst_p4dp goes unused (and probably leaked) when pgtable_l5_enabled() is not enabled ? Similar scenario might also exist in copy_pud() as well with respect to pgtable_l4_enabled().

pgd_populate()

	__pgd_populate()
		if (pgtable_l5_enabled())
			set_pgd()
Quoted 5 lines
arch/arm64/mm/trans_pgd.c +2 -0
+	}
+
 	dst_p4dp = p4d_offset(dst_pgdp, start);
 	src_p4dp = p4d_offset(src_pgdp, start);
 	do {
#2 lore raw
Quoted 25 lines · Anshuman Khandual
Quoted 22 lines · Ard Biesheuvel

From: Ard Biesheuvel <[email protected]>

Add the missing code to allocate P4D level page tables when cloning the the kernel page tables. This fixes a crash that may be observed when attempting to resume from hibernation on an LPA2 capable system with 4k pages, which therefore uses 5 levels of paging.

Presumably, kexec is equally affected.

---
 arch/arm64/mm/trans_pgd.c | 7 +++++++
 1 file changed, 7 insertions(+)
arch/arm64/mm/trans_pgd.c +0 -0
index 0f7b484cb2ff..84594f02f780 100644
@@ -162,6 +162,13 @@ static int copy_p4d(struct trans_pgd_info *info, pgd_t *dst_pgdp,
      unsigned long next;
      unsigned long addr = start;
 
Quoted 8 lines

arch/arm64/mm/trans_pgd.c static int copy_p4d(struct trans_pgd_info *info, pgd_t *dst_pgdp, · line 169

Quoted 5 lines
arch/arm64/mm/trans_pgd.c +5 -0
+     if (pgd_none(READ_ONCE(*dst_pgdp))) {
+             dst_p4dp = trans_alloc(info);
+             if (!dst_p4dp)
+                     return -ENOMEM;
+             pgd_populate(NULL, dst_pgdp, dst_p4dp);

Just wondering would not dst_p4dp goes unused (and probably leaked) when pgtable_l5_enabled() is not enabled ?

Would pgd_none() ever return TRUE in that case?

Quoted 13 lines

Similar scenario might also exist
in copy_pud() as well with respect to pgtable_l4_enabled().

pgd_populate()

        __pgd_populate()
                if (pgtable_l5_enabled())
                        set_pgd()
Quoted 5 lines
arch/arm64/mm/trans_pgd.c +2 -0
+     }
+
      dst_p4dp = p4d_offset(dst_pgdp, start);
      src_p4dp = p4d_offset(src_pgdp, start);
      do {
maintainer Applied
#3 lore raw
In reply to Ard Biesheuvel
Quoted 8 lines · Ard Biesheuvel

Add the missing code to allocate P4D level page tables when cloning the the kernel page tables. This fixes a crash that may be observed when attempting to resume from hibernation on an LPA2 capable system with 4k pages, which therefore uses 5 levels of paging.

Presumably, kexec is equally affected.

[...]

Applied to arm64 (for-next/fixes), thanks!

[1/1] arm64: Fix 5-level paging support in kexec/hibernate trampoline

      https://git.kernel.org/arm64/c/3648027de1fa

Cheers,

Signature · 5 lines
Will

https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev