[PATCH] Fix compound_head() and "bt -F" option on Linux 7.1 and later
by HAGIO KAZUHITO(萩尾 一仁)
From: Kazuhito Hagio <k-hagio-ab(a)nec.com>
Kernel commit d50569612c29 ("mm: rename the 'compound_head' field in the
'struct page' to 'compound_info'") and related patches [1] changed the
field name and its value.
Without the patch, crash prints the following warning during startup,
WARNING: SLUB: cannot determine how compound pages are linked
and "bt -F" option fails with the following error.
crash> bt -F
bt: invalid structure member offset: page_first_page
FILE: memory.c LINE: 20238 FUNCTION: compound_head()
[1] https://lore.kernel.org/all/20260227194302.274384-1-kas@kernel.org/
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
defs.h | 1 +
memory.c | 44 ++++++++++++++++++++++++++++++++++++--------
symbols.c | 1 +
3 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/defs.h b/defs.h
index e3027e2b9141..88b7bbeb2372 100644
--- a/defs.h
+++ b/defs.h
@@ -2295,6 +2295,7 @@ struct offset_table { /* stash of commonly-used offsets */
long page_compound_order;
long folio__folio_order;
long folio__flags_1;
+ long page_compound_info;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/memory.c b/memory.c
index 3f3aa274ab5a..7102e951f1d5 100644
--- a/memory.c
+++ b/memory.c
@@ -414,6 +414,7 @@ mem_init(void)
#define FOLIO_ORDER_V2 2
#define FOLIO_ORDER_V3 3
static int folio_order_version;
+static int compound_info_has_mask = FALSE;
/*
* Stash a few popular offsets and some basic kernel virtual memory
@@ -547,6 +548,7 @@ vm_init(void)
MEMBER_OFFSET_INIT(page_compound_head, "page", "compound_head");
if (INVALID_MEMBER(page_compound_head))
ANON_MEMBER_OFFSET_INIT(page_compound_head, "page", "compound_head");
+ MEMBER_OFFSET_INIT(page_compound_info, "page", "compound_info");
MEMBER_OFFSET_INIT(page_private, "page", "private");
MEMBER_OFFSET_INIT(page_freelist, "page", "freelist");
MEMBER_OFFSET_INIT(page_page_type, "page", "page_type");
@@ -1352,6 +1354,17 @@ vm_init(void)
} else if (CRASHDEBUG(1))
error(NOTE, "page_hash_table does not exist in this kernel\n");
+ /*
+ * on Linux 7.1 and later, zone.vmemmap_tails is defined only when
+ * CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP is enabled.
+ */
+#define is_power_of_2(n) (n - 1 < (n ^ (n - 1)))
+ if (VALID_MEMBER(page_compound_info) &&
+ is_power_of_2(SIZE(page)) && MEMBER_EXISTS("zone", "vmemmap_tails"))
+ compound_info_has_mask = TRUE;
+ if (CRASHDEBUG(1))
+ error(NOTE, "compound_info_has_mask = %d\n", compound_info_has_mask);
+
kmem_cache_init();
page_flags_init();
@@ -5642,10 +5655,11 @@ PG_slab_flag_init(void)
}
}
- if (VALID_MEMBER(page_compound_head)) {
+ if (VALID_MEMBER(page_compound_head) || VALID_MEMBER(page_compound_info)) {
if (CRASHDEBUG(2))
fprintf(fp,
- "PG_head_tail_mask: (UNUSED): page.compound_head exists!\n");
+ "PG_head_tail_mask: (UNUSED): page.compound_head or "
+ "page.compound_info exists!\n");
} else if (vt->flags & KMALLOC_SLUB) {
/*
* PG_slab and the following are hardwired for
@@ -9858,7 +9872,8 @@ vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose)
&page_flags, sizeof(ulong), "page.flags",
FAULT_ON_ERROR);
if (!page_slab(page, page_flags)) {
- if (((vt->flags & KMALLOC_SLUB) || VALID_MEMBER(page_compound_head)) ||
+ if (((vt->flags & KMALLOC_SLUB) || VALID_MEMBER(page_compound_head) ||
+ VALID_MEMBER(page_compound_info)) ||
((vt->flags & KMALLOC_COMMON) &&
VALID_MEMBER(page_slab) && VALID_MEMBER(page_first_page))) {
readmem(compound_head(page)+OFFSET(page_flags), KVADDR,
@@ -9873,7 +9888,8 @@ vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose)
if ((vt->flags & KMALLOC_SLUB) ||
((vt->flags & KMALLOC_COMMON) && VALID_MEMBER(page_slab) &&
- (VALID_MEMBER(page_compound_head) || VALID_MEMBER(page_first_page)))) {
+ (VALID_MEMBER(page_compound_head) || VALID_MEMBER(page_compound_info) ||
+ VALID_MEMBER(page_first_page)))) {
readmem(compound_head(page)+OFFSET(page_slab),
KVADDR, &cache, sizeof(void *),
"page.slab", FAULT_ON_ERROR);
@@ -9904,7 +9920,8 @@ is_slab_overload_page(ulong vaddr, ulong *page_head, char *buf)
if ((vt->flags & SLAB_OVERLOAD_PAGE) &&
is_page_ptr(vaddr, NULL) && VALID_MEMBER(page_slab) &&
- (VALID_MEMBER(page_compound_head) || VALID_MEMBER(page_first_page))) {
+ (VALID_MEMBER(page_compound_head) || VALID_MEMBER(page_compound_info) ||
+ VALID_MEMBER(page_first_page))) {
readmem(compound_head(vaddr)+OFFSET(page_slab),
KVADDR, &cache, sizeof(void *),
"page.slab", FAULT_ON_ERROR);
@@ -9944,7 +9961,8 @@ vaddr_to_slab(ulong vaddr)
slab = 0;
- if ((vt->flags & KMALLOC_SLUB) || VALID_MEMBER(page_compound_head))
+ if ((vt->flags & KMALLOC_SLUB) || VALID_MEMBER(page_compound_head) ||
+ VALID_MEMBER(page_compound_info))
slab = compound_head(page);
else if (vt->flags & SLAB_OVERLOAD_PAGE)
slab = compound_head(page);
@@ -20222,11 +20240,21 @@ get_kmem_cache_child_list(ulong **cache_buf, ulong root)
static ulong
compound_head(ulong page)
{
- ulong flags, first_page, compound_head;
+ ulong flags, first_page, compound_head, info, mask;
first_page = page;
- if (VALID_MEMBER(page_compound_head)) {
+ if (VALID_MEMBER(page_compound_info)) {
+ if (readmem(page + OFFSET(page_compound_info), KVADDR, &info,
+ sizeof(ulong), "page.compound_info", RETURN_ON_ERROR)) {
+ if (compound_info_has_mask) {
+ mask = (info & 1) - 1;
+ mask |= info;
+ first_page = page & mask;
+ } else if (info & 1)
+ first_page = info - 1;
+ }
+ } else if (VALID_MEMBER(page_compound_head)) {
if (readmem(page+OFFSET(page_compound_head), KVADDR, &compound_head,
sizeof(ulong), "page.compound_head", RETURN_ON_ERROR)) {
if (compound_head & 1)
diff --git a/symbols.c b/symbols.c
index 03511c8cbe8c..2071bdf77819 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10504,6 +10504,7 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(page_active));
fprintf(fp, " page_compound_head: %ld\n",
OFFSET(page_compound_head));
+ fprintf(fp, " page_compound_info: %ld\n", OFFSET(page_compound_info));
fprintf(fp, " page_private: %ld\n", OFFSET(page_private));
fprintf(fp, " page_page_type: %ld\n",
OFFSET(page_page_type));
--
2.31.1
18 minutes
[RFC 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.
Signed-off-by: Huang Shijie <huangsj(a)hygon.cn>
---
defs.h | 2 ++
kernel.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
main.c | 1 +
3 files changed, 49 insertions(+)
diff --git a/defs.h b/defs.h
index a4f70b7..98a149b 100644
--- a/defs.h
+++ b/defs.h
@@ -6040,6 +6040,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 eb9754c..15254a4 100644
--- a/kernel.c
+++ b/kernel.c
@@ -12207,3 +12207,49 @@ 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));
+
+ 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;
+ }
+ }
+ }
+}
+
+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
2 days, 12 hours
[PATCH] symbols: optimize symval_hash_init with O(1) tail insertion
by 启瑞
From: Rui Qi <qirui.001(a)bytedance.com>
Replace the O(n) tail traversal with O(1) tail insertion using the
existing val_hash_last pointer. The original code traversed the entire
linked list on every insert to find the tail, resulting in O(n^2)
complexity for hash table initialization.
The new implementation uses the val_hash_last pointer that was already
maintained in the data structure:
- Insert at tail in O(1) time
- Update val_hash_last after each insertion
- Set val_hash_next to NULL for each new entry
This reduces hash table initialization from O(n^2) to O(n).
Benchmark on a RISC-V 64-core machine (kernel 6.12.95, ~200k symbols):
$ echo q | ./crash /proc/kcore vmlinux
Before: 44.67 s (mean, n=6, σ=5.61)
After: 36.56 s (mean, n=6, σ=2.30)
Speedup: 1.22x (-18.1%), with improved consistency.
Signed-off-by: Rui Qi <qirui.001(a)bytedance.com>
---
symbols.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/symbols.c b/symbols.c
index 03511c8..0b564d2 100644
--- a/symbols.c
+++ b/symbols.c
@@ -1085,12 +1085,13 @@ symbol_value_from_proc_kallsyms(char *symname)
/*
* Install all static kernel symbol values into the symval_hash.
+ * Uses val_hash_last for O(1) tail insertion.
*/
static void
symval_hash_init(void)
{
int index;
- struct syment *sp, *sph;
+ struct syment *sp;
for (sp = st->symtable; sp < st->symend; sp++) {
index = SYMVAL_HASH_INDEX(sp->value);
@@ -1098,14 +1099,12 @@ symval_hash_init(void)
if (st->symval_hash[index].val_hash_head == NULL) {
st->symval_hash[index].val_hash_head = sp;
st->symval_hash[index].val_hash_last = sp;
- continue;
+ } else {
+ /* O(1) tail insertion using val_hash_last */
+ st->symval_hash[index].val_hash_last->val_hash_next = sp;
+ st->symval_hash[index].val_hash_last = sp;
}
-
- sph = st->symval_hash[index].val_hash_head;
- while (sph->val_hash_next)
- sph = sph->val_hash_next;
-
- sph->val_hash_next = sp;
+ sp->val_hash_next = NULL;
}
}
--
2.47.3
6 days, 22 hours
Decoding Consumer Minds: Fresh Ideas for Marketing Research Papers
by kefag22407@haotuwu.com
Marketing is no longer just about selling — it’s about understanding why people buy, share, and stay loyal. Research papers in marketing can dive into fascinating areas like consumer psychology, digital engagement, and emotional branding. Exploring topics such as the impact of social media influencers on brand perception, consumer trust in AI-driven recommendations, or sustainability as a driver of purchase intent can help uncover what really shapes modern consumer decisions.
Another promising angle is studying data and personalization in marketing. With companies relying heavily on analytics, there’s a growing need to explore how data-driven strategies influence consumer experience and brand loyalty. Researching ethical data usage, AI in customer segmentation, or neuromarketing trends can lead to insights that bridge creativity with strategy — essential for any marketer looking to make an impact in today’s competitive landscape. Have more info at: https://thedissertationhelp.co.uk/marketing-research-paper-topics/
1 week, 6 days
[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
2 weeks
Madagascar Evisa Fee
by a.lexandra.24510.1@gmail.com
Madagascar eVisa Fee 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.
website- https://evisa-madagascar.it.com/madagascar-evisa-fee-and-processing-time/
2 weeks, 3 days
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.
2 weeks, 3 days
[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
2 weeks, 3 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, 3 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, 4 days