170 lines
5.0 KiB
Diff
170 lines
5.0 KiB
Diff
|
From dbc45587f2c0024f0bc801a967bed9bd8d9f218c Mon Sep 17 00:00:00 2001
|
||
|
From: Tao Liu <ltao@redhat.com>
|
||
|
Date: Wed, 22 Feb 2023 14:32:09 +0800
|
||
|
Subject: [PATCH 78/89] Fix for "search -u" option failing in maple tree kernel
|
||
|
|
||
|
Kernel with maple tree enabled doesn't have mmap as a member of mm_struct[1],
|
||
|
so OFFSET(mm_struct_mmap) case needed to be handled differently for
|
||
|
maple tree kernel.
|
||
|
|
||
|
Before:
|
||
|
crash> search -u a
|
||
|
|
||
|
search: invalid structure member offset: mm_struct_mmap
|
||
|
FILE: memory.c LINE: 14255 FUNCTION: address_space_start()
|
||
|
|
||
|
[crash] error trace: 549500 => 548fff => 5f1c91 => 5f1c13
|
||
|
|
||
|
5f1c13: OFFSET_verify.part.36+51
|
||
|
5f1c91: OFFSET_verify+49
|
||
|
548fff: address_space_start+106
|
||
|
549500: cmd_search+855
|
||
|
|
||
|
search: invalid structure member offset: mm_struct_mmap
|
||
|
FILE: memory.c LINE: 14255 FUNCTION: address_space_start()
|
||
|
|
||
|
After:
|
||
|
crash> search -u a
|
||
|
7ffea63e6440: a
|
||
|
|
||
|
[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=763ecb035029f500d7e6dc99acd1ad299b7726a1
|
||
|
|
||
|
Signed-off-by: Tao Liu <ltao@redhat.com>
|
||
|
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||
|
---
|
||
|
memory.c | 89 +++++++++++++++++++++++++++++++++++++++++---------------
|
||
|
1 file changed, 65 insertions(+), 24 deletions(-)
|
||
|
|
||
|
diff --git a/memory.c b/memory.c
|
||
|
index d9cd616f19de..c4a6ecd18004 100644
|
||
|
--- a/memory.c
|
||
|
+++ b/memory.c
|
||
|
@@ -14245,14 +14245,28 @@ vaddr_type(ulong vaddr, struct task_context *tc)
|
||
|
static int
|
||
|
address_space_start(struct task_context *tc, ulong *addr)
|
||
|
{
|
||
|
- ulong vma;
|
||
|
+ ulong mm_mt, entry_num, i, vma = 0;
|
||
|
char *vma_buf;
|
||
|
+ struct list_pair *entry_list;
|
||
|
|
||
|
if (!tc->mm_struct)
|
||
|
return FALSE;
|
||
|
|
||
|
- fill_mm_struct(tc->mm_struct);
|
||
|
- vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
|
||
|
+ if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) {
|
||
|
+ mm_mt = tc->mm_struct + OFFSET(mm_struct_mm_mt);
|
||
|
+ entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL);
|
||
|
+ entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair));
|
||
|
+ do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list);
|
||
|
+ for (i = 0; i < entry_num; i++) {
|
||
|
+ if (!!(vma = (ulong)entry_list[i].value))
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ FREEBUF(entry_list);
|
||
|
+ } else {
|
||
|
+ fill_mm_struct(tc->mm_struct);
|
||
|
+ vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
|
||
|
+ }
|
||
|
+
|
||
|
if (!vma)
|
||
|
return FALSE;
|
||
|
vma_buf = fill_vma_cache(vma);
|
||
|
@@ -15491,6 +15505,30 @@ search_physical(struct searchinfo *si)
|
||
|
FREEBUF(pagebuf);
|
||
|
}
|
||
|
|
||
|
+static bool
|
||
|
+check_vma(ulong vma, ulong vaddr, ulong *vm_next, ulong *nextvaddr)
|
||
|
+{
|
||
|
+ char *vma_buf;
|
||
|
+ ulong vm_start, vm_end;
|
||
|
+
|
||
|
+ vma_buf = fill_vma_cache(vma);
|
||
|
+
|
||
|
+ vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start));
|
||
|
+ vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end));
|
||
|
+ if (vm_next)
|
||
|
+ *vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next));
|
||
|
+
|
||
|
+ if (vaddr <= vm_start) {
|
||
|
+ *nextvaddr = vm_start;
|
||
|
+ return TRUE;
|
||
|
+ }
|
||
|
+
|
||
|
+ if ((vaddr > vm_start) && (vaddr < vm_end)) {
|
||
|
+ *nextvaddr = vaddr;
|
||
|
+ return TRUE;
|
||
|
+ }
|
||
|
+ return FALSE;
|
||
|
+}
|
||
|
|
||
|
/*
|
||
|
* Return the next mapped user virtual address page that comes after
|
||
|
@@ -15500,37 +15538,40 @@ static int
|
||
|
next_upage(struct task_context *tc, ulong vaddr, ulong *nextvaddr)
|
||
|
{
|
||
|
ulong vma, total_vm;
|
||
|
- char *vma_buf;
|
||
|
- ulong vm_start, vm_end;
|
||
|
ulong vm_next;
|
||
|
+ ulong mm_mt, entry_num, i;
|
||
|
+ struct list_pair *entry_list;
|
||
|
|
||
|
if (!tc->mm_struct)
|
||
|
return FALSE;
|
||
|
|
||
|
- fill_mm_struct(tc->mm_struct);
|
||
|
- vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
|
||
|
+ fill_mm_struct(tc->mm_struct);
|
||
|
+ vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */
|
||
|
total_vm = ULONG(tt->mm_struct + OFFSET(mm_struct_total_vm));
|
||
|
-
|
||
|
- if (!vma || (total_vm == 0))
|
||
|
+ if (!total_vm)
|
||
|
return FALSE;
|
||
|
|
||
|
- vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */
|
||
|
-
|
||
|
- for ( ; vma; vma = vm_next) {
|
||
|
- vma_buf = fill_vma_cache(vma);
|
||
|
-
|
||
|
- vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start));
|
||
|
- vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end));
|
||
|
- vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next));
|
||
|
-
|
||
|
- if (vaddr <= vm_start) {
|
||
|
- *nextvaddr = vm_start;
|
||
|
- return TRUE;
|
||
|
+ if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) {
|
||
|
+ mm_mt = tc->mm_struct + OFFSET(mm_struct_mm_mt);
|
||
|
+ entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL);
|
||
|
+ entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair));
|
||
|
+ do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list);
|
||
|
+ for (i = 0; i < entry_num; i++) {
|
||
|
+ if (!!(vma = (ulong)entry_list[i].value) &&
|
||
|
+ check_vma(vma, vaddr, NULL, nextvaddr)) {
|
||
|
+ FREEBUF(entry_list);
|
||
|
+ return TRUE;
|
||
|
+ }
|
||
|
}
|
||
|
+ FREEBUF(entry_list);
|
||
|
+ } else {
|
||
|
+ vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
|
||
|
|
||
|
- if ((vaddr > vm_start) && (vaddr < vm_end)) {
|
||
|
- *nextvaddr = vaddr;
|
||
|
- return TRUE;
|
||
|
+ if (!vma)
|
||
|
+ return FALSE;
|
||
|
+ for ( ; vma; vma = vm_next) {
|
||
|
+ if (check_vma(vma, vaddr, &vm_next, nextvaddr))
|
||
|
+ return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
--
|
||
|
2.37.1
|
||
|
|