[PATCH] riscv64: handle leaf page table entries in vtop
by Rui Qi
RISC-V page table entries at any level may be leaf entries when V is
set and any of R/W/X is set. The riscv64 vtop walkers currently treat
non-zero intermediate entries as pointers to the next page table, so a
PMD leaf can be used as a page table address and make vtop fail with a
physical seek error.
Detect leaf entries at PGD/P4D/PUD/PMD levels and translate them using
the page size implied by that level. Continue walking only for non-leaf
table entries.
Signed-off-by: Rui Qi <qirui.001(a)bytedance.com>
---
riscv64.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/riscv64.c b/riscv64.c
index 4dcecc2f6b2c..ca26965421d7 100644
--- a/riscv64.c
+++ b/riscv64.c
@@ -602,6 +602,33 @@ riscv64_translate_pte(ulong pte, void *physaddr, ulonglong unused)
return page_present;
}
+static int
+riscv64_pte_is_leaf(ulong pte)
+{
+ return ((pte & _PAGE_PRESENT) &&
+ (pte & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)));
+}
+
+static int
+riscv64_handle_leaf_pte(ulong pte, ulong vaddr, int shift,
+ physaddr_t *paddr, int verbose)
+{
+ physaddr_t paddr_base, page_mask;
+
+ pte &= PTE_PFN_PROT_MASK;
+ paddr_base = PTOB(pte >> _PAGE_PFN_SHIFT);
+ page_mask = ~(((physaddr_t)1 << shift) - 1);
+ *paddr = (paddr_base & page_mask) + (vaddr & ~page_mask);
+
+ if (verbose) {
+ fprintf(fp, " PAGE: %016llx\n\n",
+ (ulonglong)(*paddr & page_mask));
+ riscv64_translate_pte(pte, 0, 0);
+ }
+
+ return TRUE;
+}
+
static void
riscv64_page_type_init(void)
{
@@ -655,6 +682,9 @@ riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
if (!pgd_val)
goto no_page;
+ if (riscv64_pte_is_leaf(pgd_val))
+ return riscv64_handle_leaf_pte(pgd_val, vaddr,
+ PGD_SHIFT_L3, paddr, verbose);
pgd_val &= PTE_PFN_PROT_MASK;
pmd_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
@@ -666,6 +696,9 @@ riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr, pmd_val);
if (!pmd_val)
goto no_page;
+ if (riscv64_pte_is_leaf(pmd_val))
+ return riscv64_handle_leaf_pte(pmd_val, vaddr,
+ PMD_SHIFT, paddr, verbose);
pmd_val &= PTE_PFN_PROT_MASK;
pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
@@ -1237,6 +1270,9 @@ riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
if (!pgd_val)
goto no_page;
+ if (riscv64_pte_is_leaf(pgd_val))
+ return riscv64_handle_leaf_pte(pgd_val, vaddr,
+ PGD_SHIFT_L4, paddr, verbose);
pgd_val &= PTE_PFN_PROT_MASK;
pud_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
@@ -1248,6 +1284,9 @@ riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr, pud_val);
if (!pud_val)
goto no_page;
+ if (riscv64_pte_is_leaf(pud_val))
+ return riscv64_handle_leaf_pte(pud_val, vaddr,
+ PUD_SHIFT, paddr, verbose);
pud_val &= PTE_PFN_PROT_MASK;
pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
@@ -1259,6 +1298,9 @@ riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr, pmd_val);
if (!pmd_val)
goto no_page;
+ if (riscv64_pte_is_leaf(pmd_val))
+ return riscv64_handle_leaf_pte(pmd_val, vaddr,
+ PMD_SHIFT, paddr, verbose);
pmd_val &= PTE_PFN_PROT_MASK;
pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
@@ -1316,6 +1358,9 @@ riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
if (!pgd_val)
goto no_page;
+ if (riscv64_pte_is_leaf(pgd_val))
+ return riscv64_handle_leaf_pte(pgd_val, vaddr,
+ PGD_SHIFT_L5, paddr, verbose);
pgd_val &= PTE_PFN_PROT_MASK;
p4d_base = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
@@ -1327,6 +1372,9 @@ riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, " P4D: %016lx => %016lx\n", p4d_addr, p4d_val);
if (!p4d_val)
goto no_page;
+ if (riscv64_pte_is_leaf(p4d_val))
+ return riscv64_handle_leaf_pte(p4d_val, vaddr,
+ P4D_SHIFT, paddr, verbose);
p4d_val &= PTE_PFN_PROT_MASK;
pud_base = (p4d_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
@@ -1338,6 +1386,9 @@ riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, " PUD: %016lx => %016lx\n", pud_addr, pud_val);
if (!pud_val)
goto no_page;
+ if (riscv64_pte_is_leaf(pud_val))
+ return riscv64_handle_leaf_pte(pud_val, vaddr,
+ PUD_SHIFT, paddr, verbose);
pud_val &= PTE_PFN_PROT_MASK;
pmd_base = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
@@ -1349,6 +1400,9 @@ riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, " PMD: %016lx => %016lx\n", pmd_addr, pmd_val);
if (!pmd_val)
goto no_page;
+ if (riscv64_pte_is_leaf(pmd_val))
+ return riscv64_handle_leaf_pte(pmd_val, vaddr,
+ PMD_SHIFT, paddr, verbose);
pmd_val &= PTE_PFN_PROT_MASK;
pte_base = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT();
--
2.20.1
4 days, 8 hours
[PATCH] kmem: Show page migration types
by Aaron Tomlin
Modify the "kmem" command to query and display the migration type of
pages and page blocks:
- Appending the migration type string (e.g., Unmovable, Movable,
Reclaimable, HighAtomic, CMA, Isolate) to the output of page flags
in kmem -p
- Showing the migration type for each free area sublist in kmem -f
and kmem -F when multiple lists are present per area
To support this, offsets and sizes for mem_section_usage,
mem_section_usage_pageblock_flags, and zone_pageblock_flags are
retrieved and cached. The pageblock flags bitmap is then parsed to
extract the migration type of each page block, matching the logic in the
Linux kernel buddy allocator.
An example excerpt of kmem -f is provided below:
ZONE NAME SIZE FREE MEM_MAP START_PADDR START_MAPNR
2 Normal 3680256 2752702 ffffedd284000000 100000000 1048575
AREA SIZE TYPE FREE_AREA_STRUCT BLOCKS PAGES
0 4k Unmovable ffff8a0b827d5f00 232 232
0 4k Movable ffff8a0b827d5f10 44 44
0 4k Reclaimable ffff8a0b827d5f20 0 0
0 4k HighAtomic ffff8a0b827d5f30 0 0
0 4k CMA ffff8a0b827d5f40 0 0
0 4k Isolate ffff8a0b827d5f50 0 0
1 8k Unmovable ffff8a0b827d5f68 382 764
1 8k Movable ffff8a0b827d5f78 104 208
1 8k Reclaimable ffff8a0b827d5f88 1 2
1 8k HighAtomic ffff8a0b827d5f98 0 0
Signed-off-by: Aaron Tomlin <atomlin(a)atomlin.com>
---
defs.h | 4 +
memory.c | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++---
symbols.c | 8 ++
3 files changed, 230 insertions(+), 10 deletions(-)
diff --git a/defs.h b/defs.h
index 1ee8744..ec8cc37 100644
--- a/defs.h
+++ b/defs.h
@@ -2108,6 +2108,9 @@ struct offset_table { /* stash of commonly-used offsets */
long memory_block_state;
long memory_block_nid;
long mem_section_pageblock_flags;
+ long mem_section_usage;
+ long mem_section_usage_pageblock_flags;
+ long zone_pageblock_flags;
long bus_type_p;
long device_private_device;
long device_private_knode_bus;
@@ -2389,6 +2392,7 @@ struct size_table { /* stash of commonly-used sizes */
long task_struct_start_time;
long cputime_t;
long mem_section;
+ long mem_section_usage;
long pid_link;
long unwind_table;
long rlimit;
diff --git a/memory.c b/memory.c
index 3f3aa27..7ed59a4 100644
--- a/memory.c
+++ b/memory.c
@@ -171,6 +171,10 @@ static int get_bitfield_data(struct integer_data *);
static int show_page_member_data(char *, ulong, struct meminfo *, char *);
static void dump_mem_map(struct meminfo *);
static void dump_mem_map_SPARSEMEM(struct meminfo *);
+static ulong find_pfn_zone(ulong);
+static ulong get_pageblock_bitmap(ulong);
+static char *get_migratetype_name(int);
+static char *get_page_migration_type_str(physaddr_t);
static void fill_mem_map_cache(ulong, ulong, char *);
static void page_flags_init(void);
static int page_flags_init_from_pageflag_names(void);
@@ -1255,6 +1259,8 @@ vm_init(void)
"zone", "zone_start_pfn");
MEMBER_OFFSET_INIT(zone_spanned_pages,
"zone", "spanned_pages");
+ MEMBER_OFFSET_INIT(zone_pageblock_flags,
+ "zone", "pageblock_flags");
MEMBER_OFFSET_INIT(zone_present_pages,
"zone", "present_pages");
MEMBER_OFFSET_INIT(zone_pages_min,
@@ -6115,10 +6121,19 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
bufferindex += sprintflag("%sreserved");
bufferindex += sprintf(outputbuffer+bufferindex, "\n");
} else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
- if (vt->flags & PAGEFLAGS)
+ char *mig_type = get_page_migration_type_str(phys);
+ if (vt->flags & PAGEFLAGS) {
bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
- else
- bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
+ if (strlen(mig_type) > 0 && bufferindex > 0 && outputbuffer[bufferindex-1] == '\n') {
+ bufferindex--;
+ bufferindex += sprintf(outputbuffer+bufferindex, " (%s)\n", mig_type);
+ }
+ } else {
+ if (strlen(mig_type) > 0)
+ bufferindex += sprintf(outputbuffer+bufferindex, "%lx (%s)\n", flags, mig_type);
+ else
+ bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
+ }
} else {
if ((flags >> v24_PG_locked) & 1)
@@ -6215,6 +6230,170 @@ display_members:
FREEBUF(page_cache);
}
+static ulong
+find_pfn_zone(ulong pfn)
+{
+ int n, i;
+ struct node_table *nt;
+ ulong node_zones;
+ ulong zone_start_pfn = 0, spanned_pages = 0;
+
+ if (INVALID_MEMBER(pglist_data_node_zones) ||
+ INVALID_MEMBER(zone_zone_start_pfn) ||
+ INVALID_MEMBER(zone_spanned_pages))
+ return 0;
+
+ for (n = 0; n < vt->numnodes; n++) {
+ nt = &vt->node_table[n];
+ node_zones = nt->pgdat + OFFSET(pglist_data_node_zones);
+
+ for (i = 0; i < vt->nr_zones; i++) {
+ if (!readmem(node_zones + OFFSET(zone_zone_start_pfn),
+ KVADDR, &zone_start_pfn, sizeof(ulong),
+ "zone zone_start_pfn", RETURN_ON_ERROR|QUIET))
+ goto next_zone;
+ if (!readmem(node_zones + OFFSET(zone_spanned_pages),
+ KVADDR, &spanned_pages, sizeof(ulong),
+ "zone spanned_pages", RETURN_ON_ERROR|QUIET))
+ goto next_zone;
+
+ if (pfn >= zone_start_pfn && pfn < zone_start_pfn + spanned_pages)
+ return node_zones;
+
+next_zone:
+ node_zones += SIZE(zone);
+ }
+ }
+ return 0;
+}
+
+static ulong
+get_pageblock_bitmap(ulong pfn)
+{
+ if (IS_SPARSEMEM()) {
+ ulong section_nr = pfn / PAGES_PER_SECTION();
+ ulong mem_section_addr = nr_to_section(section_nr);
+ if (!mem_section_addr)
+ return 0;
+
+ char *mem_section = read_mem_section(mem_section_addr);
+ if (!mem_section)
+ return 0;
+
+ if (VALID_MEMBER(mem_section_pageblock_flags)) {
+ return ULONG(mem_section + OFFSET(mem_section_pageblock_flags));
+ } else if (VALID_MEMBER(mem_section_usage)) {
+ ulong usage_addr = ULONG(mem_section + OFFSET(mem_section_usage));
+ if (!usage_addr)
+ return 0;
+ return usage_addr + OFFSET(mem_section_usage_pageblock_flags);
+ }
+ } else {
+ ulong zone_addr = find_pfn_zone(pfn);
+ if (zone_addr && VALID_MEMBER(zone_pageblock_flags)) {
+ ulong pageblock_flags_addr = 0;
+ if (readmem(zone_addr + OFFSET(zone_pageblock_flags),
+ KVADDR, &pageblock_flags_addr, sizeof(ulong),
+ "zone pageblock_flags", RETURN_ON_ERROR|QUIET)) {
+ return pageblock_flags_addr;
+ }
+ }
+ }
+ return 0;
+}
+
+static char *
+get_migratetype_name(int migratetype)
+{
+ static char name_buf[64];
+ ulong array_addr, string_addr;
+
+ if (kernel_symbol_exists("migratetype_names")) {
+ array_addr = symbol_value("migratetype_names") + migratetype * sizeof(void *);
+ if (readmem(array_addr, KVADDR, &string_addr, sizeof(void *), "migratetype_names entry", RETURN_ON_ERROR|QUIET)) {
+ if (read_string(string_addr, name_buf, sizeof(name_buf) - 1)) {
+ return name_buf;
+ }
+ }
+ }
+
+ switch (migratetype) {
+ case 0:
+ return "Unmovable";
+ case 1:
+ return "Movable";
+ case 2:
+ return "Reclaimable";
+ case 3:
+ return "HighAtomic";
+ case 4:
+ return "CMA";
+ case 5:
+ return "Isolate";
+ default:
+ sprintf(name_buf, "unknown_%d", migratetype);
+ return name_buf;
+ }
+}
+
+static char *
+get_page_migration_type_str(physaddr_t phys)
+{
+ ulong pfn = phys / PAGESIZE();
+ ulong pageblock_flags_addr = get_pageblock_bitmap(pfn);
+ if (!pageblock_flags_addr)
+ return "";
+
+ int nr_pageblock_bits = 4;
+ long pb_migrate_isolate = 0;
+ if (enumerator_value("PB_migrate_isolate", &pb_migrate_isolate)) {
+ nr_pageblock_bits = 8;
+ }
+
+ unsigned int pageblock_order = 10;
+ if (kernel_symbol_exists("pageblock_order")) {
+ get_symbol_data("pageblock_order", sizeof(unsigned int), &pageblock_order);
+ }
+
+ int bitidx;
+ if (IS_SPARSEMEM()) {
+ bitidx = ((pfn & (PAGES_PER_SECTION() - 1)) >> pageblock_order) * nr_pageblock_bits;
+ } else {
+ ulong zone_addr = find_pfn_zone(pfn);
+ ulong zone_start_pfn = 0;
+ if (zone_addr) {
+ if (!readmem(zone_addr + OFFSET(zone_zone_start_pfn),
+ KVADDR, &zone_start_pfn, sizeof(ulong),
+ "zone zone_start_pfn", RETURN_ON_ERROR|QUIET))
+ zone_start_pfn = 0;
+ }
+ bitidx = ((pfn - zone_start_pfn) >> pageblock_order) * nr_pageblock_bits;
+ }
+
+ ulong word_bitidx = bitidx / (sizeof(ulong) * 8);
+ bitidx &= ((sizeof(ulong) * 8) - 1);
+
+ ulong word_addr = pageblock_flags_addr + word_bitidx * sizeof(ulong);
+ ulong word = 0;
+ if (!readmem(word_addr, KVADDR, &word, sizeof(ulong), "pageblock_flags word", RETURN_ON_ERROR|QUIET)) {
+ return "";
+ }
+
+ int migratetype = (word >> bitidx) & 7;
+ if (nr_pageblock_bits == 8) {
+ int isolate_bit = 4;
+ if ((word >> (bitidx + isolate_bit)) & 1) {
+ long migrate_isolate = 0;
+ if (enumerator_value("MIGRATE_ISOLATE", &migrate_isolate))
+ migratetype = migrate_isolate;
+ else
+ migratetype = 5;
+ }
+ }
+
+ return get_migratetype_name(migratetype);
+}
+
static void
dump_mem_map(struct meminfo *mi)
{
@@ -6566,10 +6745,19 @@ dump_mem_map(struct meminfo *mi)
bufferindex += sprintflag("%sreserved");
bufferindex += sprintf(outputbuffer+bufferindex, "\n");
} else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
- if (vt->flags & PAGEFLAGS)
+ char *mig_type = get_page_migration_type_str(phys);
+ if (vt->flags & PAGEFLAGS) {
bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
- else
- bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
+ if (strlen(mig_type) > 0 && bufferindex > 0 && outputbuffer[bufferindex-1] == '\n') {
+ bufferindex--;
+ bufferindex += sprintf(outputbuffer+bufferindex, " (%s)\n", mig_type);
+ }
+ } else {
+ if (strlen(mig_type) > 0)
+ bufferindex += sprintf(outputbuffer+bufferindex, "%lx (%s)\n", flags, mig_type);
+ else
+ bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
+ }
} else {
if ((flags >> v24_PG_locked) & 1)
@@ -8412,8 +8600,12 @@ dump_zone_free_area(ulong free_area, int num, ulong verbose,
ld = &list_data;
- if (!verbose)
- fprintf(fp, "%s", free_area_hdr4);
+ if (!verbose) {
+ if (list_count > 1)
+ fprintf(fp, "AREA SIZE TYPE FREE_AREA_STRUCT BLOCKS PAGES\n");
+ else
+ fprintf(fp, "%s", free_area_hdr4);
+ }
total_free = 0;
flen = MAX(VADDR_PRLEN, strlen("FREE_AREA_STRUCT"));
@@ -8487,14 +8679,21 @@ multiple_lists:
for (j = 0, free_list = free_area; j < list_count;
j++, free_list += SIZE(list_head)) {
- if (verbose)
- fprintf(fp, "%s", free_area_hdr3);
+ if (verbose) {
+ if (list_count > 1)
+ fprintf(fp, "AREA SIZE TYPE FREE_AREA_STRUCT\n");
+ else
+ fprintf(fp, "%s", free_area_hdr3);
+ }
fprintf(fp, "%3d ", i);
chunk_size = power(2, i);
sprintf(buf, "%ldk", (chunk_size * PAGESIZE())/1024);
fprintf(fp, " %7s ", buf);
+ if (list_count > 1)
+ fprintf(fp, "%-12s ", get_migratetype_name(j));
+
readmem(free_list, KVADDR, free_list_buf,
SIZE(list_head), "free_area free_list",
FAULT_ON_ERROR);
@@ -17722,6 +17921,15 @@ sparse_mem_init(void)
MEMBER_OFFSET_INIT(mem_section_section_mem_map, "mem_section",
"section_mem_map");
+ if (MEMBER_EXISTS("mem_section", "pageblock_flags")) {
+ MEMBER_OFFSET_INIT(mem_section_pageblock_flags, "mem_section",
+ "pageblock_flags");
+ }
+ if (MEMBER_EXISTS("mem_section", "usage")) {
+ MEMBER_OFFSET_INIT(mem_section_usage, "mem_section", "usage");
+ STRUCT_SIZE_INIT(mem_section_usage, "mem_section_usage");
+ MEMBER_OFFSET_INIT(mem_section_usage_pageblock_flags, "mem_section_usage", "pageblock_flags");
+ }
if (!MAX_PHYSMEM_BITS())
error(FATAL,
diff --git a/symbols.c b/symbols.c
index 78e400b..2e3a797 100644
--- a/symbols.c
+++ b/symbols.c
@@ -11416,6 +11416,12 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(mem_section_section_mem_map));
fprintf(fp, " mem_section_pageblock_flags: %ld\n",
OFFSET(mem_section_pageblock_flags));
+ fprintf(fp, " mem_section_usage: %ld\n",
+ OFFSET(mem_section_usage));
+ fprintf(fp, "mem_section_usage_pageblock_flags: %ld\n",
+ OFFSET(mem_section_usage_pageblock_flags));
+ fprintf(fp, " zone_pageblock_flags: %ld\n",
+ OFFSET(zone_pageblock_flags));
fprintf(fp, " memory_block_dev: %ld\n",
OFFSET(memory_block_dev));
fprintf(fp, " memory_block_nid: %ld\n",
@@ -12158,6 +12164,8 @@ dump_offset_table(char *spec, ulong makestruct)
SIZE(cputime_t));
fprintf(fp, " mem_section: %ld\n",
SIZE(mem_section));
+ fprintf(fp, " mem_section_usage: %ld\n",
+ SIZE(mem_section_usage));
fprintf(fp, " pid_link: %ld\n",
SIZE(pid_link));
fprintf(fp, " upid: %ld\n",
--
2.55.0
4 days, 23 hours
[PATCH 1/2] loongarch64: fix SECTION_SIZE_BITS value
by Dave Young
The loongarch64 SECTION_SIZE_BITS does not match the mainline kernel code.
crash test failed with mem_section init failure due to access non exist
memory address for mem sections caused by wrong NR_SECTION_ROOTS
According to Wang Ming, there was some historic reason, upstream kernel
did not take the SECTION_SIZE_BITS 28, but 28 is still better. Downstream
kernels took the 28 as default.
Thus fix this by setting the related values first according to vmcoreinfo
And falling back to the 29 which aligns to current upstrem kernel.
Signed-off-by: Dave Young <yangrr.2009(a)tsinghua.org.cn>
---
[v1->v2: use vmcoreinfo exported value first]
[future work: share code between arches for converting str to number]
defs.h | 2 +-
loongarch64.c | 18 ++++++++++++++++--
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/defs.h b/defs.h
index 134e7597e966..7c25754afbcd 100644
--- a/defs.h
+++ b/defs.h
@@ -3903,7 +3903,7 @@ typedef signed int s32;
#define TIF_SIGPENDING (1)
-#define _SECTION_SIZE_BITS 28
+#define _SECTION_SIZE_BITS 29
#define _MAX_PHYSMEM_BITS 48
#endif /* LOONGARCH64 */
diff --git a/loongarch64.c b/loongarch64.c
index 39a05b854832..c95910f5ea4a 100644
--- a/loongarch64.c
+++ b/loongarch64.c
@@ -1876,6 +1876,8 @@ pt_level_alloc(char **lvl, char *name)
void
loongarch64_init(int when)
{
+ char *string;
+
switch (when) {
case SETUP_ENV:
machdep->process_elf_notes = process_elf64_notes;
@@ -1933,8 +1935,20 @@ loongarch64_init(int when)
break;
case POST_GDB:
- machdep->section_size_bits = _SECTION_SIZE_BITS;
- machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
+ string = pc->read_vmcoreinfo("NUMBER(SECTION_SIZE_BITS)");
+ if (string) {
+ machdep->section_size_bits = strtoul(string, NULL, 10);
+ free(string);
+ } else
+ machdep->section_size_bits = _SECTION_SIZE_BITS;
+
+
+ string = pc->read_vmcoreinfo("NUMBER(MAX_PHYSMEM_BITS)");
+ if (string) {
+ machdep->max_physmem_bits = strtoul(string, NULL, 10);
+ free(string);
+ } else
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
if (symbol_exists("irq_desc"))
ARRAY_LENGTH_INIT(machdep->nr_irqs, irq_desc,
--
2.51.1
5 days, 1 hour
[PATCH 1/2] add cpu_to_nid function
by Huang Shijie
Add cpu_to_nid function which we can use to get the NUMA node id
by the cpu id.
1.) For live mode: use /sys/ files to get the cpu_to_nid.
This method will succeed 100%.
2.) For vmcore mode: use "numa_node" symbol to get the cpu_to_nid.
If CONFIG_USE_PERCPU_NUMA_NODE_ID does not defined in kernel,
this method will fail.
Signed-off-by: Huang Shijie <huangsj(a)hygon.cn>
---
defs.h | 2 ++
kernel.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
main.c | 1 +
3 files changed, 69 insertions(+)
diff --git a/defs.h b/defs.h
index e3027e2..7e1515a 100644
--- a/defs.h
+++ b/defs.h
@@ -6044,6 +6044,8 @@ ulong do_maple_tree(ulong, int, struct list_pair *);
void help_init(void);
void cmd_usage(char *, int);
void display_version(void);
+int cpu_to_nid(int cpu);
+void numa_init(void);
void display_help_screen(char *);
#ifdef ARM
#define dump_machdep_table(X) arm_dump_machdep_table(X)
diff --git a/kernel.c b/kernel.c
index e53038d..32230fb 100644
--- a/kernel.c
+++ b/kernel.c
@@ -12221,3 +12221,69 @@ out:
pc->error_fp = error_fp_save;
}
#endif
+
+static int *cpu_to_nid_map;
+
+int
+cpu_to_nid(int cpu)
+{
+ if (!cpu_to_nid_map || cpu < 0 || cpu >= kt->cpus)
+ return -1;
+ if (vt->numnodes == 1)
+ return 0;
+ return cpu_to_nid_map[cpu];
+}
+
+static void
+cpu_to_nid_init(void)
+{
+ int i, j;
+ int fd;
+ char buf[64];
+
+ cpu_to_nid_map = malloc(kt->cpus * sizeof(int));
+ if (vt->numnodes == 1)
+ return;
+
+ memset(cpu_to_nid_map, -1, kt->cpus * sizeof(int));
+
+ if (ACTIVE()) {
+ for (i = 0; i < kt->cpus; i++) {
+ for (j = 0; j < vt->numnodes; j++) {
+ memset(buf, 0, sizeof(buf));
+ sprintf(buf, "/sys/devices/system/cpu/cpu%d/node%d", i, j);
+
+ fd = open(buf, O_RDONLY);
+ if (fd > 0) {
+ cpu_to_nid_map[i] = j;
+ close(fd);
+ break;
+ }
+ }
+ }
+ } else {
+ int cpu;
+
+ if (symbol_exists("numa_node")) {
+ ulong base = symbol_value("numa_node");
+
+ for (cpu = 0; cpu < kt->cpus; cpu++) {
+ ulong addr = base + kt->__per_cpu_offset[cpu];
+ int nid;
+
+ if (readmem(addr, KVADDR, &nid, sizeof(int),
+ "numa_node", RETURN_ON_ERROR|QUIET))
+ cpu_to_nid_map[cpu] = nid;
+ }
+ } else {
+ error(WARNING,
+ "numa_node symbol not found in vmcore\n");
+ }
+ }
+}
+
+void
+numa_init(void)
+{
+ cpu_to_nid_init();
+}
diff --git a/main.c b/main.c
index d5f8486..a8c77f8 100644
--- a/main.c
+++ b/main.c
@@ -793,6 +793,7 @@ main_loop(void)
kernel_init();
machdep_init(POST_GDB);
vm_init();
+ numa_init();
machdep_init(POST_VM);
module_init();
help_init();
--
2.53.0
5 days, 1 hour
[PATCH v2] 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 | 428 +++++++++++++++++++++++++-----------------------------
2 files changed, 201 insertions(+), 229 deletions(-)
diff --git a/defs.h b/defs.h
index e3027e2..ac0b128 100644
--- a/defs.h
+++ b/defs.h
@@ -3801,6 +3801,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 4dcecc2..1b6396c 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);
@@ -637,66 +633,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_pte_page_shift(int level)
+{
+ 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_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
+riscv64_vtop_nlevel_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr,
+ int verbose, int levels)
{
- ulong *pgd_ptr, pgd_val;
- ulong pmd_base, pmd_addr, pmd_val;
- ulong pte_base, pte_addr, pte_val, pte_pfn;
+ 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);
- fprintf(fp, " PAGE: %016lx not present\n\n", PAGEBASE(*paddr));
+ 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));
}
- return FALSE;
- }
- *paddr = PTOB(pte_pfn) + PAGEOFFSET(vaddr);
+ 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;
+ }
+
+ if (RISCV64_PTE_LEAF(pte)) {
+ physaddr_t base, mask;
+
+ base = riscv64_pte_paddr_base(pte);
+ mask = riscv64_pte_page_mask(level);
- if (verbose) {
- fprintf(fp, " PAGE: %016lx\n\n", PAGEBASE(*paddr));
- riscv64_translate_pte(pte_val, 0, 0);
+ 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:
if (verbose)
fprintf(fp, "invalid for %lx address\n", vaddr);
@@ -1218,174 +1356,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:
- if (verbose)
- 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);
- 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:
- if (verbose)
- fprintf(fp, "invalid for %lx address\n", vaddr);
- return FALSE;
-}
-
static int
riscv64_init_active_task_regs(void)
{
@@ -1610,11 +1580,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;
}
@@ -1669,11 +1639,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
5 days, 1 hour
subscription policy changed
by Dave Young
Hi list
We get spam emails every some time, it is very annoying. So I have changed the subscription policy to "Confirm then Moderate", hope it can avoid the spams.
First subscribers have to confirm, then a moderator needs to authorize. If the email address is a suspicious one eg. some weird gmail account I will reply with some simple question about what is crash etc to confirm the purpose of the request. Otherwise normally I will just confirm and approve the subscription.
Thanks
Dave
5 days, 18 hours
Madagascar Evisa Fee
by a.lexandra.24510.1@gmail.com
<a href="https://evisa-madagascar.it.com/madagascar-evisa-fee-and-processing-time/">Madagascar eVisa Fee</a> refers to the cost required to process an electronic visa application for traveling to Madagascar. The fee may vary depending on the type of eVisa, duration of stay, nationality, and processing requirements. Applicants are generally required to pay the applicable fee online during the application process. The payment confirms the submission and allows authorities to review the visa request. Travelers should ensure that all information provided is accurate before making payment, as fees may be non-refundable in some cases. Before applying, applicants should check the latest Madagascar eVisa fee details, accepted payment methods, and updated visa regulations for a smooth experience.
5 days, 19 hours
[PATCH] loongarch64: fix mem section init failure
by Dave Young
The loongarch64 SECTION_SIZE_BITS does not match the mainline kernel code.
crash test failed with mem_section init failure due to access non exist
memory address for mem sections caused by wrong NR_SECTION_ROOTS
Signed-off-by: Dave Young <yangrr.2009(a)tsinghua.org.cn>
---
defs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: crash/defs.h
===================================================================
--- crash.orig/defs.h 2026-08-18 09:40:48.392309457 +0800
+++ crash/defs.h 2026-08-24 14:46:52.133057387 +0800
@@ -3903,7 +3903,7 @@
#define TIF_SIGPENDING (1)
-#define _SECTION_SIZE_BITS 28
+#define _SECTION_SIZE_BITS 29
#define _MAX_PHYSMEM_BITS 48
#endif /* LOONGARCH64 */
5 days, 23 hours