3f5a509172
Release: crash-8.0.5-5 Resolves: RHEL-33667 Signed-off-by: Tao Liu <ltao@redhat.com>
262 lines
9.1 KiB
Diff
262 lines
9.1 KiB
Diff
From 93d7f647c45b80b584db815f78b7130508642c60 Mon Sep 17 00:00:00 2001
|
|
From: Kuan-Ying Lee <kuan-ying.lee@canonical.com>
|
|
Date: Sat, 13 Jul 2024 21:22:52 +0800
|
|
Subject: [PATCH 3/5] arm64: Introduction of support for 16K page with 3-level
|
|
table support
|
|
|
|
Introduction of ARM64 support for 16K page size with 3-level page
|
|
table and 47 VA bits.
|
|
|
|
Signed-off-by: Kuan-Ying Lee <kuan-ying.lee@canonical.com>
|
|
---
|
|
arm64.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
|
|
defs.h | 16 ++++++++
|
|
2 files changed, 126 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/arm64.c b/arm64.c
|
|
index 78e6609..067c879 100644
|
|
--- a/arm64.c
|
|
+++ b/arm64.c
|
|
@@ -42,6 +42,7 @@ static int arm64_kvtop(struct task_context *, ulong, physaddr_t *, int);
|
|
static int arm64_uvtop(struct task_context *, ulong, physaddr_t *, int);
|
|
static int arm64_vtop_2level_64k(ulong, ulong, physaddr_t *, int);
|
|
static int arm64_vtop_3level_64k(ulong, ulong, physaddr_t *, int);
|
|
+static int arm64_vtop_3level_16k(ulong, ulong, physaddr_t *, int);
|
|
static int arm64_vtop_3level_4k(ulong, ulong, physaddr_t *, int);
|
|
static int arm64_vtop_4level_4k(ulong, ulong, physaddr_t *, int);
|
|
static ulong arm64_get_task_pgd(ulong);
|
|
@@ -262,8 +263,7 @@ arm64_init(int when)
|
|
machdep->pagesize = 4096;
|
|
break;
|
|
case 2:
|
|
- /* TODO: machdep->pagesize = 16384; */
|
|
- error(FATAL, "16K pages not supported.");
|
|
+ machdep->pagesize = 16384;
|
|
break;
|
|
case 3:
|
|
machdep->pagesize = 65536;
|
|
@@ -393,6 +393,26 @@ arm64_init(int when)
|
|
error(FATAL, "cannot malloc ptbl space.");
|
|
break;
|
|
|
|
+ case 16384:
|
|
+ if (machdep->machspec->VA_BITS > PGDIR_SHIFT_L3_16K) {
|
|
+ machdep->flags |= VM_L3_16K;
|
|
+ if (!machdep->ptrs_per_pgd)
|
|
+ machdep->ptrs_per_pgd = PTRS_PER_PGD_L3_16K;
|
|
+ if ((machdep->pgd =
|
|
+ (char *)malloc(machdep->ptrs_per_pgd * 8)) == NULL)
|
|
+ error(FATAL, "cannot malloc pgd space.");
|
|
+ if ((machdep->pmd =
|
|
+ (char *)malloc(PTRS_PER_PMD_L3_16K * 8)) == NULL)
|
|
+ error(FATAL, "cannot malloc pmd space.");
|
|
+ if ((machdep->ptbl =
|
|
+ (char *)malloc(PTRS_PER_PTE_L3_16K * 8)) == NULL)
|
|
+ error(FATAL, "cannot malloc ptbl space.");
|
|
+ } else {
|
|
+ error(FATAL, "we only support 47 bits, 3 level for 16K page now.");
|
|
+ }
|
|
+ machdep->pud = NULL; /* not used */
|
|
+ break;
|
|
+
|
|
case 65536:
|
|
if (kernel_symbol_exists("idmap_ptrs_per_pgd") &&
|
|
readmem(symbol_value("idmap_ptrs_per_pgd"), KVADDR,
|
|
@@ -1029,6 +1049,8 @@ arm64_dump_machdep_table(ulong arg)
|
|
fprintf(fp, "%sVM_L2_64K", others++ ? "|" : "");
|
|
if (machdep->flags & VM_L3_64K)
|
|
fprintf(fp, "%sVM_L3_64K", others++ ? "|" : "");
|
|
+ if (machdep->flags & VM_L3_16K)
|
|
+ fprintf(fp, "%sVM_L3_16K", others++ ? "|" : "");
|
|
if (machdep->flags & VM_L3_4K)
|
|
fprintf(fp, "%sVM_L3_4K", others++ ? "|" : "");
|
|
if (machdep->flags & VM_L4_4K)
|
|
@@ -1076,6 +1098,8 @@ arm64_dump_machdep_table(ulong arg)
|
|
"arm64_vtop_3level_4k" :
|
|
machdep->flags & VM_L4_4K ?
|
|
"arm64_vtop_4level_4k" :
|
|
+ machdep->flags & VM_L3_16K ?
|
|
+ "arm64_vtop_3level_16k" :
|
|
machdep->flags & VM_L3_64K ?
|
|
"arm64_vtop_3level_64k" : "arm64_vtop_2level_64k");
|
|
fprintf(fp, " kvtop: arm64_kvtop()->%s()\n",
|
|
@@ -1083,6 +1107,8 @@ arm64_dump_machdep_table(ulong arg)
|
|
"arm64_vtop_3level_4k" :
|
|
machdep->flags & VM_L4_4K ?
|
|
"arm64_vtop_4level_4k" :
|
|
+ machdep->flags & VM_L3_16K ?
|
|
+ "arm64_vtop_3level_16k" :
|
|
machdep->flags & VM_L3_64K ?
|
|
"arm64_vtop_3level_64k" : "arm64_vtop_2level_64k");
|
|
fprintf(fp, " get_task_pgd: arm64_get_task_pgd()\n");
|
|
@@ -1118,6 +1144,7 @@ arm64_dump_machdep_table(ulong arg)
|
|
fprintf(fp, " last_pgd_read: %lx\n", machdep->last_pgd_read);
|
|
fprintf(fp, " last_pud_read: ");
|
|
if ((PAGESIZE() == 65536) ||
|
|
+ (PAGESIZE() == 16384) ||
|
|
((PAGESIZE() == 4096) && !(machdep->flags & VM_L4_4K)))
|
|
fprintf(fp, "(not used)\n");
|
|
else
|
|
@@ -1772,7 +1799,7 @@ arm64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbos
|
|
kernel_pgd = vt->kernel_pgd[0];
|
|
*paddr = 0;
|
|
|
|
- switch (machdep->flags & (VM_L2_64K|VM_L3_64K|VM_L3_4K|VM_L4_4K))
|
|
+ switch (machdep->flags & (VM_L2_64K|VM_L3_64K|VM_L3_4K|VM_L4_4K|VM_L3_16K))
|
|
{
|
|
case VM_L2_64K:
|
|
return arm64_vtop_2level_64k(kernel_pgd, kvaddr, paddr, verbose);
|
|
@@ -1782,6 +1809,8 @@ arm64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbos
|
|
return arm64_vtop_3level_4k(kernel_pgd, kvaddr, paddr, verbose);
|
|
case VM_L4_4K:
|
|
return arm64_vtop_4level_4k(kernel_pgd, kvaddr, paddr, verbose);
|
|
+ case VM_L3_16K:
|
|
+ return arm64_vtop_3level_16k(kernel_pgd, kvaddr, paddr, verbose);
|
|
default:
|
|
return FALSE;
|
|
}
|
|
@@ -1797,7 +1826,7 @@ arm64_uvtop(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbos
|
|
|
|
*paddr = 0;
|
|
|
|
- switch (machdep->flags & (VM_L2_64K|VM_L3_64K|VM_L3_4K|VM_L4_4K))
|
|
+ switch (machdep->flags & (VM_L2_64K|VM_L3_64K|VM_L3_4K|VM_L4_4K|VM_L3_16K))
|
|
{
|
|
case VM_L2_64K:
|
|
return arm64_vtop_2level_64k(user_pgd, uvaddr, paddr, verbose);
|
|
@@ -1807,6 +1836,8 @@ arm64_uvtop(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbos
|
|
return arm64_vtop_3level_4k(user_pgd, uvaddr, paddr, verbose);
|
|
case VM_L4_4K:
|
|
return arm64_vtop_4level_4k(user_pgd, uvaddr, paddr, verbose);
|
|
+ case VM_L3_16K:
|
|
+ return arm64_vtop_3level_16k(user_pgd, uvaddr, paddr, verbose);
|
|
default:
|
|
return FALSE;
|
|
}
|
|
@@ -1823,6 +1854,7 @@ arm64_uvtop(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbos
|
|
#define PMD_TYPE_SECT 1
|
|
#define PMD_TYPE_TABLE 2
|
|
#define SECTION_PAGE_MASK_2MB ((long)(~((MEGABYTES(2))-1)))
|
|
+#define SECTION_PAGE_MASK_32MB ((long)(~((MEGABYTES(32))-1)))
|
|
#define SECTION_PAGE_MASK_512MB ((long)(~((MEGABYTES(512))-1)))
|
|
#define SECTION_PAGE_MASK_1GB ((long)(~((GIGABYTES(1))-1)))
|
|
|
|
@@ -1965,6 +1997,80 @@ no_page:
|
|
return FALSE;
|
|
}
|
|
|
|
+static int
|
|
+arm64_vtop_3level_16k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose)
|
|
+{
|
|
+ ulong *pgd_base, *pgd_ptr, pgd_val;
|
|
+ ulong *pmd_base, *pmd_ptr, pmd_val;
|
|
+ ulong *pte_base, *pte_ptr, pte_val;
|
|
+
|
|
+ if (verbose)
|
|
+ fprintf(fp, "PAGE DIRECTORY: %lx\n", pgd);
|
|
+
|
|
+ pgd_base = (ulong *)pgd;
|
|
+ FILL_PGD(pgd_base, KVADDR, machdep->ptrs_per_pgd * sizeof(ulong));
|
|
+ pgd_ptr = pgd_base + (((vaddr) >> PGDIR_SHIFT_L3_16K) & (machdep->ptrs_per_pgd - 1));
|
|
+ pgd_val = ULONG(machdep->pgd + PGDIR_OFFSET_L3_16K(pgd_ptr));
|
|
+ if (verbose)
|
|
+ fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
|
|
+ if (!pgd_val)
|
|
+ goto no_page;
|
|
+
|
|
+ /*
|
|
+ * #define __PAGETABLE_PUD_FOLDED
|
|
+ */
|
|
+
|
|
+ pmd_base = (ulong *)PTOV(PTE_TO_PHYS(pgd_val));
|
|
+ FILL_PMD(pmd_base, KVADDR, PTRS_PER_PMD_L3_16K * sizeof(ulong));
|
|
+ pmd_ptr = pmd_base + (((vaddr) >> PMD_SHIFT_L3_16K) & (PTRS_PER_PMD_L3_16K - 1));
|
|
+ pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_ptr));
|
|
+ if (verbose)
|
|
+ fprintf(fp, " PMD: %lx => %lx\n", (ulong)pmd_ptr, pmd_val);
|
|
+ if (!pmd_val)
|
|
+ goto no_page;
|
|
+
|
|
+ if ((pmd_val & PMD_TYPE_MASK) == PMD_TYPE_SECT) {
|
|
+ ulong sectionbase = PTE_TO_PHYS(pmd_val) & SECTION_PAGE_MASK_32MB;
|
|
+ if (verbose) {
|
|
+ fprintf(fp, " PAGE: %lx (32MB%s)\n\n", sectionbase,
|
|
+ IS_ZEROPAGE(sectionbase) ? ", ZERO PAGE" : "");
|
|
+ arm64_translate_pte(pmd_val, 0, 0);
|
|
+ }
|
|
+ *paddr = sectionbase + (vaddr & ~SECTION_PAGE_MASK_32MB);
|
|
+ return TRUE;
|
|
+ }
|
|
+
|
|
+ pte_base = (ulong *)PTOV(PTE_TO_PHYS(pmd_val));
|
|
+ FILL_PTBL(pte_base, KVADDR, PTRS_PER_PTE_L3_16K * sizeof(ulong));
|
|
+ pte_ptr = pte_base + (((vaddr) >> machdep->pageshift) & (PTRS_PER_PTE_L3_16K - 1));
|
|
+ pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_ptr));
|
|
+ if (verbose)
|
|
+ fprintf(fp, " PTE: %lx => %lx\n", (ulong)pte_ptr, pte_val);
|
|
+ if (!pte_val)
|
|
+ goto no_page;
|
|
+
|
|
+ if (pte_val & PTE_VALID) {
|
|
+ *paddr = PTE_TO_PHYS(pte_val) + PAGEOFFSET(vaddr);
|
|
+ if (verbose) {
|
|
+ fprintf(fp, " PAGE: %lx %s\n\n", PAGEBASE(*paddr),
|
|
+ IS_ZEROPAGE(PAGEBASE(*paddr)) ? "(ZERO PAGE)" : "");
|
|
+ arm64_translate_pte(pte_val, 0, 0);
|
|
+ }
|
|
+ } else {
|
|
+ if (IS_UVADDR(vaddr, NULL))
|
|
+ *paddr = pte_val;
|
|
+ if (verbose) {
|
|
+ fprintf(fp, "\n");
|
|
+ arm64_translate_pte(pte_val, 0, 0);
|
|
+ }
|
|
+ goto no_page;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+no_page:
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
static int
|
|
arm64_vtop_3level_4k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose)
|
|
{
|
|
diff --git a/defs.h b/defs.h
|
|
index 49e6923..1b7649d 100644
|
|
--- a/defs.h
|
|
+++ b/defs.h
|
|
@@ -3302,6 +3302,21 @@ typedef signed int s32;
|
|
#define PGDIR_MASK_48VA (~(PGDIR_SIZE_48VA - 1))
|
|
#define PGDIR_OFFSET_48VA(X) (((ulong)(X)) & (PGDIR_SIZE_48VA - 1))
|
|
|
|
+/*
|
|
+ * 3-levels / 16K pages
|
|
+ * 47-bit VA
|
|
+ */
|
|
+#define PTRS_PER_PGD_L3_16K ((1UL) << (47 - 36))
|
|
+#define PTRS_PER_PMD_L3_16K (2048)
|
|
+#define PTRS_PER_PTE_L3_16K (2048)
|
|
+#define PGDIR_SHIFT_L3_16K (36)
|
|
+#define PGDIR_SIZE_L3_16K ((1UL) << PGDIR_SHIFT_L3_16K)
|
|
+#define PGDIR_MASK_L3_16K (~(PGDIR_SIZE_L3_16K-1))
|
|
+#define PMD_SHIFT_L3_16K (25)
|
|
+#define PMD_SIZE_L3_16K (1UL << PMD_SHIFT_L3_16K)
|
|
+#define PMD_MASK_L3_16K (~(PMD_SIZE_L3_16K-1))
|
|
+#define PGDIR_OFFSET_L3_16K(X) (((ulong)(X)) & ((machdep->ptrs_per_pgd * 8) - 1))
|
|
+
|
|
/*
|
|
* 3-levels / 64K pages
|
|
*/
|
|
@@ -3367,6 +3382,7 @@ typedef signed int s32;
|
|
#define HAS_PHYSVIRT_OFFSET (0x800)
|
|
#define OVERFLOW_STACKS (0x1000)
|
|
#define ARM64_MTE (0x2000)
|
|
+#define VM_L3_16K (0x4000)
|
|
|
|
/*
|
|
* Get kimage_voffset from /dev/crash
|
|
--
|
|
2.40.1
|
|
|