After commit ebd9aea1f27e ("arm64: head: drop idmap_ptrs_per_pgd") in
Linux kernel-v6.0, kernel removed the idmap_ptrs_per_pgd. This commit
cause the following error.

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

We cannot use "idmap_ptrs_per_pgd" to know the size of "ptrs_per_pgd".
We use VA_BITS to know the size of "ptrs_per_pgd" instead.

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

diff --git a/arm64.c b/arm64.c
index 6cc1bd8f3329..d0b2fa63a089 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 in kernel commit 
ebd9aea1f27e ("arm64:
+                        * head: drop idmap_ptrs_per_pgd"). This commit is 
included after Linux-v6.0.
+                        */
                        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));
+       /*
+        * We need to 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 2d881344cba6..9f4d676e25f9 100644
--- a/defs.h
+++ b/defs.h
@@ -3333,7 +3333,8 @@ typedef signed int s32;
  * 3-levels / 64K pages
  * 48-bit, 52-bit VA
  */
-#define PTRS_PER_PGD_L3_64K  (64)
+#define PTRS_PER_PGD_L3_64K_48  ((1UL) << (48 - 42)) // 48-bit VA
+#define PTRS_PER_PGD_L3_64K_52  ((1UL) << (52 - 42)) // 52-bit VA
 #define PTRS_PER_PMD_L3_64K  (8192)
 #define PTRS_PER_PTE_L3_64K  (8192)
 #define PGDIR_SHIFT_L3_64K   (42)
-- 
2.43.0
--
Crash-utility mailing list -- devel@lists.crash-utility.osci.io
To unsubscribe send an email to devel-le...@lists.crash-utility.osci.io
https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
Contribution Guidelines: https://github.com/crash-utility/crash/wiki

Reply via email to