[PATCH] riscv64: support leaf PTEs in page table walks
by yuan.dong1@zte.com.cn
From: yuandong <yuan.dong1(a)zte.com.cn>
The existing RISC-V virtual-to-physical address walkers descend to the
last-level PTE unconditionally. This fails when an upper-level entry is
a leaf mapping, as used for huge pages.
Replace the separate Sv39, Sv48, and Sv57 page-table walkers with a
common n-level implementation. Detect leaf entries at every level,
calculate the physical address using the level-specific page offset,
and reject misaligned leaf entries.
This allows kvtop and uvtop to translate upper-level leaf mappings
while retaining support for normal 4 KiB pages.
Signed-off-by: yuandong <yuan.dong1(a)zte.com.cn>
---
defs.h | 2 +
riscv64.c | 426 +++++++++++++++++++++++++-----------------------------
2 files changed, 201 insertions(+), 227 deletions(-)
diff --git a/defs.h b/defs.h
index a4f70b7..def33d8 100644
--- a/defs.h
+++ b/defs.h
@@ -3800,6 +3800,8 @@ typedef signed int s32;
#define VM_L5_1G (0x200)
#define IRQ_STACKS (0x400)
#define OVERFLOW_STACKS (0x800)
+#define RISCV64_PTE_LEAF(pte) \
+ ((pte) & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC))
#define RISCV64_OVERFLOW_STACK_SIZE (1 << 12)
diff --git a/riscv64.c b/riscv64.c
index f0783d5..9b0d8d3 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -19,12 +19,8 @@
#include <math.h>
static ulong riscv64_get_page_size(void);
-static int riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr,
- physaddr_t *paddr, int verbose);
-static int riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr,
- physaddr_t *paddr, int verbose);
-static int riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr,
- physaddr_t *paddr, int verbose);
+static int riscv64_vtop_nlevel_4k(ulong *pgd, ulong vaddr,
+ physaddr_t *paddr, int verbose, int levels);
static void riscv64_page_type_init(void);
static int riscv64_is_kvaddr(ulong vaddr);
static int riscv64_is_uvaddr(ulong vaddr, struct task_context *tc);
@@ -634,66 +630,208 @@ riscv64_page_type_init(void)
}
}
+static ulong
+riscv64_vtop_index(ulong vaddr, int levels, int level)
+{
+ switch (levels) {
+ case 3:
+ switch (level) {
+ case 2:
+ return pgd_index_l3_4k(vaddr);
+ case 1:
+ return pmd_index_l3_4k(vaddr);
+ case 0:
+ return pte_index_l3_4k(vaddr);
+ }
+ break;
+
+ case 4:
+ switch (level) {
+ case 3:
+ return pgd_index_l4_4k(vaddr);
+ case 2:
+ return pud_index_l4_4k(vaddr);
+ case 1:
+ return pmd_index_l4_4k(vaddr);
+ case 0:
+ return pte_index_l4_4k(vaddr);
+ }
+ break;
+
+ case 5:
+ switch (level) {
+ case 4:
+ return pgd_index_l5_4k(vaddr);
+ case 3:
+ return p4d_index_l5_4k(vaddr);
+ case 2:
+ return pud_index_l5_4k(vaddr);
+ case 1:
+ return pmd_index_l5_4k(vaddr);
+ case 0:
+ return pte_index_l5_4k(vaddr);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static const char *
+riscv64_level_name(int levels, int level)
+{
+ if (level == levels - 1)
+ return "PGD";
+
+ if (level == 3)
+ return "P4D";
+
+ if (level == 2)
+ return "PUD";
+
+ if (level == 1)
+ return "PMD";
+
+ return "PTE";
+}
+
static int
-riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
+riscv64_pte_page_shift(int level)
{
- ulong *pgd_ptr, pgd_val;
- ulong pmd_base, pmd_addr, pmd_val;
- ulong pte_base, pte_addr, pte_val, pte_pfn;
+ switch (level) {
+ case 0:
+ return PAGESHIFT();
+ case 1:
+ return PMD_SHIFT;
+ case 2:
+ return PUD_SHIFT;
+ case 3:
+ return P4D_SHIFT;
+ case 4:
+ return PGD_SHIFT_L5;
+ default:
+ return PAGESHIFT();
+ }
+}
+
+static physaddr_t
+riscv64_pte_page_mask(int level)
+{
+ return ((physaddr_t)1 << riscv64_pte_page_shift(level)) - 1;
+}
+
+static physaddr_t
+riscv64_pte_paddr_base(ulong pte)
+{
+ pte &= PTE_PFN_PROT_MASK;
+ return PTOB(pte >> _PAGE_PFN_SHIFT);
+}
+
+static physaddr_t
+riscv64_pte_to_paddr(ulong pte, ulong vaddr, int level)
+{
+ physaddr_t base, mask;
+
+ base = riscv64_pte_paddr_base(pte);
+ mask = riscv64_pte_page_mask(level);
+
+ return base + (vaddr & mask);
+}
+
+static int
+riscv64_vtop_nlevel_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr,
+ int verbose, int levels)
+{
+ int level;
+ ulong index;
+ ulong entry_addr;
+ ulong pte;
+ ulong table_addr;
+ const char *name;
+
+ if (levels < 3 || levels > 5)
+ return FALSE;
+
+ *paddr = 0;
if (verbose)
fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
- /* PGD */
- pgd_ptr = pgd + pgd_index_l3_4k(vaddr);
- FILL_PGD(pgd, KVADDR, PAGESIZE());
- pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr));
- if (verbose)
- fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
- if (!pgd_val)
- goto no_page;
- pgd_val &= PTE_PFN_PROT_MASK;
- pmd_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PMD */
- FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
- pmd_addr = pmd_base + sizeof(pmd_t) * pmd_index_l3_4k(vaddr);
- pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_addr));
- if (verbose)
- fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr, pmd_val);
- if (!pmd_val)
- goto no_page;
- pmd_val &= PTE_PFN_PROT_MASK;
- pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PTE */
- FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
- pte_addr = pte_base + sizeof(pmd_t) * pte_index_l3_4k(vaddr);
- pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_addr));
- if (verbose)
- fprintf(fp, " PTE: %lx => %lx\n", pte_addr, pte_val);
- if (!pte_val)
- goto no_page;
- pte_val &= PTE_PFN_PROT_MASK;
- pte_pfn = pte_val >> _PAGE_PFN_SHIFT;
-
- if (!(pte_val & _PAGE_PRESENT)) {
- if (verbose) {
- fprintf(fp, "\n");
- riscv64_translate_pte((ulong)pte_val, 0, 0);
+ table_addr = (ulong)pgd;
+
+ for (level = levels - 1; level >= 0; level--) {
+ name = riscv64_level_name(levels, level);
+ index = riscv64_vtop_index(vaddr, levels, level);
+
+ if (level == levels - 1) {
+ FILL_PGD((ulong *)PAGEBASE(table_addr), KVADDR,
+ PAGESIZE());
+
+ entry_addr = table_addr + sizeof(ulong) * index;
+ pte = ULONG(machdep->pgd + PAGEOFFSET(entry_addr));
+ } else {
+ FILL_PTBL(PAGEBASE(table_addr), PHYSADDR,
+ PAGESIZE());
+
+ entry_addr = table_addr + sizeof(ulong) * index;
+ pte = ULONG(machdep->ptbl + PAGEOFFSET(entry_addr));
+ }
+
+ if (verbose)
+ fprintf(fp, " %s: %016lx => %016lx\n",
+ name, entry_addr, pte);
+
+ if (!pte)
+ goto no_page;
+
+ pte &= PTE_PFN_PROT_MASK;
+
+ if (!(pte & _PAGE_PRESENT)) {
+ if (verbose) {
+ fprintf(fp, "\n");
+ riscv64_translate_pte(pte, 0, 0);
+ }
+
+ fprintf(fp, " PAGE: %016lx not present\n\n",
+ PAGEBASE(vaddr));
+ return FALSE;
}
- fprintf(fp, " PAGE: %016lx not present\n\n", PAGEBASE(*paddr));
- return FALSE;
- }
- *paddr = PTOB(pte_pfn) + PAGEOFFSET(vaddr);
+ if (RISCV64_PTE_LEAF(pte)) {
+ physaddr_t base, mask;
- if (verbose) {
- fprintf(fp, " PAGE: %016lx\n\n", PAGEBASE(*paddr));
- riscv64_translate_pte(pte_val, 0, 0);
+ base = riscv64_pte_paddr_base(pte);
+ mask = riscv64_pte_page_mask(level);
+
+ if (level && (base & mask)) {
+ if (verbose) {
+ fprintf(fp, "\n");
+ riscv64_translate_pte(pte, 0, 0);
+ }
+
+ fprintf(fp,
+ " PAGE: %016lx invalid misaligned leaf pte\n\n",
+ PAGEBASE(vaddr));
+ return FALSE;
+ }
+
+ *paddr = riscv64_pte_to_paddr(pte, vaddr, level);
+
+ if (verbose) {
+ fprintf(fp, " PAGE: %016lx\n\n",
+ (ulong)(*paddr & ~mask));
+ riscv64_translate_pte(pte, 0, 0);
+ }
+
+ return TRUE;
+ }
+
+ if (level == 0)
+ goto no_page;
+
+ table_addr = (ulong)riscv64_pte_paddr_base(pte);
}
- return TRUE;
no_page:
fprintf(fp, "invalid for %lx address\n", vaddr);
return FALSE;
@@ -1214,172 +1352,6 @@ riscv64_get_frame(struct bt_info *bt, ulong *pcp, ulong *spp)
return TRUE;
}
-static int
-riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
-{
- ulong *pgd_ptr, pgd_val;
- ulong pud_base, pud_addr, pud_val;
- ulong pmd_base, pmd_addr, pmd_val;
- ulong pte_base, pte_addr, pte_val, pte_pfn;
-
- if (verbose)
- fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
-
- /* PGD */
- pgd_ptr = pgd + pgd_index_l4_4k(vaddr);
- FILL_PGD(pgd, KVADDR, PAGESIZE());
- pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr));
- if (verbose)
- fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
- if (!pgd_val)
- goto no_page;
- pgd_val &= PTE_PFN_PROT_MASK;
- pud_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PUD */
- FILL_PUD(PAGEBASE(pud_base), PHYSADDR, PAGESIZE());
- pud_addr = pud_base + sizeof(pud_t) * pud_index_l4_4k(vaddr);
- pud_val = ULONG(machdep->pud + PAGEOFFSET(pud_addr));
- if (verbose)
- fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr, pud_val);
- if (!pud_val)
- goto no_page;
- pud_val &= PTE_PFN_PROT_MASK;
- pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PMD */
- FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
- pmd_addr = pmd_base + sizeof(pmd_t) * pmd_index_l4_4k(vaddr);
- pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_addr));
- if (verbose)
- fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr, pmd_val);
- if (!pmd_val)
- goto no_page;
- pmd_val &= PTE_PFN_PROT_MASK;
- pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PTE */
- FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
- pte_addr = pte_base + sizeof(pte_t) * pte_index_l4_4k(vaddr);
- pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_addr));
- if (verbose)
- fprintf(fp, " PTE: %lx => %lx\n", pte_addr, pte_val);
- if (!pte_val)
- goto no_page;
- pte_val &= PTE_PFN_PROT_MASK;
- pte_pfn = pte_val >> _PAGE_PFN_SHIFT;
-
- if (!(pte_val & _PAGE_PRESENT)) {
- if (verbose) {
- fprintf(fp, "\n");
- riscv64_translate_pte((ulong)pte_val, 0, 0);
- }
- fprintf(fp, " PAGE: %016lx not present\n\n", PAGEBASE(*paddr));
- return FALSE;
- }
-
- *paddr = PTOB(pte_pfn) + PAGEOFFSET(vaddr);
-
- if (verbose) {
- fprintf(fp, " PAGE: %016lx\n\n", PAGEBASE(*paddr));
- riscv64_translate_pte(pte_val, 0, 0);
- }
-
- return TRUE;
-no_page:
- fprintf(fp, "invalid for %lx address\n", vaddr);
- return FALSE;
-}
-
-static int
-riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
-{
- ulong *pgd_ptr, pgd_val;
- ulong p4d_base, p4d_addr, p4d_val;
- ulong pud_base, pud_addr, pud_val;
- ulong pmd_base, pmd_addr, pmd_val;
- ulong pte_base, pte_addr, pte_val, pte_pfn;
-
- if (verbose)
- fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
-
- /* PGD */
- pgd_ptr = pgd + pgd_index_l5_4k(vaddr);
- FILL_PGD(pgd, KVADDR, PAGESIZE());
- pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr));
- if (verbose)
- fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
- if (!pgd_val)
- goto no_page;
- pgd_val &= PTE_PFN_PROT_MASK;
- p4d_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* P4D */
- FILL_P4D(PAGEBASE(p4d_base), PHYSADDR, PAGESIZE());
- p4d_addr = p4d_base + sizeof(p4d_t) * p4d_index_l5_4k(vaddr);
- p4d_val = ULONG(machdep->machspec->p4d + PAGEOFFSET(p4d_addr));
- if (verbose)
- fprintf(fp, " P4D: %016lx => %016lx\n", p4d_addr, p4d_val);
- if (!p4d_val)
- goto no_page;
- p4d_val &= PTE_PFN_PROT_MASK;
- pud_base = (p4d_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PUD */
- FILL_PUD(PAGEBASE(pud_base), PHYSADDR, PAGESIZE());
- pud_addr = pud_base + sizeof(pud_t) * pud_index_l5_4k(vaddr);
- pud_val = ULONG(machdep->pud + PAGEOFFSET(pud_addr));
- if (verbose)
- fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr, pud_val);
- if (!pud_val)
- goto no_page;
- pud_val &= PTE_PFN_PROT_MASK;
- pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PMD */
- FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
- pmd_addr = pmd_base + sizeof(pmd_t) * pmd_index_l5_4k(vaddr);
- pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_addr));
- if (verbose)
- fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr, pmd_val);
- if (!pmd_val)
- goto no_page;
- pmd_val &= PTE_PFN_PROT_MASK;
- pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PTE */
- FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
- pte_addr = pte_base + sizeof(pte_t) * pte_index_l5_4k(vaddr);
- pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_addr));
- if (verbose)
- fprintf(fp, " PTE: %lx => %lx\n", pte_base, pte_val);
- if (!pte_val)
- goto no_page;
- pte_val &= PTE_PFN_PROT_MASK;
- pte_pfn = pte_val >> _PAGE_PFN_SHIFT;
-
- if (!(pte_val & _PAGE_PRESENT)) {
- if (verbose) {
- fprintf(fp, "\n");
- riscv64_translate_pte((ulong)pte_val, 0, 0);
- }
- printf("!_PAGE_PRESENT\n");
- return FALSE;
- }
-
- *paddr = PTOB(pte_pfn) + PAGEOFFSET(vaddr);
-
- if (verbose) {
- fprintf(fp, " PAGE: %016lx\n\n", PAGEBASE(*paddr));
- riscv64_translate_pte(pte_val, 0, 0);
- }
-
- return TRUE;
-no_page:
- fprintf(fp, "invalid for %lx address\n", vaddr);
- return FALSE;
-}
-
static int
riscv64_init_active_task_regs(void)
{
@@ -1604,11 +1576,11 @@ riscv64_uvtop(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verb
switch (machdep->flags & VM_FLAGS)
{
case VM_L3_4K:
- return riscv64_vtop_3level_4k(pgd, uvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k(pgd, uvaddr, paddr, verbose, 3);
case VM_L4_4K:
- return riscv64_vtop_4level_4k(pgd, uvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k(pgd, uvaddr, paddr, verbose, 4);
case VM_L5_4K:
- return riscv64_vtop_5level_4k(pgd, uvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k(pgd, uvaddr, paddr, verbose, 5);
default:
return FALSE;
}
@@ -1663,11 +1635,11 @@ riscv64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verb
switch (machdep->flags & VM_FLAGS)
{
case VM_L3_4K:
- return riscv64_vtop_3level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose, 3);
case VM_L4_4K:
- return riscv64_vtop_4level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose, 4);
case VM_L5_4K:
- return riscv64_vtop_5level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose, 5);
default:
return FALSE;
}
--
2.27.0
2 weeks, 5 days
[PATCH] riscv64: add get_kvaddr_ranges support
by Wang Yechao
From: yuandong <yuan.dong1(a)zte.com.cn>
The common virtual address search code relies on the architecture-specific
get_kvaddr_ranges callback to identify kernel virtual address regions.
RISC-V does not currently provide this callback, so commands using the
kernel virtual address range table cannot classify these regions correctly.
Implement riscv64_get_kvaddr_ranges() to report the linear mapping, kernel
mapping, vmalloc, module, and vmemmap ranges. Sort the ranges by their
starting virtual addresses before returning them to the common code.
This enables kernel virtual address range based operations to work
correctly on RISC-V.
Signed-off-by: yuandong <yuan.dong1(a)zte.com.cn>
---
riscv64.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/riscv64.c b/riscv64.c
index f0783d5..77a7bb6 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -38,6 +38,7 @@ static void riscv64_overflow_stack_init(void);
static void riscv64_stackframe_init(void);
static void riscv64_back_trace_cmd(struct bt_info *bt);
static int riscv64_eframe_search(struct bt_info *bt);
+static int riscv64_get_kvaddr_ranges(struct vaddr_range *);
static int riscv64_get_dumpfile_stack_frame(struct bt_info *bt,
ulong *nip, ulong *ksp);
static void riscv64_get_stack_frame(struct bt_info *bt, ulong *pcp,
@@ -262,6 +263,7 @@ riscv64_dump_machdep_table(ulong arg)
fprintf(fp, " bits: %d\n", machdep->bits);
fprintf(fp, " back_trace: riscv64_back_trace_cmd()\n");
fprintf(fp, " eframe_search: riscv64_eframe_search()\n");
+ fprintf(fp, " get_kvaddr_ranges: riscv64_get_kvaddr_ranges\n");
fprintf(fp, " processor_speed: riscv64_processor_speed()\n");
fprintf(fp, " uvtop: riscv64_uvtop()\n");
fprintf(fp, " kvtop: riscv64_kvtop()\n");
@@ -1734,6 +1736,7 @@ riscv64_init(int when)
machdep->get_stack_frame = riscv64_get_stack_frame;
machdep->back_trace = riscv64_back_trace_cmd;
machdep->eframe_search = riscv64_eframe_search;
+ machdep->get_kvaddr_ranges = riscv64_get_kvaddr_ranges;
machdep->vmalloc_start = riscv64_vmalloc_start;
machdep->processor_speed = riscv64_processor_speed;
@@ -2010,6 +2013,52 @@ riscv64_eframe_search(struct bt_info *bt)
return count;
}
+static int
+compare_kvaddr(const void *v1, const void *v2)
+{
+ struct vaddr_range *r1, *r2;
+
+ r1 = (struct vaddr_range *)v1;
+ r2 = (struct vaddr_range *)v2;
+
+ return (r1->start < r2->start ? -1 :
+ r1->start == r2->start ? 0 : 1);
+}
+
+static int
+riscv64_get_kvaddr_ranges(struct vaddr_range *vrp)
+{
+ struct machine_specific *ms;
+ int cnt;
+
+ ms = machdep->machspec;
+ cnt = 0;
+
+ vrp[cnt].type = KVADDR_UNITY_MAP;
+ vrp[cnt].start = ms->page_offset;
+ vrp[cnt++].end = vt->high_memory;
+
+ vrp[cnt].type = KVADDR_START_MAP;
+ vrp[cnt].start = ms->kernel_link_addr;
+ vrp[cnt++].end = kt->end;
+
+ vrp[cnt].type = KVADDR_VMALLOC;
+ vrp[cnt].start = ms->vmalloc_start_addr;
+ vrp[cnt++].end = ms->vmalloc_end;
+
+ vrp[cnt].type = KVADDR_MODULES;
+ vrp[cnt].start = ms->modules_vaddr;
+ vrp[cnt++].end = ms->modules_end;
+
+ vrp[cnt].type = KVADDR_VMEMMAP;
+ vrp[cnt].start = ms->vmemmap_vaddr;
+ vrp[cnt++].end = ms->vmemmap_end;
+
+ qsort(vrp, cnt, sizeof(struct vaddr_range), compare_kvaddr);
+
+ return cnt;
+}
+
#else /* !RISCV64 */
void
--
2.27.0
2 weeks, 6 days
[PATCH] riscv64: support leaf PTEs in page table walks
by Wang Yechao
From: yuandong <yuan.dong1(a)zte.com.cn>
The existing RISC-V virtual-to-physical address walkers descend to the
last-level PTE unconditionally. This fails when an upper-level entry is
a leaf mapping, as used for huge pages.
Replace the separate Sv39, Sv48, and Sv57 page-table walkers with a
common n-level implementation. Detect leaf entries at every level,
calculate the physical address using the level-specific page offset,
and reject misaligned leaf entries.
This allows kvtop and uvtop to translate upper-level leaf mappings
while retaining support for normal 4 KiB pages.
Signed-off-by: yuandong <yuan.dong1(a)zte.com.cn>
---
defs.h | 2 +
riscv64.c | 426 +++++++++++++++++++++++++-----------------------------
2 files changed, 201 insertions(+), 227 deletions(-)
diff --git a/defs.h b/defs.h
index a4f70b7..def33d8 100644
--- a/defs.h
+++ b/defs.h
@@ -3800,6 +3800,8 @@ typedef signed int s32;
#define VM_L5_1G (0x200)
#define IRQ_STACKS (0x400)
#define OVERFLOW_STACKS (0x800)
+#define RISCV64_PTE_LEAF(pte) \
+ ((pte) & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC))
#define RISCV64_OVERFLOW_STACK_SIZE (1 << 12)
diff --git a/riscv64.c b/riscv64.c
index f0783d5..9b0d8d3 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -19,12 +19,8 @@
#include <math.h>
static ulong riscv64_get_page_size(void);
-static int riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr,
- physaddr_t *paddr, int verbose);
-static int riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr,
- physaddr_t *paddr, int verbose);
-static int riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr,
- physaddr_t *paddr, int verbose);
+static int riscv64_vtop_nlevel_4k(ulong *pgd, ulong vaddr,
+ physaddr_t *paddr, int verbose, int levels);
static void riscv64_page_type_init(void);
static int riscv64_is_kvaddr(ulong vaddr);
static int riscv64_is_uvaddr(ulong vaddr, struct task_context *tc);
@@ -634,66 +630,208 @@ riscv64_page_type_init(void)
}
}
+static ulong
+riscv64_vtop_index(ulong vaddr, int levels, int level)
+{
+ switch (levels) {
+ case 3:
+ switch (level) {
+ case 2:
+ return pgd_index_l3_4k(vaddr);
+ case 1:
+ return pmd_index_l3_4k(vaddr);
+ case 0:
+ return pte_index_l3_4k(vaddr);
+ }
+ break;
+
+ case 4:
+ switch (level) {
+ case 3:
+ return pgd_index_l4_4k(vaddr);
+ case 2:
+ return pud_index_l4_4k(vaddr);
+ case 1:
+ return pmd_index_l4_4k(vaddr);
+ case 0:
+ return pte_index_l4_4k(vaddr);
+ }
+ break;
+
+ case 5:
+ switch (level) {
+ case 4:
+ return pgd_index_l5_4k(vaddr);
+ case 3:
+ return p4d_index_l5_4k(vaddr);
+ case 2:
+ return pud_index_l5_4k(vaddr);
+ case 1:
+ return pmd_index_l5_4k(vaddr);
+ case 0:
+ return pte_index_l5_4k(vaddr);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static const char *
+riscv64_level_name(int levels, int level)
+{
+ if (level == levels - 1)
+ return "PGD";
+
+ if (level == 3)
+ return "P4D";
+
+ if (level == 2)
+ return "PUD";
+
+ if (level == 1)
+ return "PMD";
+
+ return "PTE";
+}
+
static int
-riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
+riscv64_pte_page_shift(int level)
{
- ulong *pgd_ptr, pgd_val;
- ulong pmd_base, pmd_addr, pmd_val;
- ulong pte_base, pte_addr, pte_val, pte_pfn;
+ switch (level) {
+ case 0:
+ return PAGESHIFT();
+ case 1:
+ return PMD_SHIFT;
+ case 2:
+ return PUD_SHIFT;
+ case 3:
+ return P4D_SHIFT;
+ case 4:
+ return PGD_SHIFT_L5;
+ default:
+ return PAGESHIFT();
+ }
+}
+
+static physaddr_t
+riscv64_pte_page_mask(int level)
+{
+ return ((physaddr_t)1 << riscv64_pte_page_shift(level)) - 1;
+}
+
+static physaddr_t
+riscv64_pte_paddr_base(ulong pte)
+{
+ pte &= PTE_PFN_PROT_MASK;
+ return PTOB(pte >> _PAGE_PFN_SHIFT);
+}
+
+static physaddr_t
+riscv64_pte_to_paddr(ulong pte, ulong vaddr, int level)
+{
+ physaddr_t base, mask;
+
+ base = riscv64_pte_paddr_base(pte);
+ mask = riscv64_pte_page_mask(level);
+
+ return base + (vaddr & mask);
+}
+
+static int
+riscv64_vtop_nlevel_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr,
+ int verbose, int levels)
+{
+ int level;
+ ulong index;
+ ulong entry_addr;
+ ulong pte;
+ ulong table_addr;
+ const char *name;
+
+ if (levels < 3 || levels > 5)
+ return FALSE;
+
+ *paddr = 0;
if (verbose)
fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
- /* PGD */
- pgd_ptr = pgd + pgd_index_l3_4k(vaddr);
- FILL_PGD(pgd, KVADDR, PAGESIZE());
- pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr));
- if (verbose)
- fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
- if (!pgd_val)
- goto no_page;
- pgd_val &= PTE_PFN_PROT_MASK;
- pmd_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PMD */
- FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
- pmd_addr = pmd_base + sizeof(pmd_t) * pmd_index_l3_4k(vaddr);
- pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_addr));
- if (verbose)
- fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr, pmd_val);
- if (!pmd_val)
- goto no_page;
- pmd_val &= PTE_PFN_PROT_MASK;
- pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PTE */
- FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
- pte_addr = pte_base + sizeof(pmd_t) * pte_index_l3_4k(vaddr);
- pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_addr));
- if (verbose)
- fprintf(fp, " PTE: %lx => %lx\n", pte_addr, pte_val);
- if (!pte_val)
- goto no_page;
- pte_val &= PTE_PFN_PROT_MASK;
- pte_pfn = pte_val >> _PAGE_PFN_SHIFT;
-
- if (!(pte_val & _PAGE_PRESENT)) {
- if (verbose) {
- fprintf(fp, "\n");
- riscv64_translate_pte((ulong)pte_val, 0, 0);
+ table_addr = (ulong)pgd;
+
+ for (level = levels - 1; level >= 0; level--) {
+ name = riscv64_level_name(levels, level);
+ index = riscv64_vtop_index(vaddr, levels, level);
+
+ if (level == levels - 1) {
+ FILL_PGD((ulong *)PAGEBASE(table_addr), KVADDR,
+ PAGESIZE());
+
+ entry_addr = table_addr + sizeof(ulong) * index;
+ pte = ULONG(machdep->pgd + PAGEOFFSET(entry_addr));
+ } else {
+ FILL_PTBL(PAGEBASE(table_addr), PHYSADDR,
+ PAGESIZE());
+
+ entry_addr = table_addr + sizeof(ulong) * index;
+ pte = ULONG(machdep->ptbl + PAGEOFFSET(entry_addr));
+ }
+
+ if (verbose)
+ fprintf(fp, " %s: %016lx => %016lx\n",
+ name, entry_addr, pte);
+
+ if (!pte)
+ goto no_page;
+
+ pte &= PTE_PFN_PROT_MASK;
+
+ if (!(pte & _PAGE_PRESENT)) {
+ if (verbose) {
+ fprintf(fp, "\n");
+ riscv64_translate_pte(pte, 0, 0);
+ }
+
+ fprintf(fp, " PAGE: %016lx not present\n\n",
+ PAGEBASE(vaddr));
+ return FALSE;
}
- fprintf(fp, " PAGE: %016lx not present\n\n", PAGEBASE(*paddr));
- return FALSE;
- }
- *paddr = PTOB(pte_pfn) + PAGEOFFSET(vaddr);
+ if (RISCV64_PTE_LEAF(pte)) {
+ physaddr_t base, mask;
- if (verbose) {
- fprintf(fp, " PAGE: %016lx\n\n", PAGEBASE(*paddr));
- riscv64_translate_pte(pte_val, 0, 0);
+ base = riscv64_pte_paddr_base(pte);
+ mask = riscv64_pte_page_mask(level);
+
+ if (level && (base & mask)) {
+ if (verbose) {
+ fprintf(fp, "\n");
+ riscv64_translate_pte(pte, 0, 0);
+ }
+
+ fprintf(fp,
+ " PAGE: %016lx invalid misaligned leaf pte\n\n",
+ PAGEBASE(vaddr));
+ return FALSE;
+ }
+
+ *paddr = riscv64_pte_to_paddr(pte, vaddr, level);
+
+ if (verbose) {
+ fprintf(fp, " PAGE: %016lx\n\n",
+ (ulong)(*paddr & ~mask));
+ riscv64_translate_pte(pte, 0, 0);
+ }
+
+ return TRUE;
+ }
+
+ if (level == 0)
+ goto no_page;
+
+ table_addr = (ulong)riscv64_pte_paddr_base(pte);
}
- return TRUE;
no_page:
fprintf(fp, "invalid for %lx address\n", vaddr);
return FALSE;
@@ -1214,172 +1352,6 @@ riscv64_get_frame(struct bt_info *bt, ulong *pcp, ulong *spp)
return TRUE;
}
-static int
-riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
-{
- ulong *pgd_ptr, pgd_val;
- ulong pud_base, pud_addr, pud_val;
- ulong pmd_base, pmd_addr, pmd_val;
- ulong pte_base, pte_addr, pte_val, pte_pfn;
-
- if (verbose)
- fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
-
- /* PGD */
- pgd_ptr = pgd + pgd_index_l4_4k(vaddr);
- FILL_PGD(pgd, KVADDR, PAGESIZE());
- pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr));
- if (verbose)
- fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
- if (!pgd_val)
- goto no_page;
- pgd_val &= PTE_PFN_PROT_MASK;
- pud_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PUD */
- FILL_PUD(PAGEBASE(pud_base), PHYSADDR, PAGESIZE());
- pud_addr = pud_base + sizeof(pud_t) * pud_index_l4_4k(vaddr);
- pud_val = ULONG(machdep->pud + PAGEOFFSET(pud_addr));
- if (verbose)
- fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr, pud_val);
- if (!pud_val)
- goto no_page;
- pud_val &= PTE_PFN_PROT_MASK;
- pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PMD */
- FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
- pmd_addr = pmd_base + sizeof(pmd_t) * pmd_index_l4_4k(vaddr);
- pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_addr));
- if (verbose)
- fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr, pmd_val);
- if (!pmd_val)
- goto no_page;
- pmd_val &= PTE_PFN_PROT_MASK;
- pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PTE */
- FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
- pte_addr = pte_base + sizeof(pte_t) * pte_index_l4_4k(vaddr);
- pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_addr));
- if (verbose)
- fprintf(fp, " PTE: %lx => %lx\n", pte_addr, pte_val);
- if (!pte_val)
- goto no_page;
- pte_val &= PTE_PFN_PROT_MASK;
- pte_pfn = pte_val >> _PAGE_PFN_SHIFT;
-
- if (!(pte_val & _PAGE_PRESENT)) {
- if (verbose) {
- fprintf(fp, "\n");
- riscv64_translate_pte((ulong)pte_val, 0, 0);
- }
- fprintf(fp, " PAGE: %016lx not present\n\n", PAGEBASE(*paddr));
- return FALSE;
- }
-
- *paddr = PTOB(pte_pfn) + PAGEOFFSET(vaddr);
-
- if (verbose) {
- fprintf(fp, " PAGE: %016lx\n\n", PAGEBASE(*paddr));
- riscv64_translate_pte(pte_val, 0, 0);
- }
-
- return TRUE;
-no_page:
- fprintf(fp, "invalid for %lx address\n", vaddr);
- return FALSE;
-}
-
-static int
-riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
-{
- ulong *pgd_ptr, pgd_val;
- ulong p4d_base, p4d_addr, p4d_val;
- ulong pud_base, pud_addr, pud_val;
- ulong pmd_base, pmd_addr, pmd_val;
- ulong pte_base, pte_addr, pte_val, pte_pfn;
-
- if (verbose)
- fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
-
- /* PGD */
- pgd_ptr = pgd + pgd_index_l5_4k(vaddr);
- FILL_PGD(pgd, KVADDR, PAGESIZE());
- pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr));
- if (verbose)
- fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
- if (!pgd_val)
- goto no_page;
- pgd_val &= PTE_PFN_PROT_MASK;
- p4d_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* P4D */
- FILL_P4D(PAGEBASE(p4d_base), PHYSADDR, PAGESIZE());
- p4d_addr = p4d_base + sizeof(p4d_t) * p4d_index_l5_4k(vaddr);
- p4d_val = ULONG(machdep->machspec->p4d + PAGEOFFSET(p4d_addr));
- if (verbose)
- fprintf(fp, " P4D: %016lx => %016lx\n", p4d_addr, p4d_val);
- if (!p4d_val)
- goto no_page;
- p4d_val &= PTE_PFN_PROT_MASK;
- pud_base = (p4d_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PUD */
- FILL_PUD(PAGEBASE(pud_base), PHYSADDR, PAGESIZE());
- pud_addr = pud_base + sizeof(pud_t) * pud_index_l5_4k(vaddr);
- pud_val = ULONG(machdep->pud + PAGEOFFSET(pud_addr));
- if (verbose)
- fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr, pud_val);
- if (!pud_val)
- goto no_page;
- pud_val &= PTE_PFN_PROT_MASK;
- pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PMD */
- FILL_PMD(PAGEBASE(pmd_base), PHYSADDR, PAGESIZE());
- pmd_addr = pmd_base + sizeof(pmd_t) * pmd_index_l5_4k(vaddr);
- pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_addr));
- if (verbose)
- fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr, pmd_val);
- if (!pmd_val)
- goto no_page;
- pmd_val &= PTE_PFN_PROT_MASK;
- pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
-
- /* PTE */
- FILL_PTBL(PAGEBASE(pte_base), PHYSADDR, PAGESIZE());
- pte_addr = pte_base + sizeof(pte_t) * pte_index_l5_4k(vaddr);
- pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_addr));
- if (verbose)
- fprintf(fp, " PTE: %lx => %lx\n", pte_base, pte_val);
- if (!pte_val)
- goto no_page;
- pte_val &= PTE_PFN_PROT_MASK;
- pte_pfn = pte_val >> _PAGE_PFN_SHIFT;
-
- if (!(pte_val & _PAGE_PRESENT)) {
- if (verbose) {
- fprintf(fp, "\n");
- riscv64_translate_pte((ulong)pte_val, 0, 0);
- }
- printf("!_PAGE_PRESENT\n");
- return FALSE;
- }
-
- *paddr = PTOB(pte_pfn) + PAGEOFFSET(vaddr);
-
- if (verbose) {
- fprintf(fp, " PAGE: %016lx\n\n", PAGEBASE(*paddr));
- riscv64_translate_pte(pte_val, 0, 0);
- }
-
- return TRUE;
-no_page:
- fprintf(fp, "invalid for %lx address\n", vaddr);
- return FALSE;
-}
-
static int
riscv64_init_active_task_regs(void)
{
@@ -1604,11 +1576,11 @@ riscv64_uvtop(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verb
switch (machdep->flags & VM_FLAGS)
{
case VM_L3_4K:
- return riscv64_vtop_3level_4k(pgd, uvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k(pgd, uvaddr, paddr, verbose, 3);
case VM_L4_4K:
- return riscv64_vtop_4level_4k(pgd, uvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k(pgd, uvaddr, paddr, verbose, 4);
case VM_L5_4K:
- return riscv64_vtop_5level_4k(pgd, uvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k(pgd, uvaddr, paddr, verbose, 5);
default:
return FALSE;
}
@@ -1663,11 +1635,11 @@ riscv64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verb
switch (machdep->flags & VM_FLAGS)
{
case VM_L3_4K:
- return riscv64_vtop_3level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose, 3);
case VM_L4_4K:
- return riscv64_vtop_4level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose, 4);
case VM_L5_4K:
- return riscv64_vtop_5level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose);
+ return riscv64_vtop_nlevel_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose, 5);
default:
return FALSE;
}
--
2.27.0
2 weeks, 6 days
[PATCH 1/2] Fix failure of "runq -g" option on Linux 7.2 and later kernels
by HAGIO KAZUHITO(萩尾 一仁)
From: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Kernel commit b8fea7af0e40 ("sched/fair: Allocate cfs_tg_state with
percpu allocator") changed task_group.cfs_rq from a pointer array to a
per-cpu variable allocated by the per-cpu allocator.
Without the patch, the "runq -g" option fails with the following error
on the first time, and with a segmentation fault on the second time.
crash> runq -g
CPU 0
CURRENT: PID: 5687 TASK: ffff8b0bc175a2c0 COMMAND: "bash"
ROOT_TASK_GROUP: ffffffff93a55600 CFS_RQ: 0
runq: invalid kernel virtual address: 58 type: "curr"
crash> runq -g
Segmentation fault (core dumped)
Since there is no way to determine whether it is a per-cpu variable,
check wthether it is a pointer array or not.
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
Hi,
I could not find a way to determine it's a __percpu variable or not,
any better ideas?
defs.h | 2 ++
kernel.c | 14 ++++++++++++++
symbols.c | 27 +++++++++++++++++++++++++++
task.c | 30 ++++++++++++++++++++++--------
4 files changed, 65 insertions(+), 8 deletions(-)
diff --git a/defs.h b/defs.h
index a4f70b773cd7..caa4faabb73e 100644
--- a/defs.h
+++ b/defs.h
@@ -691,6 +691,7 @@ struct new_utsname {
#define KMOD_PAX (0x100ULL)
#define KMOD_MEMORY (0x200ULL)
#define IRQ_DESC_TREE_MAPLE (0x400ULL)
+#define PER_CPU_CFS_RQ (0x800ULL)
#define XEN() (kt->flags & ARCH_XEN)
#define OPENVZ() (kt->flags & ARCH_OPENVZ)
@@ -5884,6 +5885,7 @@ void parse_for_member_extended(struct datatype_member *, ulong);
void add_to_downsized(char *);
int is_downsized(char *);
int is_string(char *, char *);
+int is_ptrptr(char *, char *);
struct syment *symbol_complete_match(const char *, struct syment *);
/*
diff --git a/kernel.c b/kernel.c
index eb9754c5e082..e53038d5d8db 100644
--- a/kernel.c
+++ b/kernel.c
@@ -400,6 +400,18 @@ kernel_init()
MEMBER_OFFSET_INIT(task_group_rt_rq, "task_group", "rt_rq");
MEMBER_OFFSET_INIT(task_group_parent, "task_group", "parent");
+ /*
+ * task_group.cfs_rq was changed from a pointer array to a per-cpu
+ * variable at Linux 7.2 (b8fea7af0e40). Since there is no way to
+ * determine it, we check whether it is a pointer array or not.
+ * - struct cfs_rq **cfs_rq;
+ * + struct cfs_rq __percpu *cfs_rq;
+ */
+ if (VALID_MEMBER(task_group_cfs_rq)) {
+ if (!is_ptrptr("task_group", "cfs_rq"))
+ kt->flags2 |= PER_CPU_CFS_RQ;
+ }
+
/*
* In 2.4, smp_send_stop() sets smp_num_cpus back to 1
* in some, but not all, architectures. So if a count
@@ -6362,6 +6374,8 @@ dump_kernel_table(int verbose)
fprintf(fp, "%sKMOD_PAX", others++ ? "|" : "");
if (kt->flags2 & KMOD_MEMORY)
fprintf(fp, "%sKMOD_MEMORY", others++ ? "|" : "");
+ if (kt->flags2 & PER_CPU_CFS_RQ)
+ fprintf(fp, "%sPER_CPU_CFS_RQ", others++ ? "|" : "");
fprintf(fp, ")\n");
fprintf(fp, " stext: %lx\n", kt->stext);
diff --git a/symbols.c b/symbols.c
index 78e400ba3756..03511c8cbe8c 100644
--- a/symbols.c
+++ b/symbols.c
@@ -7933,6 +7933,33 @@ is_string(char *structure, char *member)
return retval;
}
+int
+is_ptrptr(char *structure, char *member)
+{
+ int retval;
+ char *t;
+ char buf[BUFSIZE];
+
+ retval = FALSE;
+ open_tmpfile();
+ whatis_datatype(structure, STRUCT_REQUEST, pc->tmpfile);
+ rewind(pc->tmpfile);
+ while (fgets(buf, BUFSIZE, pc->tmpfile)) {
+ if (!(t = strstr(buf, "**")))
+ continue;
+ t += 2;
+ if (t != strstr(t, member))
+ continue;
+ t += strlen(member);
+ if (*t == ';') {
+ retval = TRUE;
+ break;
+ }
+ }
+ close_tmpfile();
+
+ return retval;
+}
/*
* Generic function for dumping data structure declarations, with a small
diff --git a/task.c b/task.c
index d7f3c129a709..5920d6499687 100644
--- a/task.c
+++ b/task.c
@@ -9464,8 +9464,12 @@ print_parent_task_group_fair(void *t, int cpu)
readmem(tgi->task_group + OFFSET(task_group_cfs_rq),
KVADDR, &cfs_rq_c, sizeof(ulong),
"task_group cfs_rq", FAULT_ON_ERROR);
- readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p,
- sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR);
+
+ if (kt->flags2 & PER_CPU_CFS_RQ)
+ cfs_rq_p = cfs_rq_c + kt->__per_cpu_offset[cpu];
+ else
+ readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p,
+ sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR);
print_group_header_fair(tgi->depth, cfs_rq_p, tgi);
tgi->use = 0;
@@ -9491,8 +9495,13 @@ dump_tasks_in_lower_dequeued_cfs_rq(int depth, ulong cfs_rq, int cpu,
readmem(tgi_array[i]->task_group + OFFSET(task_group_cfs_rq),
KVADDR, &cfs_rq_c, sizeof(ulong), "task_group cfs_rq",
FAULT_ON_ERROR);
- readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p,
- sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR);
+
+ if (kt->flags2 & PER_CPU_CFS_RQ)
+ cfs_rq_p = cfs_rq_c + kt->__per_cpu_offset[cpu];
+ else
+ readmem(cfs_rq_c + cpu * sizeof(ulong), KVADDR, &cfs_rq_p,
+ sizeof(ulong), "task_group cfs_rq", FAULT_ON_ERROR);
+
if (cfs_rq == cfs_rq_p)
continue;
@@ -10355,10 +10364,15 @@ dump_tasks_by_task_group(void)
readmem(rt_rq + cpu * sizeof(ulong), KVADDR,
&rt_rq_p, sizeof(ulong), "task_group rt_rq",
FAULT_ON_ERROR);
- if (cfs_rq)
- readmem(cfs_rq + cpu * sizeof(ulong), KVADDR,
- &cfs_rq_p, sizeof(ulong), "task_group cfs_rq",
- FAULT_ON_ERROR);
+ if (cfs_rq) {
+ if (kt->flags2 & PER_CPU_CFS_RQ)
+ cfs_rq_p = cfs_rq + kt->__per_cpu_offset[cpu];
+ else
+ readmem(cfs_rq + cpu * sizeof(ulong), KVADDR,
+ &cfs_rq_p, sizeof(ulong),
+ "task_group cfs_rq", FAULT_ON_ERROR);
+ }
+
fprintf(fp, "%sCPU %d", displayed++ ? "\n" : "", cpu);
if (hide_offline_cpu(cpu)) {
--
2.31.1
1 month
[PATCH] task: Introduce -Y option to ps command to display scheduling policy and priority
by Aaron Tomlin
Adds a new option '-Y' to the 'ps' command to print scheduling policy
(e.g., NORMAL, FIFO, RR, etc.) and dynamic priority (prio) for each
task.
Signed-off-by: Aaron Tomlin <atomlin(a)atomlin.com>
---
Hi Tao, Hagio, Lianbo,
Please note that this patch has a dependencies on [PATCH] task: Introduce
-I option to ps command to exclude idle tasks [1].
Thank you,
[1]: https://lists.crash-utility.osci.io/archives/list/devel@lists.crash-utili...
defs.h | 3 ++-
help.c | 3 ++-
task.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 68 insertions(+), 4 deletions(-)
diff --git a/defs.h b/defs.h
index 80cc215..1ee8744 100644
--- a/defs.h
+++ b/defs.h
@@ -5404,8 +5404,9 @@ extern long _ZOMBIE_;
#define PS_POLICY (0x80000)
#define PS_ACTIVE (0x100000)
#define PS_EXCLUDE_IDLE (0x200000)
+#define PS_POLICY_DATA (0x400000)
-#define PS_EXCLUSIVE (PS_TGID_LIST|PS_ARGV_ENVP|PS_TIMES|PS_CHILD_LIST|PS_PPID_LIST|PS_LAST_RUN|PS_RLIMIT|PS_MSECS|PS_SUMMARY|PS_ACTIVE)
+#define PS_EXCLUSIVE (PS_TGID_LIST|PS_ARGV_ENVP|PS_TIMES|PS_CHILD_LIST|PS_PPID_LIST|PS_LAST_RUN|PS_RLIMIT|PS_MSECS|PS_SUMMARY|PS_ACTIVE|PS_POLICY_DATA)
#define MAX_PS_ARGS (100) /* maximum command-line specific requests */
diff --git a/help.c b/help.c
index c88797e..79bfa5b 100644
--- a/help.c
+++ b/help.c
@@ -1392,7 +1392,7 @@ NULL
char *help_ps[] = {
"ps",
"display process status information",
-"[-k|-u|-G|-I|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A|-H]\n [pid | task | command] ...",
+"[-k|-u|-G|-I|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A|-H|-Y]\n [pid | task | command] ...",
" This command displays process status for selected, or all, processes" ,
" in the system. If no arguments are entered, the process data is",
" is displayed for all processes. Specific processes may be selected",
@@ -1473,6 +1473,7 @@ char *help_ps[] = {
" -S display a summary consisting of the number of tasks in a task state.",
" -A display only the active task on each cpu.",
" -H display no header line.",
+" -Y display the task's scheduling policy and priority.",
"\nEXAMPLES",
" Show the process status of all current tasks:\n",
" %s> ps",
diff --git a/task.c b/task.c
index 25b929d..2a312de 100644
--- a/task.c
+++ b/task.c
@@ -118,6 +118,8 @@ static void parse_task_thread(int argcnt, char *arglist[], struct task_context *
static void stack_overflow_check_init(void);
static int has_sched_policy(ulong, ulong);
static ulong task_policy(ulong);
+static const char *task_policy_name(ulong);
+static int task_prio(ulong);
static ulong sched_policy_bit_from_str(const char *);
static ulong make_sched_policy(const char *);
void crash_get_current_task_info(unsigned long *, char **);
@@ -3534,7 +3536,7 @@ cmd_ps(void)
cpuspec = NULL;
flag = 0;
- while ((c = getopt(argcnt, args, "HAISgstcpkuGlmarC:y:")) != EOF) {
+ while ((c = getopt(argcnt, args, "HAISgstcpkuGlmarC:y:Y")) != EOF) {
switch(c)
{
case 'k':
@@ -3649,6 +3651,11 @@ cmd_ps(void)
flag |= PS_EXCLUDE_IDLE;
break;
+ case 'Y':
+ check_ps_exclusive(flag, PS_POLICY_DATA);
+ flag |= PS_POLICY_DATA;
+ break;
+
case 'H':
flag |= PS_NO_HEADER;
break;
@@ -3822,6 +3829,31 @@ show_ps_data(ulong flag, struct task_context *tc, struct psinfo *psi)
}
}
+ if (flag & PS_POLICY_DATA) {
+ task_active = is_task_active(tc->task);
+
+ if (task_active) {
+ if (hide_offline_cpu(tc->processor))
+ fprintf(fp, "- ");
+ else
+ fprintf(fp, "> ");
+ } else
+ fprintf(fp, " ");
+
+ fprintf(fp, "%7ld %7ld %3s %s %-12s %4d ",
+ tc->pid, task_to_pid(tc->ptask),
+ task_cpu(tc->processor, buf2, !VERBOSE),
+ task_pointer_string(tc, flag & PS_KSTACKP, buf3),
+ task_policy_name(tc->task),
+ task_prio(tc->task));
+
+ if (is_kernel_thread(tc->task))
+ fprintf(fp, "[%s]\n", tc->comm);
+ else
+ fprintf(fp, "%s\n", tc->comm);
+ return;
+ }
+
if (flag & PS_PPID_LIST) {
parent_list(tc->task);
fprintf(fp, "\n");
@@ -3902,6 +3934,14 @@ show_ps(ulong flag, struct psinfo *psi)
mkstring(buf, VADDR_PRLEN, CENTER|RJUST, "KSTACKP") :
mkstring(buf, VADDR_PRLEN, CENTER, "TASK"));
+ if ((flag & PS_POLICY_DATA) && !(flag & PS_NO_HEADER)) {
+ fprintf(fp,
+ " PID PPID CPU %s POLICY PRIO COMM\n",
+ flag & PS_KSTACKP ?
+ mkstring(buf, VADDR_PRLEN, CENTER|RJUST, "KSTACKP") :
+ mkstring(buf, VADDR_PRLEN, CENTER, "TASK"));
+ }
+
if (flag & PS_SHOW_ALL) {
if (flag & PS_TIMES) {
@@ -3994,7 +4034,7 @@ show_ps_summary(ulong flag)
char string[3];
} ps_state[MAX_STATES];
- if (flag & (PS_USER|PS_KERNEL|PS_GROUP|PS_EXCLUDE_IDLE))
+ if (flag & (PS_USER|PS_KERNEL|PS_GROUP|PS_EXCLUDE_IDLE|PS_POLICY_DATA))
error(FATAL, "-S option cannot be used with other options\n");
for (s = 0; s < MAX_STATES; s++)
@@ -6050,6 +6090,28 @@ task_policy(ulong task)
return policy;
}
+static const char *
+task_policy_name(ulong task)
+{
+ ulong policy_bit = task_policy(task);
+ struct sched_policy_info *info;
+
+ for (info = sched_policy_info; info->name; info++) {
+ if (policy_bit == (1UL << info->value))
+ return info->name;
+ }
+ return "UNKNOWN";
+}
+
+static int
+task_prio(ulong task)
+{
+ fill_task_struct(task);
+ if (!tt->last_task_read || INVALID_MEMBER(task_struct_prio))
+ return 0;
+ return INT(tt->task_struct + OFFSET(task_struct_prio));
+}
+
/*
* Return a task's tgid.
*/
base-commit: 6b6d58159fedf7ca355d49b867bb3b88d4708a55
--
2.54.0
1 month
[PATCH] task: Introduce -I option to ps command to exclude idle tasks
by Aaron Tomlin
Adds a new option '-I' to the 'ps' command to filter out idle
threads/tasks from the output. This filters out the idle tasks from the
main ps list, CPU-specific block lists, and task time reports, while
enforcing mutual exclusivity with the summary (-S) option.
Signed-off-by: Aaron Tomlin <atomlin(a)atomlin.com>
---
defs.h | 1 +
help.c | 3 ++-
task.c | 32 ++++++++++++++++++++++++--------
3 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/defs.h b/defs.h
index a4f70b7..80cc215 100644
--- a/defs.h
+++ b/defs.h
@@ -5403,6 +5403,7 @@ extern long _ZOMBIE_;
#define PS_SUMMARY (0x40000)
#define PS_POLICY (0x80000)
#define PS_ACTIVE (0x100000)
+#define PS_EXCLUDE_IDLE (0x200000)
#define PS_EXCLUSIVE (PS_TGID_LIST|PS_ARGV_ENVP|PS_TIMES|PS_CHILD_LIST|PS_PPID_LIST|PS_LAST_RUN|PS_RLIMIT|PS_MSECS|PS_SUMMARY|PS_ACTIVE)
diff --git a/help.c b/help.c
index 5cd5c30..c88797e 100644
--- a/help.c
+++ b/help.c
@@ -1392,7 +1392,7 @@ NULL
char *help_ps[] = {
"ps",
"display process status information",
-"[-k|-u|-G|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A|-H]\n [pid | task | command] ...",
+"[-k|-u|-G|-I|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A|-H]\n [pid | task | command] ...",
" This command displays process status for selected, or all, processes" ,
" in the system. If no arguments are entered, the process data is",
" is displayed for all processes. Specific processes may be selected",
@@ -1409,6 +1409,7 @@ char *help_ps[] = {
" -k restrict the output to only kernel threads.",
" -u restrict the output to only user tasks.",
" -G display only the thread group leader in a thread group.",
+" -I exclude idle threads/tasks from the output.",
" -y policy restrict the output to tasks having a specified scheduling policy",
" expressed by its integer value or by its (case-insensitive) name;",
" multiple policies may be entered in a comma-separated list:",
diff --git a/task.c b/task.c
index d7f3c12..25b929d 100644
--- a/task.c
+++ b/task.c
@@ -107,8 +107,8 @@ static void foreach_cleanup(void *);
static void ps_cleanup(void *);
static char *task_pointer_string(struct task_context *, ulong, char *);
static int panic_context_adjusted(struct task_context *tc);
-static void show_last_run(struct task_context *, struct psinfo *);
-static void show_milliseconds(struct task_context *, struct psinfo *);
+static void show_last_run(ulong, struct task_context *, struct psinfo *);
+static void show_milliseconds(ulong, struct task_context *, struct psinfo *);
static char *translate_nanoseconds(ulonglong, char *);
static int sort_by_last_run(const void *arg1, const void *arg2);
static void sort_context_array_by_last_run(void);
@@ -3534,7 +3534,7 @@ cmd_ps(void)
cpuspec = NULL;
flag = 0;
- while ((c = getopt(argcnt, args, "HASgstcpkuGlmarC:y:")) != EOF) {
+ while ((c = getopt(argcnt, args, "HAISgstcpkuGlmarC:y:")) != EOF) {
switch(c)
{
case 'k':
@@ -3645,6 +3645,10 @@ cmd_ps(void)
flag |= PS_ACTIVE;
break;
+ case 'I':
+ flag |= PS_EXCLUDE_IDLE;
+ break;
+
case 'H':
flag |= PS_NO_HEADER;
break;
@@ -3794,6 +3798,8 @@ show_ps_data(ulong flag, struct task_context *tc, struct psinfo *psi)
return;
if ((flag & PS_POLICY) && !has_sched_policy(tc->task, psi->policy))
return;
+ if (tc && (flag & PS_EXCLUDE_IDLE) && is_idle_thread(tc->task))
+ return;
if (flag & PS_GROUP) {
if (flag & (PS_LAST_RUN|PS_MSECS))
error(FATAL, "-G not supported with -%c option\n",
@@ -3827,11 +3833,11 @@ show_ps_data(ulong flag, struct task_context *tc, struct psinfo *psi)
return;
}
if (flag & (PS_LAST_RUN)) {
- show_last_run(tc, psi);
+ show_last_run(flag, tc, psi);
return;
}
if (flag & (PS_MSECS)) {
- show_milliseconds(tc, psi);
+ show_milliseconds(flag, tc, psi);
return;
}
if (flag & PS_ARGV_ENVP) {
@@ -3988,7 +3994,7 @@ show_ps_summary(ulong flag)
char string[3];
} ps_state[MAX_STATES];
- if (flag & (PS_USER|PS_KERNEL|PS_GROUP))
+ if (flag & (PS_USER|PS_KERNEL|PS_GROUP|PS_EXCLUDE_IDLE))
error(FATAL, "-S option cannot be used with other options\n");
for (s = 0; s < MAX_STATES; s++)
@@ -4023,7 +4029,7 @@ show_ps_summary(ulong flag)
* current state.
*/
static void
-show_last_run(struct task_context *tc, struct psinfo *psi)
+show_last_run(ulong flag, struct task_context *tc, struct psinfo *psi)
{
int i, c, others;
struct task_context *tcp;
@@ -4053,6 +4059,8 @@ show_last_run(struct task_context *tc, struct psinfo *psi)
for (i = 0; i < RUNNING_TASKS(); i++, tcp++) {
if (tcp->processor != c)
continue;
+ if ((flag & PS_EXCLUDE_IDLE) && is_idle_thread(tcp->task))
+ continue;
fprintf(fp, format, task_last_run(tcp->task));
fprintf(fp, "[%s] ",
task_state_string(tcp->task, buf, !VERBOSE));
@@ -4066,6 +4074,8 @@ show_last_run(struct task_context *tc, struct psinfo *psi)
} else {
tcp = FIRST_CONTEXT();
for (i = 0; i < RUNNING_TASKS(); i++, tcp++) {
+ if ((flag & PS_EXCLUDE_IDLE) && is_idle_thread(tcp->task))
+ continue;
fprintf(fp, format, task_last_run(tcp->task));
fprintf(fp, "[%s] ", task_state_string(tcp->task, buf, !VERBOSE));
print_task_header(fp, tcp, FALSE);
@@ -4104,7 +4114,7 @@ translate_nanoseconds(ulonglong value, char *buf)
* sched_info.last_arrival and its current state.
*/
static void
-show_milliseconds(struct task_context *tc, struct psinfo *psi)
+show_milliseconds(ulong flag, struct task_context *tc, struct psinfo *psi)
{
int i, c, others, days, max_days;
struct task_context *tcp;
@@ -4154,6 +4164,8 @@ show_milliseconds(struct task_context *tc, struct psinfo *psi)
for (i = 0; i < RUNNING_TASKS(); i++, tcp++) {
if (tcp->processor != c)
continue;
+ if ((flag & PS_EXCLUDE_IDLE) && is_idle_thread(tcp->task))
+ continue;
delta = rq_clock - task_last_run(tcp->task);
if (delta < 0)
delta = 0;
@@ -4188,6 +4200,8 @@ show_milliseconds(struct task_context *tc, struct psinfo *psi)
} else {
tcp = FIRST_CONTEXT();
for (i = 0; i < RUNNING_TASKS(); i++, tcp++) {
+ if ((flag & PS_EXCLUDE_IDLE) && is_idle_thread(tcp->task))
+ continue;
if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF))
runq = rq_sp->value +
kt->__per_cpu_offset[tcp->processor];
@@ -4562,6 +4576,8 @@ show_task_times(struct task_context *tcp, ulong flags)
continue;
if ((flags & PS_KERNEL) && !is_kernel_thread(tc->task))
continue;
+ if ((flags & PS_EXCLUDE_IDLE) && is_idle_thread(tc->task))
+ continue;
if (flags & PS_GROUP) {
tgid = task_tgid(tc->task);
if (tc->pid != tgid) {
--
2.54.0
1 month
[PATCH 0/3] RISC-V: Fix vtop warnings and improve kernel address range support
by Rui Qi
This series fixes two bugs and adds an enhancement for the riscv64
architecture support in the crash utility:
Patch 1 fixes spurious "WARNING: mem_map[] not accessible" messages
when running vtop or kmem -p on RISC-V. The root cause is that
riscv64.c never sets the VMEMMAP flag on machdep->flags, so crash
does not recognize that unmapped vmemmap holes are normal for
SPARSEMEM_VMEMMAP configurations.
Patch 2 fixes noisy "PAGE: not present" and "invalid for address"
output from the vtop page table walk functions. These messages are
printed unconditionally even when called non-verbosely by internal
routines like kmem -p or dump_mem_map. They should only appear
when verbose=1, consistent with all other diagnostic output in
these functions and with how x86_64/arm64 handle the same case.
Patch 3 adds an architecture-specific get_kvaddr_ranges callback
so that the search command can properly categorize kernel virtual
address regions including modules and vmemmap, instead of falling
back to the generic two-region default.
These patches were tested on a RISC-V 32-core machine with kernel
6.12.13.bsk.1-rc17-riscv64 and vmlinux ~700MB with debug info.
Rui Qi (3):
riscv64: Set VMEMMAP flag to fix spurious mem_map[] warnings
riscv64: Guard verbose output in vtop page table walk functions
riscv64: Add get_kvaddr_ranges callback for kernel address ranges
riscv64.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 62 insertions(+), 6 deletions(-)
--
2.20.1
1 month
[PATCH 0/6] LoongArch64: improve dumpfile stack unwinding
by Ming Wang
This series improves LoongArch64 stack unwinding for vmcore dumpfiles.
LoongArch exception entry code may run from relocated exception handler
areas rather than from the canonical vmlinux text address. Looking up
those runtime PCs directly can fail to resolve symbols such as
handle_vint, which also breaks ORC lookup and exception-frame handoff.
The series first fixes the exception return address label to report ERA,
then maps relocated exception vector PCs back to their canonical kernel
symbols. It then adds initial LoongArch64 ORC support for core kernel
text, and uses the saved IRQ-stack state to continue unwinding active
dumpfile tasks from IRQ stack back to task stack. The last two patches
tighten fallback RA handling and only print exception pt_regs with
bt -f.
Tested:
- Built each patch separately with make lzo -j4 on LoongArch64.
- Built the final tree with make -j4 on the X86_64.
- Verified kdump vmcore backtrace still shows the sysrq panic chain.
- Verified git diff --check d0ffcb681f06..HEAD.
Ming Wang (6):
LoongArch64: print exception return address as ERA
LoongArch64: resolve relocated exception vector addresses
LoongArch64: add initial ORC unwinder support
LoongArch64: unwind dumpfile active tasks from IRQ stacks
LoongArch64: avoid replacing a valid RA with stack noise
LoongArch64: print exception registers only with bt -f
defs.h | 27 ++
loongarch64.c | 689 ++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 695 insertions(+), 21 deletions(-)
--
2.43.0
1 month
[PATCH] arm64: Fix stack size and mask for 16KB pages
by Dean Liao
Dynamically configure machdep->stacksize based on page size.
Specifically, set it to 32KB for 16KB pages (default for CONFIG_ARM64_16K_PAGES)
and 64KB for 64KB pages, instead of using the hardcoded 16KB ARM64_STACK_SIZE.
Update arm64_unwind_frame and arm64_unwind_frame_v2 to use
machdep->stacksize for stack_mask calculation instead of ARM64_STACK_SIZE.
This fixes unwinding failures when the stack frame crosses the 16KB boundary
on a 32KB stack.
Signed-off-by: Dean Liao <deanliao(a)google.com>
---
arm64.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/arm64.c b/arm64.c
index d177092..3ce14aa 100644
--- a/arm64.c
+++ b/arm64.c
@@ -630,7 +630,22 @@ arm64_init(int when)
machdep->last_ptbl_read = 0;
machdep->clear_machdep_cache = arm64_clear_machdep_cache;
- machdep->stacksize = ARM64_STACK_SIZE;
+ /*
+ * Refer to arch/arm64/include/asm/memory.h in kernel source:
+ * THREAD_SIZE is PAGE_SIZE << THREAD_SIZE_ORDER.
+ * When CONFIG_VMAP_STACK is enabled, THREAD_SHIFT is at
+ * least PAGE_SHIFT.
+ * - 4KB pages -> 16KB stack (ARM64_STACK_SIZE)
+ * - 16KB pages -> 32KB stack (MIN_THREAD_SHIFT=15 if KASAN
+ * enabled, or Android default)
+ * - 64KB pages -> 64KB stack (THREAD_SHIFT=PAGE_SHIFT=16)
+ */
+ if (machdep->pagesize == 16384)
+ machdep->stacksize = 32768;
+ else if (machdep->pagesize == 65536)
+ machdep->stacksize = 65536;
+ else
+ machdep->stacksize = ARM64_STACK_SIZE;
machdep->flags |= VMEMMAP;
machdep->uvtop = arm64_uvtop;
machdep->is_uvaddr = arm64_is_uvaddr;
@@ -3311,7 +3326,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
struct arm64_pt_regs *ptregs;
struct machine_specific *ms = machdep->machspec;
- stack_mask = (unsigned long)(ARM64_STACK_SIZE) - 1;
+ stack_mask = machdep->stacksize - 1;
fp = frame->fp;
low = frame->sp;
@@ -3521,7 +3536,7 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
unsigned long irq_stack_ptr;
struct machine_specific *ms;
- stack_mask = (unsigned long)(ARM64_STACK_SIZE) - 1;
+ stack_mask = machdep->stacksize - 1;
fp = frame->fp;
low = frame->sp;
--
2.55.0.rc0.799.gd6f94ed593-goog
1 month, 1 week