File crash-arm64-fix-64K-page-and-52-bits-VA-support.patch of Package crash.41263

From 19ce5a996ce78fdec889606564a35e6569a86ad3 Mon Sep 17 00:00:00 2001
From: Kuan-Ying Lee <kuan-ying.lee@canonical.com>
Date: Tue, 3 Sep 2024 15:51:28 +0800
Subject: [PATCH] arm64: fix 64K page and 52-bits VA support

Kernel commit ebd9aea1f27e ("arm64: head: drop idmap_ptrs_per_pgd") has
removed the "idmap_ptrs_per_pgd" since Linux v6.0-rc1, which caused the
following error:

crash: invalid kernel virtual address: ffff800083700000 type: "64-bit KVADDR"

Crash tool can not get the value of ptrs_per_pgd by reading
"idmap_ptrs_per_pgd", let's use VA_BITS to get its value.

Signed-off-by: Kuan-Ying Lee <kuan-ying.lee@canonical.com>
---
 arm64.c | 18 ++++++++++++++++--
 defs.h  |  3 ++-
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/arm64.c b/arm64.c
index 6cc1bd8..b2f20d1 100644
--- a/arm64.c
+++ b/arm64.c
@@ -445,6 +445,10 @@ arm64_init(int when)
 			break;
 
 		case 65536:
+			/*
+			 * idmap_ptrs_per_pgd has been removed since Linux-v6.0-rc1, see:
+			 * commit ebd9aea1f27e ("arm64: head: drop idmap_ptrs_per_pgd")
+			 */
 			if (kernel_symbol_exists("idmap_ptrs_per_pgd") &&
 			    readmem(symbol_value("idmap_ptrs_per_pgd"), KVADDR,
 			    &value, sizeof(ulong), "idmap_ptrs_per_pgd", QUIET|RETURN_ON_ERROR))
@@ -452,8 +456,14 @@ arm64_init(int when)
 		
 			if (machdep->machspec->VA_BITS > PGDIR_SHIFT_L3_64K) {
 				machdep->flags |= VM_L3_64K;
-				if (!machdep->ptrs_per_pgd)
-					machdep->ptrs_per_pgd = PTRS_PER_PGD_L3_64K;
+				if (!machdep->ptrs_per_pgd) {
+					if (machdep->machspec->VA_BITS == 52)
+						machdep->ptrs_per_pgd = PTRS_PER_PGD_L3_64K_52;
+					else if (machdep->machspec->VA_BITS == 48)
+						machdep->ptrs_per_pgd = PTRS_PER_PGD_L3_64K_48;
+					else
+						error(FATAL, "wrong VA_BITS for 64K page.");
+				}
 				if ((machdep->pgd =
 				    (char *)malloc(machdep->ptrs_per_pgd * 8)) == NULL)
 					error(FATAL, "cannot malloc pgd space.");
@@ -1972,6 +1982,10 @@ arm64_vtop_3level_64k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose)
 
 	pgd_base = (ulong *)pgd;
 	FILL_PGD(pgd_base, KVADDR, machdep->ptrs_per_pgd * sizeof(ulong));
+	/*
+	 * Use machdep->ptrs_per_pgd to mask vaddr instead of using macro, because
+	 * 48-bits and 52-bits have different size of ptrs_per_pgd.
+	 */
 	pgd_ptr = pgd_base + (((vaddr) >> PGDIR_SHIFT_L3_64K) & (machdep->ptrs_per_pgd - 1));
         pgd_val = ULONG(machdep->pgd + PGDIR_OFFSET_L3_64K(pgd_ptr));
         if (verbose)
diff --git a/defs.h b/defs.h
index 2d88134..305f343 100644
--- a/defs.h
+++ b/defs.h
@@ -3333,7 +3333,8 @@ typedef signed int s32;
 /*
  * 3-levels / 64K pages
  */
-#define PTRS_PER_PGD_L3_64K  (64)
+#define PTRS_PER_PGD_L3_64K_48  ((1UL) << (48 - 42))
+#define PTRS_PER_PGD_L3_64K_52  ((1UL) << (52 - 42))
 #define PTRS_PER_PMD_L3_64K  (8192)
 #define PTRS_PER_PTE_L3_64K  (8192)
 #define PGDIR_SHIFT_L3_64K   (42)
-- 
2.43.0

openSUSE Build Service is sponsored by