diff --git a/SOURCES/0001-Fix-kernel-version-macros-for-revision-numbers-over-.patch b/SOURCES/0001-Fix-kernel-version-macros-for-revision-numbers-over-.patch new file mode 100644 index 0000000..3ca7cdc --- /dev/null +++ b/SOURCES/0001-Fix-kernel-version-macros-for-revision-numbers-over-.patch @@ -0,0 +1,52 @@ +From 040a56e9f9d0df15a2f8161ed3a0a907d70dda03 Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Wed, 10 May 2023 16:09:03 +0900 +Subject: [PATCH 1/6] Fix kernel version macros for revision numbers over 255 + +The current comparison macros for kernel version shift minor number only +8 bits. This can cause an unexpected result on kernels with revision +number over 255, e.g. Linux 4.14.314. + +In fact, on Linux 4.14.314 for x86_64 without CONFIG_RANDOMIZE_BASE=y +(KASLR), the following condition became false in x86_64_init(). + + ((THIS_KERNEL_VERSION >= LINUX(4,14,84)) && + (THIS_KERNEL_VERSION < LINUX(4,15,0))) + +As a result, crash used a wrong hard-coded value for PAGE_OFFSET and +failed to start a session with the following seek error. + + crash: seek error: physical address: 200e000 type: "pud page" + +Shift the major and minor number by 24 and 16 bits respectively to fix +this issue. + +Reported-by: Luiz Capitulino +Tested-by: Luiz Capitulino +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/defs.h b/defs.h +index 12ad6aaa0998..211fc9d55d33 100644 +--- a/defs.h ++++ b/defs.h +@@ -807,10 +807,10 @@ struct kernel_table { /* kernel data */ + } \ + } + +-#define THIS_KERNEL_VERSION ((kt->kernel_version[0] << 16) + \ +- (kt->kernel_version[1] << 8) + \ ++#define THIS_KERNEL_VERSION ((kt->kernel_version[0] << 24) + \ ++ (kt->kernel_version[1] << 16) + \ + (kt->kernel_version[2])) +-#define LINUX(x,y,z) (((uint)(x) << 16) + ((uint)(y) << 8) + (uint)(z)) ++#define LINUX(x,y,z) (((uint)(x) << 24) + ((uint)(y) << 16) + (uint)(z)) + + #define THIS_GCC_VERSION ((kt->gcc_version[0] << 16) + \ + (kt->gcc_version[1] << 8) + \ +-- +2.37.1 + diff --git a/SOURCES/0001-Output-prompt-when-stdin-is-not-a-TTY.patch b/SOURCES/0001-Output-prompt-when-stdin-is-not-a-TTY.patch new file mode 100644 index 0000000..d26ef54 --- /dev/null +++ b/SOURCES/0001-Output-prompt-when-stdin-is-not-a-TTY.patch @@ -0,0 +1,71 @@ +From 8527bbff71cbdfd90a67d5cec4a1d94156e6bf13 Mon Sep 17 00:00:00 2001 +From: Hsin-Yi Wang +Date: Wed, 31 May 2023 14:01:36 +0800 +Subject: [PATCH 1/5] Output prompt when stdin is not a TTY + +When stdin is not a TTY, prompt ("crash> ") won't be displayed. If +another process interact with crash with piped stdin/stdout, it will not +get the prompt as a delimiter. + +Compared to other debugger like gdb, crash seems intended to give a +prompt in this case in the beginning of process_command_line(). It +checks if pc->flags does NOT have any of +READLINE|SILENT|CMDLINE_IFILE|RCHOME_IFILE|RCLOCAL_IFILE, a +prompt should be printed. The check will never be true since READLINE is +set in setup_environment() unconditionally. + +It makes more sense to change the READLINE flag in the check to TTY +instead. Besides this change, the prompt in process_command_line() should +only be print when it's not in the middle of processing the input file +recovering from a previous FATAL command, because the prompt will be +displayed by the exec_input_file(). + +Additionally, when stdin is not TTY, repeat the command line from user +after prompt, which can give more context. + +The prompt and command line can be opt out by using the silent (-s) flag. + +Signed-off-by: Hsin-Yi Wang +Signed-off-by: Lianbo Jiang +--- + cmdline.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/cmdline.c b/cmdline.c +index ded6551c2597..b7f919ae2279 100644 +--- a/cmdline.c ++++ b/cmdline.c +@@ -64,8 +64,8 @@ process_command_line(void) + fp = stdout; + BZERO(pc->command_line, BUFSIZE); + +- if (!(pc->flags & +- (READLINE|SILENT|CMDLINE_IFILE|RCHOME_IFILE|RCLOCAL_IFILE))) ++ if (!pc->ifile_in_progress && !(pc->flags & ++ (TTY|SILENT|CMDLINE_IFILE|RCHOME_IFILE|RCLOCAL_IFILE))) + fprintf(fp, "%s", pc->prompt); + fflush(fp); + +@@ -136,12 +136,16 @@ process_command_line(void) + add_history(pc->command_line); + + check_special_handling(pc->command_line); +- } else { +- if (fgets(pc->command_line, BUFSIZE-1, stdin) == NULL) ++ } else { ++ if (fgets(pc->command_line, BUFSIZE-1, stdin) == NULL) + clean_exit(1); ++ if (!(pc->flags & SILENT)) { ++ fprintf(fp, "%s", pc->command_line); ++ fflush(fp); ++ } + clean_line(pc->command_line); + strcpy(pc->orig_line, pc->command_line); +- } ++ } + + /* + * First clean out all linefeeds and leading/trailing spaces. +-- +2.37.1 + diff --git a/SOURCES/0001-ppc64-update-the-NR_CPUS-to-8192.patch b/SOURCES/0001-ppc64-update-the-NR_CPUS-to-8192.patch index c5608f6..761741c 100644 --- a/SOURCES/0001-ppc64-update-the-NR_CPUS-to-8192.patch +++ b/SOURCES/0001-ppc64-update-the-NR_CPUS-to-8192.patch @@ -1,7 +1,7 @@ -From ae52398a13fa9a238279114ed671c7c514c154ee Mon Sep 17 00:00:00 2001 +From a48cebaa9691efe4e2c47bbd56d40ebc8acfa89e Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Mon, 9 May 2022 12:49:56 +0530 -Subject: [PATCH 01/18] ppc64: update the NR_CPUS to 8192 +Subject: [PATCH 01/89] ppc64: update the NR_CPUS to 8192 Since the kernel commit 2d8ae638bb86 ("powerpc: Make the NR_CPUS max 8192") the NR_CPUS on Linux kernel ranges from 1-8192. So let's match NR_CPUS with @@ -14,7 +14,7 @@ Signed-off-by: Lianbo Jiang 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defs.h b/defs.h -index 1e8360d65a3b..a6735d07b32f 100644 +index 89f57873f1a1..984348062bcb 100644 --- a/defs.h +++ b/defs.h @@ -136,7 +136,7 @@ @@ -27,5 +27,5 @@ index 1e8360d65a3b..a6735d07b32f 100644 #ifdef S390 #define NR_CPUS (512) -- -2.30.2 +2.37.1 diff --git a/SOURCES/0002-Fix-failure-of-dev-d-D-options-on-Linux-6.4-and-late.patch b/SOURCES/0002-Fix-failure-of-dev-d-D-options-on-Linux-6.4-and-late.patch new file mode 100644 index 0000000..89bc7d5 --- /dev/null +++ b/SOURCES/0002-Fix-failure-of-dev-d-D-options-on-Linux-6.4-and-late.patch @@ -0,0 +1,179 @@ +From 58c1816521c2e6bece3d69256b1866c9df8d93aa Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Tue, 16 May 2023 08:59:50 +0900 +Subject: [PATCH 2/6] Fix failure of "dev -d|-D" options on Linux 6.4 and later + kernels + +Kernel commit 2df418cf4b72 ("driver core: class: remove subsystem +private pointer from struct class"), which is contained in Linux 6.4 and +later kernels, removed the class.p member for struct subsys_private. As +a result, the "dev -d|-D" options fail with the following error. + + dev: invalid structure member offset: class_p + FILE: dev.c LINE: 4689 FUNCTION: init_iter() + +Search the class_kset list for the subsys_private of block class to fix +this. + +As a preparation, introduce get_subsys_private() function, which is +abstracted from the same search procedure in init_memory_block(). + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 1 + + dev.c | 20 +++++++++++++++++--- + memory.c | 35 +++-------------------------------- + tools.c | 43 +++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 64 insertions(+), 35 deletions(-) + +diff --git a/defs.h b/defs.h +index 211fc9d55d33..21cc760444d1 100644 +--- a/defs.h ++++ b/defs.h +@@ -5521,6 +5521,7 @@ struct rb_node *rb_left(struct rb_node *, struct rb_node *); + struct rb_node *rb_next(struct rb_node *); + struct rb_node *rb_last(struct rb_root *); + long percpu_counter_sum_positive(ulong fbc); ++ulong get_subsys_private(char *, char *); + + /* + * symbols.c +diff --git a/dev.c b/dev.c +index 75d30bd022a1..9d38aef9b3db 100644 +--- a/dev.c ++++ b/dev.c +@@ -4686,9 +4686,16 @@ init_iter(struct iter *i) + } else { + /* kernel version > 2.6.27, klist */ + unsigned long class_private_addr; +- readmem(block_class_addr + OFFSET(class_p), KVADDR, +- &class_private_addr, sizeof(class_private_addr), +- "class.p", FAULT_ON_ERROR); ++ ++ if (INVALID_MEMBER(class_p)) /* kernel version >= 6.4 */ ++ class_private_addr = get_subsys_private("class_kset", "block"); ++ else ++ readmem(block_class_addr + OFFSET(class_p), KVADDR, ++ &class_private_addr, sizeof(class_private_addr), ++ "class.p", FAULT_ON_ERROR); ++ ++ if (!class_private_addr) ++ error(FATAL, "cannot determine subsys_private for block.\n"); + + if (VALID_STRUCT(class_private)) { + /* 2.6.27 < kernel version <= 2.6.37-rc2 */ +@@ -4823,6 +4830,13 @@ void diskio_init(void) + if (INVALID_MEMBER(class_devices)) + MEMBER_OFFSET_INIT(class_devices, "class", "devices"); + MEMBER_OFFSET_INIT(class_p, "class", "p"); ++ if (INVALID_MEMBER(class_p)) { ++ MEMBER_OFFSET_INIT(kset_list, "kset", "list"); ++ MEMBER_OFFSET_INIT(kset_kobj, "kset", "kobj"); ++ MEMBER_OFFSET_INIT(kobject_name, "kobject", "name"); ++ MEMBER_OFFSET_INIT(kobject_entry, "kobject", "entry"); ++ MEMBER_OFFSET_INIT(subsys_private_subsys, "subsys_private", "subsys"); ++ } + MEMBER_OFFSET_INIT(class_private_devices, "class_private", + "class_devices"); + MEMBER_OFFSET_INIT(device_knode_class, "device", "knode_class"); +diff --git a/memory.c b/memory.c +index 0568f18eb9b7..953fc380c03c 100644 +--- a/memory.c ++++ b/memory.c +@@ -17865,38 +17865,9 @@ init_memory_block(int *klistcnt, ulong **klistbuf) + * v6.3-rc1 + * d2bf38c088e0 driver core: remove private pointer from struct bus_type + */ +- if (INVALID_MEMBER(bus_type_p)) { +- int i, cnt; +- char buf[32]; +- ulong bus_kset, list, name; +- +- BZERO(ld, sizeof(struct list_data)); +- +- get_symbol_data("bus_kset", sizeof(ulong), &bus_kset); +- readmem(bus_kset + OFFSET(kset_list), KVADDR, &list, +- sizeof(ulong), "bus_kset.list", FAULT_ON_ERROR); +- +- ld->flags |= LIST_ALLOCATE; +- ld->start = list; +- ld->end = bus_kset + OFFSET(kset_list); +- ld->list_head_offset = OFFSET(kobject_entry); +- +- cnt = do_list(ld); +- for (i = 0; i < cnt; i++) { +- readmem(ld->list_ptr[i] + OFFSET(kobject_name), KVADDR, &name, +- sizeof(ulong), "kobject.name", FAULT_ON_ERROR); +- read_string(name, buf, sizeof(buf)-1); +- if (CRASHDEBUG(1)) +- fprintf(fp, "kobject: %lx name: %s\n", ld->list_ptr[i], buf); +- if (STREQ(buf, "memory")) { +- /* entry is subsys_private.subsys.kobj. See bus_to_subsys(). */ +- private = ld->list_ptr[i] - OFFSET(kset_kobj) +- - OFFSET(subsys_private_subsys); +- break; +- } +- } +- FREEBUF(ld->list_ptr); +- } else { ++ if (INVALID_MEMBER(bus_type_p)) ++ private = get_subsys_private("bus_kset", "memory"); ++ else { + ulong memory_subsys = symbol_value("memory_subsys"); + readmem(memory_subsys + OFFSET(bus_type_p), KVADDR, &private, + sizeof(void *), "memory_subsys.private", FAULT_ON_ERROR); +diff --git a/tools.c b/tools.c +index c2cfa7e280bc..392a79707e61 100644 +--- a/tools.c ++++ b/tools.c +@@ -6963,3 +6963,46 @@ percpu_counter_sum_positive(ulong fbc) + + return (ret < 0) ? 0 : ret; + } ++ ++ulong ++get_subsys_private(char *kset_name, char *target_name) ++{ ++ ulong kset_addr, kset_list, name_addr, private = 0; ++ struct list_data list_data, *ld; ++ char buf[32]; ++ int i, cnt; ++ ++ if (!symbol_exists(kset_name)) ++ return 0; ++ ++ ld = &list_data; ++ BZERO(ld, sizeof(struct list_data)); ++ ++ get_symbol_data(kset_name, sizeof(ulong), &kset_addr); ++ readmem(kset_addr + OFFSET(kset_list), KVADDR, &kset_list, ++ sizeof(ulong), "kset.list", FAULT_ON_ERROR); ++ ++ ld->flags |= LIST_ALLOCATE; ++ ld->start = kset_list; ++ ld->end = kset_addr + OFFSET(kset_list); ++ ld->list_head_offset = OFFSET(kobject_entry); ++ ++ cnt = do_list(ld); ++ ++ for (i = 0; i < cnt; i++) { ++ readmem(ld->list_ptr[i] + OFFSET(kobject_name), KVADDR, &name_addr, ++ sizeof(ulong), "kobject.name", FAULT_ON_ERROR); ++ read_string(name_addr, buf, sizeof(buf)-1); ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "kobject: %lx name: %s\n", ld->list_ptr[i], buf); ++ if (STREQ(buf, target_name)) { ++ /* entry is subsys_private.subsys.kobj. See bus_to_subsys(). */ ++ private = ld->list_ptr[i] - OFFSET(kset_kobj) ++ - OFFSET(subsys_private_subsys); ++ break; ++ } ++ } ++ FREEBUF(ld->list_ptr); ++ ++ return private; ++} +-- +2.37.1 + diff --git a/SOURCES/0002-sbitmapq-remove-struct-and-member-validation-in-sbit.patch b/SOURCES/0002-sbitmapq-remove-struct-and-member-validation-in-sbit.patch index 5b4fc47..5fe6b17 100644 --- a/SOURCES/0002-sbitmapq-remove-struct-and-member-validation-in-sbit.patch +++ b/SOURCES/0002-sbitmapq-remove-struct-and-member-validation-in-sbit.patch @@ -1,7 +1,7 @@ -From 364b2e413c69daf189d2bc0238e3ba9b0dcbd937 Mon Sep 17 00:00:00 2001 +From d3682a7e57036b226d395541b590ebc460123b04 Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Mon, 23 May 2022 18:04:13 +0800 -Subject: [PATCH 02/18] sbitmapq: remove struct and member validation in +Subject: [PATCH 02/89] sbitmapq: remove struct and member validation in sbitmapq_init() Let's remove the struct and member validation from sbitmapq_init(), which @@ -58,5 +58,5 @@ index 96a61e6c2c71..7693eef6cebd 100644 } -- -2.30.2 +2.37.1 diff --git a/SOURCES/0002-x86_64-Fix-bt-command-printing-stale-entries-on-Linu.patch b/SOURCES/0002-x86_64-Fix-bt-command-printing-stale-entries-on-Linu.patch new file mode 100644 index 0000000..5c4b862 --- /dev/null +++ b/SOURCES/0002-x86_64-Fix-bt-command-printing-stale-entries-on-Linu.patch @@ -0,0 +1,345 @@ +From 77d8621876c1c6a3a25b91e464ba588a542485fb Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Thu, 18 May 2023 16:53:54 +0900 +Subject: [PATCH 2/5] x86_64: Fix "bt" command printing stale entries on Linux + 6.4 and later + +Kernel commit fb799447ae29 ("x86,objtool: Split UNWIND_HINT_EMPTY in +two"), which is contained in Linux 6.4 and later kernels, changed +ORC_TYPE_CALL macro from 0 to 2. As a result, the "bt" command cannot +use ORC entries, and can display stale entries in a call trace. + + crash> bt 1 + PID: 1 TASK: ffff93cd06294180 CPU: 51 COMMAND: "systemd" + #0 [ffffb72bc00cbc98] __schedule at ffffffff86e52aae + #1 [ffffb72bc00cbd00] schedule at ffffffff86e52f6a + #2 [ffffb72bc00cbd18] schedule_hrtimeout_range_clock at ffffffff86e58ef5 + #3 [ffffb72bc00cbd88] ep_poll at ffffffff8669624d + #4 [ffffb72bc00cbe28] do_epoll_wait at ffffffff86696371 + #5 [ffffb72bc00cbe30] do_timerfd_settime at ffffffff8669902b << + #6 [ffffb72bc00cbe60] __x64_sys_epoll_wait at ffffffff86696bf0 + #7 [ffffb72bc00cbeb0] do_syscall_64 at ffffffff86e3feb9 + #8 [ffffb72bc00cbee0] __task_pid_nr_ns at ffffffff863330d7 << + #9 [ffffb72bc00cbf08] syscall_exit_to_user_mode at ffffffff86e466b2 << stale entries + #10 [ffffb72bc00cbf18] do_syscall_64 at ffffffff86e3fec9 << + #11 [ffffb72bc00cbf50] entry_SYSCALL_64_after_hwframe at ffffffff870000aa + +Also, kernel commit ffb1b4a41016 added a member to struct orc_entry. +Although this does not affect the crash's unwinder, its debugging +information can be displayed incorrectly. + +To fix these, +(1) introduce "kernel_orc_entry_6_4" structure corresponding to 6.4 and + abstruction layer "orc_entry" structure in crash, +(2) switch ORC_TYPE_CALL to 2 or 0 with kernel's orc_entry structure. + +Related orc_entry history: + v4.14 39358a033b2e introduced struct orc_entry + v4.19 d31a580266ee added orc_entry.end member + v6.3 ffb1b4a41016 added orc_entry.signal member + v6.4 fb799447ae29 removed end member and changed type member to 3 bits + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 28 ++++++++++++- + x86_64.c | 119 +++++++++++++++++++++++++++++++++++++++++++------------ + 2 files changed, 119 insertions(+), 28 deletions(-) + +diff --git a/defs.h b/defs.h +index 11fdc17e60d0..bfda0c48d37b 100644 +--- a/defs.h ++++ b/defs.h +@@ -6363,9 +6363,29 @@ typedef struct __attribute__((__packed__)) { + unsigned int sp_reg:4; + unsigned int bp_reg:4; + unsigned int type:2; ++ unsigned int signal:1; + unsigned int end:1; + } kernel_orc_entry; + ++typedef struct __attribute__((__packed__)) { ++ signed short sp_offset; ++ signed short bp_offset; ++ unsigned int sp_reg:4; ++ unsigned int bp_reg:4; ++ unsigned int type:3; ++ unsigned int signal:1; ++} kernel_orc_entry_6_4; ++ ++typedef struct orc_entry { ++ signed short sp_offset; ++ signed short bp_offset; ++ unsigned int sp_reg; ++ unsigned int bp_reg; ++ unsigned int type; ++ unsigned int signal; ++ unsigned int end; ++} orc_entry; ++ + struct ORC_data { + int module_ORC; + uint lookup_num_blocks; +@@ -6376,10 +6396,13 @@ struct ORC_data { + ulong orc_lookup; + ulong ip_entry; + ulong orc_entry; +- kernel_orc_entry kernel_orc_entry; ++ orc_entry orc_entry_data; ++ int has_signal; ++ int has_end; + }; + +-#define ORC_TYPE_CALL 0 ++#define ORC_TYPE_CALL ((machdep->flags & ORC_6_4) ? 2 : 0) ++/* The below entries are not used and must be updated if we use them. */ + #define ORC_TYPE_REGS 1 + #define ORC_TYPE_REGS_IRET 2 + #define UNWIND_HINT_TYPE_SAVE 3 +@@ -6456,6 +6479,7 @@ struct machine_specific { + #define ORC (0x4000) + #define KPTI (0x8000) + #define L1TF (0x10000) ++#define ORC_6_4 (0x20000) + + #define VM_FLAGS (VM_ORIG|VM_2_6_11|VM_XEN|VM_XEN_RHEL4|VM_5LEVEL) + +diff --git a/x86_64.c b/x86_64.c +index 693a08bea758..87e87ae6e1e8 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -132,9 +132,9 @@ static void GART_init(void); + static void x86_64_exception_stacks_init(void); + static int in_START_KERNEL_map(ulong); + static ulong orc_ip(ulong); +-static kernel_orc_entry *__orc_find(ulong, ulong, uint, ulong); +-static kernel_orc_entry *orc_find(ulong); +-static kernel_orc_entry *orc_module_find(ulong); ++static orc_entry *__orc_find(ulong, ulong, uint, ulong); ++static orc_entry *orc_find(ulong); ++static orc_entry *orc_module_find(ulong); + static ulong ip_table_to_vaddr(ulong); + static void orc_dump(ulong); + +@@ -806,6 +806,8 @@ x86_64_dump_machdep_table(ulong arg) + fprintf(fp, "%sFRAMESIZE_DEBUG", others++ ? "|" : ""); + if (machdep->flags & ORC) + fprintf(fp, "%sORC", others++ ? "|" : ""); ++ if (machdep->flags & ORC_6_4) ++ fprintf(fp, "%sORC_6_4", others++ ? "|" : ""); + if (machdep->flags & FRAMEPOINTER) + fprintf(fp, "%sFRAMEPOINTER", others++ ? "|" : ""); + if (machdep->flags & GART_REGION) +@@ -980,6 +982,8 @@ x86_64_dump_machdep_table(ulong arg) + fprintf(fp, " ORC_data: %s", machdep->flags & ORC ? "\n" : "(unused)\n"); + if (machdep->flags & ORC) { + fprintf(fp, " module_ORC: %s\n", ms->orc.module_ORC ? "TRUE" : "FALSE"); ++ fprintf(fp, " has_signal: %s\n", ms->orc.has_signal ? "TRUE" : "FALSE"); ++ fprintf(fp, " has_end: %s\n", ms->orc.has_end ? "TRUE" : "FALSE"); + fprintf(fp, " lookup_num_blocks: %d\n", ms->orc.lookup_num_blocks); + fprintf(fp, " __start_orc_unwind_ip: %lx\n", ms->orc.__start_orc_unwind_ip); + fprintf(fp, " __stop_orc_unwind_ip: %lx\n", ms->orc.__stop_orc_unwind_ip); +@@ -988,14 +992,18 @@ x86_64_dump_machdep_table(ulong arg) + fprintf(fp, " orc_lookup: %lx\n", ms->orc.orc_lookup); + fprintf(fp, " ip_entry: %lx\n", ms->orc.ip_entry); + fprintf(fp, " orc_entry: %lx\n", ms->orc.orc_entry); +- fprintf(fp, " kernel_orc_entry:\n"); +- fprintf(fp, " sp_offset: %d\n", ms->orc.kernel_orc_entry.sp_offset); +- fprintf(fp, " bp_offset: %d\n", ms->orc.kernel_orc_entry.bp_offset); +- fprintf(fp, " sp_reg: %d\n", ms->orc.kernel_orc_entry.sp_reg); +- fprintf(fp, " bp_reg: %d\n", ms->orc.kernel_orc_entry.bp_reg); +- fprintf(fp, " type: %d\n", ms->orc.kernel_orc_entry.type); +- if (MEMBER_EXISTS("orc_entry", "end")) +- fprintf(fp, " end: %d\n", ms->orc.kernel_orc_entry.end); ++ fprintf(fp, " orc_entry_data:\n"); ++ fprintf(fp, " sp_offset: %d\n", ms->orc.orc_entry_data.sp_offset); ++ fprintf(fp, " bp_offset: %d\n", ms->orc.orc_entry_data.bp_offset); ++ fprintf(fp, " sp_reg: %d\n", ms->orc.orc_entry_data.sp_reg); ++ fprintf(fp, " bp_reg: %d\n", ms->orc.orc_entry_data.bp_reg); ++ fprintf(fp, " type: %d\n", ms->orc.orc_entry_data.type); ++ if (ms->orc.has_signal) ++ fprintf(fp, " signal: %d\n", ms->orc.orc_entry_data.signal); ++ else ++ fprintf(fp, " signal: (n/a)\n"); ++ if (ms->orc.has_end) ++ fprintf(fp, " end: %d\n", ms->orc.orc_entry_data.end); + else + fprintf(fp, " end: (n/a)\n"); + } +@@ -6440,6 +6448,12 @@ x86_64_ORC_init(void) + MEMBER_OFFSET_INIT(inactive_task_frame_bp, "inactive_task_frame", "bp"); + MEMBER_OFFSET_INIT(inactive_task_frame_ret_addr, "inactive_task_frame", "ret_addr"); + ++ orc->has_signal = MEMBER_EXISTS("orc_entry", "signal"); /* added at 6.3 */ ++ orc->has_end = MEMBER_EXISTS("orc_entry", "end"); /* removed at 6.4 */ ++ ++ if (orc->has_signal && !orc->has_end) ++ machdep->flags |= ORC_6_4; ++ + machdep->flags |= ORC; + } + +@@ -8522,7 +8536,7 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp, char *stack_ + int reterror; + int arg_exists; + int exception; +- kernel_orc_entry *korc; ++ orc_entry *korc; + + if (!(bt->flags & BT_FRAMESIZE_DEBUG)) { + if ((bt->flags & BT_FRAMESIZE_IGNORE_MASK) || +@@ -8608,11 +8622,14 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp, char *stack_ + + if ((machdep->flags & ORC) && (korc = orc_find(textaddr))) { + if (CRASHDEBUG(1)) { ++ struct ORC_data *orc = &machdep->machspec->orc; + fprintf(fp, + "rsp: %lx textaddr: %lx -> spo: %d bpo: %d spr: %d bpr: %d type: %d", + rsp, textaddr, korc->sp_offset, korc->bp_offset, + korc->sp_reg, korc->bp_reg, korc->type); +- if (MEMBER_EXISTS("orc_entry", "end")) ++ if (orc->has_signal) ++ fprintf(fp, " signal: %d", korc->signal); ++ if (orc->has_end) + fprintf(fp, " end: %d", korc->end); + fprintf(fp, "\n"); + } +@@ -9118,7 +9135,53 @@ orc_ip(ulong ip) + return (ip + ip_entry); + } + +-static kernel_orc_entry * ++static orc_entry * ++orc_get_entry(struct ORC_data *orc) ++{ ++ struct orc_entry *entry = &orc->orc_entry_data; ++ ++ if (machdep->flags & ORC_6_4) { ++ kernel_orc_entry_6_4 korc; ++ ++ if (!readmem(orc->orc_entry, KVADDR, &korc, sizeof(kernel_orc_entry_6_4), ++ "kernel orc_entry", RETURN_ON_ERROR|QUIET)) ++ return NULL; ++ ++ entry->sp_offset = korc.sp_offset; ++ entry->bp_offset = korc.bp_offset; ++ entry->sp_reg = korc.sp_reg; ++ entry->bp_reg = korc.bp_reg; ++ entry->type = korc.type; ++ entry->signal = korc.signal; ++ } else { ++ kernel_orc_entry korc; ++ ++ if (!readmem(orc->orc_entry, KVADDR, &korc, sizeof(kernel_orc_entry), ++ "kernel orc_entry", RETURN_ON_ERROR|QUIET)) ++ return NULL; ++ ++ entry->sp_offset = korc.sp_offset; ++ entry->bp_offset = korc.bp_offset; ++ entry->sp_reg = korc.sp_reg; ++ entry->bp_reg = korc.bp_reg; ++ entry->type = korc.type; ++ if (orc->has_end) { ++ /* ++ * orc_entry.signal was inserted before orc_entry.end. ++ * see ffb1b4a41016. ++ */ ++ if (orc->has_signal) { ++ entry->signal = korc.signal; ++ entry->end = korc.end; ++ } else ++ entry->end = korc.signal; /* on purpose */ ++ } ++ } ++ ++ return entry; ++} ++ ++static orc_entry * + __orc_find(ulong ip_table_ptr, ulong u_table_ptr, uint num_entries, ulong ip) + { + int index; +@@ -9128,7 +9191,7 @@ __orc_find(ulong ip_table_ptr, ulong u_table_ptr, uint num_entries, ulong ip) + int *ip_table = (int *)ip_table_ptr; + struct ORC_data *orc = &machdep->machspec->orc; + ulong vaddr; +- kernel_orc_entry *korc; ++ orc_entry *korc; + + if (CRASHDEBUG(2)) { + int i, ip_entry; +@@ -9172,18 +9235,20 @@ __orc_find(ulong ip_table_ptr, ulong u_table_ptr, uint num_entries, ulong ip) + + orc->ip_entry = (ulong)found; + orc->orc_entry = u_table_ptr + (index * SIZE(orc_entry)); +- if (!readmem(orc->orc_entry, KVADDR, &orc->kernel_orc_entry, +- sizeof(kernel_orc_entry), "kernel orc_entry", RETURN_ON_ERROR|QUIET)) ++ ++ if (!orc_get_entry(orc)) + return NULL; + +- korc = &orc->kernel_orc_entry; ++ korc = &orc->orc_entry_data; + + if (CRASHDEBUG(2)) { + fprintf(fp, " found: %lx index: %d\n", (ulong)found, index); + fprintf(fp, + " orc_entry: %lx sp_offset: %d bp_offset: %d sp_reg: %d bp_reg: %d type: %d", + orc->orc_entry, korc->sp_offset, korc->bp_offset, korc->sp_reg, korc->bp_reg, korc->type); +- if (MEMBER_EXISTS("orc_entry", "end")) ++ if (orc->has_signal) ++ fprintf(fp, " signal: %d", korc->signal); ++ if (orc->has_end) + fprintf(fp, " end: %d", korc->end); + fprintf(fp, "\n"); + } +@@ -9196,7 +9261,7 @@ __orc_find(ulong ip_table_ptr, ulong u_table_ptr, uint num_entries, ulong ip) + #define LOOKUP_START_IP (unsigned long)kt->stext + #define LOOKUP_STOP_IP (unsigned long)kt->etext + +-static kernel_orc_entry * ++static orc_entry * + orc_find(ulong ip) + { + unsigned int idx, start, stop; +@@ -9266,7 +9331,7 @@ orc_find(ulong ip) + orc->__start_orc_unwind + (start * SIZE(orc_entry)), stop - start, ip); + } + +-static kernel_orc_entry * ++static orc_entry * + orc_module_find(ulong ip) + { + struct load_module *lm; +@@ -9313,7 +9378,7 @@ static void + orc_dump(ulong ip) + { + struct ORC_data *orc = &machdep->machspec->orc; +- kernel_orc_entry *korc; ++ orc_entry *korc; + ulong vaddr, offset; + struct syment *sp, *orig; + +@@ -9336,13 +9401,15 @@ next_in_func: + fprintf(fp, "%s+%ld -> ", sp->name, offset); + else + fprintf(fp, "(unresolved) -> "); +- if (!readmem(orc->orc_entry, KVADDR, &orc->kernel_orc_entry, sizeof(kernel_orc_entry), +- "kernel orc_entry", RETURN_ON_ERROR)) ++ ++ if (!orc_get_entry(orc)) + error(FATAL, "cannot read orc_entry\n"); +- korc = &orc->kernel_orc_entry; ++ korc = &orc->orc_entry_data; + fprintf(fp, "orc: %lx spo: %d bpo: %d spr: %d bpr: %d type: %d", + orc->orc_entry, korc->sp_offset, korc->bp_offset, korc->sp_reg, korc->bp_reg, korc->type); +- if (MEMBER_EXISTS("orc_entry", "end")) ++ if (orc->has_signal) ++ fprintf(fp, " signal: %d", korc->signal); ++ if (orc->has_end) + fprintf(fp, " end: %d", korc->end); + fprintf(fp, "\n"); + +-- +2.37.1 + diff --git a/SOURCES/0003-Fix-invalid-structure-size-error-during-crash-startu.patch b/SOURCES/0003-Fix-invalid-structure-size-error-during-crash-startu.patch new file mode 100644 index 0000000..5d6a9af --- /dev/null +++ b/SOURCES/0003-Fix-invalid-structure-size-error-during-crash-startu.patch @@ -0,0 +1,48 @@ +From ec1e61b33a705b8be8d116a541c7b076b0429deb Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Mon, 12 Jun 2023 18:50:05 +0800 +Subject: [PATCH 3/5] Fix invalid structure size error during crash startup on + ppc64 + +The crash utility will fail to start session on ppc64 with the following +error: + + # crash vmlinux vmcore -s + + crash: invalid structure size: note_buf + FILE: diskdump.c LINE: 121 FUNCTION: have_crash_notes() + + [./crash] error trace: 101859ac => 10291798 => 10291450 => 10266038 + + 10266038: SIZE_verify+156 + 10291450: have_crash_notes+308 + 10291798: map_cpus_to_prstatus_kdump_cmprs+448 + 101859ac: task_init+11980 + +The reason is that the size of note_buf is not initialized before using +SIZE(note_buf) in the have_crash_notes() on some architectures including +ppc64. Let's initialize it in task_init() to fix this issue. + +Fixes: db8c030857b4 ("diskdump/netdump: fix segmentation fault caused by failure of stopping CPUs") +Signed-off-by: Lianbo Jiang +--- + task.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/task.c b/task.c +index 88941c7b0e4d..2b7467b4193d 100644 +--- a/task.c ++++ b/task.c +@@ -675,6 +675,9 @@ task_init(void) + tt->this_task = pid_to_task(active_pid); + } + else { ++ if (INVALID_SIZE(note_buf)) ++ STRUCT_SIZE_INIT(note_buf, "note_buf_t"); ++ + if (KDUMP_DUMPFILE()) + map_cpus_to_prstatus(); + else if (ELF_NOTES_VALID() && DISKDUMP_DUMPFILE()) +-- +2.37.1 + diff --git a/SOURCES/0003-Fix-kmem-v-option-displaying-no-regions-on-Linux-6.3.patch b/SOURCES/0003-Fix-kmem-v-option-displaying-no-regions-on-Linux-6.3.patch new file mode 100644 index 0000000..5a2f744 --- /dev/null +++ b/SOURCES/0003-Fix-kmem-v-option-displaying-no-regions-on-Linux-6.3.patch @@ -0,0 +1,86 @@ +From 342cf340ed0386880fe2a3115d6bef32eabb511b Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Thu, 18 May 2023 11:48:28 +0900 +Subject: [PATCH 3/6] Fix "kmem -v" option displaying no regions on Linux 6.3 + and later + +Kernel commit 869176a09606 ("mm/vmalloc.c: add flags to mark vm_map_ram +area"), which is contained in Linux 6.3 and later, added "flags" member +to struct vmap_area. This was the revival of the "flags" member as +kernel commit 688fcbfc06e4 had eliminated it before. + +As a result, crash started to use the old procedure using the member and +displays no vmalloc'd regions, because it does not have the same flag +value as the old one. + + crash> kmem -v + VMAP_AREA VM_STRUCT ADDRESS RANGE SIZE + crash> + +To fix this, also check if vmap_area.purge_list exists, which was +introduced with the flags and removed later, to determine that the flags +member is the old one. + +Related vmap_area history: + v2.6.28 db64fe02258f introduced vmap_area with flags and purge_list + v5.4 688fcbfc06e4 removed flags + v5.11 96e2db456135 removed purge_list + v6.3 869176a09606 added flags again + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 1 + + memory.c | 4 +++- + symbols.c | 1 + + 3 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/defs.h b/defs.h +index 21cc760444d1..bfa07c3f5150 100644 +--- a/defs.h ++++ b/defs.h +@@ -2216,6 +2216,7 @@ struct offset_table { /* stash of commonly-used offsets */ + long in6_addr_in6_u; + long kset_kobj; + long subsys_private_subsys; ++ long vmap_area_purge_list; + }; + + struct size_table { /* stash of commonly-used sizes */ +diff --git a/memory.c b/memory.c +index 953fc380c03c..15fa8b2f08f1 100644 +--- a/memory.c ++++ b/memory.c +@@ -429,6 +429,7 @@ vm_init(void) + MEMBER_OFFSET_INIT(vmap_area_vm, "vmap_area", "vm"); + if (INVALID_MEMBER(vmap_area_vm)) + MEMBER_OFFSET_INIT(vmap_area_vm, "vmap_area", "private"); ++ MEMBER_OFFSET_INIT(vmap_area_purge_list, "vmap_area", "purge_list"); + STRUCT_SIZE_INIT(vmap_area, "vmap_area"); + if (VALID_MEMBER(vmap_area_va_start) && + VALID_MEMBER(vmap_area_va_end) && +@@ -9063,7 +9064,8 @@ dump_vmap_area(struct meminfo *vi) + readmem(ld->list_ptr[i], KVADDR, vmap_area_buf, + SIZE(vmap_area), "vmap_area struct", FAULT_ON_ERROR); + +- if (VALID_MEMBER(vmap_area_flags)) { ++ if (VALID_MEMBER(vmap_area_flags) && ++ VALID_MEMBER(vmap_area_purge_list)) { + flags = ULONG(vmap_area_buf + OFFSET(vmap_area_flags)); + if (flags != VM_VM_AREA) + continue; +diff --git a/symbols.c b/symbols.c +index f0721023816d..7b1d59203b90 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -9169,6 +9169,7 @@ dump_offset_table(char *spec, ulong makestruct) + OFFSET(vmap_area_vm)); + fprintf(fp, " vmap_area_flags: %ld\n", + OFFSET(vmap_area_flags)); ++ fprintf(fp, " vmap_area_purge_list: %ld\n", OFFSET(vmap_area_purge_list)); + + fprintf(fp, " module_size_of_struct: %ld\n", + OFFSET(module_size_of_struct)); +-- +2.37.1 + diff --git a/SOURCES/0003-sbitmapq-fix-invalid-offset-for-sbitmap_queue_alloc_.patch b/SOURCES/0003-sbitmapq-fix-invalid-offset-for-sbitmap_queue_alloc_.patch index eb1d17f..d0c3a88 100644 --- a/SOURCES/0003-sbitmapq-fix-invalid-offset-for-sbitmap_queue_alloc_.patch +++ b/SOURCES/0003-sbitmapq-fix-invalid-offset-for-sbitmap_queue_alloc_.patch @@ -1,7 +1,7 @@ -From a295cb40cd5d24fb5995cc78d29c5def3843d285 Mon Sep 17 00:00:00 2001 +From 0242075b6b4321419790f196c405c088394b9462 Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Mon, 23 May 2022 18:04:14 +0800 -Subject: [PATCH 03/18] sbitmapq: fix invalid offset for +Subject: [PATCH 03/89] sbitmapq: fix invalid offset for "sbitmap_queue_alloc_hint" on Linux v5.13-rc1 Kernel commit c548e62bcf6a ("scsi: sbitmap: Move allocation hint @@ -21,7 +21,7 @@ Signed-off-by: Lianbo Jiang 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/defs.h b/defs.h -index a6735d07b32f..0aeb98c4f654 100644 +index 984348062bcb..8b4cc38f73bf 100644 --- a/defs.h +++ b/defs.h @@ -2168,6 +2168,7 @@ struct offset_table { /* stash of commonly-used offsets */ @@ -32,7 +32,7 @@ index a6735d07b32f..0aeb98c4f654 100644 }; struct size_table { /* stash of commonly-used sizes */ -@@ -5907,6 +5908,7 @@ struct sbitmap_context { +@@ -5915,6 +5916,7 @@ struct sbitmap_context { unsigned shift; unsigned map_nr; ulong map_addr; @@ -101,10 +101,10 @@ index 7693eef6cebd..2921d5447c65 100644 MEMBER_OFFSET_INIT(sbitmap_queue_sb, "sbitmap_queue", "sb"); MEMBER_OFFSET_INIT(sbitmap_queue_alloc_hint, "sbitmap_queue", "alloc_hint"); diff --git a/symbols.c b/symbols.c -index ba5e2741347d..fd0eb06899f0 100644 +index 4afbc227da97..d5ce3e0873a1 100644 --- a/symbols.c +++ b/symbols.c -@@ -10708,6 +10708,8 @@ dump_offset_table(char *spec, ulong makestruct) +@@ -10720,6 +10720,8 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(sbitmap_map_nr)); fprintf(fp, " sbitmap_map: %ld\n", OFFSET(sbitmap_map)); @@ -114,5 +114,5 @@ index ba5e2741347d..fd0eb06899f0 100644 OFFSET(sbitmap_queue_sb)); fprintf(fp, " sbitmap_queue_alloc_hint: %ld\n", -- -2.30.2 +2.37.1 diff --git a/SOURCES/0004-Revert-Fix-segfault-in-arm64_is_kernel_exception_fra.patch b/SOURCES/0004-Revert-Fix-segfault-in-arm64_is_kernel_exception_fra.patch new file mode 100644 index 0000000..12c0f5c --- /dev/null +++ b/SOURCES/0004-Revert-Fix-segfault-in-arm64_is_kernel_exception_fra.patch @@ -0,0 +1,68 @@ +From 91a76958e4a8a9fb67ac61166ff36e8dc961b3b9 Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Wed, 7 Jun 2023 18:37:33 +0900 +Subject: [PATCH 4/5] Revert "Fix segfault in arm64_is_kernel_exception_frame() + when corrupt stack pointer address is given" + +This reverts commit 9868ebc8e648e5791764a51567a23efae7170d9b. + +The commit 9868ebc8e648e5791764a51567a23efae7170d9b causes the issue +that bt command fails to show backtraces for the tasks that is running +in the user mode at the moment of the kernel panic as follows: + + crash> bt 1734 + PID: 1734 TASK: ffff000000392200 CPU: 4 COMMAND: "insmod" + bt: invalid stack pointer is given + +The root cause is that while the commit added a sanity check into +STACK_OFFSET_TYPE() to validate if a given candidate address of any +interrupt or exception frame is contained within the range of the +corresponding kernel stack, the premise that the STACK_OFFSET_TYPE() +should not return out-of-the-buffer address, is wrong. + +Reexamining the relevant surrounding part of the backtracing code, it +looks to me now that the STACK_OFFSET_TYPE() is originally expected to +return an out-of-the-buffer address, like the address of the top of +the corresponding kernel stack, e.g. at here: + + static int + arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame) + { + ... + if (bt->flags & BT_USER_SPACE) + start = (ulong *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(bt->stacktop))]; + else { + +Note that the above bt 1734 aborts here. + +Hence, the current implementation policy around STACK_OFFSET_TYPE() +looks that the caller side is responsible for understanding the fact +in advance and for avoiding making buffer overrun carefully. + +To fix this issue, revert the commit. + +Signed-off-by: HATAYAMA Daisuke +Signed-off-by: Lianbo Jiang +--- + defs.h | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/defs.h b/defs.h +index bfda0c48d37b..3e7d6cfbc6a8 100644 +--- a/defs.h ++++ b/defs.h +@@ -976,10 +976,7 @@ struct bt_info { + + #define STACK_OFFSET_TYPE(OFF) \ + (((ulong)(OFF) > STACKSIZE()) ? \ +- (((ulong)(OFF) < (ulong)(bt->stackbase) || (ulong)(OFF) >= (ulong)(bt->stackbase) + STACKSIZE()) ? \ +- error(FATAL, "invalid stack pointer is given\n") : \ +- (ulong)((ulong)(OFF) - (ulong)(bt->stackbase))) : \ +- (ulong)(OFF)) ++ (ulong)((ulong)(OFF) - (ulong)(bt->stackbase)) : (ulong)(OFF)) + + #define GET_STACK_ULONG(OFF) \ + *((ulong *)((char *)(&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(OFF))]))) +-- +2.37.1 + diff --git a/SOURCES/0004-arm64-x86_64-Enhance-vtop-command-to-show-zero_pfn-i.patch b/SOURCES/0004-arm64-x86_64-Enhance-vtop-command-to-show-zero_pfn-i.patch new file mode 100644 index 0000000..e3e9cae --- /dev/null +++ b/SOURCES/0004-arm64-x86_64-Enhance-vtop-command-to-show-zero_pfn-i.patch @@ -0,0 +1,225 @@ +From a0eceb041dfa248d66f9f9a455106184b7823bec Mon Sep 17 00:00:00 2001 +From: Rongwei Wang +Date: Mon, 29 May 2023 19:55:51 +0800 +Subject: [PATCH 4/6] arm64/x86_64: Enhance "vtop" command to show zero_pfn + information + +Enhance the "vtop" command to show "ZERO PAGE" information when PTE or +PMD has attached to {huge_}zero_pfn. For example: + + crash> vtop -c 13674 ffff8917e000 + VIRTUAL PHYSICAL + ffff8917e000 836e71000 + + PAGE DIRECTORY: ffff000802f8d000 + PGD: ffff000802f8dff8 => 884e29003 + PUD: ffff000844e29ff0 => 884e93003 + PMD: ffff000844e93240 => 840413003 + PTE: ffff000800413bf0 => 160000836e71fc3 + PAGE: 836e71000 (ZERO PAGE) + ... + +Hugepage case: + crash> vtop -c 14538 ffff95800000 + VIRTUAL PHYSICAL + ffff95800000 910c00000 + + PAGE DIRECTORY: ffff000801fa0000 + PGD: ffff000801fa0ff8 => 884f53003 + PUD: ffff000844f53ff0 => 8426cb003 + PMD: ffff0008026cb560 => 60000910c00fc1 + PAGE: 910c00000 (2MB, ZERO PAGE) + ... + +Note that +1. support displaying zero page only for THP (except for 1G THP) +2. do not support hugetlb cases. + +Signed-off-by: Rongwei Wang +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + arm64.c | 24 ++++++++++++++++-------- + defs.h | 5 +++++ + memory.c | 23 +++++++++++++++++++++++ + x86_64.c | 9 +++++---- + 4 files changed, 49 insertions(+), 12 deletions(-) + +diff --git a/arm64.c b/arm64.c +index 56fb841f43f8..efbdccbec9d3 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -1787,7 +1787,8 @@ arm64_vtop_2level_64k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose) + if ((pgd_val & PMD_TYPE_MASK) == PMD_TYPE_SECT) { + ulong sectionbase = (pgd_val & SECTION_PAGE_MASK_512MB) & PHYS_MASK; + if (verbose) { +- fprintf(fp, " PAGE: %lx (512MB)\n\n", sectionbase); ++ fprintf(fp, " PAGE: %lx (512MB%s)\n\n", sectionbase, ++ IS_ZEROPAGE(sectionbase) ? ", ZERO PAGE" : ""); + arm64_translate_pte(pgd_val, 0, 0); + } + *paddr = sectionbase + (vaddr & ~SECTION_PAGE_MASK_512MB); +@@ -1806,7 +1807,8 @@ arm64_vtop_2level_64k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose) + if (pte_val & PTE_VALID) { + *paddr = (PAGEBASE(pte_val) & PHYS_MASK) + PAGEOFFSET(vaddr); + if (verbose) { +- fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr)); ++ fprintf(fp, " PAGE: %lx %s\n\n", PAGEBASE(*paddr), ++ IS_ZEROPAGE(PAGEBASE(*paddr)) ? "(ZERO PAGE)" : ""); + arm64_translate_pte(pte_val, 0, 0); + } + } else { +@@ -1859,7 +1861,8 @@ arm64_vtop_3level_64k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose) + if ((pmd_val & PMD_TYPE_MASK) == PMD_TYPE_SECT) { + ulong sectionbase = PTE_TO_PHYS(pmd_val) & SECTION_PAGE_MASK_512MB; + if (verbose) { +- fprintf(fp, " PAGE: %lx (512MB)\n\n", sectionbase); ++ fprintf(fp, " PAGE: %lx (512MB%s)\n\n", sectionbase, ++ IS_ZEROPAGE(sectionbase) ? ", ZERO PAGE" : ""); + arm64_translate_pte(pmd_val, 0, 0); + } + *paddr = sectionbase + (vaddr & ~SECTION_PAGE_MASK_512MB); +@@ -1878,7 +1881,8 @@ arm64_vtop_3level_64k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose) + if (pte_val & PTE_VALID) { + *paddr = PTE_TO_PHYS(pte_val) + PAGEOFFSET(vaddr); + if (verbose) { +- fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr)); ++ fprintf(fp, " PAGE: %lx %s\n\n", PAGEBASE(*paddr), ++ IS_ZEROPAGE(PAGEBASE(*paddr)) ? "(ZERO PAGE)" : ""); + arm64_translate_pte(pte_val, 0, 0); + } + } else { +@@ -1940,7 +1944,8 @@ arm64_vtop_3level_4k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose) + if ((pmd_val & PMD_TYPE_MASK) == PMD_TYPE_SECT) { + ulong sectionbase = (pmd_val & SECTION_PAGE_MASK_2MB) & PHYS_MASK; + if (verbose) { +- fprintf(fp, " PAGE: %lx (2MB)\n\n", sectionbase); ++ fprintf(fp, " PAGE: %lx (2MB%s)\n\n", sectionbase, ++ IS_ZEROPAGE(sectionbase) ? ", ZERO PAGE" : ""); + arm64_translate_pte(pmd_val, 0, 0); + } + *paddr = sectionbase + (vaddr & ~SECTION_PAGE_MASK_2MB); +@@ -1959,7 +1964,8 @@ arm64_vtop_3level_4k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose) + if (pte_val & PTE_VALID) { + *paddr = (PAGEBASE(pte_val) & PHYS_MASK) + PAGEOFFSET(vaddr); + if (verbose) { +- fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr)); ++ fprintf(fp, " PAGE: %lx %s\n\n", PAGEBASE(*paddr), ++ IS_ZEROPAGE(PAGEBASE(*paddr)) ? "(ZERO PAGE)" : ""); + arm64_translate_pte(pte_val, 0, 0); + } + } else { +@@ -2029,7 +2035,8 @@ arm64_vtop_4level_4k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose) + if ((pmd_val & PMD_TYPE_MASK) == PMD_TYPE_SECT) { + ulong sectionbase = (pmd_val & SECTION_PAGE_MASK_2MB) & PHYS_MASK; + if (verbose) { +- fprintf(fp, " PAGE: %lx (2MB)\n\n", sectionbase); ++ fprintf(fp, " PAGE: %lx (2MB%s)\n\n", sectionbase, ++ IS_ZEROPAGE(sectionbase) ? ", ZERO PAGE" : ""); + arm64_translate_pte(pmd_val, 0, 0); + } + *paddr = sectionbase + (vaddr & ~SECTION_PAGE_MASK_2MB); +@@ -2048,7 +2055,8 @@ arm64_vtop_4level_4k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose) + if (pte_val & PTE_VALID) { + *paddr = (PAGEBASE(pte_val) & PHYS_MASK) + PAGEOFFSET(vaddr); + if (verbose) { +- fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr)); ++ fprintf(fp, " PAGE: %lx %s\n\n", PAGEBASE(*paddr), ++ IS_ZEROPAGE(PAGEBASE(*paddr)) ? "(ZERO PAGE)" : ""); + arm64_translate_pte(pte_val, 0, 0); + } + } else { +diff --git a/defs.h b/defs.h +index bfa07c3f5150..7d8bb8ab3de1 100644 +--- a/defs.h ++++ b/defs.h +@@ -2619,6 +2619,8 @@ struct vm_table { /* kernel VM-related data */ + char *name; + } *pageflags_data; + ulong max_mem_section_nr; ++ ulong zero_paddr; ++ ulong huge_zero_paddr; + }; + + #define NODES (0x1) +@@ -3000,6 +3002,9 @@ struct load_module { + #define VIRTPAGEBASE(X) (((ulong)(X)) & (ulong)machdep->pagemask) + #define PHYSPAGEBASE(X) (((physaddr_t)(X)) & (physaddr_t)machdep->pagemask) + ++#define IS_ZEROPAGE(paddr) ((paddr) == vt->zero_paddr || \ ++ (paddr) == vt->huge_zero_paddr) ++ + /* + * Sparse memory stuff + * These must follow the definitions in the kernel mmzone.h +diff --git a/memory.c b/memory.c +index 15fa8b2f08f1..ea3005a5c01f 100644 +--- a/memory.c ++++ b/memory.c +@@ -1209,6 +1209,27 @@ vm_init(void) + machdep->memory_size())); + vt->paddr_prlen = strlen(buf); + ++ vt->zero_paddr = ~0UL; ++ if (kernel_symbol_exists("zero_pfn")) { ++ ulong zero_pfn; ++ ++ if (readmem(symbol_value("zero_pfn"), KVADDR, ++ &zero_pfn, sizeof(zero_pfn), ++ "read zero_pfn", QUIET|RETURN_ON_ERROR)) ++ vt->zero_paddr = zero_pfn << PAGESHIFT(); ++ } ++ ++ vt->huge_zero_paddr = ~0UL; ++ if (kernel_symbol_exists("huge_zero_pfn")) { ++ ulong huge_zero_pfn; ++ ++ if (readmem(symbol_value("huge_zero_pfn"), KVADDR, ++ &huge_zero_pfn, sizeof(huge_zero_pfn), ++ "read huge_zero_pfn", QUIET|RETURN_ON_ERROR) && ++ huge_zero_pfn != ~0UL) ++ vt->huge_zero_paddr = huge_zero_pfn << PAGESHIFT(); ++ } ++ + if (vt->flags & PERCPU_KMALLOC_V1) + vt->dump_kmem_cache = dump_kmem_cache_percpu_v1; + else if (vt->flags & PERCPU_KMALLOC_V2) +@@ -14065,6 +14086,8 @@ dump_vm_table(int verbose) + } else { + fprintf(fp, " node_online_map: (unused)\n"); + } ++ fprintf(fp, " zero_paddr: %lx\n", vt->zero_paddr); ++ fprintf(fp, " huge_zero_paddr: %lx\n", vt->huge_zero_paddr); + fprintf(fp, " nr_vm_stat_items: %d\n", vt->nr_vm_stat_items); + fprintf(fp, " vm_stat_items: %s", (vt->flags & VM_STAT) ? + "\n" : "(not used)\n"); +diff --git a/x86_64.c b/x86_64.c +index 5019c69e452e..693a08bea758 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -2114,8 +2114,9 @@ x86_64_uvtop_level4(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, in + goto no_upage; + if (pmd_pte & _PAGE_PSE) { + if (verbose) { +- fprintf(fp, " PAGE: %lx (2MB)\n\n", +- PAGEBASE(pmd_pte) & PHYSICAL_PAGE_MASK); ++ fprintf(fp, " PAGE: %lx (2MB%s)\n\n", ++ PAGEBASE(pmd_pte) & PHYSICAL_PAGE_MASK, ++ IS_ZEROPAGE(PAGEBASE(pmd_pte) & PHYSICAL_PAGE_MASK) ? ", ZERO PAGE" : ""); + x86_64_translate_pte(pmd_pte, 0, 0); + } + +@@ -2143,8 +2144,8 @@ x86_64_uvtop_level4(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, in + *paddr = (PAGEBASE(pte) & PHYSICAL_PAGE_MASK) + PAGEOFFSET(uvaddr); + + if (verbose) { +- fprintf(fp, " PAGE: %lx\n\n", +- PAGEBASE(*paddr) & PHYSICAL_PAGE_MASK); ++ fprintf(fp, " PAGE: %lx %s\n\n", PAGEBASE(*paddr) & PHYSICAL_PAGE_MASK, ++ IS_ZEROPAGE(PAGEBASE(*paddr) & PHYSICAL_PAGE_MASK) ? "(ZERO PAGE)" : ""); + x86_64_translate_pte(pte, 0, 0); + } + +-- +2.37.1 + diff --git a/SOURCES/0004-sbitmapq-fix-invalid-offset-for-sbitmap_queue_round_.patch b/SOURCES/0004-sbitmapq-fix-invalid-offset-for-sbitmap_queue_round_.patch index 1a2b611..e44b922 100644 --- a/SOURCES/0004-sbitmapq-fix-invalid-offset-for-sbitmap_queue_round_.patch +++ b/SOURCES/0004-sbitmapq-fix-invalid-offset-for-sbitmap_queue_round_.patch @@ -1,7 +1,7 @@ -From 530fe6ad7e4d7ff6254596c1219d25ed929e3867 Mon Sep 17 00:00:00 2001 +From ccdf0e45c66ca0bbe3eb468c661b405971801c2e Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Mon, 23 May 2022 18:04:15 +0800 -Subject: [PATCH 04/18] sbitmapq: fix invalid offset for +Subject: [PATCH 04/89] sbitmapq: fix invalid offset for "sbitmap_queue_round_robin" on Linux v5.13-rc1 Kernel commit efe1f3a1d583 ("scsi: sbitmap: Maintain allocation @@ -22,7 +22,7 @@ Signed-off-by: Lianbo Jiang 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/defs.h b/defs.h -index 0aeb98c4f654..ecbced24d2e3 100644 +index 8b4cc38f73bf..66f74f640d84 100644 --- a/defs.h +++ b/defs.h @@ -2169,6 +2169,7 @@ struct offset_table { /* stash of commonly-used offsets */ @@ -33,7 +33,7 @@ index 0aeb98c4f654..ecbced24d2e3 100644 }; struct size_table { /* stash of commonly-used sizes */ -@@ -5909,6 +5910,7 @@ struct sbitmap_context { +@@ -5917,6 +5918,7 @@ struct sbitmap_context { unsigned map_nr; ulong map_addr; ulong alloc_hint; @@ -86,10 +86,10 @@ index 2921d5447c65..7b318b533702 100644 MEMBER_OFFSET_INIT(sbitmap_queue_sb, "sbitmap_queue", "sb"); MEMBER_OFFSET_INIT(sbitmap_queue_alloc_hint, "sbitmap_queue", "alloc_hint"); diff --git a/symbols.c b/symbols.c -index fd0eb06899f0..5d12a021c769 100644 +index d5ce3e0873a1..7431aaecec9d 100644 --- a/symbols.c +++ b/symbols.c -@@ -10710,6 +10710,8 @@ dump_offset_table(char *spec, ulong makestruct) +@@ -10722,6 +10722,8 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(sbitmap_map)); fprintf(fp, " sbitmap_alloc_hint: %ld\n", OFFSET(sbitmap_alloc_hint)); @@ -99,5 +99,5 @@ index fd0eb06899f0..5d12a021c769 100644 OFFSET(sbitmap_queue_sb)); fprintf(fp, " sbitmap_queue_alloc_hint: %ld\n", -- -2.30.2 +2.37.1 diff --git a/SOURCES/0005-arm64-Fix-again-segfault-in-arm64_is_kernel_exceptio.patch b/SOURCES/0005-arm64-Fix-again-segfault-in-arm64_is_kernel_exceptio.patch new file mode 100644 index 0000000..1526ec3 --- /dev/null +++ b/SOURCES/0005-arm64-Fix-again-segfault-in-arm64_is_kernel_exceptio.patch @@ -0,0 +1,45 @@ +From 6c8cd9b5dcf48221e5f75fc5850bb4719d77acce Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Wed, 7 Jun 2023 18:37:34 +0900 +Subject: [PATCH 5/5] arm64: Fix again segfault in + arm64_is_kernel_exception_frame() when corrupt stack pointer address is given + +This is the second trial from the commit +9868ebc8e648e5791764a51567a23efae7170d9b that was reverted at the +previous commit. + +As described in the previous commit, result of STACK_OFFSET_TYPE() can +be an address out of bt->stackbuf and hence the address needs to be +checked prior to being referred to as an pt_regs object. + +So, to fix the issue, let's check if stkptr points to within the range +of the kernel stack first. + +[ kh: added a warning at Lianbo's suggestion ] + +Signed-off-by: HATAYAMA Daisuke +Signed-off-by: Lianbo Jiang +--- + arm64.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arm64.c b/arm64.c +index efbdccbec9d3..67b1a2244810 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -2381,6 +2381,12 @@ arm64_is_kernel_exception_frame(struct bt_info *bt, ulong stkptr) + struct arm64_pt_regs *regs; + struct machine_specific *ms = machdep->machspec; + ++ if (stkptr > STACKSIZE() && !INSTACK(stkptr, bt)) { ++ if (CRASHDEBUG(1)) ++ error(WARNING, "stkptr: %lx is outside the kernel stack range\n", stkptr); ++ return FALSE; ++ } ++ + regs = (struct arm64_pt_regs *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(stkptr))]; + + if (INSTACK(regs->sp, bt) && INSTACK(regs->regs[29], bt) && +-- +2.37.1 + diff --git a/SOURCES/0005-diskdump-netdump-fix-segmentation-fault-caused-by-fa.patch b/SOURCES/0005-diskdump-netdump-fix-segmentation-fault-caused-by-fa.patch new file mode 100644 index 0000000..9b70742 --- /dev/null +++ b/SOURCES/0005-diskdump-netdump-fix-segmentation-fault-caused-by-fa.patch @@ -0,0 +1,165 @@ +From db8c030857b4e318728c51c20da687906c109d0d Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Tue, 30 May 2023 19:38:34 +0900 +Subject: [PATCH 5/6] diskdump/netdump: fix segmentation fault caused by + failure of stopping CPUs + +There's no NMI on ARM. Hence, stopping the non-panicking CPUs from the +panicking CPU via IPI can fail easily if interrupts are being masked +in those moment. Moreover, crash_notes are not initialized for such +unstopped CPUs and the corresponding NT_PRSTATUS notes are not +attached to vmcore. However, crash utility never takes it +consideration such uninitialized crash_notes and then ends with +mapping different NT_PRSTATUS to actually unstopped CPUs. This corrupt +mapping can result crash utility into segmentation fault in the +operations where register values in NT_PRSTATUS notes are used. + +For example: + + crash> bt 1408 + PID: 1408 TASK: ffff000003e22200 CPU: 2 COMMAND: "repro" + Segmentation fault (core dumped) + + crash> help -D + diskdump_data: + filename: 127.0.0.1-2023-05-26-02:21:27/vmcore-ld1 + flags: 46 (KDUMP_CMPRS_LOCAL|ERROR_EXCLUDED|LZO_SUPPORTED) + ...snip... + notes_buf: 1815df0 + num_vmcoredd_notes: 0 + num_prstatus_notes: 5 + notes[0]: 1815df0 (NT_PRSTATUS) + si.signo: 0 si.code: 0 si.errno: 0 + ...snip... + PSTATE: 80400005 FPVALID: 00000000 + notes[4]: 1808f10 (NT_PRSTATUS) + Segmentation fault (core dumped) + +To fix this issue, let's map NT_PRSTATUS to some CPU only if the +corresponding crash_notes is checked to be initialized. + +[ kh: moved existence check for crash_notes out of the loop ] + +Signed-off-by: HATAYAMA Daisuke +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 1 + + diskdump.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- + netdump.c | 7 ++++++- + 3 files changed, 51 insertions(+), 2 deletions(-) + +diff --git a/defs.h b/defs.h +index 7d8bb8ab3de1..6520d2f13f48 100644 +--- a/defs.h ++++ b/defs.h +@@ -7118,6 +7118,7 @@ int dumpfile_is_split(void); + void show_split_dumpfiles(void); + void x86_process_elf_notes(void *, unsigned long); + void *diskdump_get_prstatus_percpu(int); ++int have_crash_notes(int cpu); + void map_cpus_to_prstatus_kdump_cmprs(void); + void diskdump_display_regs(int, FILE *); + void process_elf32_notes(void *, ulong); +diff --git a/diskdump.c b/diskdump.c +index 94bca4ded572..2c284ff3f97f 100644 +--- a/diskdump.c ++++ b/diskdump.c +@@ -101,12 +101,54 @@ int dumpfile_is_split(void) + return KDUMP_SPLIT(); + } + ++int have_crash_notes(int cpu) ++{ ++ ulong crash_notes, notes_ptr; ++ char *buf, *p; ++ Elf64_Nhdr *note = NULL; ++ ++ if (!readmem(symbol_value("crash_notes"), KVADDR, &crash_notes, ++ sizeof(crash_notes), "crash_notes", RETURN_ON_ERROR)) { ++ error(WARNING, "cannot read \"crash_notes\"\n"); ++ return FALSE; ++ } ++ ++ if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) ++ notes_ptr = crash_notes + kt->__per_cpu_offset[cpu]; ++ else ++ notes_ptr = crash_notes; ++ ++ buf = GETBUF(SIZE(note_buf)); ++ ++ if (!readmem(notes_ptr, KVADDR, buf, ++ SIZE(note_buf), "note_buf_t", RETURN_ON_ERROR)) { ++ error(WARNING, "cpu %d: cannot read NT_PRSTATUS note\n", cpu); ++ return FALSE; ++ } ++ ++ note = (Elf64_Nhdr *)buf; ++ p = buf + sizeof(Elf64_Nhdr); ++ ++ if (note->n_type != NT_PRSTATUS) { ++ error(WARNING, "cpu %d: invalid NT_PRSTATUS note (n_type != NT_PRSTATUS)\n", cpu); ++ return FALSE; ++ } ++ ++ if (!STRNEQ(p, "CORE")) { ++ error(WARNING, "cpu %d: invalid NT_PRSTATUS note (name != \"CORE\")\n", cpu); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ + void + map_cpus_to_prstatus_kdump_cmprs(void) + { + void **nt_ptr; + int online, i, j, nrcpus; + size_t size; ++ int crash_notes_exists; + + if (pc->flags2 & QEMU_MEM_DUMP_COMPRESSED) /* notes exist for all cpus */ + goto resize_note_pointers; +@@ -129,9 +171,10 @@ map_cpus_to_prstatus_kdump_cmprs(void) + * Re-populate the array with the notes mapping to online cpus + */ + nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS); ++ crash_notes_exists = kernel_symbol_exists("crash_notes"); + + for (i = 0, j = 0; i < nrcpus; i++) { +- if (in_cpu_map(ONLINE_MAP, i)) { ++ if (in_cpu_map(ONLINE_MAP, i) && (!crash_notes_exists || have_crash_notes(i))) { + dd->nt_prstatus_percpu[i] = nt_ptr[j++]; + dd->num_prstatus_notes = + MAX(dd->num_prstatus_notes, i+1); +diff --git a/netdump.c b/netdump.c +index 4eba66cecb55..61ddeaa08831 100644 +--- a/netdump.c ++++ b/netdump.c +@@ -75,6 +75,7 @@ map_cpus_to_prstatus(void) + void **nt_ptr; + int online, i, j, nrcpus; + size_t size; ++ int crash_notes_exists; + + if (pc->flags2 & QEMU_MEM_DUMP_ELF) /* notes exist for all cpus */ + return; +@@ -97,10 +98,14 @@ map_cpus_to_prstatus(void) + * Re-populate the array with the notes mapping to online cpus + */ + nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS); ++ crash_notes_exists = kernel_symbol_exists("crash_notes"); + + for (i = 0, j = 0; i < nrcpus; i++) { +- if (in_cpu_map(ONLINE_MAP, i)) ++ if (in_cpu_map(ONLINE_MAP, i) && (!crash_notes_exists || have_crash_notes(i))) { + nd->nt_prstatus_percpu[i] = nt_ptr[j++]; ++ nd->num_prstatus_notes = ++ MAX(nd->num_prstatus_notes, i+1); ++ } + } + + FREEBUF(nt_ptr); +-- +2.37.1 + diff --git a/SOURCES/0005-sbitmapq-fix-invalid-offset-for-sbitmap_word_depth-o.patch b/SOURCES/0005-sbitmapq-fix-invalid-offset-for-sbitmap_word_depth-o.patch index 838fb5b..89bf994 100644 --- a/SOURCES/0005-sbitmapq-fix-invalid-offset-for-sbitmap_word_depth-o.patch +++ b/SOURCES/0005-sbitmapq-fix-invalid-offset-for-sbitmap_word_depth-o.patch @@ -1,7 +1,7 @@ -From 3750803f6ae5f5ad071f86ca916dbbb17b7a83a5 Mon Sep 17 00:00:00 2001 +From 0637e7bee77f127ff6a36fc7a9e52408a3106173 Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Mon, 23 May 2022 18:04:16 +0800 -Subject: [PATCH 05/18] sbitmapq: fix invalid offset for "sbitmap_word_depth" +Subject: [PATCH 05/89] sbitmapq: fix invalid offset for "sbitmap_word_depth" on Linux v5.18-rc1 Kernel commit 3301bc53358a ("lib/sbitmap: kill 'depth' from sbitmap_word") @@ -97,5 +97,5 @@ index 7b318b533702..e8ebd62fe01c 100644 scanned += depth; word = w_word & ~w_cleared; -- -2.30.2 +2.37.1 diff --git a/SOURCES/0006-Fix-segfault-in-arm64_is_kernel_exception_frame-when.patch b/SOURCES/0006-Fix-segfault-in-arm64_is_kernel_exception_frame-when.patch new file mode 100644 index 0000000..230738d --- /dev/null +++ b/SOURCES/0006-Fix-segfault-in-arm64_is_kernel_exception_frame-when.patch @@ -0,0 +1,62 @@ +From 9868ebc8e648e5791764a51567a23efae7170d9b Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Tue, 30 May 2023 19:38:35 +0900 +Subject: [PATCH 6/6] Fix segfault in arm64_is_kernel_exception_frame() when + corrupt stack pointer address is given + +Due to the corrupted mapping fixed by the previous commit, +arm64_is_kernel_exception_frame() can receive invalid stack pointer +address via the 2nd argument; different NT_PRSTATUS contains different +task's stack pointer address. However, macro STACK_OFFSET_TYPE() never +checks if a given address is within the range of the kernel stack of +the corresponding task and hence can result in referring to outside of +bt->stackbuf. + + static int + arm64_is_kernel_exception_frame(struct bt_info *bt, ulong stkptr) + { + struct arm64_pt_regs *regs; + struct machine_specific *ms = machdep->machspec; + + regs = (struct arm64_pt_regs *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(stkptr))]; + + => if (INSTACK(regs->sp, bt) && INSTACK(regs->regs[29], bt) && + !(regs->pstate & (0xffffffff00000000ULL | PSR_MODE32_BIT)) && + is_kernel_text(regs->pc) && + is_kernel_text(regs->regs[30] | ms->CONFIG_ARM64_KERNELPACMASK)) { + +To fix this issue, check if the given stack pointer address points to +the range of the kernel stack of the corresponding task, and abort if +it turns out to be invalid. + +Although the corrupted mapping has already been fixed, this fix is +still needed because corrupt stack pointer address can still be passed +here from different reasons. Consider, for example, that data on the +kernel stack can be modified abnormally due to any kernel bugs or +hardware issues. + +Signed-off-by: HATAYAMA Daisuke +Signed-off-by: Lianbo Jiang +--- + defs.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/defs.h b/defs.h +index 6520d2f13f48..11fdc17e60d0 100644 +--- a/defs.h ++++ b/defs.h +@@ -976,7 +976,10 @@ struct bt_info { + + #define STACK_OFFSET_TYPE(OFF) \ + (((ulong)(OFF) > STACKSIZE()) ? \ +- (ulong)((ulong)(OFF) - (ulong)(bt->stackbase)) : (ulong)(OFF)) ++ (((ulong)(OFF) < (ulong)(bt->stackbase) || (ulong)(OFF) >= (ulong)(bt->stackbase) + STACKSIZE()) ? \ ++ error(FATAL, "invalid stack pointer is given\n") : \ ++ (ulong)((ulong)(OFF) - (ulong)(bt->stackbase))) : \ ++ (ulong)(OFF)) + + #define GET_STACK_ULONG(OFF) \ + *((ulong *)((char *)(&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(OFF))]))) +-- +2.37.1 + diff --git a/SOURCES/0007-bt-x86_64-filter-out-idle-task-stack.patch b/SOURCES/0006-bt-x86_64-filter-out-idle-task-stack.patch similarity index 92% rename from SOURCES/0007-bt-x86_64-filter-out-idle-task-stack.patch rename to SOURCES/0006-bt-x86_64-filter-out-idle-task-stack.patch index ebbc530..6d44a47 100644 --- a/SOURCES/0007-bt-x86_64-filter-out-idle-task-stack.patch +++ b/SOURCES/0006-bt-x86_64-filter-out-idle-task-stack.patch @@ -1,7 +1,7 @@ -From 6833262bf87177d8affe4f91b2e7d2c76ecdf636 Mon Sep 17 00:00:00 2001 +From 3ce590be037dc11c31a013e435484926276eee9f Mon Sep 17 00:00:00 2001 From: Qi Zheng Date: Tue, 24 May 2022 20:25:53 +0800 -Subject: [PATCH 07/18] bt: x86_64: filter out idle task stack +Subject: [PATCH 06/89] bt: x86_64: filter out idle task stack When we use crash to troubleshoot softlockup and other problems, we often use the 'bt -a' command to print the stacks of running @@ -62,10 +62,10 @@ Signed-off-by: Lianbo Jiang 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/defs.h b/defs.h -index ecbced24d2e3..c8444b4e54eb 100644 +index 66f74f640d84..52e4b14aa27c 100644 --- a/defs.h +++ b/defs.h -@@ -5832,6 +5832,7 @@ ulong cpu_map_addr(const char *type); +@@ -5840,6 +5840,7 @@ ulong cpu_map_addr(const char *type); #define BT_SHOW_ALL_REGS (0x2000000000000ULL) #define BT_REGS_NOT_FOUND (0x4000000000000ULL) #define BT_OVERFLOW_STACK (0x8000000000000ULL) @@ -74,10 +74,10 @@ index ecbced24d2e3..c8444b4e54eb 100644 #define BT_REF_HEXVAL (0x1) diff --git a/help.c b/help.c -index 51a0fe3d687c..e1bbc5abe029 100644 +index 00712a690593..00c833da13cc 100644 --- a/help.c +++ b/help.c -@@ -1909,12 +1909,14 @@ char *help_bt[] = { +@@ -1915,12 +1915,14 @@ char *help_bt[] = { "bt", "backtrace", "[-a|-c cpu(s)|-g|-r|-t|-T|-l|-e|-E|-f|-F|-o|-O|-v|-p] [-R ref] [-s [-x|d]]" @@ -93,7 +93,7 @@ index 51a0fe3d687c..e1bbc5abe029 100644 " -p display the stack trace of the panic task only.", " (only applicable to crash dumps)", " -c cpu display the stack trace of the active task on one or more CPUs,", -@@ -2004,6 +2006,35 @@ char *help_bt[] = { +@@ -2010,6 +2012,35 @@ char *help_bt[] = { " DS: 002b ESI: bfffc8a0 ES: 002b EDI: 00000000 ", " SS: 002b ESP: bfffc82c EBP: bfffd224 ", " CS: 0023 EIP: 400d032e ERR: 0000008e EFLAGS: 00000246 ", @@ -130,7 +130,7 @@ index 51a0fe3d687c..e1bbc5abe029 100644 " %s> bt -c 0,1", " PID: 0 TASK: ffffffff81a8d020 CPU: 0 COMMAND: \"swapper\"", diff --git a/kernel.c b/kernel.c -index d0921cf567d9..411e9da1e54f 100644 +index 9ae7ee1ebe64..185b09335733 100644 --- a/kernel.c +++ b/kernel.c @@ -2503,7 +2503,7 @@ cmd_bt(void) @@ -168,10 +168,10 @@ index d0921cf567d9..411e9da1e54f 100644 bt->stkptr = esp; return; diff --git a/x86_64.c b/x86_64.c -index ecaefd2f46a8..cfafbcc4dabe 100644 +index 1305afd791a1..f4e5d9e77cef 100644 --- a/x86_64.c +++ b/x86_64.c -@@ -4918,6 +4918,9 @@ x86_64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp) +@@ -4915,6 +4915,9 @@ x86_64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp) if (bt->flags & BT_DUMPFILE_SEARCH) return x86_64_get_dumpfile_stack_frame(bt, pcp, spp); @@ -181,7 +181,7 @@ index ecaefd2f46a8..cfafbcc4dabe 100644 if (pcp) *pcp = x86_64_get_pc(bt); if (spp) -@@ -4960,6 +4963,9 @@ x86_64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *rip, ulong *rsp) +@@ -4957,6 +4960,9 @@ x86_64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *rip, ulong *rsp) estack = -1; panic = FALSE; @@ -191,7 +191,7 @@ index ecaefd2f46a8..cfafbcc4dabe 100644 panic_task = tt->panic_task == bt->task ? TRUE : FALSE; if (panic_task && bt->machdep) { -@@ -5098,6 +5104,8 @@ next_sysrq: +@@ -5095,6 +5101,8 @@ next_sysrq: if (!panic_task && STREQ(sym, "crash_nmi_callback")) { *rip = *up; *rsp = bt->stackbase + ((char *)(up) - bt->stackbuf); @@ -201,5 +201,5 @@ index ecaefd2f46a8..cfafbcc4dabe 100644 } -- -2.30.2 +2.37.1 diff --git a/SOURCES/0008-bt-arm64-add-support-for-bt-n-idle.patch b/SOURCES/0007-bt-arm64-add-support-for-bt-n-idle.patch similarity index 91% rename from SOURCES/0008-bt-arm64-add-support-for-bt-n-idle.patch rename to SOURCES/0007-bt-arm64-add-support-for-bt-n-idle.patch index 4712ac4..20d4bc5 100644 --- a/SOURCES/0008-bt-arm64-add-support-for-bt-n-idle.patch +++ b/SOURCES/0007-bt-arm64-add-support-for-bt-n-idle.patch @@ -1,7 +1,7 @@ -From 0f162febebc4d11a165dd40cee00f3b0ba691a52 Mon Sep 17 00:00:00 2001 +From f436ae7f01db8ec13080f41a2754b2d282166ed7 Mon Sep 17 00:00:00 2001 From: Qi Zheng Date: Tue, 24 May 2022 20:25:54 +0800 -Subject: [PATCH 08/18] bt: arm64: add support for 'bt -n idle' +Subject: [PATCH 07/89] bt: arm64: add support for 'bt -n idle' The '-n idle' option of bt command can help us filter the stack of the idle process when debugging the dumpfiles @@ -65,10 +65,10 @@ index 65f6cdf69fa6..0f615cf52bef 100644 if (!ret) error(WARNING, diff --git a/help.c b/help.c -index e1bbc5abe029..99214c1590fa 100644 +index 00c833da13cc..e1ac6f93fde2 100644 --- a/help.c +++ b/help.c -@@ -1915,7 +1915,7 @@ char *help_bt[] = { +@@ -1921,7 +1921,7 @@ char *help_bt[] = { " -a displays the stack traces of the active task on each CPU.", " (only applicable to crash dumps)", " -A same as -a, but also displays vector registers (S390X only).", @@ -78,7 +78,7 @@ index e1bbc5abe029..99214c1590fa 100644 " -p display the stack trace of the panic task only.", " (only applicable to crash dumps)", diff --git a/kernel.c b/kernel.c -index 411e9da1e54f..a521ef30cdb0 100644 +index 185b09335733..bd0bf8c6cf03 100644 --- a/kernel.c +++ b/kernel.c @@ -2673,7 +2673,8 @@ cmd_bt(void) @@ -92,5 +92,5 @@ index 411e9da1e54f..a521ef30cdb0 100644 else option_not_supported(c); -- -2.30.2 +2.37.1 diff --git a/SOURCES/0010-Enhance-dev-d-D-options-to-support-blk-mq-sbitmap.patch b/SOURCES/0008-Enhance-dev-d-D-options-to-support-blk-mq-sbitmap.patch similarity index 96% rename from SOURCES/0010-Enhance-dev-d-D-options-to-support-blk-mq-sbitmap.patch rename to SOURCES/0008-Enhance-dev-d-D-options-to-support-blk-mq-sbitmap.patch index 6e8b008..2f9028b 100644 --- a/SOURCES/0010-Enhance-dev-d-D-options-to-support-blk-mq-sbitmap.patch +++ b/SOURCES/0008-Enhance-dev-d-D-options-to-support-blk-mq-sbitmap.patch @@ -1,7 +1,7 @@ -From 7095c8fd029e3a33117e3b67de73f504686ebfe2 Mon Sep 17 00:00:00 2001 +From 0a988a8b46741aad6f2503163735ae72485cd04f Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Thu, 2 Jun 2022 20:12:55 +0800 -Subject: [PATCH 10/18] Enhance "dev -d|-D" options to support blk-mq sbitmap +Subject: [PATCH 08/89] Enhance "dev -d|-D" options to support blk-mq sbitmap Since Linux 5.16-rc1, which kernel commit 9a14d6ce4135 ("block: remove debugfs blk_mq_ctx dispatched/merged/completed attributes") removed the @@ -19,7 +19,7 @@ Signed-off-by: Kazuhito Hagio 3 files changed, 238 insertions(+), 39 deletions(-) diff --git a/defs.h b/defs.h -index c8444b4e54eb..2681586a33dc 100644 +index 52e4b14aa27c..f2b6ab14c6aa 100644 --- a/defs.h +++ b/defs.h @@ -2170,6 +2170,16 @@ struct offset_table { /* stash of commonly-used offsets */ @@ -337,10 +337,10 @@ index a493e51ac95c..4be4c96df8b0 100644 MEMBER_OFFSET_INIT(subsys_private_klist_devices, "subsys_private", "klist_devices"); diff --git a/symbols.c b/symbols.c -index 5d12a021c769..c1f09556d710 100644 +index 7431aaecec9d..520debdb311e 100644 --- a/symbols.c +++ b/symbols.c -@@ -10385,6 +10385,12 @@ dump_offset_table(char *spec, ulong makestruct) +@@ -10397,6 +10397,12 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(kset_list)); fprintf(fp, " request_list_count: %ld\n", OFFSET(request_list_count)); @@ -353,7 +353,7 @@ index 5d12a021c769..c1f09556d710 100644 fprintf(fp, " request_queue_in_flight: %ld\n", OFFSET(request_queue_in_flight)); fprintf(fp, " request_queue_rq: %ld\n", -@@ -10393,10 +10399,25 @@ dump_offset_table(char *spec, ulong makestruct) +@@ -10405,10 +10411,25 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(request_queue_mq_ops)); fprintf(fp, " request_queue_queue_ctx: %ld\n", OFFSET(request_queue_queue_ctx)); @@ -379,7 +379,7 @@ index 5d12a021c769..c1f09556d710 100644 fprintf(fp, " subsys_private_klist_devices: %ld\n", OFFSET(subsys_private_klist_devices)); fprintf(fp, " subsystem_kset: %ld\n", -@@ -11003,6 +11024,7 @@ dump_offset_table(char *spec, ulong makestruct) +@@ -11015,6 +11036,7 @@ dump_offset_table(char *spec, ulong makestruct) fprintf(fp, " sbitmap: %ld\n", SIZE(sbitmap)); fprintf(fp, " sbitmap_queue: %ld\n", SIZE(sbitmap_queue)); fprintf(fp, " sbq_wait_state: %ld\n", SIZE(sbq_wait_state)); @@ -388,5 +388,5 @@ index 5d12a021c769..c1f09556d710 100644 fprintf(fp, "\n array_table:\n"); /* -- -2.30.2 +2.37.1 diff --git a/SOURCES/0011-Fix-for-dev-d-D-options-to-support-blk-mq-change-on-.patch b/SOURCES/0009-Fix-for-dev-d-D-options-to-support-blk-mq-change-on-.patch similarity index 93% rename from SOURCES/0011-Fix-for-dev-d-D-options-to-support-blk-mq-change-on-.patch rename to SOURCES/0009-Fix-for-dev-d-D-options-to-support-blk-mq-change-on-.patch index 6167735..1675a90 100644 --- a/SOURCES/0011-Fix-for-dev-d-D-options-to-support-blk-mq-change-on-.patch +++ b/SOURCES/0009-Fix-for-dev-d-D-options-to-support-blk-mq-change-on-.patch @@ -1,7 +1,7 @@ -From 68ce0b9a35d77d767872dd1a729c50e4695a30a8 Mon Sep 17 00:00:00 2001 +From 7b91ac6d20b741c1c8487a04d2b9d8aee5772471 Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Thu, 2 Jun 2022 20:12:56 +0800 -Subject: [PATCH 11/18] Fix for "dev -d|-D" options to support blk-mq change on +Subject: [PATCH 09/89] Fix for "dev -d|-D" options to support blk-mq change on Linux v5.18-rc1 Kernel commit 4e5cc99e1e48 ("blk-mq: manage hctx map via xarray") removed @@ -27,7 +27,7 @@ Signed-off-by: Lianbo Jiang 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/defs.h b/defs.h -index 2681586a33dc..7d3b73422f48 100644 +index f2b6ab14c6aa..c524a05d8105 100644 --- a/defs.h +++ b/defs.h @@ -2180,6 +2180,7 @@ struct offset_table { /* stash of commonly-used offsets */ @@ -104,10 +104,10 @@ index 4be4c96df8b0..0172c83ffaea 100644 "rq_dispatched"); MEMBER_OFFSET_INIT(blk_mq_ctx_rq_completed, "blk_mq_ctx", diff --git a/symbols.c b/symbols.c -index c1f09556d710..bee1faf92c83 100644 +index 520debdb311e..69004a2e66e3 100644 --- a/symbols.c +++ b/symbols.c -@@ -10403,6 +10403,8 @@ dump_offset_table(char *spec, ulong makestruct) +@@ -10415,6 +10415,8 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(request_queue_queue_hw_ctx)); fprintf(fp, " request_queue_nr_hw_queues: %ld\n", OFFSET(request_queue_nr_hw_queues)); @@ -117,5 +117,5 @@ index c1f09556d710..bee1faf92c83 100644 OFFSET(blk_mq_ctx_rq_dispatched)); fprintf(fp, " blk_mq_ctx_rq_completed: %ld\n", -- -2.30.2 +2.37.1 diff --git a/SOURCES/0012-Doc-update-man-page-for-the-bpf-and-sbitmapq-command.patch b/SOURCES/0010-Doc-update-man-page-for-the-bpf-and-sbitmapq-command.patch similarity index 89% rename from SOURCES/0012-Doc-update-man-page-for-the-bpf-and-sbitmapq-command.patch rename to SOURCES/0010-Doc-update-man-page-for-the-bpf-and-sbitmapq-command.patch index fc436ae..589d92d 100644 --- a/SOURCES/0012-Doc-update-man-page-for-the-bpf-and-sbitmapq-command.patch +++ b/SOURCES/0010-Doc-update-man-page-for-the-bpf-and-sbitmapq-command.patch @@ -1,7 +1,7 @@ -From c672d7a4c290712b32c54329cbdc1e74d122e813 Mon Sep 17 00:00:00 2001 +From 2d9e180858b3212507fcba7a7cb9d13f6a935a2f Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Mon, 6 Jun 2022 19:09:16 +0800 -Subject: [PATCH 12/18] Doc: update man page for the "bpf" and "sbitmapq" +Subject: [PATCH 10/89] Doc: update man page for the "bpf" and "sbitmapq" commands The information of the "bpf" and "sbitmapq" commands is missing in the man @@ -39,5 +39,5 @@ index 1f3657b11e4c..e553a0b4adb3 100644 searches a range of user or kernel memory space for given value. .TP -- -2.30.2 +2.37.1 diff --git a/SOURCES/0013-sbitmapq-Fix-for-sbitmap_queue-without-ws_active-mem.patch b/SOURCES/0011-sbitmapq-Fix-for-sbitmap_queue-without-ws_active-mem.patch similarity index 93% rename from SOURCES/0013-sbitmapq-Fix-for-sbitmap_queue-without-ws_active-mem.patch rename to SOURCES/0011-sbitmapq-Fix-for-sbitmap_queue-without-ws_active-mem.patch index c9d7b95..7a64e49 100644 --- a/SOURCES/0013-sbitmapq-Fix-for-sbitmap_queue-without-ws_active-mem.patch +++ b/SOURCES/0011-sbitmapq-Fix-for-sbitmap_queue-without-ws_active-mem.patch @@ -1,7 +1,7 @@ -From 9ce31a14d1083cbb2beb4a8e6eb7b88234b79a99 Mon Sep 17 00:00:00 2001 +From aff3d6e19c9a9ffe4e5d55850aa42a4dc9cf0485 Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 10 Jun 2022 11:49:47 +0900 -Subject: [PATCH 13/18] sbitmapq: Fix for sbitmap_queue without ws_active +Subject: [PATCH 11/89] sbitmapq: Fix for sbitmap_queue without ws_active member The sbitmap_queue.ws_active member was added by kernel commit 5d2ee7122c73 @@ -44,5 +44,5 @@ index e8ebd62fe01c..152c28e6875f 100644 sqc->round_robin = BOOL(sbitmap_queue_buf + OFFSET(sbitmap_queue_round_robin)); sqc->min_shallow_depth = UINT(sbitmap_queue_buf + OFFSET(sbitmap_queue_min_shallow_depth)); -- -2.30.2 +2.37.1 diff --git a/SOURCES/0014-sbitmapq-Fix-for-sbitmap_word-without-cleared-member.patch b/SOURCES/0012-sbitmapq-Fix-for-sbitmap_word-without-cleared-member.patch similarity index 96% rename from SOURCES/0014-sbitmapq-Fix-for-sbitmap_word-without-cleared-member.patch rename to SOURCES/0012-sbitmapq-Fix-for-sbitmap_word-without-cleared-member.patch index 6018402..2e28c28 100644 --- a/SOURCES/0014-sbitmapq-Fix-for-sbitmap_word-without-cleared-member.patch +++ b/SOURCES/0012-sbitmapq-Fix-for-sbitmap_word-without-cleared-member.patch @@ -1,7 +1,7 @@ -From 0d3e86fee5eead93b521a0e20a0e099ede4ab72b Mon Sep 17 00:00:00 2001 +From 040e8be3b13746d1f64a36040b4ca613cf18eff0 Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 10 Jun 2022 11:49:47 +0900 -Subject: [PATCH 14/18] sbitmapq: Fix for sbitmap_word without cleared member +Subject: [PATCH 12/89] sbitmapq: Fix for sbitmap_word without cleared member The sbitmap_word.cleared member was added by kernel commit ea86ea2cdced ("sbitmap: ammortize cost of clearing bits") at Linux 5.0. Without the @@ -106,5 +106,5 @@ index 152c28e6875f..c9f7209f9e3e 100644 fprintf(fp, "map_nr = %u\n", sc->map_nr); -- -2.30.2 +2.37.1 diff --git a/SOURCES/0015-sbitmapq-Fix-for-sbitmap_queue-without-min_shallow_d.patch b/SOURCES/0013-sbitmapq-Fix-for-sbitmap_queue-without-min_shallow_d.patch similarity index 93% rename from SOURCES/0015-sbitmapq-Fix-for-sbitmap_queue-without-min_shallow_d.patch rename to SOURCES/0013-sbitmapq-Fix-for-sbitmap_queue-without-min_shallow_d.patch index 3871a6f..6bfc841 100644 --- a/SOURCES/0015-sbitmapq-Fix-for-sbitmap_queue-without-min_shallow_d.patch +++ b/SOURCES/0013-sbitmapq-Fix-for-sbitmap_queue-without-min_shallow_d.patch @@ -1,7 +1,7 @@ -From 12fe6c7cdd768f87ce6e903a2bbfb0c0591585c5 Mon Sep 17 00:00:00 2001 +From 8ea476439a57ee5552c752c582faf1d057ea4f6d Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 10 Jun 2022 11:49:47 +0900 -Subject: [PATCH 15/18] sbitmapq: Fix for sbitmap_queue without +Subject: [PATCH 13/89] sbitmapq: Fix for sbitmap_queue without min_shallow_depth member The sbitmap_queue.min_shallow_depth member was added by kernel commit @@ -45,5 +45,5 @@ index c9f7209f9e3e..bb2f19e6207b 100644 FREEBUF(sbitmap_queue_buf); } -- -2.30.2 +2.37.1 diff --git a/SOURCES/0016-Make-dev-d-D-options-parse-sbitmap-on-Linux-4.18-and.patch b/SOURCES/0014-Make-dev-d-D-options-parse-sbitmap-on-Linux-4.18-and.patch similarity index 95% rename from SOURCES/0016-Make-dev-d-D-options-parse-sbitmap-on-Linux-4.18-and.patch rename to SOURCES/0014-Make-dev-d-D-options-parse-sbitmap-on-Linux-4.18-and.patch index cc88afd..32cfcfe 100644 --- a/SOURCES/0016-Make-dev-d-D-options-parse-sbitmap-on-Linux-4.18-and.patch +++ b/SOURCES/0014-Make-dev-d-D-options-parse-sbitmap-on-Linux-4.18-and.patch @@ -1,7 +1,7 @@ -From c07068266b41450ca6821ee0a1a3adf34206015f Mon Sep 17 00:00:00 2001 +From 04b6edada1180b0391ddf980d09b4bac8a0c3aba Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 10 Jun 2022 15:21:53 +0900 -Subject: [PATCH 16/18] Make "dev -d|-D" options parse sbitmap on Linux 4.18 +Subject: [PATCH 14/89] Make "dev -d|-D" options parse sbitmap on Linux 4.18 and later There have been a few reports that the "dev -d|-D" options displayed @@ -80,5 +80,5 @@ index 0172c83ffaea..db97f8aebdc2 100644 sizeof(ulong), "request_queue.queue_ctx", FAULT_ON_ERROR); -- -2.30.2 +2.37.1 diff --git a/SOURCES/0017-sbitmapq-Fix-for-kernels-without-struct-wait_queue_h.patch b/SOURCES/0015-sbitmapq-Fix-for-kernels-without-struct-wait_queue_h.patch similarity index 91% rename from SOURCES/0017-sbitmapq-Fix-for-kernels-without-struct-wait_queue_h.patch rename to SOURCES/0015-sbitmapq-Fix-for-kernels-without-struct-wait_queue_h.patch index fe4a544..bbcb421 100644 --- a/SOURCES/0017-sbitmapq-Fix-for-kernels-without-struct-wait_queue_h.patch +++ b/SOURCES/0015-sbitmapq-Fix-for-kernels-without-struct-wait_queue_h.patch @@ -1,7 +1,7 @@ -From 6bc3b74c6e2b0aaebe1bc164594e53b010efef56 Mon Sep 17 00:00:00 2001 +From 60af53c7b69df11dec05d2a396e5272856e4243d Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 10 Jun 2022 15:52:34 +0900 -Subject: [PATCH 17/18] sbitmapq: Fix for kernels without struct +Subject: [PATCH 15/89] sbitmapq: Fix for kernels without struct wait_queue_head The current struct wait_queue_head was renamed by kernel commit @@ -40,5 +40,5 @@ index bb2f19e6207b..be5d30a8ea88 100644 sbq_wait_state_buf = GETBUF(sbq_wait_state_size); -- -2.30.2 +2.37.1 diff --git a/SOURCES/0018-sbitmapq-Limit-kernels-without-sbitmap-again.patch b/SOURCES/0016-sbitmapq-Limit-kernels-without-sbitmap-again.patch similarity index 91% rename from SOURCES/0018-sbitmapq-Limit-kernels-without-sbitmap-again.patch rename to SOURCES/0016-sbitmapq-Limit-kernels-without-sbitmap-again.patch index 791e5ab..eaca7e3 100644 --- a/SOURCES/0018-sbitmapq-Limit-kernels-without-sbitmap-again.patch +++ b/SOURCES/0016-sbitmapq-Limit-kernels-without-sbitmap-again.patch @@ -1,7 +1,7 @@ -From b8f2ae6b494d706b1e4855b439c4930a6a6a2f5c Mon Sep 17 00:00:00 2001 +From 46db4c6a66067d96248be664a09fdd93575cb0f2 Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 10 Jun 2022 16:00:14 +0900 -Subject: [PATCH 18/18] sbitmapq: Limit kernels without sbitmap again +Subject: [PATCH 16/89] sbitmapq: Limit kernels without sbitmap again commit 364b2e413c69 ("sbitmapq: remove struct and member validation in sbitmapq_init()") allowed the use of the "sbitmapq" command @@ -39,5 +39,5 @@ index be5d30a8ea88..12d6512a1e4d 100644 MEMBER_OFFSET_INIT(sbitmap_word_word, "sbitmap_word", "word"); MEMBER_OFFSET_INIT(sbitmap_word_cleared, "sbitmap_word", "cleared"); -- -2.30.2 +2.37.1 diff --git a/SOURCES/0001-Fix-for-dev-command-on-Linux-5.11-and-later.patch b/SOURCES/0017-Fix-for-dev-command-on-Linux-5.11-and-later.patch similarity index 96% rename from SOURCES/0001-Fix-for-dev-command-on-Linux-5.11-and-later.patch rename to SOURCES/0017-Fix-for-dev-command-on-Linux-5.11-and-later.patch index c34327e..66a0cf5 100644 --- a/SOURCES/0001-Fix-for-dev-command-on-Linux-5.11-and-later.patch +++ b/SOURCES/0017-Fix-for-dev-command-on-Linux-5.11-and-later.patch @@ -1,7 +1,7 @@ -From f623cad20b092002d627a03451ea256add2e53d0 Mon Sep 17 00:00:00 2001 +From b6b1f17766583873cde5335e6e631fe3887cb564 Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Wed, 15 Jun 2022 10:50:13 +0900 -Subject: [PATCH 01/28] Fix for "dev" command on Linux 5.11 and later +Subject: [PATCH 17/89] Fix for "dev" command on Linux 5.11 and later The following kernel commits eventually removed the bdev_map array in Linux v5.11 kernel: diff --git a/SOURCES/0002-Extend-field-length-of-task-attributes.patch b/SOURCES/0018-Extend-field-length-of-task-attributes.patch similarity index 96% rename from SOURCES/0002-Extend-field-length-of-task-attributes.patch rename to SOURCES/0018-Extend-field-length-of-task-attributes.patch index 7ea7483..6843d00 100644 --- a/SOURCES/0002-Extend-field-length-of-task-attributes.patch +++ b/SOURCES/0018-Extend-field-length-of-task-attributes.patch @@ -1,7 +1,7 @@ -From 6bc60e8cc87701c8f68c1cda56dd7120b5565700 Mon Sep 17 00:00:00 2001 +From 21c2bf4844893fe9499fda156d043b0ff6c5f3af Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Wed, 22 Jun 2022 08:32:59 +0900 -Subject: [PATCH 02/28] Extend field length of task attributes +Subject: [PATCH 18/89] Extend field length of task attributes Nowadays, some machines have many CPU cores and memory, and some distributions have a larger kernel.pid_max parameter, e.g. 7 digits. diff --git a/SOURCES/0003-ppc64-fix-bt-for-S-case.patch b/SOURCES/0019-ppc64-fix-bt-for-S-case.patch similarity index 91% rename from SOURCES/0003-ppc64-fix-bt-for-S-case.patch rename to SOURCES/0019-ppc64-fix-bt-for-S-case.patch index edd0869..af5d2ed 100644 --- a/SOURCES/0003-ppc64-fix-bt-for-S-case.patch +++ b/SOURCES/0019-ppc64-fix-bt-for-S-case.patch @@ -1,7 +1,7 @@ -From 1c918c621e48f53ea69a143aabc59c8366102236 Mon Sep 17 00:00:00 2001 +From 00f8699daacba46fd706758024c375825264db32 Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Mon, 4 Jul 2022 10:55:41 +0530 -Subject: [PATCH 03/28] ppc64: fix bt for '-S' case +Subject: [PATCH 19/89] ppc64: fix bt for '-S' case Passing '-S' option to 'bt' command was intended to specify the stack pointer manually. But get_stack_frame() handling on ppc64 is ignoring diff --git a/SOURCES/0004-ppc64-dynamically-allocate-h-w-interrupt-stack.patch b/SOURCES/0020-ppc64-dynamically-allocate-h-w-interrupt-stack.patch similarity index 97% rename from SOURCES/0004-ppc64-dynamically-allocate-h-w-interrupt-stack.patch rename to SOURCES/0020-ppc64-dynamically-allocate-h-w-interrupt-stack.patch index 21e7af1..6a7de8f 100644 --- a/SOURCES/0004-ppc64-dynamically-allocate-h-w-interrupt-stack.patch +++ b/SOURCES/0020-ppc64-dynamically-allocate-h-w-interrupt-stack.patch @@ -1,7 +1,7 @@ -From 6a89173a25450b679e4a713793b2ed36b077fe56 Mon Sep 17 00:00:00 2001 +From 32282bab0edf1aebd96bb8fe5ee66b3855474831 Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Mon, 4 Jul 2022 10:55:42 +0530 -Subject: [PATCH 04/28] ppc64: dynamically allocate h/w interrupt stack +Subject: [PATCH 20/89] ppc64: dynamically allocate h/w interrupt stack Only older kernel (v2.4) used h/w interrupt stack to store frames when CPU received IPI. Memory used for this in 'struct machine_specific' is diff --git a/SOURCES/0005-ppc64-rename-ppc64_paca_init-to-ppc64_paca_percpu_of.patch b/SOURCES/0021-ppc64-rename-ppc64_paca_init-to-ppc64_paca_percpu_of.patch similarity index 94% rename from SOURCES/0005-ppc64-rename-ppc64_paca_init-to-ppc64_paca_percpu_of.patch rename to SOURCES/0021-ppc64-rename-ppc64_paca_init-to-ppc64_paca_percpu_of.patch index 3249bb6..da730f2 100644 --- a/SOURCES/0005-ppc64-rename-ppc64_paca_init-to-ppc64_paca_percpu_of.patch +++ b/SOURCES/0021-ppc64-rename-ppc64_paca_init-to-ppc64_paca_percpu_of.patch @@ -1,7 +1,7 @@ -From 4dbf7e296f6fde05894a55e23fbaf0d50e3b38b9 Mon Sep 17 00:00:00 2001 +From 275b62afe8fd7446fc31025998b6d0fd47ec8be0 Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Mon, 4 Jul 2022 10:55:43 +0530 -Subject: [PATCH 05/28] ppc64: rename ppc64_paca_init to +Subject: [PATCH 21/89] ppc64: rename ppc64_paca_init to ppc64_paca_percpu_offset_init ppc64_paca_init() function is specifically used to initialize percpu diff --git a/SOURCES/0006-ppc64-handle-backtrace-when-CPU-is-in-an-emergency-s.patch b/SOURCES/0022-ppc64-handle-backtrace-when-CPU-is-in-an-emergency-s.patch similarity index 98% rename from SOURCES/0006-ppc64-handle-backtrace-when-CPU-is-in-an-emergency-s.patch rename to SOURCES/0022-ppc64-handle-backtrace-when-CPU-is-in-an-emergency-s.patch index adbc896..71be282 100644 --- a/SOURCES/0006-ppc64-handle-backtrace-when-CPU-is-in-an-emergency-s.patch +++ b/SOURCES/0022-ppc64-handle-backtrace-when-CPU-is-in-an-emergency-s.patch @@ -1,7 +1,7 @@ -From f256095c61355d8db11502709ab3a084343f2bec Mon Sep 17 00:00:00 2001 +From 26b0949228786562fdf73fef145a829c0adb9c70 Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Mon, 4 Jul 2022 10:55:44 +0530 -Subject: [PATCH 06/28] ppc64: handle backtrace when CPU is in an emergency +Subject: [PATCH 22/89] ppc64: handle backtrace when CPU is in an emergency stack A CPU could be in an emergency stack when it is running in real mode diff --git a/SOURCES/0007-ppc64-print-emergency-stacks-info-with-mach-command.patch b/SOURCES/0023-ppc64-print-emergency-stacks-info-with-mach-command.patch similarity index 93% rename from SOURCES/0007-ppc64-print-emergency-stacks-info-with-mach-command.patch rename to SOURCES/0023-ppc64-print-emergency-stacks-info-with-mach-command.patch index 349e5be..6f5f09d 100644 --- a/SOURCES/0007-ppc64-print-emergency-stacks-info-with-mach-command.patch +++ b/SOURCES/0023-ppc64-print-emergency-stacks-info-with-mach-command.patch @@ -1,7 +1,7 @@ -From 9429b15851f184fbff187d9a751451c9ed8ae5c9 Mon Sep 17 00:00:00 2001 +From 5ef39b9dda5ab29ddbbc72d54829ddbc66238518 Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Mon, 4 Jul 2022 10:55:45 +0530 -Subject: [PATCH 07/28] ppc64: print emergency stacks info with 'mach' command +Subject: [PATCH 23/89] ppc64: print emergency stacks info with 'mach' command Print top address of emergency stacks with 'mach' command. diff --git a/SOURCES/0008-ppc64-use-a-variable-for-machdep-machspec.patch b/SOURCES/0024-ppc64-use-a-variable-for-machdep-machspec.patch similarity index 99% rename from SOURCES/0008-ppc64-use-a-variable-for-machdep-machspec.patch rename to SOURCES/0024-ppc64-use-a-variable-for-machdep-machspec.patch index f8b3a77..c63522e 100644 --- a/SOURCES/0008-ppc64-use-a-variable-for-machdep-machspec.patch +++ b/SOURCES/0024-ppc64-use-a-variable-for-machdep-machspec.patch @@ -1,7 +1,7 @@ -From 656f0b50866247a2fdb2d0c917f0a7a3f34c2e7d Mon Sep 17 00:00:00 2001 +From 1365bde4820805457a35743be2dbb1035f4eeede Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Mon, 4 Jul 2022 10:55:46 +0530 -Subject: [PATCH 08/28] ppc64: use a variable for machdep->machspec +Subject: [PATCH 24/89] ppc64: use a variable for machdep->machspec machdpep->machspec is referred to multiple times. The compiler would likely optimize this but nonetheless, use a variable to optimize in diff --git a/SOURCES/0009-arm64-Fix-for-st-_stext_vmlinux-not-initialized-when.patch b/SOURCES/0025-arm64-Fix-for-st-_stext_vmlinux-not-initialized-when.patch similarity index 89% rename from SOURCES/0009-arm64-Fix-for-st-_stext_vmlinux-not-initialized-when.patch rename to SOURCES/0025-arm64-Fix-for-st-_stext_vmlinux-not-initialized-when.patch index 74a6998..c724a6a 100644 --- a/SOURCES/0009-arm64-Fix-for-st-_stext_vmlinux-not-initialized-when.patch +++ b/SOURCES/0025-arm64-Fix-for-st-_stext_vmlinux-not-initialized-when.patch @@ -1,7 +1,7 @@ -From b077c3569788f5eb5ddf85bf41026b452d253a90 Mon Sep 17 00:00:00 2001 +From ee5ab26db61025b2f5ed3a4b529394187df54d36 Mon Sep 17 00:00:00 2001 From: Qianli Zhao Date: Mon, 4 Jul 2022 16:40:01 +0800 -Subject: [PATCH 09/28] arm64: Fix for st->_stext_vmlinux not initialized when +Subject: [PATCH 25/89] arm64: Fix for st->_stext_vmlinux not initialized when set VA_BITS_ACTUAL Setting st->_stext_vmlinux to UNINITIALIZED to search for "_stext" diff --git a/SOURCES/0010-Fix-gcc-11-compiler-warnings-on-filesys.c.patch b/SOURCES/0026-Fix-gcc-11-compiler-warnings-on-filesys.c.patch similarity index 92% rename from SOURCES/0010-Fix-gcc-11-compiler-warnings-on-filesys.c.patch rename to SOURCES/0026-Fix-gcc-11-compiler-warnings-on-filesys.c.patch index ba88af8..b12832e 100644 --- a/SOURCES/0010-Fix-gcc-11-compiler-warnings-on-filesys.c.patch +++ b/SOURCES/0026-Fix-gcc-11-compiler-warnings-on-filesys.c.patch @@ -1,7 +1,7 @@ -From 6132fe21e0d5f2951c860f8850aeaacf1588dfb0 Mon Sep 17 00:00:00 2001 +From f141628a62b795f52a5d57f5d3e844b6a49114da Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 22 Jul 2022 13:44:50 +0900 -Subject: [PATCH 10/28] Fix gcc-11 compiler warnings on filesys.c +Subject: [PATCH 26/89] Fix gcc-11 compiler warnings on filesys.c Without the patch, the following gcc-11 compiler warnings are emitted for filesys.c: diff --git a/SOURCES/0011-Fix-gcc-11-compiler-warning-on-symbols.c.patch b/SOURCES/0027-Fix-gcc-11-compiler-warning-on-symbols.c.patch similarity index 91% rename from SOURCES/0011-Fix-gcc-11-compiler-warning-on-symbols.c.patch rename to SOURCES/0027-Fix-gcc-11-compiler-warning-on-symbols.c.patch index b835023..6aaa1fb 100644 --- a/SOURCES/0011-Fix-gcc-11-compiler-warning-on-symbols.c.patch +++ b/SOURCES/0027-Fix-gcc-11-compiler-warning-on-symbols.c.patch @@ -1,7 +1,7 @@ -From 98484914b7f4ba34da0625baa0ed6d449c1fa3ad Mon Sep 17 00:00:00 2001 +From 12898df249a5db826d2390467aaadd49de29074e Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 22 Jul 2022 13:44:50 +0900 -Subject: [PATCH 11/28] Fix gcc-11 compiler warning on symbols.c +Subject: [PATCH 27/89] Fix gcc-11 compiler warning on symbols.c Without the patch, the following gcc-11 compiler warning is emitted for symbols.c: diff --git a/SOURCES/0012-Fix-gcc-11-compiler-warning-on-makedumpfile.c.patch b/SOURCES/0028-Fix-gcc-11-compiler-warning-on-makedumpfile.c.patch similarity index 89% rename from SOURCES/0012-Fix-gcc-11-compiler-warning-on-makedumpfile.c.patch rename to SOURCES/0028-Fix-gcc-11-compiler-warning-on-makedumpfile.c.patch index 2b6e24a..d5ed4d2 100644 --- a/SOURCES/0012-Fix-gcc-11-compiler-warning-on-makedumpfile.c.patch +++ b/SOURCES/0028-Fix-gcc-11-compiler-warning-on-makedumpfile.c.patch @@ -1,7 +1,7 @@ -From 9bb8a48d9424fc00ccd073125cdee9613b389cc6 Mon Sep 17 00:00:00 2001 +From 8d9e6c5b02c9c417264b76279b8f77b0995b6f74 Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 22 Jul 2022 13:44:50 +0900 -Subject: [PATCH 12/28] Fix gcc-11 compiler warning on makedumpfile.c +Subject: [PATCH 28/89] Fix gcc-11 compiler warning on makedumpfile.c Without the patch, the following gcc-11 compiler warning is emitted for makedumpfile.c: diff --git a/SOURCES/0013-Fix-gcc-11-compiler-warning-on-kvmdump.c.patch b/SOURCES/0029-Fix-gcc-11-compiler-warning-on-kvmdump.c.patch similarity index 94% rename from SOURCES/0013-Fix-gcc-11-compiler-warning-on-kvmdump.c.patch rename to SOURCES/0029-Fix-gcc-11-compiler-warning-on-kvmdump.c.patch index f1f8d51..b39cbdd 100644 --- a/SOURCES/0013-Fix-gcc-11-compiler-warning-on-kvmdump.c.patch +++ b/SOURCES/0029-Fix-gcc-11-compiler-warning-on-kvmdump.c.patch @@ -1,7 +1,7 @@ -From 75739a08e952b6bd7434f4625a8fbe921361cbe8 Mon Sep 17 00:00:00 2001 +From 6618a57d40ff48726c26d54813f3f8090037760b Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 22 Jul 2022 13:44:50 +0900 -Subject: [PATCH 13/28] Fix gcc-11 compiler warning on kvmdump.c +Subject: [PATCH 29/89] Fix gcc-11 compiler warning on kvmdump.c Without the patch, the following gcc-11 compiler warning is emitted for kvmdump.c: diff --git a/SOURCES/0014-x86_64-Fix-for-AMD-SME-issue.patch b/SOURCES/0030-x86_64-Fix-for-AMD-SME-issue.patch similarity index 97% rename from SOURCES/0014-x86_64-Fix-for-AMD-SME-issue.patch rename to SOURCES/0030-x86_64-Fix-for-AMD-SME-issue.patch index 565bca7..487bc7d 100644 --- a/SOURCES/0014-x86_64-Fix-for-AMD-SME-issue.patch +++ b/SOURCES/0030-x86_64-Fix-for-AMD-SME-issue.patch @@ -1,7 +1,7 @@ -From b584eb81ff27e42547d01c521b488aaeaa35b460 Mon Sep 17 00:00:00 2001 +From 59e9621ac2a7cb3f001fdab53c1e7e3590f8762d Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Thu, 28 Jul 2022 15:11:20 +0800 -Subject: [PATCH 14/28] x86_64: Fix for AMD SME issue +Subject: [PATCH 30/89] x86_64: Fix for AMD SME issue Kernel commit changes(see [1]/[2]) may cause the failure of crash-utility with the following error: diff --git a/SOURCES/0015-Makefile-Fix-unnecessary-re-patching-with-coreutils-.patch b/SOURCES/0031-Makefile-Fix-unnecessary-re-patching-with-coreutils-.patch similarity index 86% rename from SOURCES/0015-Makefile-Fix-unnecessary-re-patching-with-coreutils-.patch rename to SOURCES/0031-Makefile-Fix-unnecessary-re-patching-with-coreutils-.patch index d4dac37..f837407 100644 --- a/SOURCES/0015-Makefile-Fix-unnecessary-re-patching-with-coreutils-.patch +++ b/SOURCES/0031-Makefile-Fix-unnecessary-re-patching-with-coreutils-.patch @@ -1,7 +1,7 @@ -From 619e36c18791333ee3a7fea759ce20396e711a46 Mon Sep 17 00:00:00 2001 +From 6be4f19f32bfa6d5a52580b733afca8a5b849c23 Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Mon, 22 Aug 2022 11:59:46 +0900 -Subject: [PATCH 15/28] Makefile: Fix unnecessary re-patching with +Subject: [PATCH 31/89] Makefile: Fix unnecessary re-patching with coreutils-9.0 "sum" command in coreutils-9.0 (e.g. Fedora 36) started to output a file @@ -17,7 +17,7 @@ Signed-off-by: Lianbo Jiang 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile -index 059759b3e4ab..dd81df6c198c 100644 +index c031db4ca23f..2549d1d39273 100644 --- a/Makefile +++ b/Makefile @@ -269,7 +269,7 @@ rebuild: diff --git a/SOURCES/0016-arm64-use-TCR_EL1_T1SZ-to-get-the-correct-info-if-va.patch b/SOURCES/0032-arm64-use-TCR_EL1_T1SZ-to-get-the-correct-info-if-va.patch similarity index 96% rename from SOURCES/0016-arm64-use-TCR_EL1_T1SZ-to-get-the-correct-info-if-va.patch rename to SOURCES/0032-arm64-use-TCR_EL1_T1SZ-to-get-the-correct-info-if-va.patch index 0a4a4a3..241c71f 100644 --- a/SOURCES/0016-arm64-use-TCR_EL1_T1SZ-to-get-the-correct-info-if-va.patch +++ b/SOURCES/0032-arm64-use-TCR_EL1_T1SZ-to-get-the-correct-info-if-va.patch @@ -1,7 +1,7 @@ -From 28a41ec7a471474094d8ab39f3a69b44d0f9ebcf Mon Sep 17 00:00:00 2001 +From 1bd4bd41e67dae5a970d34f33c566812f9f2c6af Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Mon, 22 Aug 2022 09:29:32 +0000 -Subject: [PATCH 16/28] arm64: use TCR_EL1_T1SZ to get the correct info if +Subject: [PATCH 32/89] arm64: use TCR_EL1_T1SZ to get the correct info if vabits_actual is missing After kernel commit 0d9b1ffefabe ("arm64: mm: make vabits_actual a build diff --git a/SOURCES/0017-Fix-task-R-by-adding-end-identifier-for-union-in-tas.patch b/SOURCES/0033-Fix-task-R-by-adding-end-identifier-for-union-in-tas.patch similarity index 92% rename from SOURCES/0017-Fix-task-R-by-adding-end-identifier-for-union-in-tas.patch rename to SOURCES/0033-Fix-task-R-by-adding-end-identifier-for-union-in-tas.patch index 47cfdd4..51f51e7 100644 --- a/SOURCES/0017-Fix-task-R-by-adding-end-identifier-for-union-in-tas.patch +++ b/SOURCES/0033-Fix-task-R-by-adding-end-identifier-for-union-in-tas.patch @@ -1,7 +1,7 @@ -From c32abfea658ef33c20a942700277cb52baf95bfa Mon Sep 17 00:00:00 2001 +From 5df8fdf1f591176682e6fac18e6631c3a2aab1dc Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Thu, 25 Aug 2022 14:39:44 +0800 -Subject: [PATCH 17/28] Fix "task -R" by adding end identifier for union in +Subject: [PATCH 33/89] Fix "task -R" by adding end identifier for union in task_struct Previously, the start and end identifiers for union are " {\n" and diff --git a/SOURCES/0018-Let-gdb-get-kernel-module-symbols-info-from-crash.patch b/SOURCES/0034-Let-gdb-get-kernel-module-symbols-info-from-crash.patch similarity index 94% rename from SOURCES/0018-Let-gdb-get-kernel-module-symbols-info-from-crash.patch rename to SOURCES/0034-Let-gdb-get-kernel-module-symbols-info-from-crash.patch index 6ee260e..702dad6 100644 --- a/SOURCES/0018-Let-gdb-get-kernel-module-symbols-info-from-crash.patch +++ b/SOURCES/0034-Let-gdb-get-kernel-module-symbols-info-from-crash.patch @@ -1,7 +1,7 @@ -From 5948cb9b3e622e3c87216c7c6479f509c8aeb7c1 Mon Sep 17 00:00:00 2001 +From 38064b8d5866f8a4f7e7867f187ad95e67f16209 Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Wed, 16 Nov 2022 17:36:03 +0800 -Subject: [PATCH 18/28] Let gdb get kernel module symbols info from crash +Subject: [PATCH 34/89] Let gdb get kernel module symbols info from crash Gdb will try to resolve an address to its corresponding symbol name such as when printing a structure. It works fine for kernel symbols, because gdb can @@ -65,7 +65,7 @@ index f8fbfdfd1152..b7d76330141a 100644 void restore_gdb_sanity(void); int is_gdb_command(int, ulong); diff --git a/gdb-7.6.patch b/gdb-7.6.patch -index c63ad7d81cb0..f1c3aa734241 100644 +index c63ad7d81cb0..d0becd055666 100644 --- a/gdb-7.6.patch +++ b/gdb-7.6.patch @@ -2568,3 +2568,36 @@ diff -up gdb-7.6/opcodes/configure.orig gdb-7.6/opcodes/configure @@ -106,7 +106,7 @@ index c63ad7d81cb0..f1c3aa734241 100644 + /* If the nearest symbol is too far away, don't print anything symbolic. */ + diff --git a/gdb_interface.c b/gdb_interface.c -index 1f10006a2d63..f9d0018998df 100644 +index 1f10006a2d63..95298a94c702 100644 --- a/gdb_interface.c +++ b/gdb_interface.c @@ -945,6 +945,18 @@ gdb_print_callback(ulong addr) diff --git a/SOURCES/0019-x86_64-Correct-the-identifier-when-locating-the-call.patch b/SOURCES/0035-x86_64-Correct-the-identifier-when-locating-the-call.patch similarity index 94% rename from SOURCES/0019-x86_64-Correct-the-identifier-when-locating-the-call.patch rename to SOURCES/0035-x86_64-Correct-the-identifier-when-locating-the-call.patch index c64feba..af2a26c 100644 --- a/SOURCES/0019-x86_64-Correct-the-identifier-when-locating-the-call.patch +++ b/SOURCES/0035-x86_64-Correct-the-identifier-when-locating-the-call.patch @@ -1,7 +1,7 @@ -From 93cd670426aaf4951bceb8f24f0ce63c24e16f5d Mon Sep 17 00:00:00 2001 +From 6a766b5159ebb971a399bb32a8a58599df977cdb Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Wed, 16 Nov 2022 20:09:22 +0800 -Subject: [PATCH 19/28] x86_64: Correct the identifier when locating the call +Subject: [PATCH 35/89] x86_64: Correct the identifier when locating the call instruction The previous implementation to locate the call instruction is diff --git a/SOURCES/0020-Add-debian-ubuntu-vmlinux-location-to-default-search.patch b/SOURCES/0036-Add-debian-ubuntu-vmlinux-location-to-default-search.patch similarity index 88% rename from SOURCES/0020-Add-debian-ubuntu-vmlinux-location-to-default-search.patch rename to SOURCES/0036-Add-debian-ubuntu-vmlinux-location-to-default-search.patch index 5cdfff4..ad2d34b 100644 --- a/SOURCES/0020-Add-debian-ubuntu-vmlinux-location-to-default-search.patch +++ b/SOURCES/0036-Add-debian-ubuntu-vmlinux-location-to-default-search.patch @@ -1,7 +1,7 @@ -From 931ea86070e9b56bf698ae3a4f20647d42325d6d Mon Sep 17 00:00:00 2001 +From 792730b32cb15b59af2833cfd6819b8408b20e89 Mon Sep 17 00:00:00 2001 From: "Chunguang.Xu" Date: Thu, 25 Aug 2022 12:07:20 +0800 -Subject: [PATCH 20/28] Add debian/ubuntu vmlinux location to default search +Subject: [PATCH 36/89] Add debian/ubuntu vmlinux location to default search dirs Now crash cannot find debian/ubuntu kernel vmlinux, we need to diff --git a/SOURCES/0021-Fix-gcc-12-compiler-warnings-on-lkcd_-.c.patch b/SOURCES/0037-Fix-gcc-12-compiler-warnings-on-lkcd_-.c.patch similarity index 96% rename from SOURCES/0021-Fix-gcc-12-compiler-warnings-on-lkcd_-.c.patch rename to SOURCES/0037-Fix-gcc-12-compiler-warnings-on-lkcd_-.c.patch index 6d88076..8280557 100644 --- a/SOURCES/0021-Fix-gcc-12-compiler-warnings-on-lkcd_-.c.patch +++ b/SOURCES/0037-Fix-gcc-12-compiler-warnings-on-lkcd_-.c.patch @@ -1,7 +1,7 @@ -From a4f8fe965e1ed0d27aff0cdf30e2c571da2e5356 Mon Sep 17 00:00:00 2001 +From 1312fdbc514dc47e591b2d94994c6f467581c6f1 Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Thu, 1 Sep 2022 14:03:09 +0900 -Subject: [PATCH 21/28] Fix gcc-12 compiler warnings on lkcd_*.c +Subject: [PATCH 37/89] Fix gcc-12 compiler warnings on lkcd_*.c Without the patch, the following gcc-12 compiler warnings are emitted for lkcd_*.c: diff --git a/SOURCES/0022-Fix-for-the-invalid-linux_banner-pointer-issue.patch b/SOURCES/0038-Fix-for-the-invalid-linux_banner-pointer-issue.patch similarity index 90% rename from SOURCES/0022-Fix-for-the-invalid-linux_banner-pointer-issue.patch rename to SOURCES/0038-Fix-for-the-invalid-linux_banner-pointer-issue.patch index 7302b92..4c15b7a 100644 --- a/SOURCES/0022-Fix-for-the-invalid-linux_banner-pointer-issue.patch +++ b/SOURCES/0038-Fix-for-the-invalid-linux_banner-pointer-issue.patch @@ -1,7 +1,7 @@ -From 598377606649ee3cdcc1694d975bed27005612ee Mon Sep 17 00:00:00 2001 +From 61e5c455516622cabf4a01c1643ca2175ef9510c Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Wed, 16 Nov 2022 20:46:48 +0800 -Subject: [PATCH 22/28] Fix for the invalid linux_banner pointer issue +Subject: [PATCH 38/89] Fix for the invalid linux_banner pointer issue Currently, crash may fail with the following error: diff --git a/SOURCES/0023-Fix-kmem-failing-to-print-task-context-when-address-.patch b/SOURCES/0039-Fix-kmem-failing-to-print-task-context-when-address-.patch similarity index 91% rename from SOURCES/0023-Fix-kmem-failing-to-print-task-context-when-address-.patch rename to SOURCES/0039-Fix-kmem-failing-to-print-task-context-when-address-.patch index 8a6079d..7435df2 100644 --- a/SOURCES/0023-Fix-kmem-failing-to-print-task-context-when-address-.patch +++ b/SOURCES/0039-Fix-kmem-failing-to-print-task-context-when-address-.patch @@ -1,7 +1,7 @@ -From 488896b1ab0ca8bc4cc6aa608b6ee1744ae480e7 Mon Sep 17 00:00:00 2001 +From a72184ebeec704158a2b225fa7fe0869b9b93a93 Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Mon, 19 Sep 2022 17:49:21 +0800 -Subject: [PATCH 23/28] Fix "kmem" failing to print task context when address +Subject: [PATCH 39/89] Fix "kmem" failing to print task context when address is vmalloced stack When kernel enabled CONFIG_VMAP_STACK, stack can be allocated to @@ -38,7 +38,7 @@ Signed-off-by: Lianbo Jiang 1 file changed, 4 insertions(+) diff --git a/memory.c b/memory.c -index a31a430e2823..e44b59d2e805 100644 +index 7339f0cd0224..9ab578134fa1 100644 --- a/memory.c +++ b/memory.c @@ -13477,6 +13477,10 @@ kmem_search(struct meminfo *mi) diff --git a/SOURCES/0024-Fix-page-offset-issue-when-converting-physical-to-vi.patch b/SOURCES/0040-Fix-page-offset-issue-when-converting-physical-to-vi.patch similarity index 89% rename from SOURCES/0024-Fix-page-offset-issue-when-converting-physical-to-vi.patch rename to SOURCES/0040-Fix-page-offset-issue-when-converting-physical-to-vi.patch index 18c20ba..2f6a221 100644 --- a/SOURCES/0024-Fix-page-offset-issue-when-converting-physical-to-vi.patch +++ b/SOURCES/0040-Fix-page-offset-issue-when-converting-physical-to-vi.patch @@ -1,7 +1,7 @@ -From d0726d96b92e5dacd1df56756e168a50a4e62589 Mon Sep 17 00:00:00 2001 +From f18c391b650ace3cea6e48278b969425a328e4cf Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Mon, 19 Sep 2022 17:49:22 +0800 -Subject: [PATCH 24/28] Fix page offset issue when converting physical to +Subject: [PATCH 40/89] Fix page offset issue when converting physical to virtual address When trying to convert a physical address to its virtual @@ -23,7 +23,7 @@ Signed-off-by: Lianbo Jiang 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/memory.c b/memory.c -index e44b59d2e805..a60c3f9493f6 100644 +index 9ab578134fa1..1b6f9ba17e57 100644 --- a/memory.c +++ b/memory.c @@ -8861,7 +8861,7 @@ dump_vmlist(struct meminfo *vi) diff --git a/SOURCES/0025-Let-kmem-print-task-context-with-physical-address.patch b/SOURCES/0041-Let-kmem-print-task-context-with-physical-address.patch similarity index 93% rename from SOURCES/0025-Let-kmem-print-task-context-with-physical-address.patch rename to SOURCES/0041-Let-kmem-print-task-context-with-physical-address.patch index d6cf91f..035a390 100644 --- a/SOURCES/0025-Let-kmem-print-task-context-with-physical-address.patch +++ b/SOURCES/0041-Let-kmem-print-task-context-with-physical-address.patch @@ -1,7 +1,7 @@ -From 74759e0e9736e86c7d2439bfe74ca5eb51b0a52b Mon Sep 17 00:00:00 2001 +From 2c24770e3ceab8eebd9788256967b79145f53123 Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Mon, 19 Sep 2022 17:49:23 +0800 -Subject: [PATCH 25/28] Let "kmem" print task context with physical address +Subject: [PATCH 41/89] Let "kmem" print task context with physical address Patch [1] enables "kmem" to print task context if the given virtual address is a vmalloced stack. @@ -43,7 +43,7 @@ Signed-off-by: Lianbo Jiang 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/memory.c b/memory.c -index a60c3f9493f6..ff6b571361eb 100644 +index 1b6f9ba17e57..c80ef61bdcf7 100644 --- a/memory.c +++ b/memory.c @@ -13506,6 +13506,10 @@ kmem_search(struct meminfo *mi) diff --git a/SOURCES/0026-ppc64-still-allow-to-move-on-if-the-emergency-stacks.patch b/SOURCES/0042-ppc64-still-allow-to-move-on-if-the-emergency-stacks.patch similarity index 96% rename from SOURCES/0026-ppc64-still-allow-to-move-on-if-the-emergency-stacks.patch rename to SOURCES/0042-ppc64-still-allow-to-move-on-if-the-emergency-stacks.patch index c01b957..cb46aa3 100644 --- a/SOURCES/0026-ppc64-still-allow-to-move-on-if-the-emergency-stacks.patch +++ b/SOURCES/0042-ppc64-still-allow-to-move-on-if-the-emergency-stacks.patch @@ -1,7 +1,7 @@ -From edbd19bb260f7a98bc9e0b49fe2f0b8214885797 Mon Sep 17 00:00:00 2001 +From e39a2560928ef6f7e8dad80cb9a7521bdf0495e3 Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Tue, 4 Oct 2022 18:57:11 +0800 -Subject: [PATCH 26/28] ppc64: still allow to move on if the emergency stacks +Subject: [PATCH 42/89] ppc64: still allow to move on if the emergency stacks info fails to initialize Currently crash will fail and then exit, if the initialization of diff --git a/SOURCES/0027-Fix-segmentation-fault-in-page_flags_init_from_pagef.patch b/SOURCES/0043-Fix-segmentation-fault-in-page_flags_init_from_pagef.patch similarity index 89% rename from SOURCES/0027-Fix-segmentation-fault-in-page_flags_init_from_pagef.patch rename to SOURCES/0043-Fix-segmentation-fault-in-page_flags_init_from_pagef.patch index 45044d3..9589c22 100644 --- a/SOURCES/0027-Fix-segmentation-fault-in-page_flags_init_from_pagef.patch +++ b/SOURCES/0043-Fix-segmentation-fault-in-page_flags_init_from_pagef.patch @@ -1,7 +1,7 @@ -From cdcf2d3f4c69ffa8a29b70120ee4fca6e390123b Mon Sep 17 00:00:00 2001 +From 975265a8056566ace8eaa6cf532fd42754e915a9 Mon Sep 17 00:00:00 2001 From: Matias Ezequiel Vara Larsen Date: Mon, 24 Oct 2022 11:35:29 +0200 -Subject: [PATCH 27/28] Fix segmentation fault in +Subject: [PATCH 43/89] Fix segmentation fault in page_flags_init_from_pageflag_names() When read_string() fails in page_flags_init_from_pageflag_names(), @@ -22,7 +22,7 @@ Signed-off-by: Lianbo Jiang 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memory.c b/memory.c -index ff6b571361eb..ddbf458277f0 100644 +index c80ef61bdcf7..8724c4aa3d8a 100644 --- a/memory.c +++ b/memory.c @@ -6599,7 +6599,7 @@ page_flags_init_from_pageflag_names(void) diff --git a/SOURCES/0028-Fix-for-ps-vm-commands-to-display-correct-MEM-and-RS.patch b/SOURCES/0044-Fix-for-ps-vm-commands-to-display-correct-MEM-and-RS.patch similarity index 93% rename from SOURCES/0028-Fix-for-ps-vm-commands-to-display-correct-MEM-and-RS.patch rename to SOURCES/0044-Fix-for-ps-vm-commands-to-display-correct-MEM-and-RS.patch index c532993..0dfc4db 100644 --- a/SOURCES/0028-Fix-for-ps-vm-commands-to-display-correct-MEM-and-RS.patch +++ b/SOURCES/0044-Fix-for-ps-vm-commands-to-display-correct-MEM-and-RS.patch @@ -1,7 +1,7 @@ -From 74fe453f2b5ddf1e1571d006d486cb214817a0ed Mon Sep 17 00:00:00 2001 +From 4a6f318a39f78648a3bb13d74e31e3a331254e30 Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Wed, 9 Nov 2022 14:21:57 +0800 -Subject: [PATCH 28/28] Fix for "ps/vm" commands to display correct %MEM and +Subject: [PATCH 44/89] Fix for "ps/vm" commands to display correct %MEM and RSS values The ps/vm commands may print the bogus value of the %MEM and RSS, the @@ -25,7 +25,7 @@ Signed-off-by: Lianbo Jiang 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/memory.c b/memory.c -index ddbf458277f0..2167281b6039 100644 +index 8724c4aa3d8a..9c15c1b745ef 100644 --- a/memory.c +++ b/memory.c @@ -4714,18 +4714,29 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm) diff --git a/SOURCES/0045-ps-Provide-an-option-to-display-no-header-line.patch b/SOURCES/0045-ps-Provide-an-option-to-display-no-header-line.patch new file mode 100644 index 0000000..eebda8d --- /dev/null +++ b/SOURCES/0045-ps-Provide-an-option-to-display-no-header-line.patch @@ -0,0 +1,72 @@ +From acd2b8a54e4532f859173fe9f0d1b92b44cbc848 Mon Sep 17 00:00:00 2001 +From: Aaron Tomlin +Date: Tue, 29 Nov 2022 14:05:26 +0000 +Subject: [PATCH 45/89] ps: Provide an option to display no header line + +One might often find it useful to redirect/or filter the output +generated by the 'ps' command. This simple patch provides an option +(i.e. '-H') to display no header line so it does not need to be +considered e.g. + +crash> ps -u -H | head -5 + 1 0 1 ffff956e8028d280 IN 0.0 174276 9272 systemd + 1067 1 2 ffff956e81380000 IN 0.1 59480 15788 systemd-journal + 1080 1 0 ffff956e8d152940 IN 0.0 36196 3548 systemd-udevd + 1278 1 6 ffff956e8aa60000 IN 0.0 17664 3072 systemd-oomd + 1366 1 7 ffff956e88548000 IN 0.0 10868 2328 dbus-broker-lau + +Signed-off-by: Aaron Tomlin +Signed-off-by: Lianbo Jiang +--- + help.c | 3 ++- + task.c | 6 +++++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/help.c b/help.c +index e1ac6f93fde2..2cb570b244f4 100644 +--- a/help.c ++++ b/help.c +@@ -1385,7 +1385,7 @@ NULL + char *help_ps[] = { + "ps", + "display process status information", +-"[-k|-u|-G|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A]\n [pid | task | command] ...", ++"[-k|-u|-G|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S|-A|-H]\n [pid | task | command] ...", + " This command displays process status for selected, or all, processes" , + " in the system. If no arguments are entered, the process data is", + " is displayed for all processes. Specific processes may be selected", +@@ -1464,6 +1464,7 @@ char *help_ps[] = { + " -r display resource limits (rlimits) of selected, or all, tasks.", + " -S display a summary consisting of the number of tasks in a task state.", + " -A display only the active task on each cpu.", ++" -H display no header line.", + "\nEXAMPLES", + " Show the process status of all current tasks:\n", + " %s> ps", +diff --git a/task.c b/task.c +index db2abc8106a2..88941c7b0e4d 100644 +--- a/task.c ++++ b/task.c +@@ -3504,7 +3504,7 @@ cmd_ps(void) + cpuspec = NULL; + flag = 0; + +- while ((c = getopt(argcnt, args, "ASgstcpkuGlmarC:y:")) != EOF) { ++ while ((c = getopt(argcnt, args, "HASgstcpkuGlmarC:y:")) != EOF) { + switch(c) + { + case 'k': +@@ -3615,6 +3615,10 @@ cmd_ps(void) + flag |= PS_ACTIVE; + break; + ++ case 'H': ++ flag |= PS_NO_HEADER; ++ break; ++ + default: + argerrs++; + break; +-- +2.37.1 + diff --git a/SOURCES/0046-arm64-fix-backtraces-of-KASAN-kernel-dumpfile-trunca.patch b/SOURCES/0046-arm64-fix-backtraces-of-KASAN-kernel-dumpfile-trunca.patch new file mode 100644 index 0000000..a3da9e1 --- /dev/null +++ b/SOURCES/0046-arm64-fix-backtraces-of-KASAN-kernel-dumpfile-trunca.patch @@ -0,0 +1,150 @@ +From 6122f0d067ed5c522ad11fb91b6db3ea1d34f355 Mon Sep 17 00:00:00 2001 +From: Ding Hui +Date: Thu, 1 Dec 2022 15:01:45 +0800 +Subject: [PATCH 46/89] arm64: fix backtraces of KASAN kernel dumpfile + truncated + +We met "bt" command on KASAN kernel vmcore display truncated backtraces +like this: + + crash> bt + PID: 4131 TASK: ffff8001521df000 CPU: 3 COMMAND: "bash" + #0 [ffff2000224b0cb0] machine_kexec_prepare at ffff2000200bff4c + +After digging the root cause, it turns out that arm64_in_kdump_text() +found wrong bt->bptr at "machine_kexec" branch. + +Disassemble machine_kexec() of KASAN vmlinux (gcc 7.3.0): + + crash> dis -x machine_kexec + 0xffff2000200bff50 : stp x29, x30, [sp,#-208]! + 0xffff2000200bff54 : mov x29, sp + 0xffff2000200bff58 : stp x19, x20, [sp,#16] + 0xffff2000200bff5c : str x24, [sp,#56] + 0xffff2000200bff60 : str x26, [sp,#72] + 0xffff2000200bff64 : mov x2, #0x8ab3 + 0xffff2000200bff68 : add x1, x29, #0x70 + 0xffff2000200bff6c : lsr x1, x1, #3 + 0xffff2000200bff70 : movk x2, #0x41b5, lsl #16 + 0xffff2000200bff74 : mov x19, #0x200000000000 + 0xffff2000200bff78 : adrp x3, 0xffff2000224b0000 + 0xffff2000200bff7c : movk x19, #0xdfff, lsl #48 + 0xffff2000200bff80 : add x3, x3, #0xcb0 + 0xffff2000200bff84 : add x4, x1, x19 + 0xffff2000200bff88 : stp x2, x3, [x29,#112] + 0xffff2000200bff8c : adrp x2, 0xffff2000200bf000 + 0xffff2000200bff90 : add x2, x2, #0xf50 + 0xffff2000200bff94 : str x2, [x29,#128] + 0xffff2000200bff98 : mov w2, #0xf1f1f1f1 + 0xffff2000200bff9c : str w2, [x1,x19] + 0xffff2000200bffa0 : mov w2, #0xf200 + 0xffff2000200bffa4 : mov w1, #0xf3f3f3f3 + 0xffff2000200bffa8 : movk w2, #0xf2f2, lsl #16 + 0xffff2000200bffac : stp w2, w1, [x4,#4] + +We notice that: +1. machine_kexec() start address is 0xffff2000200bff50 +2. the instruction at machine_kexec+0x44 stores the same value + 0xffff2000200bff50 (comes from 0xffff2000200bf000 + 0xf50) + into stack postion [x29,#128]. + +When arm64_in_kdump_text() searches for LR from stack, it met +0xffff2000200bff50 firstly, so got wrong bt->bptr. + +We know that the real LR is always greater than the start address +of a function, so let's fix it by changing the search conditon to +(*ptr > xxx_start) && (*ptr < xxx_end). + +Signed-off-by: Ding Hui +Signed-off-by: Lianbo Jiang +--- + arm64.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/arm64.c b/arm64.c +index c3e26a371a61..7e8a7db1fcc4 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -3479,7 +3479,7 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame) + ms = machdep->machspec; + for (ptr = start - 8; ptr >= base; ptr--) { + if (bt->flags & BT_OPT_BACK_TRACE) { +- if ((*ptr >= ms->crash_kexec_start) && ++ if ((*ptr > ms->crash_kexec_start) && + (*ptr < ms->crash_kexec_end) && + INSTACK(*(ptr - 1), bt)) { + bt->bptr = ((ulong)(ptr - 1) - (ulong)base) +@@ -3488,7 +3488,7 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame) + fprintf(fp, "%lx: %lx (crash_kexec)\n", bt->bptr, *ptr); + return TRUE; + } +- if ((*ptr >= ms->crash_save_cpu_start) && ++ if ((*ptr > ms->crash_save_cpu_start) && + (*ptr < ms->crash_save_cpu_end) && + INSTACK(*(ptr - 1), bt)) { + bt->bptr = ((ulong)(ptr - 1) - (ulong)base) +@@ -3498,14 +3498,14 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame) + return TRUE; + } + } else { +- if ((*ptr >= ms->machine_kexec_start) && (*ptr < ms->machine_kexec_end)) { ++ if ((*ptr > ms->machine_kexec_start) && (*ptr < ms->machine_kexec_end)) { + bt->bptr = ((ulong)ptr - (ulong)base) + + task_to_stackbase(bt->tc->task); + if (CRASHDEBUG(1)) + fprintf(fp, "%lx: %lx (machine_kexec)\n", bt->bptr, *ptr); + return TRUE; + } +- if ((*ptr >= ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) { ++ if ((*ptr > ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) { + /* + * Stash the first crash_kexec frame in case the machine_kexec + * frame is not found. +@@ -3519,7 +3519,7 @@ arm64_in_kdump_text(struct bt_info *bt, struct arm64_stackframe *frame) + } + continue; + } +- if ((*ptr >= ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) { ++ if ((*ptr > ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) { + bt->bptr = ((ulong)ptr - (ulong)base) + + task_to_stackbase(bt->tc->task); + if (CRASHDEBUG(1)) +@@ -3566,7 +3566,7 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) + + for (ptr = start - 8; ptr >= base; ptr--) { + if (bt->flags & BT_OPT_BACK_TRACE) { +- if ((*ptr >= ms->crash_kexec_start) && ++ if ((*ptr > ms->crash_kexec_start) && + (*ptr < ms->crash_kexec_end) && + INSTACK(*(ptr - 1), bt)) { + bt->bptr = ((ulong)(ptr - 1) - (ulong)base) + stackbase; +@@ -3576,7 +3576,7 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) + FREEBUF(stackbuf); + return TRUE; + } +- if ((*ptr >= ms->crash_save_cpu_start) && ++ if ((*ptr > ms->crash_save_cpu_start) && + (*ptr < ms->crash_save_cpu_end) && + INSTACK(*(ptr - 1), bt)) { + bt->bptr = ((ulong)(ptr - 1) - (ulong)base) + stackbase; +@@ -3587,7 +3587,7 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) + return TRUE; + } + } else { +- if ((*ptr >= ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) { ++ if ((*ptr > ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) { + bt->bptr = ((ulong)ptr - (ulong)base) + stackbase; + if (CRASHDEBUG(1)) + fprintf(fp, "%lx: %lx (crash_kexec on IRQ stack)\n", +@@ -3595,7 +3595,7 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) + FREEBUF(stackbuf); + return TRUE; + } +- if ((*ptr >= ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) { ++ if ((*ptr > ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) { + bt->bptr = ((ulong)ptr - (ulong)base) + stackbase; + if (CRASHDEBUG(1)) + fprintf(fp, "%lx: %lx (crash_save_cpu on IRQ stack)\n", +-- +2.37.1 + diff --git a/SOURCES/0047-arm64-handle-vabits_actual-symbol-missing-case.patch b/SOURCES/0047-arm64-handle-vabits_actual-symbol-missing-case.patch new file mode 100644 index 0000000..5d46bb2 --- /dev/null +++ b/SOURCES/0047-arm64-handle-vabits_actual-symbol-missing-case.patch @@ -0,0 +1,37 @@ +From 69786ee12c4842d2cbd39ea42df65c45fb043edd Mon Sep 17 00:00:00 2001 +From: Pavankumar Kondeti +Date: Thu, 8 Dec 2022 09:55:07 +0530 +Subject: [PATCH 47/89] arm64: handle vabits_actual symbol missing case + +After kernel commit 0d9b1ffefabe ("arm64: mm: make vabits_actual +a build time constant if possible") introduced in Linux v5.19, +the crash will not find vabits_actual symbol if VA_BITS <= 48. +Add a fallback option to initialize VA_BITS based on the user +supplied machdep option. + +Tested ramdumps loading in both 6.0 and 5.15 kernels. + +Signed-off-by: Pavankumar Kondeti +Signed-off-by: Lianbo Jiang +--- + arm64.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arm64.c b/arm64.c +index 7e8a7db1fcc4..56fb841f43f8 100644 +--- a/arm64.c ++++ b/arm64.c +@@ -4671,6 +4671,10 @@ arm64_calc_VA_BITS(void) + return; + } else if (arm64_set_va_bits_by_tcr()) { + return; ++ } else if (machdep->machspec->VA_BITS_ACTUAL) { ++ machdep->machspec->VA_BITS = machdep->machspec->VA_BITS_ACTUAL; ++ machdep->machspec->VA_START = _VA_START(machdep->machspec->VA_BITS_ACTUAL); ++ return; + } + + if (!(sp = symbol_search("swapper_pg_dir")) && +-- +2.37.1 + diff --git a/SOURCES/0048-x86_64-Fix-for-move-of-per-cpu-variables-into-struct.patch b/SOURCES/0048-x86_64-Fix-for-move-of-per-cpu-variables-into-struct.patch new file mode 100644 index 0000000..a6e9128 --- /dev/null +++ b/SOURCES/0048-x86_64-Fix-for-move-of-per-cpu-variables-into-struct.patch @@ -0,0 +1,144 @@ +From 1f6b58b323f669293b4ef8d497fe7867d1411143 Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Wed, 7 Dec 2022 09:46:56 +0900 +Subject: [PATCH 48/89] x86_64: Fix for move of per-cpu variables into struct + pcpu_hot + +The following kernel commits, which are contained in Linux 6.2-rc1 and +later kernels, introduced struct pcpu_hot and moved several per-cpu +variables into it. + + d7b6d709a76a x86/percpu: Move irq_stack variables next to current_task + 7443b296e699 x86/percpu: Move cpu_number next to current_task + e57ef2ed97c1 x86: Put hot per CPU variables into a struct + +Without the patch, crash fails to start session with the following +error: + + $ crash vmlinux vmcore + ... + bt: invalid size request: 0 type: "stack contents" + bt: read of stack at 0 failed + + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + x86_64.c | 44 +++++++++++++++++++++++++++++++++----------- + 1 file changed, 33 insertions(+), 11 deletions(-) + +diff --git a/x86_64.c b/x86_64.c +index 292c240e887e..1113a1055f77 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -1287,12 +1287,15 @@ x86_64_per_cpu_init(void) + { + int i, cpus, cpunumber; + struct machine_specific *ms; +- struct syment *irq_sp, *curr_sp, *cpu_sp, *hardirq_stack_ptr_sp; ++ struct syment *irq_sp, *curr_sp, *cpu_sp, *hardirq_stack_ptr_sp, *pcpu_sp; + ulong hardirq_stack_ptr; + ulong __per_cpu_load = 0; ++ long hardirq_addr = 0, cpu_addr = 0, curr_addr = 0; + + ms = machdep->machspec; + ++ pcpu_sp = per_cpu_symbol_search("pcpu_hot"); ++ + hardirq_stack_ptr_sp = per_cpu_symbol_search("hardirq_stack_ptr"); + irq_sp = per_cpu_symbol_search("per_cpu__irq_stack_union"); + cpu_sp = per_cpu_symbol_search("per_cpu__cpu_number"); +@@ -1321,7 +1324,7 @@ x86_64_per_cpu_init(void) + return; + } + +- if (!cpu_sp || (!irq_sp && !hardirq_stack_ptr_sp)) ++ if (!pcpu_sp && (!cpu_sp || (!irq_sp && !hardirq_stack_ptr_sp))) + return; + + if (MEMBER_EXISTS("irq_stack_union", "irq_stack")) +@@ -1334,10 +1337,21 @@ x86_64_per_cpu_init(void) + if (kernel_symbol_exists("__per_cpu_load")) + __per_cpu_load = symbol_value("__per_cpu_load"); + ++ if (pcpu_sp) { ++ hardirq_addr = pcpu_sp->value + MEMBER_OFFSET("pcpu_hot", "hardirq_stack_ptr"); ++ cpu_addr = pcpu_sp->value + MEMBER_OFFSET("pcpu_hot", "cpu_number"); ++ curr_addr = pcpu_sp->value + MEMBER_OFFSET("pcpu_hot", "current_task"); ++ } else { ++ if (hardirq_stack_ptr_sp) ++ hardirq_addr = hardirq_stack_ptr_sp->value; ++ cpu_addr = cpu_sp->value; ++ curr_addr = curr_sp->value; ++ } ++ + for (i = cpus = 0; i < NR_CPUS; i++) { + if (__per_cpu_load && kt->__per_cpu_offset[i] == __per_cpu_load) + break; +- if (!readmem(cpu_sp->value + kt->__per_cpu_offset[i], ++ if (!readmem(cpu_addr + kt->__per_cpu_offset[i], + KVADDR, &cpunumber, sizeof(int), + "cpu number (per_cpu)", QUIET|RETURN_ON_ERROR)) + break; +@@ -1346,8 +1360,8 @@ x86_64_per_cpu_init(void) + break; + cpus++; + +- if (hardirq_stack_ptr_sp) { +- if (!readmem(hardirq_stack_ptr_sp->value + kt->__per_cpu_offset[i], ++ if (pcpu_sp || hardirq_stack_ptr_sp) { ++ if (!readmem(hardirq_addr + kt->__per_cpu_offset[i], + KVADDR, &hardirq_stack_ptr, sizeof(void *), + "hardirq_stack_ptr (per_cpu)", QUIET|RETURN_ON_ERROR)) + continue; +@@ -1370,13 +1384,13 @@ x86_64_per_cpu_init(void) + else + kt->cpus = cpus; + +- if (DUMPFILE() && curr_sp) { ++ if (DUMPFILE() && (pcpu_sp || curr_sp)) { + if ((ms->current = calloc(kt->cpus, sizeof(ulong))) == NULL) + error(FATAL, + "cannot calloc %d x86_64 current pointers!\n", + kt->cpus); + for (i = 0; i < kt->cpus; i++) +- if (!readmem(curr_sp->value + kt->__per_cpu_offset[i], ++ if (!readmem(curr_addr + kt->__per_cpu_offset[i], + KVADDR, &ms->current[i], sizeof(ulong), + "current_task (per_cpu)", RETURN_ON_ERROR)) + continue; +@@ -5622,11 +5636,19 @@ x86_64_get_smp_cpus(void) + char *cpu_pda_buf; + ulong level4_pgt, cpu_pda_addr; + struct syment *sp; +- ulong __per_cpu_load = 0; ++ ulong __per_cpu_load = 0, cpu_addr; + + if (!VALID_STRUCT(x8664_pda)) { +- if (!(sp = per_cpu_symbol_search("per_cpu__cpu_number")) || +- !(kt->flags & PER_CPU_OFF)) ++ ++ if (!(kt->flags & PER_CPU_OFF)) ++ return 1; ++ ++ if ((sp = per_cpu_symbol_search("pcpu_hot")) && ++ (cpu_addr = MEMBER_OFFSET("pcpu_hot", "cpu_number")) != INVALID_OFFSET) ++ cpu_addr += sp->value; ++ else if ((sp = per_cpu_symbol_search("per_cpu__cpu_number"))) ++ cpu_addr = sp->value; ++ else + return 1; + + if (kernel_symbol_exists("__per_cpu_load")) +@@ -5635,7 +5657,7 @@ x86_64_get_smp_cpus(void) + for (i = cpus = 0; i < NR_CPUS; i++) { + if (__per_cpu_load && kt->__per_cpu_offset[i] == __per_cpu_load) + break; +- if (!readmem(sp->value + kt->__per_cpu_offset[i], ++ if (!readmem(cpu_addr + kt->__per_cpu_offset[i], + KVADDR, &cpunumber, sizeof(int), + "cpu number (per_cpu)", QUIET|RETURN_ON_ERROR)) + break; +-- +2.37.1 + diff --git a/SOURCES/0049-Fix-for-mm_struct.rss_stat-conversion-into-percpu_co.patch b/SOURCES/0049-Fix-for-mm_struct.rss_stat-conversion-into-percpu_co.patch new file mode 100644 index 0000000..4a67dab --- /dev/null +++ b/SOURCES/0049-Fix-for-mm_struct.rss_stat-conversion-into-percpu_co.patch @@ -0,0 +1,163 @@ +From c05bbb36fcb468bce384ee4b8e30a0f5748bc4ae Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Thu, 15 Dec 2022 11:31:38 +0900 +Subject: [PATCH 49/89] Fix for mm_struct.rss_stat conversion into + percpu_counter + +Kernel commit f1a7941243c1 ("mm: convert mm's rss stats into +percpu_counter"), which is contained in Linux 6.2-rc1 and later +kernels, changed mm_struct.rss_stat from struct mm_rss_stat into an +array of struct percpu_counter. + +Without the patch, "ps" and several commands fail with the following +error message: + + ps: invalid structure member offset: mm_rss_stat_count + FILE: memory.c LINE: 4724 FUNCTION: get_task_mem_usage() + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 3 +++ + kernel.c | 2 ++ + memory.c | 14 +++++++++++++- + symbols.c | 6 ++++-- + tools.c | 28 ++++++++++++++++++++++++++++ + 5 files changed, 50 insertions(+), 3 deletions(-) + +diff --git a/defs.h b/defs.h +index b7d76330141a..e4732c885371 100644 +--- a/defs.h ++++ b/defs.h +@@ -2181,6 +2181,7 @@ struct offset_table { /* stash of commonly-used offsets */ + long blk_mq_tags_nr_reserved_tags; + long blk_mq_tags_rqs; + long request_queue_hctx_table; ++ long percpu_counter_counters; + }; + + struct size_table { /* stash of commonly-used sizes */ +@@ -2351,6 +2352,7 @@ struct size_table { /* stash of commonly-used sizes */ + long sbitmap_queue; + long sbq_wait_state; + long blk_mq_tags; ++ long percpu_counter; + }; + + struct array_table { +@@ -5307,6 +5309,7 @@ struct rb_node *rb_right(struct rb_node *, struct rb_node *); + struct rb_node *rb_left(struct rb_node *, struct rb_node *); + struct rb_node *rb_next(struct rb_node *); + struct rb_node *rb_last(struct rb_root *); ++long percpu_counter_sum_positive(ulong fbc); + + /* + * symbols.c +diff --git a/kernel.c b/kernel.c +index 2a1c1c391414..3ca513962970 100644 +--- a/kernel.c ++++ b/kernel.c +@@ -316,6 +316,8 @@ kernel_init() + } + + MEMBER_OFFSET_INIT(percpu_counter_count, "percpu_counter", "count"); ++ MEMBER_OFFSET_INIT(percpu_counter_counters, "percpu_counter", "counters"); ++ STRUCT_SIZE_INIT(percpu_counter, "percpu_counter"); + + if (STRUCT_EXISTS("runqueue")) { + rqstruct = "runqueue"; +diff --git a/memory.c b/memory.c +index 9c15c1b745ef..9d003713534b 100644 +--- a/memory.c ++++ b/memory.c +@@ -4713,7 +4713,7 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm) + /* + * Latest kernels have mm_struct.mm_rss_stat[]. + */ +- if (VALID_MEMBER(mm_struct_rss_stat)) { ++ if (VALID_MEMBER(mm_struct_rss_stat) && VALID_MEMBER(mm_rss_stat_count)) { + long anonpages, filepages, count; + + anonpages = tt->anonpages; +@@ -4737,6 +4737,18 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm) + (anonpages * sizeof(long))); + if (count > 0) + rss += count; ++ ++ } else if (VALID_MEMBER(mm_struct_rss_stat)) { ++ /* 6.2: struct percpu_counter rss_stat[NR_MM_COUNTERS] */ ++ ulong fbc; ++ ++ fbc = tc->mm_struct + OFFSET(mm_struct_rss_stat) + ++ (tt->filepages * SIZE(percpu_counter)); ++ rss += percpu_counter_sum_positive(fbc); ++ ++ fbc = tc->mm_struct + OFFSET(mm_struct_rss_stat) + ++ (tt->anonpages * SIZE(percpu_counter)); ++ rss += percpu_counter_sum_positive(fbc); + } + + /* Check whether SPLIT_RSS_COUNTING is enabled */ +diff --git a/symbols.c b/symbols.c +index a94660538492..657f50706819 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -10645,8 +10645,8 @@ dump_offset_table(char *spec, ulong makestruct) + OFFSET(ktime_t_nsec)); + fprintf(fp, " atomic_t_counter: %ld\n", + OFFSET(atomic_t_counter)); +- fprintf(fp, " percpu_counter_count: %ld\n", +- OFFSET(percpu_counter_count)); ++ fprintf(fp, " percpu_counter_count: %ld\n", OFFSET(percpu_counter_count)); ++ fprintf(fp, " percpu_counter_counters: %ld\n", OFFSET(percpu_counter_counters)); + fprintf(fp, " sk_buff_head_next: %ld\n", + OFFSET(sk_buff_head_next)); + fprintf(fp, " sk_buff_head_qlen: %ld\n", +@@ -11040,6 +11040,8 @@ dump_offset_table(char *spec, ulong makestruct) + fprintf(fp, " sbq_wait_state: %ld\n", SIZE(sbq_wait_state)); + fprintf(fp, " blk_mq_tags: %ld\n", SIZE(blk_mq_tags)); + ++ fprintf(fp, " percpu_counter: %ld\n", SIZE(percpu_counter)); ++ + fprintf(fp, "\n array_table:\n"); + /* + * Use get_array_length() for those fields not set up at init-time; +diff --git a/tools.c b/tools.c +index 6fa3c70bac2b..7f64bd6328cf 100644 +--- a/tools.c ++++ b/tools.c +@@ -6902,3 +6902,31 @@ rb_last(struct rb_root *root) + + return node; + } ++ ++long ++percpu_counter_sum_positive(ulong fbc) ++{ ++ int i, count; ++ ulong addr; ++ long ret; ++ ++ if (INVALID_MEMBER(percpu_counter_count)) ++ return 0; ++ ++ readmem(fbc + OFFSET(percpu_counter_count), KVADDR, &ret, ++ sizeof(long long), "percpu_counter.count", FAULT_ON_ERROR); ++ ++ if (INVALID_MEMBER(percpu_counter_counters)) /* !CONFIG_SMP */ ++ return (ret < 0) ? 0 : ret; ++ ++ readmem(fbc + OFFSET(percpu_counter_counters), KVADDR, &addr, ++ sizeof(void *), "percpu_counter.counters", FAULT_ON_ERROR); ++ ++ for (i = 0; i < kt->cpus; i++) { ++ readmem(addr + kt->__per_cpu_offset[i], KVADDR, &count, ++ sizeof(int), "percpu_counter.counters count", FAULT_ON_ERROR); ++ ret += count; ++ } ++ ++ return (ret < 0) ? 0 : ret; ++} +-- +2.37.1 + diff --git a/SOURCES/0050-Fix-mount-command-to-appropriately-display-the-mount.patch b/SOURCES/0050-Fix-mount-command-to-appropriately-display-the-mount.patch new file mode 100644 index 0000000..53f009f --- /dev/null +++ b/SOURCES/0050-Fix-mount-command-to-appropriately-display-the-mount.patch @@ -0,0 +1,48 @@ +From 1c56f2a37c79fa07c64dce34605d7b4a8a903243 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Wed, 21 Dec 2022 17:09:08 +0800 +Subject: [PATCH 50/89] Fix "mount" command to appropriately display the mount + dumps + +Recently the following failure has been observed on some vmcores when +using the mount command: + + crash> mount + MOUNT SUPERBLK TYPE DEVNAME DIRNAME + ffff97a4818a3480 ffff979500013800 rootfs none / + ffff97e4846ca700 ffff97e484653000 sysfs sysfs /sys + ... + ffff97b484753420 0 mount: invalid kernel virtual address: 0 type: "super_block buffer" + +The kernel virtual address of the super_block is zero when the mount +command fails with the vfsmnt address 0xffff97b484753420. And the +remaining mount information will be discarded. That is not expected. + +Check the address and skip it with a warning, if this is an invalid +kernel virtual address, that can avoid truncating the remaining mount +dumps. + +Reported-by: Dave Wysochanski +Signed-off-by: Lianbo Jiang +--- + filesys.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/filesys.c b/filesys.c +index c2ea78de821d..d64b54a9b822 100644 +--- a/filesys.c ++++ b/filesys.c +@@ -1491,6 +1491,10 @@ show_mounts(ulong one_vfsmount, int flags, struct task_context *namespace_contex + } + + sbp = ULONG(vfsmount_buf + OFFSET(vfsmount_mnt_sb)); ++ if (!IS_KVADDR(sbp)) { ++ error(WARNING, "cannot get super_block from vfsmnt: 0x%lx\n", *vfsmnt); ++ continue; ++ } + + if (flags) + fprintf(fp, "%s", mount_hdr); +-- +2.37.1 + diff --git a/SOURCES/0051-Add-RISCV64-framework-code-support.patch b/SOURCES/0051-Add-RISCV64-framework-code-support.patch new file mode 100644 index 0000000..9e35bea --- /dev/null +++ b/SOURCES/0051-Add-RISCV64-framework-code-support.patch @@ -0,0 +1,692 @@ +From 8ac8ab4f0e2d81b51b79b30f410c09e394b17e9c Mon Sep 17 00:00:00 2001 +From: Xianting Tian +Date: Thu, 20 Oct 2022 09:50:06 +0800 +Subject: [PATCH 51/89] Add RISCV64 framework code support + +This patch mainly added some environment configurations, macro definitions, +specific architecture structures and some function declarations supported +by the RISCV64 architecture. + +We can use the build command to get the simplest version crash tool: + make target=RISCV64 -j2 + +Co-developed-by: Lifang Xia +Signed-off-by: Xianting Tian +Signed-off-by: Lianbo Jiang +--- + Makefile | 7 +- + README | 6 +- + configure.c | 43 ++++++++++++- + defs.h | 154 +++++++++++++++++++++++++++++++++++++++++++- + diskdump.c | 11 +++- + help.c | 6 +- + lkcd_vmdump_v1.h | 8 +-- + lkcd_vmdump_v2_v3.h | 8 +-- + netdump.c | 9 ++- + ramdump.c | 2 + + riscv64.c | 54 ++++++++++++++++ + symbols.c | 10 +++ + 12 files changed, 294 insertions(+), 24 deletions(-) + create mode 100644 riscv64.c + +diff --git a/Makefile b/Makefile +index 2549d1d39273..c0de5ef8ff75 100644 +--- a/Makefile ++++ b/Makefile +@@ -64,7 +64,7 @@ CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \ + kernel.c test.c gdb_interface.c configure.c net.c dev.c bpf.c \ + printk.c \ + alpha.c x86.c ppc.c ia64.c s390.c s390x.c s390dbf.c ppc64.c x86_64.c \ +- arm.c arm64.c mips.c mips64.c sparc64.c \ ++ arm.c arm64.c mips.c mips64.c riscv64.c sparc64.c \ + extensions.c remote.c va_server.c va_server_v1.c symbols.c cmdline.c \ + lkcd_common.c lkcd_v1.c lkcd_v2_v3.c lkcd_v5.c lkcd_v7.c lkcd_v8.c\ + lkcd_fix_mem.c s390_dump.c lkcd_x86_trace.c \ +@@ -84,7 +84,7 @@ OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \ + build_data.o kernel.o test.o gdb_interface.o net.o dev.o bpf.o \ + printk.o \ + alpha.o x86.o ppc.o ia64.o s390.o s390x.o s390dbf.o ppc64.o x86_64.o \ +- arm.o arm64.o mips.o mips64.o sparc64.o \ ++ arm.o arm64.o mips.o mips64.o riscv64.o sparc64.o \ + extensions.o remote.o va_server.o va_server_v1.o symbols.o cmdline.o \ + lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \ + lkcd_fix_mem.o s390_dump.o netdump.o diskdump.o makedumpfile.o xendump.o \ +@@ -447,6 +447,9 @@ mips.o: ${GENERIC_HFILES} ${REDHAT_HFILES} mips.c + mips64.o: ${GENERIC_HFILES} ${REDHAT_HFILES} mips64.c + ${CC} -c ${CRASH_CFLAGS} mips64.c ${WARNING_OPTIONS} ${WARNING_ERROR} + ++riscv64.o: ${GENERIC_HFILES} ${REDHAT_HFILES} riscv64.c ++ ${CC} -c ${CRASH_CFLAGS} riscv64.c ${WARNING_OPTIONS} ${WARNING_ERROR} ++ + sparc64.o: ${GENERIC_HFILES} ${REDHAT_HFILES} sparc64.c + ${CC} -c ${CRASH_CFLAGS} sparc64.c ${WARNING_OPTIONS} ${WARNING_ERROR} + +diff --git a/README b/README +index 00386f6f8224..13a9de5d2ccb 100644 +--- a/README ++++ b/README +@@ -37,8 +37,8 @@ + These are the current prerequisites: + + o At this point, x86, ia64, x86_64, ppc64, ppc, arm, arm64, alpha, mips, +- mips64, s390 and s390x-based kernels are supported. Other architectures +- may be addressed in the future. ++ mips64, riscv64, s390 and s390x-based kernels are supported. Other ++ architectures may be addressed in the future. + + o One size fits all -- the utility can be run on any Linux kernel version + version dating back to 2.2.5-15. A primary design goal is to always +@@ -98,6 +98,8 @@ + arm64 dumpfiles may be built by typing "make target=ARM64". + o On an x86_64 host, an x86_64 binary that can be used to analyze + ppc64le dumpfiles may be built by typing "make target=PPC64". ++ o On an x86_64 host, an x86_64 binary that can be used to analyze ++ riscv64 dumpfiles may be built by typing "make target=RISCV64". + + Traditionally when vmcores are compressed via the makedumpfile(8) facility + the libz compression library is used, and by default the crash utility +diff --git a/configure.c b/configure.c +index b691a139b960..7de89553dbd3 100644 +--- a/configure.c ++++ b/configure.c +@@ -107,6 +107,7 @@ void add_extra_lib(char *); + #undef MIPS + #undef SPARC64 + #undef MIPS64 ++#undef RISCV64 + + #define UNKNOWN 0 + #define X86 1 +@@ -122,6 +123,7 @@ void add_extra_lib(char *); + #define MIPS 11 + #define SPARC64 12 + #define MIPS64 13 ++#define RISCV64 14 + + #define TARGET_X86 "TARGET=X86" + #define TARGET_ALPHA "TARGET=ALPHA" +@@ -136,6 +138,7 @@ void add_extra_lib(char *); + #define TARGET_MIPS "TARGET=MIPS" + #define TARGET_MIPS64 "TARGET=MIPS64" + #define TARGET_SPARC64 "TARGET=SPARC64" ++#define TARGET_RISCV64 "TARGET=RISCV64" + + #define TARGET_CFLAGS_X86 "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64" + #define TARGET_CFLAGS_ALPHA "TARGET_CFLAGS=" +@@ -158,6 +161,8 @@ void add_extra_lib(char *); + #define TARGET_CFLAGS_MIPS_ON_X86_64 "TARGET_CFLAGS=-m32 -D_FILE_OFFSET_BITS=64" + #define TARGET_CFLAGS_MIPS64 "TARGET_CFLAGS=" + #define TARGET_CFLAGS_SPARC64 "TARGET_CFLAGS=" ++#define TARGET_CFLAGS_RISCV64 "TARGET_CFLAGS=" ++#define TARGET_CFLAGS_RISCV64_ON_X86_64 "TARGET_CFLAGS=" + + #define GDB_TARGET_DEFAULT "GDB_CONF_FLAGS=" + #define GDB_TARGET_ARM_ON_X86 "GDB_CONF_FLAGS=--target=arm-elf-linux" +@@ -168,6 +173,7 @@ void add_extra_lib(char *); + #define GDB_TARGET_PPC64_ON_X86_64 "GDB_CONF_FLAGS=--target=powerpc64le-unknown-linux-gnu" + #define GDB_TARGET_MIPS_ON_X86 "GDB_CONF_FLAGS=--target=mipsel-elf-linux" + #define GDB_TARGET_MIPS_ON_X86_64 "GDB_CONF_FLAGS=--target=mipsel-elf-linux CFLAGS=-m32" ++#define GDB_TARGET_RISCV64_ON_X86_64 "GDB_CONF_FLAGS=--target=riscv64-unknown-linux-gnu" + + /* + * The original plan was to allow the use of a particular version +@@ -394,6 +400,9 @@ get_current_configuration(struct supported_gdb_version *sp) + #ifdef __sparc_v9__ + target_data.target = SPARC64; + #endif ++#if defined(__riscv) && (__riscv_xlen == 64) ++ target_data.target = RISCV64; ++#endif + + set_initial_target(sp); + +@@ -447,6 +456,12 @@ get_current_configuration(struct supported_gdb_version *sp) + if ((target_data.initial_gdb_target != UNKNOWN) && + (target_data.host != target_data.initial_gdb_target)) + arch_mismatch(sp); ++ } else if ((target_data.target == X86_64) && ++ (name_to_target((char *)target_data.target_as_param) == RISCV64)) { ++ /* ++ * Build an RISCV64 crash binary on an X86_64 host. ++ */ ++ target_data.target = RISCV64; + } else { + fprintf(stderr, + "\ntarget=%s is not supported on the %s host architecture\n\n", +@@ -487,6 +502,14 @@ get_current_configuration(struct supported_gdb_version *sp) + (target_data.target != MIPS64)) + arch_mismatch(sp); + ++ if ((target_data.initial_gdb_target == RISCV64) && ++ (target_data.target != RISCV64)) { ++ if (target_data.target == X86_64) ++ target_data.target = RISCV64; ++ else ++ arch_mismatch(sp); ++ } ++ + if ((target_data.initial_gdb_target == X86) && + (target_data.target != X86)) { + if (target_data.target == X86_64) +@@ -650,6 +673,9 @@ show_configuration(void) + case SPARC64: + printf("TARGET: SPARC64\n"); + break; ++ case RISCV64: ++ printf("TARGET: RISCV64\n"); ++ break; + } + + if (strlen(target_data.program)) { +@@ -767,6 +793,14 @@ build_configure(struct supported_gdb_version *sp) + target = TARGET_SPARC64; + target_CFLAGS = TARGET_CFLAGS_SPARC64; + break; ++ case RISCV64: ++ target = TARGET_RISCV64; ++ if (target_data.host == X86_64) { ++ target_CFLAGS = TARGET_CFLAGS_RISCV64_ON_X86_64; ++ gdb_conf_flags = GDB_TARGET_RISCV64_ON_X86_64; ++ } else ++ target_CFLAGS = TARGET_CFLAGS_RISCV64; ++ break; + } + + ldflags = get_extra_flags("LDFLAGS.extra", NULL); +@@ -1364,7 +1398,7 @@ make_spec_file(struct supported_gdb_version *sp) + printf("Vendor: Red Hat, Inc.\n"); + printf("Packager: Dave Anderson \n"); + printf("ExclusiveOS: Linux\n"); +- printf("ExclusiveArch: %%{ix86} alpha ia64 ppc ppc64 ppc64pseries ppc64iseries x86_64 s390 s390x arm aarch64 ppc64le mips mipsel mips64el sparc64\n"); ++ printf("ExclusiveArch: %%{ix86} alpha ia64 ppc ppc64 ppc64pseries ppc64iseries x86_64 s390 s390x arm aarch64 ppc64le mips mipsel mips64el sparc64 riscv64\n"); + printf("Buildroot: %%{_tmppath}/%%{name}-root\n"); + printf("BuildRequires: ncurses-devel zlib-devel bison\n"); + printf("Requires: binutils\n"); +@@ -1597,6 +1631,8 @@ set_initial_target(struct supported_gdb_version *sp) + target_data.initial_gdb_target = MIPS; + else if (strncmp(buf, "SPARC64", strlen("SPARC64")) == 0) + target_data.initial_gdb_target = SPARC64; ++ else if (strncmp(buf, "RISCV64", strlen("RISCV64")) == 0) ++ target_data.initial_gdb_target = RISCV64; + } + + char * +@@ -1617,6 +1653,7 @@ target_to_name(int target) + case MIPS: return("MIPS"); + case MIPS64: return("MIPS64"); + case SPARC64: return("SPARC64"); ++ case RISCV64: return("RISCV64"); + } + + return "UNKNOWN"; +@@ -1681,6 +1718,10 @@ name_to_target(char *name) + return MIPS64; + else if (strncmp(name, "sparc64", strlen("sparc64")) == 0) + return SPARC64; ++ else if (strncmp(name, "RISCV64", strlen("RISCV64")) == 0) ++ return RISCV64; ++ else if (strncmp(name, "riscv64", strlen("riscv64")) == 0) ++ return RISCV64; + + return UNKNOWN; + } +diff --git a/defs.h b/defs.h +index e4732c885371..f46b666dde13 100644 +--- a/defs.h ++++ b/defs.h +@@ -76,7 +76,7 @@ + #if !defined(X86) && !defined(X86_64) && !defined(ALPHA) && !defined(PPC) && \ + !defined(IA64) && !defined(PPC64) && !defined(S390) && !defined(S390X) && \ + !defined(ARM) && !defined(ARM64) && !defined(MIPS) && !defined(MIPS64) && \ +- !defined(SPARC64) ++ !defined(RISCV64) && !defined(SPARC64) + #ifdef __alpha__ + #define ALPHA + #endif +@@ -118,6 +118,9 @@ + #ifdef __sparc_v9__ + #define SPARC64 + #endif ++#if defined(__riscv) && (__riscv_xlen == 64) ++#define RISCV64 ++#endif + #endif + + #ifdef X86 +@@ -159,6 +162,9 @@ + #ifdef SPARC64 + #define NR_CPUS (4096) + #endif ++#ifdef RISCV64 ++#define NR_CPUS (256) ++#endif + + #define NR_DEVICE_DUMPS (64) + +@@ -3486,6 +3492,63 @@ struct arm64_stackframe { + #define _MAX_PHYSMEM_BITS 48 + #endif /* MIPS64 */ + ++#ifdef RISCV64 ++#define _64BIT_ ++#define MACHINE_TYPE "RISCV64" ++ ++/* ++ * Direct memory mapping ++ */ ++#define PTOV(X) \ ++ (((unsigned long)(X)+(machdep->kvbase)) - machdep->machspec->phys_base) ++#define VTOP(X) ({ \ ++ ulong _X = X; \ ++ (THIS_KERNEL_VERSION >= LINUX(5,13,0) && \ ++ (_X) >= machdep->machspec->kernel_link_addr) ? \ ++ (((unsigned long)(_X)-(machdep->machspec->kernel_link_addr)) + \ ++ machdep->machspec->phys_base): \ ++ (((unsigned long)(_X)-(machdep->kvbase)) + \ ++ machdep->machspec->phys_base); \ ++ }) ++#define PAGEBASE(X) (((ulong)(X)) & (ulong)machdep->pagemask) ++ ++/* ++ * Stack size order ++ */ ++#define THREAD_SIZE_ORDER 2 ++ ++#define PAGE_OFFSET (machdep->machspec->page_offset) ++#define VMALLOC_START (machdep->machspec->vmalloc_start_addr) ++#define VMALLOC_END (machdep->machspec->vmalloc_end) ++#define VMEMMAP_VADDR (machdep->machspec->vmemmap_vaddr) ++#define VMEMMAP_END (machdep->machspec->vmemmap_end) ++#define MODULES_VADDR (machdep->machspec->modules_vaddr) ++#define MODULES_END (machdep->machspec->modules_end) ++#define IS_VMALLOC_ADDR(X) riscv64_IS_VMALLOC_ADDR((ulong)(X)) ++ ++/* from arch/riscv/include/asm/pgtable.h */ ++#define __SWP_TYPE_SHIFT 6 ++#define __SWP_TYPE_BITS 5 ++#define __SWP_TYPE_MASK ((1UL << __SWP_TYPE_BITS) - 1) ++#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) ++ ++#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS) ++ ++#define SWP_TYPE(entry) (((entry) >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK) ++#define SWP_OFFSET(entry) ((entry) >> __SWP_OFFSET_SHIFT) ++#define __swp_type(entry) SWP_TYPE(entry) ++#define __swp_offset(entry) SWP_OFFSET(entry) ++ ++#define TIF_SIGPENDING (THIS_KERNEL_VERSION >= LINUX(2,6,23) ? 1 : 2) ++ ++/* from arch/riscv/include/asm/sparsemem.h */ ++#define _SECTION_SIZE_BITS 27 ++#define _MAX_PHYSMEM_BITS 56 /* 56-bit physical address supported */ ++#define PHYS_MASK_SHIFT _MAX_PHYSMEM_BITS ++#define PHYS_MASK (((1UL) << PHYS_MASK_SHIFT) - 1) ++ ++#endif /* RISCV64 */ ++ + #ifdef X86 + #define _32BIT_ + #define MACHINE_TYPE "X86" +@@ -4534,6 +4597,10 @@ struct machine_specific { + #define MAX_HEXADDR_STRLEN (16) + #define UVADDR_PRLEN (16) + #endif ++#ifdef RISCV64 ++#define MAX_HEXADDR_STRLEN (16) ++#define UVADDR_PRLEN (16) ++#endif + + #define BADADDR ((ulong)(-1)) + #define BADVAL ((ulong)(-1)) +@@ -5131,6 +5198,9 @@ void dump_build_data(void); + #ifdef MIPS64 + #define machdep_init(X) mips64_init(X) + #endif ++#ifdef RISCV64 ++#define machdep_init(X) riscv64_init(X) ++#endif + #ifdef SPARC64 + #define machdep_init(X) sparc64_init(X) + #endif +@@ -5618,6 +5688,9 @@ void display_help_screen(char *); + #ifdef SPARC64 + #define dump_machdep_table(X) sparc64_dump_machdep_table(X) + #endif ++#ifdef RISCV64 ++#define dump_machdep_table(X) riscv64_dump_machdep_table(X) ++#endif + extern char *help_pointer[]; + extern char *help_alias[]; + extern char *help_ascii[]; +@@ -6695,6 +6768,85 @@ struct machine_specific { + + #endif /* MIPS64 */ + ++/* ++ * riscv64.c ++ */ ++void riscv64_display_regs_from_elf_notes(int, FILE *); ++ ++#ifdef RISCV64 ++void riscv64_init(int); ++void riscv64_dump_machdep_table(ulong); ++int riscv64_IS_VMALLOC_ADDR(ulong); ++ ++#define display_idt_table() \ ++ error(FATAL, "-d option is not applicable to RISCV64 architecture\n") ++ ++/* from arch/riscv/include/asm/ptrace.h */ ++struct riscv64_register { ++ ulong regs[36]; ++}; ++ ++struct riscv64_pt_regs { ++ ulong badvaddr; ++ ulong cause; ++ ulong epc; ++}; ++ ++struct riscv64_unwind_frame { ++ ulong fp; ++ ulong sp; ++ ulong pc; ++}; ++ ++#define KSYMS_START (0x1) ++ ++struct machine_specific { ++ ulong phys_base; ++ ulong page_offset; ++ ulong vmalloc_start_addr; ++ ulong vmalloc_end; ++ ulong vmemmap_vaddr; ++ ulong vmemmap_end; ++ ulong modules_vaddr; ++ ulong modules_end; ++ ulong kernel_link_addr; ++ ++ ulong _page_present; ++ ulong _page_read; ++ ulong _page_write; ++ ulong _page_exec; ++ ulong _page_user; ++ ulong _page_global; ++ ulong _page_accessed; ++ ulong _page_dirty; ++ ulong _page_soft; ++ ++ ulong _pfn_shift; ++ ++ struct riscv64_register *crash_task_regs; ++}; ++/* from arch/riscv/include/asm/pgtable-bits.h */ ++#define _PAGE_PRESENT (machdep->machspec->_page_present) ++#define _PAGE_READ (machdep->machspec->_page_read) ++#define _PAGE_WRITE (machdep->machspec->_page_write) ++#define _PAGE_EXEC (machdep->machspec->_page_exec) ++#define _PAGE_USER (machdep->machspec->_page_user) ++#define _PAGE_GLOBAL (machdep->machspec->_page_global) ++#define _PAGE_ACCESSED (machdep->machspec->_page_accessed) ++#define _PAGE_DIRTY (machdep->machspec->_page_dirty) ++#define _PAGE_SOFT (machdep->machspec->_page_soft) ++#define _PAGE_SEC (machdep->machspec->_page_sec) ++#define _PAGE_SHARE (machdep->machspec->_page_share) ++#define _PAGE_BUF (machdep->machspec->_page_buf) ++#define _PAGE_CACHE (machdep->machspec->_page_cache) ++#define _PAGE_SO (machdep->machspec->_page_so) ++#define _PAGE_SPECIAL _PAGE_SOFT ++#define _PAGE_TABLE _PAGE_PRESENT ++#define _PAGE_PROT_NONE _PAGE_READ ++#define _PAGE_PFN_SHIFT 10 ++ ++#endif /* RISCV64 */ ++ + /* + * sparc64.c + */ +diff --git a/diskdump.c b/diskdump.c +index 09fac543011a..136cbd63f799 100644 +--- a/diskdump.c ++++ b/diskdump.c +@@ -622,6 +622,9 @@ restart: + else if (STRNEQ(header->utsname.machine, "aarch64") && + machine_type_mismatch(file, "ARM64", NULL, 0)) + goto err; ++ else if (STRNEQ(header->utsname.machine, "riscv64") && ++ machine_type_mismatch(file, "RISCV64", NULL, 0)) ++ goto err; + + if (header->block_size != block_size) { + block_size = header->block_size; +@@ -780,6 +783,8 @@ restart: + dd->machine_type = EM_AARCH64; + else if (machine_type("SPARC64")) + dd->machine_type = EM_SPARCV9; ++ else if (machine_type("RISCV64")) ++ dd->machine_type = EM_RISCV; + else { + error(INFO, "%s: unsupported machine type: %s\n", + DISKDUMP_VALID() ? "diskdump" : "compressed kdump", +@@ -1751,7 +1756,8 @@ dump_note_offsets(FILE *fp) + qemu = FALSE; + if (machine_type("X86_64") || machine_type("S390X") || + machine_type("ARM64") || machine_type("PPC64") || +- machine_type("SPARC64") || machine_type("MIPS64")) { ++ machine_type("SPARC64") || machine_type("MIPS64") || ++ machine_type("RISCV64")) { + note64 = (void *)dd->notes_buf + tot; + len = sizeof(Elf64_Nhdr); + if (STRNEQ((char *)note64 + len, "QEMU")) +@@ -2558,7 +2564,8 @@ dump_registers_for_compressed_kdump(void) + if (!KDUMP_CMPRS_VALID() || (dd->header->header_version < 4) || + !(machine_type("X86") || machine_type("X86_64") || + machine_type("ARM64") || machine_type("PPC64") || +- machine_type("MIPS") || machine_type("MIPS64"))) ++ machine_type("MIPS") || machine_type("MIPS64") || ++ machine_type("RISCV64"))) + error(FATAL, "-r option not supported for this dumpfile\n"); + + if (machine_type("ARM64") && (kt->cpus != dd->num_prstatus_notes)) +diff --git a/help.c b/help.c +index 2cb570b244f4..bfba43f6e9fd 100644 +--- a/help.c ++++ b/help.c +@@ -9518,8 +9518,8 @@ char *README[] = { + " These are the current prerequisites: ", + "", + " o At this point, x86, ia64, x86_64, ppc64, ppc, arm, arm64, alpha, mips,", +-" mips64, s390 and s390x-based kernels are supported. Other architectures", +-" may be addressed in the future.", ++" mips64, riscv64, s390 and s390x-based kernels are supported. Other", ++" architectures may be addressed in the future.", + "", + " o One size fits all -- the utility can be run on any Linux kernel version", + " version dating back to 2.2.5-15. A primary design goal is to always", +@@ -9578,6 +9578,8 @@ README_ENTER_DIRECTORY, + " arm64 dumpfiles may be built by typing \"make target=ARM64\".", + " o On an x86_64 host, an x86_64 binary that can be used to analyze", + " ppc64le dumpfiles may be built by typing \"make target=PPC64\".", ++" o On an x86_64 host, an x86_64 binary that can be used to analyze", ++" riscv64 dumpfiles may be built by typing \"make target=RISCV64\".", + "", + " Traditionally when vmcores are compressed via the makedumpfile(8) facility", + " the libz compression library is used, and by default the crash utility", +diff --git a/lkcd_vmdump_v1.h b/lkcd_vmdump_v1.h +index 4933427fc755..98ee09495869 100644 +--- a/lkcd_vmdump_v1.h ++++ b/lkcd_vmdump_v1.h +@@ -114,14 +114,8 @@ typedef struct _dump_header_s { + struct new_utsname dh_utsname; + + /* the dump registers */ +-#ifndef IA64 +-#ifndef S390 +-#ifndef S390X +-#ifndef ARM64 ++#if !defined(IA64) && !defined(S390) && !defined(S390X) && !defined(ARM64) && !defined(RISCV64) + struct pt_regs dh_regs; +-#endif +-#endif +-#endif + #endif + + /* the address of the current task */ +diff --git a/lkcd_vmdump_v2_v3.h b/lkcd_vmdump_v2_v3.h +index 984c2c25e3c6..ef3067f88e1e 100644 +--- a/lkcd_vmdump_v2_v3.h ++++ b/lkcd_vmdump_v2_v3.h +@@ -37,7 +37,7 @@ + + #if defined(ARM) || defined(X86) || defined(PPC) || defined(S390) || \ + defined(S390X) || defined(ARM64) || defined(MIPS) || \ +- defined(MIPS64) || defined(SPARC64) ++ defined(MIPS64) || defined(SPARC64) || defined(RISCV64) + + /* + * Kernel header file for Linux crash dumps. +@@ -84,13 +84,9 @@ typedef struct _dump_header_asm_s { + uint32_t dha_eip; + + /* the dump registers */ +-#ifndef S390 +-#ifndef S390X +-#ifndef ARM64 ++#if !defined(S390) && !defined(S390X) && !defined(ARM64) && !defined(RISCV64) + struct pt_regs dha_regs; + #endif +-#endif +-#endif + + } dump_header_asm_t; + +diff --git a/netdump.c b/netdump.c +index e8721d89f1a3..c4c8baae0d20 100644 +--- a/netdump.c ++++ b/netdump.c +@@ -300,6 +300,12 @@ is_netdump(char *file, ulong source_query) + goto bailout; + break; + ++ case EM_RISCV: ++ if (machine_type_mismatch(file, "RISCV64", NULL, ++ source_query)) ++ goto bailout; ++ break; ++ + default: + if (machine_type_mismatch(file, "(unknown)", NULL, + source_query)) +@@ -2935,7 +2941,8 @@ dump_registers_for_elf_dumpfiles(void) + + if (!(machine_type("X86") || machine_type("X86_64") || + machine_type("ARM64") || machine_type("PPC64") || +- machine_type("MIPS") || machine_type("MIPS64"))) ++ machine_type("MIPS") || machine_type("MIPS64") || ++ machine_type("RISCV64"))) + error(FATAL, "-r option not supported for this dumpfile\n"); + + if (NETDUMP_DUMPFILE()) { +diff --git a/ramdump.c b/ramdump.c +index a206fcbbab3c..d2bd7ffb0b4b 100644 +--- a/ramdump.c ++++ b/ramdump.c +@@ -188,6 +188,8 @@ char *ramdump_to_elf(void) + e_machine = EM_MIPS; + else if (machine_type("X86_64")) + e_machine = EM_X86_64; ++ else if (machine_type("RISCV64")) ++ e_machine = EM_RISCV; + else + error(FATAL, "ramdump: unsupported machine type: %s\n", + MACHINE_TYPE); +diff --git a/riscv64.c b/riscv64.c +new file mode 100644 +index 000000000000..4f858a418a8c +--- /dev/null ++++ b/riscv64.c +@@ -0,0 +1,54 @@ ++/* riscv64.c - core analysis suite ++ * ++ * Copyright (C) 2022 Alibaba Group Holding Limited. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#include "defs.h" ++#ifdef RISCV64 ++ ++#include ++ ++void ++riscv64_dump_machdep_table(ulong arg) ++{ ++} ++ ++/* ++ * Include both vmalloc'd and module address space as VMALLOC space. ++ */ ++int ++riscv64_IS_VMALLOC_ADDR(ulong vaddr) ++{ ++ return ((vaddr >= VMALLOC_START && vaddr <= VMALLOC_END) || ++ (vaddr >= VMEMMAP_VADDR && vaddr <= VMEMMAP_END) || ++ (vaddr >= MODULES_VADDR && vaddr <= MODULES_END)); ++} ++ ++void ++riscv64_init(int when) ++{ ++} ++ ++void ++riscv64_display_regs_from_elf_notes(int cpu, FILE *ofp) ++{ ++} ++ ++#else /* !RISCV64 */ ++ ++void ++riscv64_display_regs_from_elf_notes(int cpu, FILE *ofp) ++{ ++ return; ++} ++ ++#endif /* !RISCV64 */ +diff --git a/symbols.c b/symbols.c +index 657f50706819..d1b35a56aa71 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -3745,6 +3745,11 @@ is_kernel(char *file) + goto bailout; + break; + ++ case EM_RISCV: ++ if (machine_type_mismatch(file, "RISCV64", NULL, 0)) ++ goto bailout; ++ break; ++ + default: + if (machine_type_mismatch(file, "(unknown)", NULL, 0)) + goto bailout; +@@ -4004,6 +4009,11 @@ is_shared_object(char *file) + if (machine_type("MIPS64")) + return TRUE; + break; ++ ++ case EM_RISCV: ++ if (machine_type("RISCV64")) ++ return TRUE; ++ break; + } + + if (CRASHDEBUG(1)) +-- +2.37.1 + diff --git a/SOURCES/0052-RISCV64-Make-crash-tool-enter-command-line-and-suppo.patch b/SOURCES/0052-RISCV64-Make-crash-tool-enter-command-line-and-suppo.patch new file mode 100644 index 0000000..22ce68c --- /dev/null +++ b/SOURCES/0052-RISCV64-Make-crash-tool-enter-command-line-and-suppo.patch @@ -0,0 +1,1287 @@ +From 3de94420220d407f11207a804a71b80bf65bd041 Mon Sep 17 00:00:00 2001 +From: Xianting Tian +Date: Thu, 20 Oct 2022 09:50:07 +0800 +Subject: [PATCH 52/89] RISCV64: Make crash tool enter command line and support + some commands + +1. Add riscv64_init() implementation, do all necessary machine-specific setup, + which will be called multiple times during initialization. +2. Add riscv64 sv39/48/57 pagetable macro definitions, the function of converting + virtual address to a physical address via 4K page table. + For 2M and 1G pagesize, they will be implemented in the future(currently not supported). +3. Add the implementation of the vtop command, which is used to convert a + virtual address to a physical address(call the functions defined in 2). +4. Add the implementation to get virtual memory layout, va_bits, phys_ram_base + from vmcoreinfo. As these configurations changes from time to time, we sent + a Linux kernel patch to export these configurations, which can simplify the + development of crash tool. + The kernel commit: 649d6b1019a2 ("RISC-V: Add arch_crash_save_vmcoreinfo") +5. Add riscv64_get_smp_cpus() implementation, get the number of cpus. +6. Add riscv64_get_page_size() implementation, get page size. +And so on. + +With this patch, we can enter crash command line, and run "vtop", "mod", "rd", +"*", "p", "kmem" ... + +Tested on QEMU RISCV64 end and SoC platform of T-head Xuantie 910 CPU. + + KERNEL: vmlinux + DUMPFILE: vmcore + CPUS: 1 + DATE: Fri Jul 15 10:24:25 CST 2022 + UPTIME: 00:00:33 +LOAD AVERAGE: 0.05, 0.01, 0.00 + TASKS: 41 + NODENAME: buildroot + RELEASE: 5.18.9 + VERSION: #30 SMP Fri Jul 15 09:47:03 CST 2022 + MACHINE: riscv64 (unknown Mhz) + MEMORY: 1 GB + PANIC: "Kernel panic - not syncing: sysrq triggered crash" + PID: 113 + COMMAND: "sh" + TASK: ff60000002269600 [THREAD_INFO: ff60000002269600] + CPU: 0 + STATE: TASK_RUNNING (PANIC) + +crash> p mem_map +mem_map = $1 = (struct page *) 0xff6000003effbf00 + +crash> p /x *(struct page *) 0xff6000003effbf00 +$5 = { + flags = 0x1000, + { + { + { + lru = { + next = 0xff6000003effbf08, + prev = 0xff6000003effbf08 + }, + { + __filler = 0xff6000003effbf08, + mlock_count = 0x3effbf08 + } + }, + mapping = 0x0, + index = 0x0, + private = 0x0 + }, + +crash> mod + MODULE NAME BASE SIZE OBJECT FILE +ffffffff0113e740 nvme_core ffffffff01133000 98304 (not loaded) [CONFIG_KALLSYMS] +ffffffff011542c0 nvme ffffffff0114c000 61440 (not loaded) [CONFIG_KALLSYMS] + +crash> rd ffffffff0113e740 8 +ffffffff0113e740: 0000000000000000 ffffffff810874f8 .........t...... +ffffffff0113e750: ffffffff011542c8 726f635f656d766e .B......nvme_cor +ffffffff0113e760: 0000000000000065 0000000000000000 e............... +ffffffff0113e770: 0000000000000000 0000000000000000 ................ + +crash> vtop ffffffff0113e740 +VIRTUAL PHYSICAL +ffffffff0113e740 8254d740 + + PGD: ffffffff810e9ff8 => 2ffff001 + P4D: 0000000000000000 => 000000002fffec01 + PUD: 00005605c2957470 => 0000000020949801 + PMD: 00007fff7f1750c0 => 0000000020947401 + PTE: 0 => 209534e7 + PAGE: 000000008254d000 + + PTE PHYSICAL FLAGS +209534e7 8254d000 (PRESENT|READ|WRITE|GLOBAL|ACCESSED|DIRTY) + + PAGE PHYSICAL MAPPING INDEX CNT FLAGS +ff6000003f0777d8 8254d000 0 0 1 0 + +Tested-by: Yixun Lan +Signed-off-by: Xianting Tian +Signed-off-by: Lianbo Jiang +--- + defs.h | 97 ++++++ + diskdump.c | 10 + + riscv64.c | 994 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 1101 insertions(+) + +diff --git a/defs.h b/defs.h +index f46b666dde13..9c91f38328d0 100644 +--- a/defs.h ++++ b/defs.h +@@ -3496,6 +3496,85 @@ struct arm64_stackframe { + #define _64BIT_ + #define MACHINE_TYPE "RISCV64" + ++typedef struct { ulong pgd; } pgd_t; ++typedef struct { ulong p4d; } p4d_t; ++typedef struct { ulong pud; } pud_t; ++typedef struct { ulong pmd; } pmd_t; ++typedef struct { ulong pte; } pte_t; ++typedef signed int s32; ++ ++/* arch/riscv/include/asm/pgtable-64.h */ ++#define PGD_SHIFT_L3 (30) ++#define PGD_SHIFT_L4 (39) ++#define PGD_SHIFT_L5 (48) ++ ++#define P4D_SHIFT (39) ++#define PUD_SHIFT (30) ++#define PMD_SHIFT (21) ++ ++#define PTRS_PER_PGD (512) ++#define PTRS_PER_P4D (512) ++#define PTRS_PER_PUD (512) ++#define PTRS_PER_PMD (512) ++#define PTRS_PER_PTE (512) ++ ++/* ++ * Mask for bit 0~53(PROT and PPN) of PTE ++ * 63 6261 60 54 53 10 9 8 7 6 5 4 3 2 1 0 ++ * N PBMT Reserved P P N RSW D A G U X W R V ++ */ ++#define PTE_PFN_PROT_MASK 0x3FFFFFFFFFFFFF ++ ++/* ++ * 3-levels / 4K pages ++ * ++ * sv39 ++ * PGD | PMD | PTE | OFFSET | ++ * 9 | 9 | 9 | 12 | ++ */ ++#define pgd_index_l3_4k(addr) (((addr) >> PGD_SHIFT_L3) & (PTRS_PER_PGD - 1)) ++#define pmd_index_l3_4k(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) ++#define pte_index_l3_4k(addr) (((addr) >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) ++ ++/* ++ * 4-levels / 4K pages ++ * ++ * sv48 ++ * PGD | PUD | PMD | PTE | OFFSET | ++ * 9 | 9 | 9 | 9 | 12 | ++ */ ++#define pgd_index_l4_4k(addr) (((addr) >> PGD_SHIFT_L4) & (PTRS_PER_PGD - 1)) ++#define pud_index_l4_4k(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) ++#define pmd_index_l4_4k(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) ++#define pte_index_l4_4k(addr) (((addr) >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) ++ ++/* ++ * 5-levels / 4K pages ++ * ++ * sv57 ++ * PGD | P4D | PUD | PMD | PTE | OFFSET | ++ * 9 | 9 | 9 | 9 | 9 | 12 | ++ */ ++#define pgd_index_l5_4k(addr) (((addr) >> PGD_SHIFT_L5) & (PTRS_PER_PGD - 1)) ++#define p4d_index_l5_4k(addr) (((addr) >> P4D_SHIFT) & (PTRS_PER_P4D - 1)) ++#define pud_index_l5_4k(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) ++#define pmd_index_l5_4k(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) ++#define pte_index_l5_4k(addr) (((addr) >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) ++ ++#define VM_L3_4K (0x2) ++#define VM_L3_2M (0x4) ++#define VM_L3_1G (0x8) ++#define VM_L4_4K (0x10) ++#define VM_L4_2M (0x20) ++#define VM_L4_1G (0x40) ++#define VM_L5_4K (0x80) ++#define VM_L5_2M (0x100) ++#define VM_L5_1G (0x200) ++ ++#define VM_FLAGS (VM_L3_4K | VM_L3_2M | VM_L3_1G | \ ++ VM_L4_4K | VM_L4_2M | VM_L4_1G | \ ++ VM_L5_4K | VM_L5_2M | VM_L5_1G) ++ + /* + * Direct memory mapping + */ +@@ -3547,6 +3626,14 @@ struct arm64_stackframe { + #define PHYS_MASK_SHIFT _MAX_PHYSMEM_BITS + #define PHYS_MASK (((1UL) << PHYS_MASK_SHIFT) - 1) + ++#define IS_LAST_P4D_READ(p4d) ((ulong)(p4d) == machdep->machspec->last_p4d_read) ++#define FILL_P4D(P4D, TYPE, SIZE) \ ++ if (!IS_LAST_P4D_READ(P4D)) { \ ++ readmem((ulonglong)((ulong)(P4D)), TYPE, machdep->machspec->p4d, \ ++ SIZE, "p4d page", FAULT_ON_ERROR); \ ++ machdep->machspec->last_p4d_read = (ulong)(P4D); \ ++ } ++ + #endif /* RISCV64 */ + + #ifdef X86 +@@ -6822,6 +6909,10 @@ struct machine_specific { + ulong _page_soft; + + ulong _pfn_shift; ++ ulong va_bits; ++ char *p4d; ++ ulong last_p4d_read; ++ ulong struct_page_size; + + struct riscv64_register *crash_task_regs; + }; +@@ -6845,6 +6936,12 @@ struct machine_specific { + #define _PAGE_PROT_NONE _PAGE_READ + #define _PAGE_PFN_SHIFT 10 + ++/* from 'struct pt_regs' definitions of RISC-V arch */ ++#define RISCV64_REGS_EPC 0 ++#define RISCV64_REGS_RA 1 ++#define RISCV64_REGS_SP 2 ++#define RISCV64_REGS_FP 8 ++ + #endif /* RISCV64 */ + + /* +diff --git a/diskdump.c b/diskdump.c +index 136cbd63f799..90e67d7df1db 100644 +--- a/diskdump.c ++++ b/diskdump.c +@@ -1531,6 +1531,12 @@ get_diskdump_regs_mips(struct bt_info *bt, ulong *eip, ulong *esp) + machdep->get_stack_frame(bt, eip, esp); + } + ++static void ++get_diskdump_regs_riscv64(struct bt_info *bt, ulong *eip, ulong *esp) ++{ ++ machdep->get_stack_frame(bt, eip, esp); ++} ++ + static void + get_diskdump_regs_sparc64(struct bt_info *bt, ulong *eip, ulong *esp) + { +@@ -1610,6 +1616,10 @@ get_diskdump_regs(struct bt_info *bt, ulong *eip, ulong *esp) + get_diskdump_regs_sparc64(bt, eip, esp); + break; + ++ case EM_RISCV: ++ get_diskdump_regs_riscv64(bt, eip, esp); ++ break; ++ + default: + error(FATAL, "%s: unsupported machine type: %s\n", + DISKDUMP_VALID() ? "diskdump" : "compressed kdump", +diff --git a/riscv64.c b/riscv64.c +index 4f858a418a8c..d8de3d56e1b7 100644 +--- a/riscv64.c ++++ b/riscv64.c +@@ -16,10 +16,314 @@ + #ifdef RISCV64 + + #include ++#include ++ ++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 void riscv64_page_type_init(void); ++static int riscv64_is_kvaddr(ulong vaddr); ++static int riscv64_is_uvaddr(ulong vaddr, struct task_context *tc); ++static int riscv64_uvtop(struct task_context *tc, ulong vaddr, ++ physaddr_t *paddr, int verbose); ++static int riscv64_kvtop(struct task_context *tc, ulong kvaddr, ++ physaddr_t *paddr, int verbose); ++static void riscv64_cmd_mach(void); ++static int riscv64_translate_pte(ulong, void *, ulonglong); ++static int riscv64_init_active_task_regs(void); ++static int riscv64_get_crash_notes(void); ++static int riscv64_get_elf_notes(void); ++static void riscv64_get_va_range(struct machine_specific *ms); ++static void riscv64_get_va_bits(struct machine_specific *ms); ++static void riscv64_get_struct_page_size(struct machine_specific *ms); ++ ++#define REG_FMT "%016lx" ++#define SZ_2G 0x80000000 ++ ++/* ++ * Holds registers during the crash. ++ */ ++static struct riscv64_register *panic_task_regs; ++ ++/* from arch/riscv/include/asm/stacktrace.h */ ++struct stackframe { ++ ulong fp; ++ ulong ra; ++}; ++ ++static struct machine_specific riscv64_machine_specific = { ++ ._page_present = (1 << 0), ++ ._page_read = (1 << 1), ++ ._page_write = (1 << 2), ++ ._page_exec = (1 << 3), ++ ._page_user = (1 << 4), ++ ._page_global = (1 << 5), ++ ._page_accessed = (1 << 6), ++ ._page_dirty = (1 << 7), ++ ._page_soft = (1 << 8), ++ ++ .va_bits = 0, ++ .struct_page_size = 0, ++}; ++ ++static void ++pt_level_alloc(char **lvl, char *name) ++{ ++ size_t sz = PAGESIZE(); ++ void *pointer = malloc(sz); ++ ++ if (!pointer) ++ error(FATAL, name); ++ *lvl = pointer; ++} ++ ++static ulong ++riscv64_get_page_size(void) ++{ ++ return memory_page_size(); ++} ++ ++static ulong ++riscv64_vmalloc_start(void) ++{ ++ return ((ulong)VMALLOC_START); ++} ++ ++/* Get the size of struct page {} */ ++static void riscv64_get_struct_page_size(struct machine_specific *ms) ++{ ++ char *string; ++ ++ string = pc->read_vmcoreinfo("SIZE(page)"); ++ if (string) { ++ ms->struct_page_size = atol(string); ++ free(string); ++ } ++} ++ ++static void ++riscv64_cmd_mach(void) ++{ ++ /* TODO: */ ++} ++ ++static int ++riscv64_verify_symbol(const char *name, ulong value, char type) ++{ ++ /* TODO: */ ++ return TRUE; ++} + + void + riscv64_dump_machdep_table(ulong arg) + { ++ /* TODO: */ ++} ++ ++static ulong ++riscv64_processor_speed(void) ++{ ++ /* TODO: */ ++ return 0; ++} ++ ++static unsigned long riscv64_get_kernel_version(void) ++{ ++ char *string; ++ char buf[BUFSIZE]; ++ char *p1, *p2; ++ ++ if (THIS_KERNEL_VERSION) ++ return THIS_KERNEL_VERSION; ++ ++ string = pc->read_vmcoreinfo("OSRELEASE"); ++ if (string) { ++ strcpy(buf, string); ++ ++ p1 = p2 = buf; ++ while (*p2 != '.') ++ p2++; ++ *p2 = NULLCHAR; ++ kt->kernel_version[0] = atoi(p1); ++ ++ p1 = ++p2; ++ while (*p2 != '.') ++ p2++; ++ *p2 = NULLCHAR; ++ kt->kernel_version[1] = atoi(p1); ++ ++ p1 = ++p2; ++ while ((*p2 >= '0') && (*p2 <= '9')) ++ p2++; ++ *p2 = NULLCHAR; ++ kt->kernel_version[2] = atoi(p1); ++ free(string); ++ } ++ return THIS_KERNEL_VERSION; ++} ++ ++static void ++riscv64_get_phys_ram_base(struct machine_specific *ms) ++{ ++ unsigned long kernel_version = riscv64_get_kernel_version(); ++ ++ /* ++ * phys_ram_base is defined in Linux kernel since 5.14. ++ */ ++ if (kernel_version >= LINUX(5,14,0)) { ++ char *string; ++ if ((string = pc->read_vmcoreinfo("NUMBER(phys_ram_base)"))) { ++ ms->phys_base = atol(string); ++ free(string); ++ } else ++ error(FATAL, "cannot read phys_ram_base\n"); ++ } else ++ /* ++ * For qemu rv64 env and hardware platform, default phys base ++ * may different, eg, ++ * hardware platform: 0x200000 ++ * qemu rv64 env: 0x80200000 ++ * ++ * But we only can set one default value, in this case, qemu ++ * rv64 env may can't work. ++ */ ++ ms->phys_base = 0x200000; ++} ++ ++static void riscv64_get_va_bits(struct machine_specific *ms) ++{ ++ unsigned long kernel_version = riscv64_get_kernel_version(); ++ ++ /* ++ * VA_BITS is defined in Linux kernel since 5.17. So we use the ++ * default va bits 39 when Linux version < 5.17. ++ */ ++ if (kernel_version >= LINUX(5,17,0)) { ++ char *string; ++ if ((string = pc->read_vmcoreinfo("NUMBER(VA_BITS)"))) { ++ ms->va_bits = atol(string); ++ free(string); ++ } ++ } else ++ ms->va_bits = 39; ++} ++ ++static void riscv64_get_va_range(struct machine_specific *ms) ++{ ++ unsigned long kernel_version = riscv64_get_kernel_version(); ++ char *string; ++ ++ if ((string = pc->read_vmcoreinfo("NUMBER(PAGE_OFFSET)"))) { ++ ms->page_offset = htol(string, QUIET, NULL); ++ free(string); ++ } else ++ goto error; ++ ++ if ((string = pc->read_vmcoreinfo("NUMBER(VMALLOC_START)"))) { ++ ms->vmalloc_start_addr = htol(string, QUIET, NULL); ++ free(string); ++ } else ++ goto error; ++ ++ if ((string = pc->read_vmcoreinfo("NUMBER(VMALLOC_END)"))) { ++ ms->vmalloc_end = htol(string, QUIET, NULL); ++ free(string); ++ } else ++ goto error; ++ ++ if ((string = pc->read_vmcoreinfo("NUMBER(VMEMMAP_START)"))) { ++ ms->vmemmap_vaddr = htol(string, QUIET, NULL); ++ free(string); ++ } else ++ goto error; ++ ++ if ((string = pc->read_vmcoreinfo("NUMBER(VMEMMAP_END)"))) { ++ ms->vmemmap_end = htol(string, QUIET, NULL); ++ free(string); ++ } else ++ goto error; ++ ++ if ((string = pc->read_vmcoreinfo("NUMBER(KERNEL_LINK_ADDR)"))) { ++ ms->kernel_link_addr = htol(string, QUIET, NULL); ++ free(string); ++ } else ++ goto error; ++ ++ /* ++ * From Linux 5.13, the kernel mapping is moved to the last 2GB ++ * of the address space, modules use the 2GB memory range right ++ * before the kernel. Before Linux 5.13, modules area is embedded ++ * in vmalloc area. ++ * ++ */ ++ if (kernel_version >= LINUX(5,13,0)) { ++ if ((string = pc->read_vmcoreinfo("NUMBER(MODULES_VADDR)"))) { ++ ms->modules_vaddr = htol(string, QUIET, NULL); ++ free(string); ++ } else ++ goto error; ++ ++ if ((string = pc->read_vmcoreinfo("NUMBER(MODULES_END)"))) { ++ ms->modules_end = htol(string, QUIET, NULL); ++ free(string); ++ } else ++ goto error; ++ } else { ++ ms->modules_vaddr = ms->vmalloc_start_addr; ++ ms->modules_end = ms->vmalloc_end; ++ } ++ ++ if (CRASHDEBUG(1)) { ++ fprintf(fp, "vmemmap : 0x%lx - 0x%lx\n", ++ ms->vmemmap_vaddr, ms->vmemmap_end); ++ fprintf(fp, "vmalloc : 0x%lx - 0x%lx\n", ++ ms->vmalloc_start_addr, ms->vmalloc_end); ++ fprintf(fp, "mudules : 0x%lx - 0x%lx\n", ++ ms->modules_vaddr, ms->modules_end); ++ fprintf(fp, "lowmem : 0x%lx -\n", ms->page_offset); ++ fprintf(fp, "kernel link addr : 0x%lx\n", ++ ms->kernel_link_addr); ++ } ++ return; ++error: ++ error(FATAL, "cannot get vm layout\n"); ++} ++ ++static int ++riscv64_is_kvaddr(ulong vaddr) ++{ ++ if (IS_VMALLOC_ADDR(vaddr)) ++ return TRUE; ++ ++ return (vaddr >= machdep->kvbase); ++} ++ ++static int ++riscv64_is_uvaddr(ulong vaddr, struct task_context *unused) ++{ ++ if (IS_VMALLOC_ADDR(vaddr)) ++ return FALSE; ++ ++ return (vaddr < machdep->kvbase); ++} ++ ++static int ++riscv64_is_task_addr(ulong task) ++{ ++ if (tt->flags & THREAD_INFO) ++ return IS_KVADDR(task); ++ ++ return (IS_KVADDR(task) && ALIGNED_STACK_OFFSET(task) == 0); ++} ++ ++static int ++riscv64_get_smp_cpus(void) ++{ ++ return (get_cpus_present() > 0) ? get_cpus_present() : kt->cpus; + } + + /* +@@ -33,11 +337,701 @@ riscv64_IS_VMALLOC_ADDR(ulong vaddr) + (vaddr >= MODULES_VADDR && vaddr <= MODULES_END)); + } + ++/* ++ * Translate a PTE, returning TRUE if the page is present. ++ * If a physaddr pointer is passed in, don't print anything. ++ */ ++static int ++riscv64_translate_pte(ulong pte, void *physaddr, ulonglong unused) ++{ ++ char ptebuf[BUFSIZE]; ++ char physbuf[BUFSIZE]; ++ char buf[BUFSIZE]; ++ int page_present; ++ int len1, len2, others; ++ ulong paddr; ++ ++ paddr = PTOB(pte >> _PAGE_PFN_SHIFT); ++ page_present = !!(pte & _PAGE_PRESENT); ++ ++ if (physaddr) { ++ *(ulong *)physaddr = paddr; ++ return page_present; ++ } ++ ++ sprintf(ptebuf, "%lx", pte); ++ len1 = MAX(strlen(ptebuf), strlen("PTE")); ++ fprintf(fp, "%s ", mkstring(buf, len1, CENTER | LJUST, "PTE")); ++ ++ if (!page_present) ++ return page_present; ++ ++ sprintf(physbuf, "%lx", paddr); ++ len2 = MAX(strlen(physbuf), strlen("PHYSICAL")); ++ fprintf(fp, "%s ", mkstring(buf, len2, CENTER | LJUST, "PHYSICAL")); ++ ++ fprintf(fp, "FLAGS\n"); ++ fprintf(fp, "%s %s ", ++ mkstring(ptebuf, len1, CENTER | RJUST, NULL), ++ mkstring(physbuf, len2, CENTER | RJUST, NULL)); ++ ++ fprintf(fp, "("); ++ others = 0; ++ ++#define CHECK_PAGE_FLAG(flag) \ ++ if ((_PAGE_##flag) && (pte & _PAGE_##flag)) \ ++ fprintf(fp, "%s" #flag, others++ ? "|" : "") ++ if (pte) { ++ CHECK_PAGE_FLAG(PRESENT); ++ CHECK_PAGE_FLAG(READ); ++ CHECK_PAGE_FLAG(WRITE); ++ CHECK_PAGE_FLAG(EXEC); ++ CHECK_PAGE_FLAG(USER); ++ CHECK_PAGE_FLAG(GLOBAL); ++ CHECK_PAGE_FLAG(ACCESSED); ++ CHECK_PAGE_FLAG(DIRTY); ++ CHECK_PAGE_FLAG(SOFT); ++ } else { ++ fprintf(fp, "no mapping"); ++ } ++ ++ fprintf(fp, ")\n"); ++ ++ return page_present; ++} ++ ++static void ++riscv64_page_type_init(void) ++{ ++ ulong va_bits = machdep->machspec->va_bits; ++ ++ /* ++ * For RISCV64 arch, any level of PTE may be a leaf PTE, ++ * so in addition to 4KiB pages, ++ * Sv39 supports 2 MiB megapages, 1 GiB gigapages; ++ * Sv48 supports 2 MiB megapages, 1 GiB gigapages, 512 GiB terapages; ++ * Sv57 supports 2 MiB megapages, 1 GiB gigapages, 512 GiB terapages, and 256 TiB petapages. ++ * ++ * refs to riscv-privileged spec. ++ * ++ * We just support 4KiB, 2MiB, 1GiB now. ++ */ ++ switch (machdep->pagesize) ++ { ++ case 0x1000: // 4 KiB ++ machdep->flags |= (va_bits == 57 ? VM_L5_4K : ++ (va_bits == 48 ? VM_L4_4K : VM_L3_4K)); ++ break; ++ case 0x200000: // 2 MiB ++ /* TODO: */ ++ case 0x40000000: // 1 GiB ++ /* TODO: */ ++ default: ++ if (machdep->pagesize) ++ error(FATAL, "invalid/unsupported page size: %d\n", ++ machdep->pagesize); ++ else ++ error(FATAL, "cannot determine page size\n"); ++ } ++} ++ ++static int ++riscv64_vtop_3level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) ++{ ++ ulong *pgd_ptr, pgd_val; ++ ulong pmd_val; ++ ulong pte_val, pte_pfn; ++ ulong pt_phys; ++ ++ /* 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; ++ pt_phys = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); ++ ++ /* PMD */ ++ FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); ++ pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) * ++ pmd_index_l3_4k(vaddr))); ++ if (verbose) ++ fprintf(fp, " PMD: %016lx => %016lx\n", pt_phys, pmd_val); ++ if (!pmd_val) ++ goto no_page; ++ pmd_val &= PTE_PFN_PROT_MASK; ++ pt_phys = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); ++ ++ /* PTE */ ++ FILL_PTBL(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); ++ pte_val = ULONG(machdep->ptbl + PAGEOFFSET(sizeof(pte_t) * ++ pte_index_l3_4k(vaddr))); ++ if (verbose) ++ fprintf(fp, " PTE: %lx => %lx\n", pt_phys, 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\n"); ++ return FALSE; ++} ++ ++static int ++riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) ++{ ++ ulong *pgd_ptr, pgd_val; ++ ulong pud_val; ++ ulong pmd_val; ++ ulong pte_val, pte_pfn; ++ ulong pt_phys; ++ ++ /* 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; ++ pt_phys = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); ++ ++ /* PUD */ ++ FILL_PUD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); ++ pud_val = ULONG(machdep->pud + PAGEOFFSET(sizeof(pud_t) * ++ pud_index_l4_4k(vaddr))); ++ if (verbose) ++ fprintf(fp, " PUD: %016lx => %016lx\n", pt_phys, pud_val); ++ if (!pud_val) ++ goto no_page; ++ pud_val &= PTE_PFN_PROT_MASK; ++ pt_phys = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); ++ ++ /* PMD */ ++ FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); ++ pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) * ++ pmd_index_l4_4k(vaddr))); ++ if (verbose) ++ fprintf(fp, " PMD: %016lx => %016lx\n", pt_phys, pmd_val); ++ if (!pmd_val) ++ goto no_page; ++ pmd_val &= PTE_PFN_PROT_MASK; ++ pt_phys = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); ++ ++ /* PTE */ ++ FILL_PTBL(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); ++ pte_val = ULONG(machdep->ptbl + PAGEOFFSET(sizeof(pte_t) * ++ pte_index_l4_4k(vaddr))); ++ if (verbose) ++ fprintf(fp, " PTE: %lx => %lx\n", pt_phys, 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\n"); ++ return FALSE; ++} ++ ++static int ++riscv64_vtop_5level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) ++{ ++ ulong *pgd_ptr, pgd_val; ++ ulong p4d_val; ++ ulong pud_val; ++ ulong pmd_val; ++ ulong pte_val, pte_pfn; ++ ulong pt_phys; ++ ++ /* 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; ++ pt_phys = (pgd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); ++ ++ /* P4D */ ++ FILL_P4D(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); ++ p4d_val = ULONG(machdep->machspec->p4d + PAGEOFFSET(sizeof(p4d_t) * ++ p4d_index_l5_4k(vaddr))); ++ if (verbose) ++ fprintf(fp, " P4D: %016lx => %016lx\n", pt_phys, p4d_val); ++ if (!p4d_val) ++ goto no_page; ++ p4d_val &= PTE_PFN_PROT_MASK; ++ pt_phys = (p4d_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); ++ ++ /* PUD */ ++ FILL_PUD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); ++ pud_val = ULONG(machdep->pud + PAGEOFFSET(sizeof(pud_t) * ++ pud_index_l5_4k(vaddr))); ++ if (verbose) ++ fprintf(fp, " PUD: %016lx => %016lx\n", pt_phys, pud_val); ++ if (!pud_val) ++ goto no_page; ++ pud_val &= PTE_PFN_PROT_MASK; ++ pt_phys = (pud_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); ++ ++ /* PMD */ ++ FILL_PMD(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); ++ pmd_val = ULONG(machdep->pmd + PAGEOFFSET(sizeof(pmd_t) * ++ pmd_index_l4_4k(vaddr))); ++ if (verbose) ++ fprintf(fp, " PMD: %016lx => %016lx\n", pt_phys, pmd_val); ++ if (!pmd_val) ++ goto no_page; ++ pmd_val &= PTE_PFN_PROT_MASK; ++ pt_phys = (pmd_val >> _PAGE_PFN_SHIFT) << PAGESHIFT(); ++ ++ /* PTE */ ++ FILL_PTBL(PAGEBASE(pt_phys), PHYSADDR, PAGESIZE()); ++ pte_val = ULONG(machdep->ptbl + PAGEOFFSET(sizeof(pte_t) * ++ pte_index_l4_4k(vaddr))); ++ if (verbose) ++ fprintf(fp, " PTE: %lx => %lx\n", pt_phys, 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\n"); ++ return FALSE; ++} ++ ++static int ++riscv64_init_active_task_regs(void) ++{ ++ int retval; ++ ++ retval = riscv64_get_crash_notes(); ++ if (retval == TRUE) ++ return retval; ++ ++ return riscv64_get_elf_notes(); ++} ++ ++/* ++ * Retrieve task registers for the time of the crash. ++ */ ++static int ++riscv64_get_crash_notes(void) ++{ ++ struct machine_specific *ms = machdep->machspec; ++ ulong crash_notes; ++ Elf64_Nhdr *note; ++ ulong offset; ++ char *buf, *p; ++ ulong *notes_ptrs; ++ ulong i; ++ ++ /* ++ * crash_notes contains per cpu memory for storing cpu states ++ * in case of system crash. ++ */ ++ if (!symbol_exists("crash_notes")) ++ return FALSE; ++ ++ crash_notes = symbol_value("crash_notes"); ++ ++ notes_ptrs = (ulong *)GETBUF(kt->cpus*sizeof(notes_ptrs[0])); ++ ++ /* ++ * Read crash_notes for the first CPU. crash_notes are in standard ELF ++ * note format. ++ */ ++ if (!readmem(crash_notes, KVADDR, ¬es_ptrs[kt->cpus-1], ++ sizeof(notes_ptrs[kt->cpus-1]), "crash_notes", ++ RETURN_ON_ERROR)) { ++ error(WARNING, "cannot read crash_notes\n"); ++ FREEBUF(notes_ptrs); ++ return FALSE; ++ } ++ ++ if (symbol_exists("__per_cpu_offset")) { ++ ++ /* ++ * Add __per_cpu_offset for each cpu to form the pointer to the notes ++ */ ++ for (i = 0; i < kt->cpus; i++) ++ notes_ptrs[i] = notes_ptrs[kt->cpus-1] + kt->__per_cpu_offset[i]; ++ } ++ ++ buf = GETBUF(SIZE(note_buf)); ++ ++ if (!(panic_task_regs = calloc((size_t)kt->cpus, sizeof(*panic_task_regs)))) ++ error(FATAL, "cannot calloc panic_task_regs space\n"); ++ ++ for (i = 0; i < kt->cpus; i++) { ++ ++ if (!readmem(notes_ptrs[i], KVADDR, buf, SIZE(note_buf), "note_buf_t", ++ RETURN_ON_ERROR)) { ++ error(WARNING, ++ "cannot find NT_PRSTATUS note for cpu: %d\n", i); ++ goto fail; ++ } ++ ++ /* ++ * Do some sanity checks for this note before reading registers from it. ++ */ ++ note = (Elf64_Nhdr *)buf; ++ p = buf + sizeof(Elf64_Nhdr); ++ ++ /* ++ * dumpfiles created with qemu won't have crash_notes, but there will ++ * be elf notes; dumpfiles created by kdump do not create notes for ++ * offline cpus. ++ */ ++ if (note->n_namesz == 0 && (DISKDUMP_DUMPFILE() || KDUMP_DUMPFILE())) { ++ if (DISKDUMP_DUMPFILE()) ++ note = diskdump_get_prstatus_percpu(i); ++ else if (KDUMP_DUMPFILE()) ++ note = netdump_get_prstatus_percpu(i); ++ if (note) { ++ /* ++ * SIZE(note_buf) accounts for a "final note", which is a ++ * trailing empty elf note header. ++ */ ++ long notesz = SIZE(note_buf) - sizeof(Elf64_Nhdr); ++ ++ if (sizeof(Elf64_Nhdr) + roundup(note->n_namesz, 4) + ++ note->n_descsz == notesz) ++ BCOPY((char *)note, buf, notesz); ++ } else { ++ error(WARNING, ++ "cannot find NT_PRSTATUS note for cpu: %d\n", i); ++ continue; ++ } ++ } ++ ++ /* ++ * Check the sanity of NT_PRSTATUS note only for each online cpu. ++ */ ++ if (note->n_type != NT_PRSTATUS) { ++ error(WARNING, "invalid NT_PRSTATUS note (n_type != NT_PRSTATUS)\n"); ++ goto fail; ++ } ++ if (!STRNEQ(p, "CORE")) { ++ error(WARNING, "invalid NT_PRSTATUS note (name != \"CORE\"\n"); ++ goto fail; ++ } ++ ++ /* ++ * Find correct location of note data. This contains elf_prstatus ++ * structure which has registers etc. for the crashed task. ++ */ ++ offset = sizeof(Elf64_Nhdr); ++ offset = roundup(offset + note->n_namesz, 4); ++ p = buf + offset; /* start of elf_prstatus */ ++ ++ BCOPY(p + OFFSET(elf_prstatus_pr_reg), &panic_task_regs[i], ++ sizeof(panic_task_regs[i])); ++ } ++ ++ /* ++ * And finally we have the registers for the crashed task. This is ++ * used later on when dumping backtrace. ++ */ ++ ms->crash_task_regs = panic_task_regs; ++ ++ FREEBUF(buf); ++ FREEBUF(notes_ptrs); ++ return TRUE; ++ ++fail: ++ FREEBUF(buf); ++ FREEBUF(notes_ptrs); ++ free(panic_task_regs); ++ return FALSE; ++} ++ ++static int ++riscv64_get_elf_notes(void) ++{ ++ struct machine_specific *ms = machdep->machspec; ++ int i; ++ ++ if (!DISKDUMP_DUMPFILE() && !KDUMP_DUMPFILE()) ++ return FALSE; ++ ++ panic_task_regs = calloc(kt->cpus, sizeof(*panic_task_regs)); ++ if (!panic_task_regs) ++ error(FATAL, "cannot calloc panic_task_regs space\n"); ++ ++ for (i = 0; i < kt->cpus; i++) { ++ Elf64_Nhdr *note = NULL; ++ size_t len; ++ ++ if (DISKDUMP_DUMPFILE()) ++ note = diskdump_get_prstatus_percpu(i); ++ else if (KDUMP_DUMPFILE()) ++ note = netdump_get_prstatus_percpu(i); ++ ++ if (!note) { ++ error(WARNING, ++ "cannot find NT_PRSTATUS note for cpu: %d\n", i); ++ continue; ++ } ++ ++ len = sizeof(Elf64_Nhdr); ++ len = roundup(len + note->n_namesz, 4); ++ ++ BCOPY((char *)note + len + OFFSET(elf_prstatus_pr_reg), ++ &panic_task_regs[i], sizeof(panic_task_regs[i])); ++ } ++ ++ ms->crash_task_regs = panic_task_regs; ++ ++ return TRUE; ++} ++ ++/* ++ * Translates a user virtual address to its physical address. ++ */ ++static int ++riscv64_uvtop(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbose) ++{ ++ ulong mm, active_mm; ++ ulong *pgd; ++ ++ if (!tc) ++ error(FATAL, "current context invalid\n"); ++ ++ *paddr = 0; ++ ++ if (is_kernel_thread(tc->task) && IS_KVADDR(uvaddr)) { ++ readmem(tc->task + OFFSET(task_struct_active_mm), ++ KVADDR, &active_mm, sizeof(void *), ++ "task active_mm contents", FAULT_ON_ERROR); ++ ++ if (!active_mm) ++ error(FATAL, ++ "no active_mm for this kernel thread\n"); ++ ++ readmem(active_mm + OFFSET(mm_struct_pgd), ++ KVADDR, &pgd, sizeof(long), ++ "mm_struct pgd", FAULT_ON_ERROR); ++ } else { ++ if ((mm = task_mm(tc->task, TRUE))) ++ pgd = ULONG_PTR(tt->mm_struct + OFFSET(mm_struct_pgd)); ++ else ++ readmem(tc->mm_struct + OFFSET(mm_struct_pgd), ++ KVADDR, &pgd, sizeof(long), "mm_struct pgd", ++ FAULT_ON_ERROR); ++ } ++ ++ switch (machdep->flags & VM_FLAGS) ++ { ++ case VM_L3_4K: ++ return riscv64_vtop_3level_4k(pgd, uvaddr, paddr, verbose); ++ case VM_L4_4K: ++ return riscv64_vtop_4level_4k(pgd, uvaddr, paddr, verbose); ++ case VM_L5_4K: ++ return riscv64_vtop_5level_4k(pgd, uvaddr, paddr, verbose); ++ default: ++ return FALSE; ++ } ++} ++ ++static int ++riscv64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbose) ++{ ++ ulong kernel_pgd; ++ ++ if (!IS_KVADDR(kvaddr)) ++ return FALSE; ++ ++ if (!vt->vmalloc_start) { ++ *paddr = VTOP(kvaddr); ++ return TRUE; ++ } ++ ++ if (!IS_VMALLOC_ADDR(kvaddr)) { ++ *paddr = VTOP(kvaddr); ++ if (!verbose) ++ return TRUE; ++ } ++ ++ kernel_pgd = vt->kernel_pgd[0]; ++ *paddr = 0; ++ ++ switch (machdep->flags & VM_FLAGS) ++ { ++ case VM_L3_4K: ++ return riscv64_vtop_3level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose); ++ case VM_L4_4K: ++ return riscv64_vtop_4level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose); ++ case VM_L5_4K: ++ return riscv64_vtop_5level_4k((ulong *)kernel_pgd, kvaddr, paddr, verbose); ++ default: ++ return FALSE; ++ } ++} ++ + void + riscv64_init(int when) + { ++ switch (when) { ++ case SETUP_ENV: ++ machdep->process_elf_notes = process_elf64_notes; ++ break; ++ ++ case PRE_SYMTAB: ++ machdep->verify_symbol = riscv64_verify_symbol; ++ machdep->machspec = &riscv64_machine_specific; ++ if (pc->flags & KERNEL_DEBUG_QUERY) ++ return; ++ ++ machdep->verify_paddr = generic_verify_paddr; ++ machdep->ptrs_per_pgd = PTRS_PER_PGD; ++ break; ++ ++ case PRE_GDB: ++ machdep->pagesize = riscv64_get_page_size(); ++ machdep->pageshift = ffs(machdep->pagesize) - 1; ++ machdep->pageoffset = machdep->pagesize - 1; ++ machdep->pagemask = ~((ulonglong)machdep->pageoffset); ++ machdep->stacksize = machdep->pagesize << THREAD_SIZE_ORDER; ++ ++ riscv64_get_phys_ram_base(machdep->machspec); ++ riscv64_get_struct_page_size(machdep->machspec); ++ riscv64_get_va_bits(machdep->machspec); ++ riscv64_get_va_range(machdep->machspec); ++ ++ pt_level_alloc(&machdep->pgd, "cannot malloc pgd space."); ++ pt_level_alloc(&machdep->machspec->p4d, "cannot malloc p4d space."); ++ pt_level_alloc(&machdep->pud, "cannot malloc pud space."); ++ pt_level_alloc(&machdep->pmd, "cannot malloc pmd space."); ++ pt_level_alloc(&machdep->ptbl, "cannot malloc ptbl space."); ++ ++ machdep->last_pgd_read = 0; ++ machdep->machspec->last_p4d_read = 0; ++ machdep->last_pud_read = 0; ++ machdep->last_pmd_read = 0; ++ machdep->last_ptbl_read = 0; ++ ++ machdep->kvbase = machdep->machspec->page_offset; ++ machdep->identity_map_base = machdep->kvbase; ++ machdep->is_kvaddr = riscv64_is_kvaddr; ++ machdep->is_uvaddr = riscv64_is_uvaddr; ++ machdep->uvtop = riscv64_uvtop; ++ machdep->kvtop = riscv64_kvtop; ++ machdep->cmd_mach = riscv64_cmd_mach; ++ ++ machdep->vmalloc_start = riscv64_vmalloc_start; ++ machdep->processor_speed = riscv64_processor_speed; ++ machdep->get_stackbase = generic_get_stackbase; ++ machdep->get_stacktop = generic_get_stacktop; ++ machdep->translate_pte = riscv64_translate_pte; ++ machdep->memory_size = generic_memory_size; ++ machdep->is_task_addr = riscv64_is_task_addr; ++ machdep->get_smp_cpus = riscv64_get_smp_cpus; ++ machdep->value_to_symbol = generic_machdep_value_to_symbol; ++ machdep->show_interrupts = generic_show_interrupts; ++ machdep->get_irq_affinity = generic_get_irq_affinity; ++ machdep->init_kernel_pgd = NULL; /* pgd set by symbol_value("swapper_pg_dir") */ ++ break; ++ ++ case POST_GDB: ++ machdep->section_size_bits = _SECTION_SIZE_BITS; ++ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS; ++ riscv64_page_type_init(); ++ ++ if (!machdep->hz) ++ machdep->hz = 250; ++ ++ if (symbol_exists("irq_desc")) ++ ARRAY_LENGTH_INIT(machdep->nr_irqs, irq_desc, ++ "irq_desc", NULL, 0); ++ else if (kernel_symbol_exists("nr_irqs")) ++ get_symbol_data("nr_irqs", sizeof(unsigned int), ++ &machdep->nr_irqs); ++ ++ MEMBER_OFFSET_INIT(elf_prstatus_pr_reg, "elf_prstatus", ++ "pr_reg"); ++ ++ STRUCT_SIZE_INIT(note_buf, "note_buf_t"); ++ break; ++ ++ case POST_VM: ++ /* ++ * crash_notes contains machine specific information about the ++ * crash. In particular, it contains CPU registers at the time ++ * of the crash. We need this information to extract correct ++ * backtraces from the panic task. ++ */ ++ if (!ACTIVE() && !riscv64_init_active_task_regs()) ++ error(WARNING, ++ "cannot retrieve registers for active task%s\n\n", ++ kt->cpus > 1 ? "s" : ""); ++ break; ++ } + } + ++/* ++ * 'help -r' command output ++ */ + void + riscv64_display_regs_from_elf_notes(int cpu, FILE *ofp) + { +-- +2.37.1 + diff --git a/SOURCES/0053-RISCV64-Add-dis-command-support.patch b/SOURCES/0053-RISCV64-Add-dis-command-support.patch new file mode 100644 index 0000000..96bb576 --- /dev/null +++ b/SOURCES/0053-RISCV64-Add-dis-command-support.patch @@ -0,0 +1,44 @@ +From 4876c73ca54a8ee2e02032d1b10832e0de9adde3 Mon Sep 17 00:00:00 2001 +From: Xianting Tian +Date: Thu, 20 Oct 2022 09:50:08 +0800 +Subject: [PATCH 53/89] RISCV64: Add 'dis' command support + +Use generic_dis_filter() function to support dis command implementation. + +With this patch, we can get the disassembled code, +crash> dis __crash_kexec +0xffffffff80088580 <__crash_kexec>: addi sp,sp,-352 +0xffffffff80088582 <__crash_kexec+2>: sd s0,336(sp) +0xffffffff80088584 <__crash_kexec+4>: sd s1,328(sp) +0xffffffff80088586 <__crash_kexec+6>: sd s2,320(sp) +0xffffffff80088588 <__crash_kexec+8>: addi s0,sp,352 +0xffffffff8008858a <__crash_kexec+10>: sd ra,344(sp) +0xffffffff8008858c <__crash_kexec+12>: sd s3,312(sp) +0xffffffff8008858e <__crash_kexec+14>: sd s4,304(sp) +0xffffffff80088590 <__crash_kexec+16>: auipc s2,0x1057 +0xffffffff80088594 <__crash_kexec+20>: addi s2,s2,-1256 +0xffffffff80088598 <__crash_kexec+24>: ld a5,0(s2) +0xffffffff8008859c <__crash_kexec+28>: mv s1,a0 +0xffffffff8008859e <__crash_kexec+30>: auipc a0,0xfff + +Signed-off-by: Xianting Tian +Signed-off-by: Lianbo Jiang +--- + riscv64.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/riscv64.c b/riscv64.c +index d8de3d56e1b7..1e20a09a81ae 100644 +--- a/riscv64.c ++++ b/riscv64.c +@@ -988,6 +988,7 @@ riscv64_init(int when) + machdep->is_task_addr = riscv64_is_task_addr; + machdep->get_smp_cpus = riscv64_get_smp_cpus; + machdep->value_to_symbol = generic_machdep_value_to_symbol; ++ machdep->dis_filter = generic_dis_filter; + machdep->show_interrupts = generic_show_interrupts; + machdep->get_irq_affinity = generic_get_irq_affinity; + machdep->init_kernel_pgd = NULL; /* pgd set by symbol_value("swapper_pg_dir") */ +-- +2.37.1 + diff --git a/SOURCES/0054-RISCV64-Add-irq-command-support.patch b/SOURCES/0054-RISCV64-Add-irq-command-support.patch new file mode 100644 index 0000000..4197573 --- /dev/null +++ b/SOURCES/0054-RISCV64-Add-irq-command-support.patch @@ -0,0 +1,36 @@ +From b4d78e7f96564ecbdbfe4b4b70a1c6d65429bbb9 Mon Sep 17 00:00:00 2001 +From: Xianting Tian +Date: Thu, 20 Oct 2022 09:50:09 +0800 +Subject: [PATCH 54/89] RISCV64: Add irq command support + +With the patch, we can get the irq info, +crash> irq + IRQ IRQ_DESC/_DATA IRQACTION NAME + 0 (unused) (unused) + 1 ff60000001329600 ff60000001d17180 "101000.rtc" + 2 ff60000001329800 ff60000001d17680 "ttyS0" + 3 ff60000001329a00 ff60000001c33c00 "virtio0" + 4 ff60000001329c00 ff60000001c33f80 "virtio1" + 5 ff6000000120f400 ff60000001216000 "riscv-timer" + +Signed-off-by: Xianting Tian +Signed-off-by: Lianbo Jiang +--- + riscv64.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/riscv64.c b/riscv64.c +index 1e20a09a81ae..2355daca7aac 100644 +--- a/riscv64.c ++++ b/riscv64.c +@@ -989,6 +989,7 @@ riscv64_init(int when) + machdep->get_smp_cpus = riscv64_get_smp_cpus; + machdep->value_to_symbol = generic_machdep_value_to_symbol; + machdep->dis_filter = generic_dis_filter; ++ machdep->dump_irq = generic_dump_irq; + machdep->show_interrupts = generic_show_interrupts; + machdep->get_irq_affinity = generic_get_irq_affinity; + machdep->init_kernel_pgd = NULL; /* pgd set by symbol_value("swapper_pg_dir") */ +-- +2.37.1 + diff --git a/SOURCES/0055-RISCV64-Add-bt-command-support.patch b/SOURCES/0055-RISCV64-Add-bt-command-support.patch new file mode 100644 index 0000000..b8fc538 --- /dev/null +++ b/SOURCES/0055-RISCV64-Add-bt-command-support.patch @@ -0,0 +1,413 @@ +From 75afbf54dd183b05a8b7363390df4a198155580a Mon Sep 17 00:00:00 2001 +From: Xianting Tian +Date: Thu, 20 Oct 2022 09:50:10 +0800 +Subject: [PATCH 55/89] RISCV64: Add 'bt' command support + +1, Add the implementation to get stack frame from active & inactive + task's stack. +2, Add 'bt -l' command support get a line number associated with a + current pc address. +3, Add 'bt -f' command support to display all stack data contained + in a frame + +With the patch, we can get the backtrace, +crash> bt +PID: 113 TASK: ff6000000226c200 CPU: 0 COMMAND: "sh" + #0 [ff20000010333b90] riscv_crash_save_regs at ffffffff800078f8 + #1 [ff20000010333cf0] panic at ffffffff806578c6 + #2 [ff20000010333d50] sysrq_reset_seq_param_set at ffffffff8038c03c + #3 [ff20000010333da0] __handle_sysrq at ffffffff8038c604 + #4 [ff20000010333e00] write_sysrq_trigger at ffffffff8038cae4 + #5 [ff20000010333e20] proc_reg_write at ffffffff801b7ee8 + #6 [ff20000010333e40] vfs_write at ffffffff80152bb2 + #7 [ff20000010333e80] ksys_write at ffffffff80152eda + #8 [ff20000010333ed0] sys_write at ffffffff80152f52 + +crash> bt -l +PID: 113 TASK: ff6000000226c200 CPU: 0 COMMAND: "sh" + #0 [ff20000010333b90] riscv_crash_save_regs at ffffffff800078f8 + /buildroot/qemu_riscv64_virt_defconfig/build/linux-custom/arch/riscv/kernel/crash_save_regs.S: 47 + #1 [ff20000010333cf0] panic at ffffffff806578c6 + /buildroot/qemu_riscv64_virt_defconfig/build/linux-custom/kernel/panic.c: 276 + ... ... + +crash> bt -f +PID: 113 TASK: ff6000000226c200 CPU: 0 COMMAND: "sh" + #0 [ff20000010333b90] riscv_crash_save_regs at ffffffff800078f8 + [PC: ffffffff800078f8 RA: ffffffff806578c6 SP: ff20000010333b90 SIZE: 352] + ff20000010333b90: ff20000010333bb0 ffffffff800078f8 + ff20000010333ba0: ffffffff8008862c ff20000010333b90 + ff20000010333bb0: ffffffff810dde38 ff6000000226c200 + ff20000010333bc0: ffffffff8032be68 0720072007200720 + ... ... + +Signed-off-by: Xianting Tian +Signed-off-by: Lianbo Jiang +--- + netdump.c | 13 +++ + riscv64.c | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 296 insertions(+) + +diff --git a/netdump.c b/netdump.c +index c4c8baae0d20..4ef5807a641b 100644 +--- a/netdump.c ++++ b/netdump.c +@@ -42,6 +42,7 @@ static void get_netdump_regs_ppc64(struct bt_info *, ulong *, ulong *); + static void get_netdump_regs_arm(struct bt_info *, ulong *, ulong *); + static void get_netdump_regs_arm64(struct bt_info *, ulong *, ulong *); + static void get_netdump_regs_mips(struct bt_info *, ulong *, ulong *); ++static void get_netdump_regs_riscv(struct bt_info *, ulong *, ulong *); + static void check_dumpfile_size(char *); + static int proc_kcore_init_32(FILE *, int); + static int proc_kcore_init_64(FILE *, int); +@@ -2675,6 +2676,10 @@ get_netdump_regs(struct bt_info *bt, ulong *eip, ulong *esp) + return get_netdump_regs_mips(bt, eip, esp); + break; + ++ case EM_RISCV: ++ get_netdump_regs_riscv(bt, eip, esp); ++ break; ++ + default: + error(FATAL, + "support for ELF machine type %d not available\n", +@@ -2931,6 +2936,8 @@ display_regs_from_elf_notes(int cpu, FILE *ofp) + mips_display_regs_from_elf_notes(cpu, ofp); + } else if (machine_type("MIPS64")) { + mips64_display_regs_from_elf_notes(cpu, ofp); ++ } else if (machine_type("RISCV64")) { ++ riscv64_display_regs_from_elf_notes(cpu, ofp); + } + } + +@@ -3877,6 +3884,12 @@ get_netdump_regs_mips(struct bt_info *bt, ulong *eip, ulong *esp) + machdep->get_stack_frame(bt, eip, esp); + } + ++static void ++get_netdump_regs_riscv(struct bt_info *bt, ulong *eip, ulong *esp) ++{ ++ machdep->get_stack_frame(bt, eip, esp); ++} ++ + int + is_partial_netdump(void) + { +diff --git a/riscv64.c b/riscv64.c +index 2355daca7aac..4c9b35bb93f2 100644 +--- a/riscv64.c ++++ b/riscv64.c +@@ -33,6 +33,17 @@ static int riscv64_uvtop(struct task_context *tc, ulong vaddr, + static int riscv64_kvtop(struct task_context *tc, ulong kvaddr, + physaddr_t *paddr, int verbose); + static void riscv64_cmd_mach(void); ++static void riscv64_stackframe_init(void); ++static void riscv64_back_trace_cmd(struct bt_info *bt); ++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, ++ ulong *spp); ++static int riscv64_get_frame(struct bt_info *bt, ulong *pcp, ++ ulong *spp); ++static void riscv64_display_full_frame(struct bt_info *bt, ++ struct riscv64_unwind_frame *current, ++ struct riscv64_unwind_frame *previous); + static int riscv64_translate_pte(ulong, void *, ulonglong); + static int riscv64_init_active_task_regs(void); + static int riscv64_get_crash_notes(void); +@@ -498,6 +509,275 @@ no_page: + return FALSE; + } + ++/* ++ * 'bt -f' command output ++ * Display all stack data contained in a frame ++ */ ++static void ++riscv64_display_full_frame(struct bt_info *bt, struct riscv64_unwind_frame *current, ++ struct riscv64_unwind_frame *previous) ++{ ++ int i, u_idx; ++ ulong *up; ++ ulong words, addr; ++ char buf[BUFSIZE]; ++ ++ if (previous->sp < current->sp) ++ return; ++ ++ if (!(INSTACK(previous->sp, bt) && INSTACK(current->sp, bt))) ++ return; ++ ++ words = (previous->sp - current->sp) / sizeof(ulong) + 1; ++ addr = current->sp; ++ u_idx = (current->sp - bt->stackbase) / sizeof(ulong); ++ ++ for (i = 0; i < words; i++, u_idx++) { ++ if (!(i & 1)) ++ fprintf(fp, "%s %lx: ", i ? "\n" : "", addr); ++ ++ up = (ulong *)(&bt->stackbuf[u_idx*sizeof(ulong)]); ++ fprintf(fp, "%s ", format_stack_entry(bt, buf, *up, 0)); ++ addr += sizeof(ulong); ++ } ++ fprintf(fp, "\n"); ++} ++ ++static void ++riscv64_stackframe_init(void) ++{ ++ long task_struct_thread = MEMBER_OFFSET("task_struct", "thread"); ++ ++ /* from arch/riscv/include/asm/processor.h */ ++ long thread_reg_ra = MEMBER_OFFSET("thread_struct", "ra"); ++ long thread_reg_sp = MEMBER_OFFSET("thread_struct", "sp"); ++ long thread_reg_fp = MEMBER_OFFSET("thread_struct", "s"); ++ ++ if ((task_struct_thread == INVALID_OFFSET) || ++ (thread_reg_ra == INVALID_OFFSET) || ++ (thread_reg_sp == INVALID_OFFSET) || ++ (thread_reg_fp == INVALID_OFFSET) ) ++ error(FATAL, ++ "cannot determine thread_struct offsets\n"); ++ ++ ASSIGN_OFFSET(task_struct_thread_context_pc) = ++ task_struct_thread + thread_reg_ra; ++ ASSIGN_OFFSET(task_struct_thread_context_sp) = ++ task_struct_thread + thread_reg_sp; ++ ASSIGN_OFFSET(task_struct_thread_context_fp) = ++ task_struct_thread + thread_reg_fp; ++} ++ ++static void ++riscv64_dump_backtrace_entry(struct bt_info *bt, struct syment *sym, ++ struct riscv64_unwind_frame *current, ++ struct riscv64_unwind_frame *previous, int level) ++{ ++ const char *name = sym ? sym->name : "(invalid)"; ++ struct load_module *lm; ++ char *name_plus_offset = NULL; ++ struct syment *symp; ++ ulong symbol_offset; ++ char buf[BUFSIZE]; ++ ++ if (bt->flags & BT_SYMBOL_OFFSET) { ++ symp = value_search(current->pc, &symbol_offset); ++ ++ if (symp && symbol_offset) ++ name_plus_offset = ++ value_to_symstr(current->pc, buf, bt->radix); ++ } ++ ++ fprintf(fp, "%s#%d [%016lx] %s at %016lx", ++ level < 10 ? " " : "", ++ level, ++ current->sp, ++ name_plus_offset ? name_plus_offset : name, ++ current->pc); ++ ++ if (module_symbol(current->pc, NULL, &lm, NULL, 0)) ++ fprintf(fp, " [%s]", lm->mod_name); ++ ++ fprintf(fp, "\n"); ++ ++ /* ++ * 'bt -l', get a line number associated with a current pc address. ++ */ ++ if (bt->flags & BT_LINE_NUMBERS) { ++ get_line_number(current->pc, buf, FALSE); ++ if (strlen(buf)) ++ fprintf(fp, " %s\n", buf); ++ } ++ ++ /* bt -f */ ++ if (bt->flags & BT_FULL) { ++ fprintf(fp, " " ++ "[PC: %016lx RA: %016lx SP: %016lx SIZE: %ld]\n", ++ current->pc, ++ previous->pc, ++ current->sp, ++ previous->sp - current->sp); ++ riscv64_display_full_frame(bt, current, previous); ++ } ++} ++ ++/* ++ * Unroll a kernel stack. ++ */ ++static void ++riscv64_back_trace_cmd(struct bt_info *bt) ++{ ++ struct riscv64_unwind_frame current, previous; ++ struct stackframe curr_frame; ++ int level = 0; ++ ++ if (bt->flags & BT_REGS_NOT_FOUND) ++ return; ++ ++ current.pc = bt->instptr; ++ current.sp = bt->stkptr; ++ current.fp = bt->frameptr; ++ ++ if (!INSTACK(current.sp, bt)) ++ return; ++ ++ for (;;) { ++ struct syment *symbol = NULL; ++ struct stackframe *frameptr; ++ ulong low, high; ++ ulong offset; ++ ++ if (CRASHDEBUG(8)) ++ fprintf(fp, "level %d pc %#lx sp %lx fp 0x%lx\n", ++ level, current.pc, current.sp, current.fp); ++ ++ /* Validate frame pointer */ ++ low = current.sp + sizeof(struct stackframe); ++ high = bt->stacktop; ++ if (current.fp < low || current.fp > high || current.fp & 0x7) { ++ if (CRASHDEBUG(8)) ++ fprintf(fp, "fp 0x%lx sp 0x%lx low 0x%lx high 0x%lx\n", ++ current.fp, current.sp, low, high); ++ return; ++ } ++ ++ symbol = value_search(current.pc, &offset); ++ if (!symbol) ++ return; ++ ++ frameptr = (struct stackframe *)current.fp - 1; ++ if (!readmem((ulong)frameptr, KVADDR, &curr_frame, ++ sizeof(curr_frame), "get stack frame", RETURN_ON_ERROR)) ++ return; ++ ++ previous.pc = curr_frame.ra; ++ previous.fp = curr_frame.fp; ++ previous.sp = current.fp; ++ ++ riscv64_dump_backtrace_entry(bt, symbol, ¤t, &previous, level++); ++ ++ current.pc = previous.pc; ++ current.fp = previous.fp; ++ current.sp = previous.sp; ++ ++ if (CRASHDEBUG(8)) ++ fprintf(fp, "next %d pc %#lx sp %#lx fp %lx\n", ++ level, current.pc, current.sp, current.fp); ++ } ++} ++ ++/* ++ * Get a stack frame combination of pc and ra from the most relevant spot. ++ */ ++static void ++riscv64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp) ++{ ++ ulong ksp = 0, nip = 0; ++ int ret = 0; ++ ++ if (DUMPFILE() && is_task_active(bt->task)) ++ ret = riscv64_get_dumpfile_stack_frame(bt, &nip, &ksp); ++ else ++ ret = riscv64_get_frame(bt, &nip, &ksp); ++ ++ if (!ret) ++ error(WARNING, "cannot determine starting stack frame for task %lx\n", ++ bt->task); ++ ++ if (pcp) ++ *pcp = nip; ++ if (spp) ++ *spp = ksp; ++} ++ ++/* ++ * Get the starting point for the active cpu in a diskdump. ++ */ ++static int ++riscv64_get_dumpfile_stack_frame(struct bt_info *bt, ulong *nip, ulong *ksp) ++{ ++ const struct machine_specific *ms = machdep->machspec; ++ struct riscv64_register *regs; ++ ulong epc, sp; ++ ++ if (!ms->crash_task_regs) { ++ bt->flags |= BT_REGS_NOT_FOUND; ++ return FALSE; ++ } ++ ++ /* ++ * We got registers for panic task from crash_notes. Just return them. ++ */ ++ regs = &ms->crash_task_regs[bt->tc->processor]; ++ epc = regs->regs[RISCV64_REGS_EPC]; ++ sp = regs->regs[RISCV64_REGS_SP]; ++ ++ /* ++ * Set stack frame ptr. ++ */ ++ bt->frameptr = regs->regs[RISCV64_REGS_FP]; ++ ++ if (nip) ++ *nip = epc; ++ if (ksp) ++ *ksp = sp; ++ ++ bt->machdep = regs; ++ ++ return TRUE; ++} ++ ++/* ++ * Do the work for riscv64_get_stack_frame() for non-active tasks. ++ * Get SP and PC values for idle tasks. ++ */ ++static int ++riscv64_get_frame(struct bt_info *bt, ulong *pcp, ulong *spp) ++{ ++ if (!bt->tc || !(tt->flags & THREAD_INFO)) ++ return FALSE; ++ ++ if (!readmem(bt->task + OFFSET(task_struct_thread_context_pc), ++ KVADDR, pcp, sizeof(*pcp), ++ "thread_struct.ra", ++ RETURN_ON_ERROR)) ++ return FALSE; ++ ++ if (!readmem(bt->task + OFFSET(task_struct_thread_context_sp), ++ KVADDR, spp, sizeof(*spp), ++ "thread_struct.sp", ++ RETURN_ON_ERROR)) ++ return FALSE; ++ ++ if (!readmem(bt->task + OFFSET(task_struct_thread_context_fp), ++ KVADDR, &bt->frameptr, sizeof(bt->frameptr), ++ "thread_struct.fp", ++ RETURN_ON_ERROR)) ++ return FALSE; ++ ++ return TRUE; ++} ++ + static int + riscv64_vtop_4level_4k(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) + { +@@ -978,6 +1258,8 @@ riscv64_init(int when) + machdep->uvtop = riscv64_uvtop; + machdep->kvtop = riscv64_kvtop; + machdep->cmd_mach = riscv64_cmd_mach; ++ machdep->get_stack_frame = riscv64_get_stack_frame; ++ machdep->back_trace = riscv64_back_trace_cmd; + + machdep->vmalloc_start = riscv64_vmalloc_start; + machdep->processor_speed = riscv64_processor_speed; +@@ -998,6 +1280,7 @@ riscv64_init(int when) + case POST_GDB: + machdep->section_size_bits = _SECTION_SIZE_BITS; + machdep->max_physmem_bits = _MAX_PHYSMEM_BITS; ++ riscv64_stackframe_init(); + riscv64_page_type_init(); + + if (!machdep->hz) +-- +2.37.1 + diff --git a/SOURCES/0056-RISCV64-Add-help-r-command-support.patch b/SOURCES/0056-RISCV64-Add-help-r-command-support.patch new file mode 100644 index 0000000..348e025 --- /dev/null +++ b/SOURCES/0056-RISCV64-Add-help-r-command-support.patch @@ -0,0 +1,80 @@ +From 15ac3968a929adebc27985be77fe90d3847abd57 Mon Sep 17 00:00:00 2001 +From: Xianting Tian +Date: Thu, 20 Oct 2022 09:50:11 +0800 +Subject: [PATCH 56/89] RISCV64: Add 'help -r' command support + +Add support form printing out the registers from the dump file. + +With the patch, we can get the regs, +crash> help -r +CPU 0: +epc : 00ffffffa5537400 ra : ffffffff80088620 sp : ff2000001039bb90 + gp : ffffffff810dde38 tp : ff60000002269600 t0 : ffffffff8032be5c + t1 : 0720072007200720 t2 : 666666666666663c s0 : ff2000001039bcf0 + s1 : 0000000000000000 a0 : ff2000001039bb98 a1 : 0000000000000001 + a2 : 0000000000000010 a3 : 0000000000000000 a4 : 0000000000000000 + a5 : ff60000001c7d000 a6 : 000000000000003c a7 : ffffffff8035c998 + s2 : ffffffff810df0a8 s3 : ffffffff810df718 s4 : ff2000001039bb98 + s5 : 0000000000000000 s6 : 0000000000000007 s7 : ffffffff80c4a468 + s8 : 00fffffffde45410 s9 : 0000000000000007 s10: 00aaaaaad1640700 + s11: 0000000000000001 t3 : ff60000001218f00 t4 : ff60000001218f00 + t5 : ff60000001218000 t6 : ff2000001039b988 + +Signed-off-by: Xianting Tian +Signed-off-by: Lianbo Jiang +--- + riscv64.c | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/riscv64.c b/riscv64.c +index 4c9b35bb93f2..6d1d3b5f36d1 100644 +--- a/riscv64.c ++++ b/riscv64.c +@@ -1320,6 +1320,44 @@ riscv64_init(int when) + void + riscv64_display_regs_from_elf_notes(int cpu, FILE *ofp) + { ++ const struct machine_specific *ms = machdep->machspec; ++ struct riscv64_register *regs; ++ ++ if (!ms->crash_task_regs) { ++ error(INFO, "registers not collected for cpu %d\n", cpu); ++ return; ++ } ++ ++ regs = &ms->crash_task_regs[cpu]; ++ if (!regs->regs[RISCV64_REGS_SP] && !regs->regs[RISCV64_REGS_EPC]) { ++ error(INFO, "registers not collected for cpu %d\n", cpu); ++ return; ++ } ++ ++ /* Print riscv64 32 regs */ ++ fprintf(ofp, ++ "epc : " REG_FMT " ra : " REG_FMT " sp : " REG_FMT "\n" ++ " gp : " REG_FMT " tp : " REG_FMT " t0 : " REG_FMT "\n" ++ " t1 : " REG_FMT " t2 : " REG_FMT " s0 : " REG_FMT "\n" ++ " s1 : " REG_FMT " a0 : " REG_FMT " a1 : " REG_FMT "\n" ++ " a2 : " REG_FMT " a3 : " REG_FMT " a4 : " REG_FMT "\n" ++ " a5 : " REG_FMT " a6 : " REG_FMT " a7 : " REG_FMT "\n" ++ " s2 : " REG_FMT " s3 : " REG_FMT " s4 : " REG_FMT "\n" ++ " s5 : " REG_FMT " s6 : " REG_FMT " s7 : " REG_FMT "\n" ++ " s8 : " REG_FMT " s9 : " REG_FMT " s10: " REG_FMT "\n" ++ " s11: " REG_FMT " t3 : " REG_FMT " t4 : " REG_FMT "\n" ++ " t5 : " REG_FMT " t6 : " REG_FMT "\n", ++ regs->regs[0], regs->regs[1], regs->regs[2], ++ regs->regs[3], regs->regs[4], regs->regs[5], ++ regs->regs[6], regs->regs[7], regs->regs[8], ++ regs->regs[9], regs->regs[10], regs->regs[11], ++ regs->regs[12], regs->regs[13], regs->regs[14], ++ regs->regs[15], regs->regs[16], regs->regs[17], ++ regs->regs[18], regs->regs[19], regs->regs[20], ++ regs->regs[21], regs->regs[22], regs->regs[23], ++ regs->regs[24], regs->regs[25], regs->regs[26], ++ regs->regs[27], regs->regs[28], regs->regs[29], ++ regs->regs[30], regs->regs[31]); + } + + #else /* !RISCV64 */ +-- +2.37.1 + diff --git a/SOURCES/0057-RISCV64-Add-help-m-M-command-support.patch b/SOURCES/0057-RISCV64-Add-help-m-M-command-support.patch new file mode 100644 index 0000000..55cadf3 --- /dev/null +++ b/SOURCES/0057-RISCV64-Add-help-m-M-command-support.patch @@ -0,0 +1,141 @@ +From 012c8ebc3d6d71c995522dcf8d8aad530cdb4d02 Mon Sep 17 00:00:00 2001 +From: Xianting Tian +Date: Thu, 20 Oct 2022 09:50:12 +0800 +Subject: [PATCH 57/89] RISCV64: Add 'help -m/M' command support + +Add riscv64_dump_machdep_table() implementation, display machdep_table. + +crash> help -m + flags: 80 () + kvbase: ff60000000000000 + identity_map_base: ff60000000000000 + pagesize: 4096 + pageshift: 12 + pagemask: fffffffffffff000 + pageoffset: fff + pgdir_shift: 48 + ptrs_per_pgd: 512 + ptrs_per_pte: 512 + stacksize: 16384 + hz: 250 + memsize: 1071644672 (0x3fe00000) + bits: 64 + back_trace: riscv64_back_trace_cmd() + processor_speed: riscv64_processor_speed() + uvtop: riscv64_uvtop() + kvtop: riscv64_kvtop() + get_stack_frame: riscv64_get_stack_frame() + get_stackbase: generic_get_stackbase() + get_stacktop: generic_get_stacktop() + translate_pte: riscv64_translate_pte() + memory_size: generic_memory_size() + vmalloc_start: riscv64_vmalloc_start() + is_task_addr: riscv64_is_task_addr() + verify_symbol: riscv64_verify_symbol() + dis_filter: generic_dis_filter() + dump_irq: generic_dump_irq() + show_interrupts: generic_show_interrupts() + get_irq_affinity: generic_get_irq_affinity() + cmd_mach: riscv64_cmd_mach() + get_smp_cpus: riscv64_get_smp_cpus() + is_kvaddr: riscv64_is_kvaddr() + is_uvaddr: riscv64_is_uvaddr() + verify_paddr: generic_verify_paddr() + init_kernel_pgd: NULL + value_to_symbol: generic_machdep_value_to_symbol() + line_number_hooks: NULL + last_pgd_read: ffffffff810e9000 + last_p4d_read: 81410000 + last_pud_read: 81411000 + last_pmd_read: 81412000 + last_ptbl_read: 81415000 + pgd: 560d586f3ab0 + p4d: 560d586f4ac0 + pud: 560d586f5ad0 + pmd: 560d586f6ae0 + ptbl: 560d586f7af0 + section_size_bits: 27 + max_physmem_bits: 56 + sections_per_root: 0 + machspec: 560d57d204a0 + +Signed-off-by: Xianting Tian +Signed-off-by: Lianbo Jiang +--- + riscv64.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 59 insertions(+), 1 deletion(-) + +diff --git a/riscv64.c b/riscv64.c +index 6d1d3b5f36d1..5e8c7d12227c 100644 +--- a/riscv64.c ++++ b/riscv64.c +@@ -132,7 +132,65 @@ riscv64_verify_symbol(const char *name, ulong value, char type) + void + riscv64_dump_machdep_table(ulong arg) + { +- /* TODO: */ ++ int others = 0; ++ ++ fprintf(fp, " flags: %lx (", machdep->flags); ++ if (machdep->flags & KSYMS_START) ++ fprintf(fp, "%sKSYMS_START", others++ ? "|" : ""); ++ fprintf(fp, ")\n"); ++ ++ fprintf(fp, " kvbase: %lx\n", machdep->kvbase); ++ fprintf(fp, " identity_map_base: %lx\n", machdep->identity_map_base); ++ fprintf(fp, " pagesize: %d\n", machdep->pagesize); ++ fprintf(fp, " pageshift: %d\n", machdep->pageshift); ++ fprintf(fp, " pagemask: %llx\n", machdep->pagemask); ++ fprintf(fp, " pageoffset: %lx\n", machdep->pageoffset); ++ fprintf(fp, " pgdir_shift: %ld\n", machdep->machspec->va_bits - 9); ++ fprintf(fp, " ptrs_per_pgd: %u\n", PTRS_PER_PGD); ++ fprintf(fp, " ptrs_per_pte: %d\n", PTRS_PER_PTE); ++ fprintf(fp, " stacksize: %ld\n", machdep->stacksize); ++ fprintf(fp, " hz: %d\n", machdep->hz); ++ fprintf(fp, " memsize: %ld (0x%lx)\n", ++ machdep->memsize, machdep->memsize); ++ fprintf(fp, " bits: %d\n", machdep->bits); ++ fprintf(fp, " back_trace: riscv64_back_trace_cmd()\n"); ++ fprintf(fp, " processor_speed: riscv64_processor_speed()\n"); ++ fprintf(fp, " uvtop: riscv64_uvtop()\n"); ++ fprintf(fp, " kvtop: riscv64_kvtop()\n"); ++ fprintf(fp, " get_stack_frame: riscv64_get_stack_frame()\n"); ++ fprintf(fp, " get_stackbase: generic_get_stackbase()\n"); ++ fprintf(fp, " get_stacktop: generic_get_stacktop()\n"); ++ fprintf(fp, " translate_pte: riscv64_translate_pte()\n"); ++ fprintf(fp, " memory_size: generic_memory_size()\n"); ++ fprintf(fp, " vmalloc_start: riscv64_vmalloc_start()\n"); ++ fprintf(fp, " is_task_addr: riscv64_is_task_addr()\n"); ++ fprintf(fp, " verify_symbol: riscv64_verify_symbol()\n"); ++ fprintf(fp, " dis_filter: generic_dis_filter()\n"); ++ fprintf(fp, " dump_irq: generic_dump_irq()\n"); ++ fprintf(fp, " show_interrupts: generic_show_interrupts()\n"); ++ fprintf(fp, " get_irq_affinity: generic_get_irq_affinity()\n"); ++ fprintf(fp, " cmd_mach: riscv64_cmd_mach()\n"); ++ fprintf(fp, " get_smp_cpus: riscv64_get_smp_cpus()\n"); ++ fprintf(fp, " is_kvaddr: riscv64_is_kvaddr()\n"); ++ fprintf(fp, " is_uvaddr: riscv64_is_uvaddr()\n"); ++ fprintf(fp, " verify_paddr: generic_verify_paddr()\n"); ++ fprintf(fp, " init_kernel_pgd: NULL\n"); ++ fprintf(fp, " value_to_symbol: generic_machdep_value_to_symbol()\n"); ++ fprintf(fp, " line_number_hooks: NULL\n"); ++ fprintf(fp, " last_pgd_read: %lx\n", machdep->last_pgd_read); ++ fprintf(fp, " last_p4d_read: %lx\n", machdep->machspec->last_p4d_read); ++ fprintf(fp, " last_pud_read: %lx\n", machdep->last_pud_read); ++ fprintf(fp, " last_pmd_read: %lx\n", machdep->last_pmd_read); ++ fprintf(fp, " last_ptbl_read: %lx\n", machdep->last_ptbl_read); ++ fprintf(fp, " pgd: %lx\n", (ulong)machdep->pgd); ++ fprintf(fp, " p4d: %lx\n", (ulong)machdep->machspec->p4d); ++ fprintf(fp, " pud: %lx\n", (ulong)machdep->pud); ++ fprintf(fp, " pmd: %lx\n", (ulong)machdep->pmd); ++ fprintf(fp, " ptbl: %lx\n", (ulong)machdep->ptbl); ++ fprintf(fp, " section_size_bits: %ld\n", machdep->section_size_bits); ++ fprintf(fp, " max_physmem_bits: %ld\n", machdep->max_physmem_bits); ++ fprintf(fp, " sections_per_root: %ld\n", machdep->sections_per_root); ++ fprintf(fp, " machspec: %lx\n", (ulong)machdep->machspec); + } + + static ulong +-- +2.37.1 + diff --git a/SOURCES/0058-RISCV64-Add-mach-command-support.patch b/SOURCES/0058-RISCV64-Add-mach-command-support.patch new file mode 100644 index 0000000..3357e81 --- /dev/null +++ b/SOURCES/0058-RISCV64-Add-mach-command-support.patch @@ -0,0 +1,83 @@ +From 7a942ad69e1a4270dba89de9bff4f93cd6d87578 Mon Sep 17 00:00:00 2001 +From: Xianting Tian +Date: Thu, 20 Oct 2022 09:50:13 +0800 +Subject: [PATCH 58/89] RISCV64: Add 'mach' command support + +With the patch we can get some basic machine state information, +crash> mach + MACHINE TYPE: riscv64 + MEMORY SIZE: 1 GB + CPUS: 1 + PROCESSOR SPEED: (unknown) + HZ: 250 + PAGE SIZE: 4096 + KERNEL STACK SIZE: 16384 + +Signed-off-by: Xianting Tian +Signed-off-by: Lianbo Jiang +--- + riscv64.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 44 insertions(+), 1 deletion(-) + +diff --git a/riscv64.c b/riscv64.c +index 5e8c7d12227c..ff77e41b9407 100644 +--- a/riscv64.c ++++ b/riscv64.c +@@ -116,10 +116,53 @@ static void riscv64_get_struct_page_size(struct machine_specific *ms) + } + } + ++/* ++ * "mach" command output. ++ */ ++static void ++riscv64_display_machine_stats(void) ++{ ++ struct new_utsname *uts; ++ char buf[BUFSIZE]; ++ ulong mhz; ++ ++ uts = &kt->utsname; ++ ++ fprintf(fp, " MACHINE TYPE: %s\n", uts->machine); ++ fprintf(fp, " MEMORY SIZE: %s\n", get_memory_size(buf)); ++ fprintf(fp, " CPUS: %d\n", get_cpus_to_display()); ++ fprintf(fp, " PROCESSOR SPEED: "); ++ if ((mhz = machdep->processor_speed())) ++ fprintf(fp, "%ld Mhz\n", mhz); ++ else ++ fprintf(fp, "(unknown)\n"); ++ fprintf(fp, " HZ: %d\n", machdep->hz); ++ fprintf(fp, " PAGE SIZE: %d\n", PAGESIZE()); ++ fprintf(fp, " KERNEL STACK SIZE: %ld\n", STACKSIZE()); ++} ++ + static void + riscv64_cmd_mach(void) + { +- /* TODO: */ ++ int c; ++ ++ while ((c = getopt(argcnt, args, "cmo")) != EOF) { ++ switch (c) { ++ case 'c': ++ case 'm': ++ case 'o': ++ option_not_supported(c); ++ break; ++ default: ++ argerrs++; ++ break; ++ } ++ } ++ ++ if (argerrs) ++ cmd_usage(pc->curcmd, SYNOPSIS); ++ ++ riscv64_display_machine_stats(); + } + + static int +-- +2.37.1 + diff --git a/SOURCES/0059-RISCV64-Add-the-implementation-of-symbol-verify.patch b/SOURCES/0059-RISCV64-Add-the-implementation-of-symbol-verify.patch new file mode 100644 index 0000000..2342486 --- /dev/null +++ b/SOURCES/0059-RISCV64-Add-the-implementation-of-symbol-verify.patch @@ -0,0 +1,45 @@ +From ba2d96e12463157fe2ed9c134ad9cf42481427e8 Mon Sep 17 00:00:00 2001 +From: Xianting Tian +Date: Thu, 20 Oct 2022 09:50:14 +0800 +Subject: [PATCH 59/89] RISCV64: Add the implementation of symbol verify + +Verify the symbol to accept or reject a symbol from the kernel namelist. + +Signed-off-by: Xianting Tian +Signed-off-by: Lianbo Jiang +--- + riscv64.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/riscv64.c b/riscv64.c +index ff77e41b9407..6b9a68840d4c 100644 +--- a/riscv64.c ++++ b/riscv64.c +@@ -165,10 +165,23 @@ riscv64_cmd_mach(void) + riscv64_display_machine_stats(); + } + ++/* ++ * Accept or reject a symbol from the kernel namelist. ++ */ + static int + riscv64_verify_symbol(const char *name, ulong value, char type) + { +- /* TODO: */ ++ if (CRASHDEBUG(8) && name && strlen(name)) ++ fprintf(fp, "%08lx %s\n", value, name); ++ ++ if (!(machdep->flags & KSYMS_START)) { ++ if (STREQ(name, "_text") || STREQ(name, "_stext")) ++ machdep->flags |= KSYMS_START; ++ ++ return (name && strlen(name) && !STRNEQ(name, "__func__.") && ++ !STRNEQ(name, "__crc_")); ++ } ++ + return TRUE; + } + +-- +2.37.1 + diff --git a/SOURCES/0060-SLUB-Fix-for-offset-change-of-struct-slab-members-on.patch b/SOURCES/0060-SLUB-Fix-for-offset-change-of-struct-slab-members-on.patch new file mode 100644 index 0000000..54f1f45 --- /dev/null +++ b/SOURCES/0060-SLUB-Fix-for-offset-change-of-struct-slab-members-on.patch @@ -0,0 +1,149 @@ +From 47d375ac822d413999c92520402c4868ce2275cc Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Fri, 16 Dec 2022 14:03:46 +0900 +Subject: [PATCH 60/89] SLUB: Fix for offset change of struct slab members on + Linux 6.2-rc1 + +The following kernel commits split slab info from struct page into +struct slab in Linux 5.17. + + d122019bf061 ("mm: Split slab into its own type") + 07f910f9b729 ("mm: Remove slab from struct page") + +Crash commit 5f390ed811b0 followed the change for SLUB, but crash still +uses the offset of page.lru inappropriately. Luckily, it could work +because it was the same value as the offset of slab.slab_list until +Linux 6.1. + +However, kernel commit 130d4df57390 ("mm/sl[au]b: rearrange struct slab +fields to allow larger rcu_head") in Linux 6.2-rc1 changed the offset of +slab.slab_list. As a result, without the patch, "kmem -s|-S" options +print the following errors and fail to print values correctly for +kernels configured with CONFIG_SLUB. + + crash> kmem -S filp + CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME + kmem: filp: partial list slab: ffffcc650405ab88 invalid page.inuse: -1 + ffff8fa0401eca00 232 1267 1792 56 8k filp + ... + KMEM_CACHE_NODE NODE SLABS PARTIAL PER-CPU + ffff8fa0401cb8c0 0 56 24 8 + NODE 0 PARTIAL: + SLAB MEMORY NODE TOTAL ALLOCATED FREE + kmem: filp: invalid partial list slab pointer: ffffcc650405ab88 + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 1 + + memory.c | 16 ++++++++++------ + symbols.c | 1 + + 3 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/defs.h b/defs.h +index 9c91f38328d0..31702e707bee 100644 +--- a/defs.h ++++ b/defs.h +@@ -2188,6 +2188,7 @@ struct offset_table { /* stash of commonly-used offsets */ + long blk_mq_tags_rqs; + long request_queue_hctx_table; + long percpu_counter_counters; ++ long slab_slab_list; + }; + + struct size_table { /* stash of commonly-used sizes */ +diff --git a/memory.c b/memory.c +index 9d003713534b..d05737cc1429 100644 +--- a/memory.c ++++ b/memory.c +@@ -781,6 +781,8 @@ vm_init(void) + if (INVALID_MEMBER(page_slab)) + MEMBER_OFFSET_INIT(page_slab, "slab", "slab_cache"); + ++ MEMBER_OFFSET_INIT(slab_slab_list, "slab", "slab_list"); ++ + MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page"); + if (INVALID_MEMBER(page_slab_page)) + ANON_MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page"); +@@ -19474,6 +19476,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) + { + ulong next, last, list_head, flags; + int first; ++ long list_off = VALID_MEMBER(slab_slab_list) ? OFFSET(slab_slab_list) : OFFSET(page_lru); + + if (!node_ptr) + return; +@@ -19487,7 +19490,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) + next == list_head ? " (empty)\n" : ""); + first = 0; + while (next != list_head) { +- si->slab = last = next - OFFSET(page_lru); ++ si->slab = last = next - list_off; + if (first++ == 0) + fprintf(fp, " %s", slab_hdr); + +@@ -19510,7 +19513,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) + + if (!IS_KVADDR(next) || + ((next != list_head) && +- !is_page_ptr(next - OFFSET(page_lru), NULL))) { ++ !is_page_ptr(next - list_off, NULL))) { + error(INFO, + "%s: partial list slab: %lx invalid page.lru.next: %lx\n", + si->curname, last, next); +@@ -19537,7 +19540,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) + next == list_head ? " (empty)\n" : ""); + first = 0; + while (next != list_head) { +- si->slab = next - OFFSET(page_lru); ++ si->slab = next - list_off; + if (first++ == 0) + fprintf(fp, " %s", slab_hdr); + +@@ -19754,6 +19757,7 @@ count_partial(ulong node, struct meminfo *si, ulong *free) + short inuse, objects; + ulong total_inuse; + ulong count = 0; ++ long list_off = VALID_MEMBER(slab_slab_list) ? OFFSET(slab_slab_list) : OFFSET(page_lru); + + count = 0; + total_inuse = 0; +@@ -19765,12 +19769,12 @@ count_partial(ulong node, struct meminfo *si, ulong *free) + hq_open(); + + while (next != list_head) { +- if (!readmem(next - OFFSET(page_lru) + OFFSET(page_inuse), ++ if (!readmem(next - list_off + OFFSET(page_inuse), + KVADDR, &inuse, sizeof(ushort), "page.inuse", RETURN_ON_ERROR)) { + hq_close(); + return -1; + } +- last = next - OFFSET(page_lru); ++ last = next - list_off; + + if (inuse == -1) { + error(INFO, +@@ -19796,7 +19800,7 @@ count_partial(ulong node, struct meminfo *si, ulong *free) + } + if (!IS_KVADDR(next) || + ((next != list_head) && +- !is_page_ptr(next - OFFSET(page_lru), NULL))) { ++ !is_page_ptr(next - list_off, NULL))) { + error(INFO, "%s: partial list slab: %lx invalid page.lru.next: %lx\n", + si->curname, last, next); + break; +diff --git a/symbols.c b/symbols.c +index d1b35a56aa71..9e6fca73eaf9 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -9722,6 +9722,7 @@ dump_offset_table(char *spec, ulong makestruct) + OFFSET(slab_inuse)); + fprintf(fp, " slab_free: %ld\n", + OFFSET(slab_free)); ++ fprintf(fp, " slab_slab_list: %ld\n", OFFSET(slab_slab_list)); + + fprintf(fp, " kmem_cache_size: %ld\n", + OFFSET(kmem_cache_size)); +-- +2.37.1 + diff --git a/SOURCES/0061-Fix-for-kmem-i-to-display-correct-SLAB-statistics-on.patch b/SOURCES/0061-Fix-for-kmem-i-to-display-correct-SLAB-statistics-on.patch new file mode 100644 index 0000000..472bc21 --- /dev/null +++ b/SOURCES/0061-Fix-for-kmem-i-to-display-correct-SLAB-statistics-on.patch @@ -0,0 +1,49 @@ +From 699717c7720cb2a397ce59d0a0380c65d2693033 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Fri, 23 Dec 2022 18:42:35 +0800 +Subject: [PATCH 61/89] Fix for "kmem -i" to display correct SLAB statistics on + Linux 5.9 and later + +Kernel commit d42f3245c7e2 ("mm: memcg: convert vmstat slab counters to +bytes"), which is contained in Linux v5.9-rc1 and later kernels, renamed +NR_SLAB_{RECLAIMABLE,UNRECLAIMABLE} to NR_SLAB_{RECLAIMABLE,UNRECLAIMABLE}_B. + +Without the patch, "kmem -i" command will display incorrect SLAB +statistics: + + crash> kmem -i | grep -e PAGES -e SLAB + PAGES TOTAL PERCENTAGE + SLAB 89458 349.4 MB 0% of TOTAL MEM + ^^^^^ ^^^^^ + +With the patch, the actual result is: + crash> kmem -i | grep -e PAGES -e SLAB + PAGES TOTAL PERCENTAGE + SLAB 261953 1023.3 MB 0% of TOTAL MEM + +Reported-by: Buland Kumar Singh +Signed-off-by: Lianbo Jiang +Signed-off-by: Kazuhito Hagio +--- + memory.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/memory.c b/memory.c +index d05737cc1429..625a94b7d7d4 100644 +--- a/memory.c ++++ b/memory.c +@@ -8388,6 +8388,11 @@ dump_kmeminfo(void) + get_slabs = nr_slab; + if (dump_vm_stat("NR_SLAB_UNRECLAIMABLE", &nr_slab, 0)) + get_slabs += nr_slab; ++ } else if (dump_vm_stat("NR_SLAB_RECLAIMABLE_B", &nr_slab, 0)) { ++ /* 5.9 and later */ ++ get_slabs = nr_slab; ++ if (dump_vm_stat("NR_SLAB_UNRECLAIMABLE_B", &nr_slab, 0)) ++ get_slabs += nr_slab; + } + } + +-- +2.37.1 + diff --git a/SOURCES/0062-Fix-build-failure-due-to-no-EM_RISCV-with-glibc-2.23.patch b/SOURCES/0062-Fix-build-failure-due-to-no-EM_RISCV-with-glibc-2.23.patch new file mode 100644 index 0000000..81baa5c --- /dev/null +++ b/SOURCES/0062-Fix-build-failure-due-to-no-EM_RISCV-with-glibc-2.23.patch @@ -0,0 +1,49 @@ +From 4003c972c5ff0814847865a9f5487c8561a598ad Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Tue, 27 Dec 2022 09:53:46 +0900 +Subject: [PATCH 62/89] Fix build failure due to no EM_RISCV with glibc-2.23 + and earlier + +With glibc-2.23 and earlier (e.g. RHEL7), crash build fails with errors +like this due to EM_RISCV undeclared: + + $ make -j 24 warn + TARGET: X86_64 + CRASH: 8.0.2++ + GDB: 10.2 + ... + symbols.c: In function 'is_kernel': + symbols.c:3746:8: error: 'EM_RISCV' undeclared (first use in this function) + case EM_RISCV: + ^ + ... + +Define EM_RISCV as 243 [1][2] if not defined. + +[1] https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=94e73c95d9b5 +[2] http://www.sco.com/developers/gabi/latest/ch4.eheader.html + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/defs.h b/defs.h +index 31702e707bee..cb04562d0d92 100644 +--- a/defs.h ++++ b/defs.h +@@ -3493,6 +3493,10 @@ struct arm64_stackframe { + #define _MAX_PHYSMEM_BITS 48 + #endif /* MIPS64 */ + ++#ifndef EM_RISCV ++#define EM_RISCV 243 ++#endif ++ + #ifdef RISCV64 + #define _64BIT_ + #define MACHINE_TYPE "RISCV64" +-- +2.37.1 + diff --git a/SOURCES/0063-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.1-and-later.patch b/SOURCES/0063-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.1-and-later.patch new file mode 100644 index 0000000..90d232d --- /dev/null +++ b/SOURCES/0063-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.1-and-later.patch @@ -0,0 +1,46 @@ +From 652681dd7fa37a20d7ef3a51a27afa7d6d3f1872 Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Thu, 5 Jan 2023 17:18:51 +0900 +Subject: [PATCH 63/89] SLAB: Fix for "kmem -s|-S" options on Linux 6.1 and + later + +Kernel commit e36ce448a08d ("mm/slab: use kmalloc_node() for off slab +freelist_idx_t array allocation"), which is contained in Linux 6.1 and +later kernels, removed kmem_cache.freelist_cache member on kernels +configured with CONFIG_SLAB=y. + +Without the patch, crash does not set SLAB_OVERLOAD_PAGE and +"kmem -s|-S" options fail with the following error: + + kmem: invalid structure member offset: slab_list + FILE: memory.c LINE: 12156 FUNCTION: verify_slab_v2() + +Use kmem_cache.freelist_size instead, which was introduced together +with kmem_cache.freelist_cache by kernel commit 8456a648cf44. + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + memory.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/memory.c b/memory.c +index 625a94b7d7d4..71ded688206f 100644 +--- a/memory.c ++++ b/memory.c +@@ -535,8 +535,11 @@ vm_init(void) + /* + * slab: overload struct slab over struct page + * https://lkml.org/lkml/2013/10/16/155 ++ * ++ * commit e36ce448a08d removed kmem_cache.freelist_cache in 6.1, ++ * so use freelist_size instead. + */ +- if (MEMBER_EXISTS("kmem_cache", "freelist_cache")) { ++ if (MEMBER_EXISTS("kmem_cache", "freelist_size")) { + vt->flags |= SLAB_OVERLOAD_PAGE; + ANON_MEMBER_OFFSET_INIT(page_s_mem, "page", "s_mem"); + ANON_MEMBER_OFFSET_INIT(page_freelist, "page", "freelist"); +-- +2.37.1 + diff --git a/SOURCES/0064-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.2-rc1-and-l.patch b/SOURCES/0064-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.2-rc1-and-l.patch new file mode 100644 index 0000000..ca84cdc --- /dev/null +++ b/SOURCES/0064-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.2-rc1-and-l.patch @@ -0,0 +1,233 @@ +From 4060546b051751e7e593100027d2a160723a17ee Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Thu, 5 Jan 2023 17:36:42 +0900 +Subject: [PATCH 64/89] SLAB: Fix for "kmem -s|-S" options on Linux 6.2-rc1 and + later + +Kernel commit 130d4df57390 ("mm/sl[au]b: rearrange struct slab fields to +allow larger rcu_head"), which is contained in Linux 6.2-rc1 and later +kernels, changed the offset of slab.slab_list and now it's not equal to +the offset of page.lru. + +Without the patch, "kmem -s|-S" options print errors and zeros for slab +counters like this for kernels configured with CONFIG_SLAB=y. + + crash> kmem -s + CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME + kmem: rpc_inode_cache: partial list: page/slab: fffff31ac4125190 bad active counter: 99476865 + kmem: rpc_inode_cache: partial list: page/slab: fffff31ac4125190 bad s_mem pointer: 100000003 + kmem: rpc_inode_cache: full list: page/slab: fffff31ac4125150 bad active counter: 99476225 + kmem: rpc_inode_cache: full list: page/slab: fffff31ac4125150 bad active counter: 99476225 + kmem: rpc_inode_cache: full list: page/slab: fffff31ac4125150 bad s_mem pointer: 100000005 + ffff930202adfb40 704 0 0 0 4k rpc_inode_cache + ... + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + memory.c | 45 +++++++++++++++++++++++++-------------------- + 1 file changed, 25 insertions(+), 20 deletions(-) + +diff --git a/memory.c b/memory.c +index 71ded688206f..156de2f7b5a3 100644 +--- a/memory.c ++++ b/memory.c +@@ -78,6 +78,7 @@ struct meminfo { /* general purpose memory information structure */ + int *freelist; + int freelist_index_size; + ulong random; ++ ulong list_offset; + }; + + /* +@@ -553,6 +554,8 @@ vm_init(void) + MEMBER_OFFSET_INIT(page_freelist, "slab", "freelist"); + if (INVALID_MEMBER(page_active)) + MEMBER_OFFSET_INIT(page_active, "slab", "active"); ++ ++ MEMBER_OFFSET_INIT(slab_slab_list, "slab", "slab_list"); + } + + if (!VALID_STRUCT(kmem_slab_s) && VALID_STRUCT(slab_s)) { +@@ -10767,6 +10770,8 @@ dump_kmem_cache_percpu_v2(struct meminfo *si) + if (vt->flags & SLAB_OVERLOAD_PAGE) { + si->freelist = si->kmem_bufctl; + si->freelist_index_size = slab_freelist_index_size(); ++ si->list_offset = VALID_MEMBER(slab_slab_list) ? ++ OFFSET(slab_slab_list) : OFFSET(page_lru); + } + for (i = 0; i < vt->kmem_max_cpus; i++) + si->cpudata[i] = (ulong *) +@@ -11983,7 +11988,7 @@ do_slab_chain_slab_overload_page(long cmd, struct meminfo *si) + } + last = si->slab; + +- readmem(si->slab - OFFSET(page_lru), KVADDR, page_buf, ++ readmem(si->slab - si->list_offset, KVADDR, page_buf, + SIZE(page), "page (slab) buffer", + FAULT_ON_ERROR); + +@@ -11996,8 +12001,7 @@ do_slab_chain_slab_overload_page(long cmd, struct meminfo *si) + + si->num_slabs++; + +- si->slab = ULONG(page_buf + +- OFFSET(page_lru)); ++ si->slab = ULONG(page_buf + si->list_offset); + + /* + * Check for slab transition. (Tony Dziedzic) +@@ -12024,11 +12028,11 @@ do_slab_chain_slab_overload_page(long cmd, struct meminfo *si) + case SLAB_WALKTHROUGH: + if (si->flags & SLAB_OVERLOAD_PAGE_PTR) { + specified_slab = si->spec_addr; +- si->slab = si->spec_addr + OFFSET(page_lru); ++ si->slab = si->spec_addr + si->list_offset; + } else { + specified_slab = si->slab; + if (si->slab) +- si->slab += OFFSET(page_lru); ++ si->slab += si->list_offset; + } + si->flags |= (SLAB_WALKTHROUGH|SLAB_FIRST_NODE); + si->flags &= ~SLAB_GET_COUNTS; +@@ -12082,7 +12086,7 @@ do_slab_chain_slab_overload_page(long cmd, struct meminfo *si) + if (si->slab == slab_chains[s]) + continue; + +- readmem(si->slab - OFFSET(page_lru), KVADDR, page_buf, ++ readmem(si->slab - si->list_offset, KVADDR, page_buf, + SIZE(page), "page (slab) buffer", + FAULT_ON_ERROR); + +@@ -12242,7 +12246,7 @@ verify_slab_overload_page(struct meminfo *si, ulong last, int s) + + errcnt = 0; + +- if (!readmem(si->slab - OFFSET(page_lru), KVADDR, page_buf, ++ if (!readmem(si->slab - si->list_offset, KVADDR, page_buf, + SIZE(page), "page (slab) buffer", QUIET|RETURN_ON_ERROR)) { + error(INFO, "%s: %s list: bad slab pointer: %lx\n", + si->curname, list, si->slab); +@@ -12250,7 +12254,7 @@ verify_slab_overload_page(struct meminfo *si, ulong last, int s) + return FALSE; + } + +- list_head = (struct kernel_list_head *)(page_buf + OFFSET(page_lru)); ++ list_head = (struct kernel_list_head *)(page_buf + si->list_offset); + if (!IS_KVADDR((ulong)list_head->next) || + !accessible((ulong)list_head->next)) { + error(INFO, "%s: %s list: page/slab: %lx bad next pointer: %lx\n", +@@ -12569,7 +12573,7 @@ dump_slab_overload_page(struct meminfo *si) + int tmp; + ulong slab_overload_page, freelist; + +- slab_overload_page = si->slab - OFFSET(page_lru); ++ slab_overload_page = si->slab - si->list_offset; + + readmem(slab_overload_page + OFFSET(page_s_mem), + KVADDR, &si->s_mem, sizeof(ulong), +@@ -12796,12 +12800,12 @@ gather_slab_free_list_slab_overload_page(struct meminfo *si) + + if (CRASHDEBUG(1)) + fprintf(fp, "slab page: %lx active: %ld si->c_num: %ld\n", +- si->slab - OFFSET(page_lru), si->s_inuse, si->c_num); ++ si->slab - si->list_offset, si->s_inuse, si->c_num); + + if (si->s_inuse == si->c_num ) + return; + +- slab_overload_page = si->slab - OFFSET(page_lru); ++ slab_overload_page = si->slab - si->list_offset; + readmem(slab_overload_page + OFFSET(page_freelist), + KVADDR, &freelist, sizeof(void *), "page freelist", + FAULT_ON_ERROR); +@@ -13099,7 +13103,7 @@ dump_slab_objects_percpu(struct meminfo *si) + + if ((si->flags & ADDRESS_SPECIFIED) && + (vt->flags & SLAB_OVERLOAD_PAGE)) { +- readmem(si->slab - OFFSET(page_lru) + OFFSET(page_freelist), ++ readmem(si->slab - si->list_offset + OFFSET(page_freelist), + KVADDR, &freelist, sizeof(ulong), "page.freelist", + FAULT_ON_ERROR); + +@@ -18713,6 +18717,9 @@ dump_kmem_cache_slub(struct meminfo *si) + + si->cache_buf = GETBUF(SIZE(kmem_cache)); + ++ si->list_offset = VALID_MEMBER(slab_slab_list) ? ++ OFFSET(slab_slab_list) : OFFSET(page_lru); ++ + if (VALID_MEMBER(page_objects) && + OFFSET(page_objects) == OFFSET(page_inuse)) + si->flags |= SLAB_BITFIELD; +@@ -19484,7 +19491,6 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) + { + ulong next, last, list_head, flags; + int first; +- long list_off = VALID_MEMBER(slab_slab_list) ? OFFSET(slab_slab_list) : OFFSET(page_lru); + + if (!node_ptr) + return; +@@ -19498,7 +19504,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) + next == list_head ? " (empty)\n" : ""); + first = 0; + while (next != list_head) { +- si->slab = last = next - list_off; ++ si->slab = last = next - si->list_offset; + if (first++ == 0) + fprintf(fp, " %s", slab_hdr); + +@@ -19521,7 +19527,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) + + if (!IS_KVADDR(next) || + ((next != list_head) && +- !is_page_ptr(next - list_off, NULL))) { ++ !is_page_ptr(next - si->list_offset, NULL))) { + error(INFO, + "%s: partial list slab: %lx invalid page.lru.next: %lx\n", + si->curname, last, next); +@@ -19548,7 +19554,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node) + next == list_head ? " (empty)\n" : ""); + first = 0; + while (next != list_head) { +- si->slab = next - list_off; ++ si->slab = next - si->list_offset; + if (first++ == 0) + fprintf(fp, " %s", slab_hdr); + +@@ -19765,7 +19771,6 @@ count_partial(ulong node, struct meminfo *si, ulong *free) + short inuse, objects; + ulong total_inuse; + ulong count = 0; +- long list_off = VALID_MEMBER(slab_slab_list) ? OFFSET(slab_slab_list) : OFFSET(page_lru); + + count = 0; + total_inuse = 0; +@@ -19777,12 +19782,12 @@ count_partial(ulong node, struct meminfo *si, ulong *free) + hq_open(); + + while (next != list_head) { +- if (!readmem(next - list_off + OFFSET(page_inuse), ++ if (!readmem(next - si->list_offset + OFFSET(page_inuse), + KVADDR, &inuse, sizeof(ushort), "page.inuse", RETURN_ON_ERROR)) { + hq_close(); + return -1; + } +- last = next - list_off; ++ last = next - si->list_offset; + + if (inuse == -1) { + error(INFO, +@@ -19808,7 +19813,7 @@ count_partial(ulong node, struct meminfo *si, ulong *free) + } + if (!IS_KVADDR(next) || + ((next != list_head) && +- !is_page_ptr(next - list_off, NULL))) { ++ !is_page_ptr(next - si->list_offset, NULL))) { + error(INFO, "%s: partial list slab: %lx invalid page.lru.next: %lx\n", + si->curname, last, next); + break; +-- +2.37.1 + diff --git a/SOURCES/0065-Port-the-maple-tree-data-structures-and-functions.patch b/SOURCES/0065-Port-the-maple-tree-data-structures-and-functions.patch new file mode 100644 index 0000000..c3b6760 --- /dev/null +++ b/SOURCES/0065-Port-the-maple-tree-data-structures-and-functions.patch @@ -0,0 +1,633 @@ +From 5b61f450d213cda90dd0f50a02594a0b87151c89 Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Tue, 10 Jan 2023 14:56:27 +0800 +Subject: [PATCH 65/89] Port the maple tree data structures and functions + +There have been two ways to iterate vm_area_struct until Linux 6.0: + 1) by rbtree, aka vma.vm_rb; + 2) by linked list, aka vma.vm_{next,prev}. +However with the maple tree patches[1][2] in Linux 6.1, vm_rb and +vm_{next,prev} are removed from vm_area_struct. The vm_area_dump() +in crash mainly uses the linked list for vma iteration, which will +not work for this case. So the maple tree iteration needs to be +ported to crash. + +For crash, currently it only iteratively reads the maple tree, +no more rcu safe or maple tree modification features needed. +So we only port a subset of kernel maple tree features. +In addition, we need to modify the ported kernel source code, +making it compatible with crash. + +This patch deals with the two issues: + 1) Poring mt_dump() function and all its dependencies from + kernel source to crash, to enable crash maple tree iteration, + 2) adapting the ported code with crash. + +[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=524e00b36e8c547f5582eef3fb645a8d9fc5e3df +[2]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=763ecb035029f500d7e6dc99acd1ad299b7726a1 + +Signed-off-by: Tao Liu +Signed-off-by: Lianbo Jiang +--- + Makefile | 10 +- + defs.h | 19 +++ + maple_tree.c | 407 +++++++++++++++++++++++++++++++++++++++++++++++++++ + maple_tree.h | 82 +++++++++++ + 4 files changed, 515 insertions(+), 3 deletions(-) + create mode 100644 maple_tree.c + create mode 100644 maple_tree.h + +diff --git a/Makefile b/Makefile +index c0de5ef8ff75..b290836ffc83 100644 +--- a/Makefile ++++ b/Makefile +@@ -59,6 +59,7 @@ IBM_HFILES=ibm_common.h + SADUMP_HFILES=sadump.h + UNWIND_HFILES=unwind.h unwind_i.h rse.h unwind_x86.h unwind_x86_64.h + VMWARE_HFILES=vmware_vmss.h ++MAPLE_TREE_HFILES=maple_tree.h + + CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \ + kernel.c test.c gdb_interface.c configure.c net.c dev.c bpf.c \ +@@ -73,12 +74,12 @@ CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \ + xen_hyper.c xen_hyper_command.c xen_hyper_global_data.c \ + xen_hyper_dump_tables.c kvmdump.c qemu.c qemu-load.c sadump.c ipcs.c \ + ramdump.c vmware_vmss.c vmware_guestdump.c \ +- xen_dom0.c kaslr_helper.c sbitmap.c ++ xen_dom0.c kaslr_helper.c sbitmap.c maple_tree.c + + SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \ + ${REDHAT_CFILES} ${REDHAT_HFILES} ${UNWIND_HFILES} \ + ${LKCD_DUMP_HFILES} ${LKCD_TRACE_HFILES} ${LKCD_OBSOLETE_HFILES}\ +- ${IBM_HFILES} ${SADUMP_HFILES} ${VMWARE_HFILES} ++ ${IBM_HFILES} ${SADUMP_HFILES} ${VMWARE_HFILES} ${MAPLE_TREE_HFILES} + + OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \ + build_data.o kernel.o test.o gdb_interface.o net.o dev.o bpf.o \ +@@ -93,7 +94,7 @@ OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \ + xen_hyper.o xen_hyper_command.o xen_hyper_global_data.o \ + xen_hyper_dump_tables.o kvmdump.o qemu.o qemu-load.o sadump.o ipcs.o \ + ramdump.o vmware_vmss.o vmware_guestdump.o \ +- xen_dom0.o kaslr_helper.o sbitmap.o ++ xen_dom0.o kaslr_helper.o sbitmap.o maple_tree.o + + MEMORY_DRIVER_FILES=memory_driver/Makefile memory_driver/crash.c memory_driver/README + +@@ -548,6 +549,9 @@ kaslr_helper.o: ${GENERIC_HFILES} kaslr_helper.c + bpf.o: ${GENERIC_HFILES} bpf.c + ${CC} -c ${CRASH_CFLAGS} bpf.c ${WARNING_OPTIONS} ${WARNING_ERROR} + ++maple_tree.o: ${GENERIC_HFILES} ${MAPLE_TREE_HFILES} maple_tree.c ++ ${CC} -c ${CRASH_CFLAGS} maple_tree.c ${WARNING_OPTIONS} ${WARNING_ERROR} ++ + ${PROGRAM}: force + @$(MAKE) all + +diff --git a/defs.h b/defs.h +index cb04562d0d92..46ed10e17cd2 100644 +--- a/defs.h ++++ b/defs.h +@@ -2189,6 +2189,21 @@ struct offset_table { /* stash of commonly-used offsets */ + long request_queue_hctx_table; + long percpu_counter_counters; + long slab_slab_list; ++ long mm_struct_mm_mt; ++ long maple_tree_ma_root; ++ long maple_tree_ma_flags; ++ long maple_node_parent; ++ long maple_node_ma64; ++ long maple_node_mr64; ++ long maple_node_slot; ++ long maple_arange_64_pivot; ++ long maple_arange_64_slot; ++ long maple_arange_64_gap; ++ long maple_arange_64_meta; ++ long maple_range_64_pivot; ++ long maple_range_64_slot; ++ long maple_metadata_end; ++ long maple_metadata_gap; + }; + + struct size_table { /* stash of commonly-used sizes */ +@@ -2360,6 +2375,8 @@ struct size_table { /* stash of commonly-used sizes */ + long sbq_wait_state; + long blk_mq_tags; + long percpu_counter; ++ long maple_tree; ++ long maple_node; + }; + + struct array_table { +@@ -5730,6 +5747,8 @@ int same_file(char *, char *); + #ifndef GDB_COMMON + int cleanup_memory_driver(void); + ++void maple_init(void); ++int do_mptree(struct tree_data *); + + /* + * help.c +diff --git a/maple_tree.c b/maple_tree.c +new file mode 100644 +index 000000000000..474faeda6252 +--- /dev/null ++++ b/maple_tree.c +@@ -0,0 +1,407 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Maple Tree implementation ++ * Copyright (c) 2018-2022 Oracle Corporation ++ * Authors: Liam R. Howlett ++ * Matthew Wilcox ++ * ++ * The following are copied and modified from lib/maple_tree.c ++ */ ++ ++#include "maple_tree.h" ++#include "defs.h" ++ ++unsigned char *mt_slots = NULL; ++unsigned char *mt_pivots = NULL; ++ulong mt_max[4] = {0}; ++ ++#define MAPLE_BUFSIZE 512 ++ ++static inline ulong mte_to_node(ulong maple_enode_entry) ++{ ++ return maple_enode_entry & ~MAPLE_NODE_MASK; ++} ++ ++static inline enum maple_type mte_node_type(ulong maple_enode_entry) ++{ ++ return (maple_enode_entry >> MAPLE_NODE_TYPE_SHIFT) & ++ MAPLE_NODE_TYPE_MASK; ++} ++ ++static inline ulong mt_slot(void **slots, unsigned char offset) ++{ ++ return (ulong)slots[offset]; ++} ++ ++static inline bool ma_is_leaf(const enum maple_type type) ++{ ++ return type < maple_range_64; ++} ++ ++/*************** For cmd_tree ********************/ ++ ++struct maple_tree_ops { ++ void (*entry)(ulong node, ulong slot, const char *path, ++ ulong index, void *private); ++ void *private; ++ bool is_td; ++}; ++ ++static const char spaces[] = " "; ++ ++static void do_mt_range64(ulong, ulong, ulong, uint, char *, ulong *, ++ struct maple_tree_ops *); ++static void do_mt_arange64(ulong, ulong, ulong, uint, char *, ulong *, ++ struct maple_tree_ops *); ++static void do_mt_entry(ulong, ulong, ulong, uint, uint, char *, ulong *, ++ struct maple_tree_ops *); ++static void do_mt_node(ulong, ulong, ulong, uint, char *, ulong *, ++ struct maple_tree_ops *); ++struct req_entry *fill_member_offsets(char *); ++void dump_struct_members_fast(struct req_entry *, int, ulong); ++void dump_struct_members_for_tree(struct tree_data *, int, ulong); ++ ++static void mt_dump_range(ulong min, ulong max, uint depth) ++{ ++ if (min == max) ++ fprintf(fp, "%.*s%lu: ", depth * 2, spaces, min); ++ else ++ fprintf(fp, "%.*s%lu-%lu: ", depth * 2, spaces, min, max); ++} ++ ++static inline bool mt_is_reserved(ulong entry) ++{ ++ return (entry < MAPLE_RESERVED_RANGE) && xa_is_internal(entry); ++} ++ ++static inline bool mte_is_leaf(ulong maple_enode_entry) ++{ ++ return ma_is_leaf(mte_node_type(maple_enode_entry)); ++} ++ ++static uint mt_height(char *mt_buf) ++{ ++ return (UINT(mt_buf + OFFSET(maple_tree_ma_flags)) & ++ MT_FLAGS_HEIGHT_MASK) ++ >> MT_FLAGS_HEIGHT_OFFSET; ++} ++ ++static void dump_mt_range64(char *mr64_buf) ++{ ++ int i; ++ ++ fprintf(fp, " contents: "); ++ for (i = 0; i < mt_slots[maple_range_64] - 1; i++) ++ fprintf(fp, "%p %lu ", ++ VOID_PTR(mr64_buf + OFFSET(maple_range_64_slot) ++ + sizeof(void *) * i), ++ ULONG(mr64_buf + OFFSET(maple_range_64_pivot) ++ + sizeof(ulong) * i)); ++ fprintf(fp, "%p\n", VOID_PTR(mr64_buf + OFFSET(maple_range_64_slot) ++ + sizeof(void *) * i)); ++} ++ ++static void dump_mt_arange64(char *ma64_buf) ++{ ++ int i; ++ ++ fprintf(fp, " contents: "); ++ for (i = 0; i < mt_slots[maple_arange_64]; i++) ++ fprintf(fp, "%lu ", ULONG(ma64_buf + OFFSET(maple_arange_64_gap) ++ + sizeof(ulong) * i)); ++ ++ fprintf(fp, "| %02X %02X| ", ++ UCHAR(ma64_buf + OFFSET(maple_arange_64_meta) + ++ OFFSET(maple_metadata_end)), ++ UCHAR(ma64_buf + OFFSET(maple_arange_64_meta) + ++ OFFSET(maple_metadata_gap))); ++ ++ for (i = 0; i < mt_slots[maple_arange_64] - 1; i++) ++ fprintf(fp, "%p %lu ", ++ VOID_PTR(ma64_buf + OFFSET(maple_arange_64_slot) + ++ sizeof(void *) * i), ++ ULONG(ma64_buf + OFFSET(maple_arange_64_pivot) + ++ sizeof(ulong) * i)); ++ fprintf(fp, "%p\n", VOID_PTR(ma64_buf + OFFSET(maple_arange_64_slot) + ++ sizeof(void *) * i)); ++} ++ ++static void dump_mt_entry(ulong entry, ulong min, ulong max, uint depth) ++{ ++ mt_dump_range(min, max, depth); ++ ++ if (xa_is_value(entry)) ++ fprintf(fp, "value %ld (0x%lx) [0x%lx]\n", xa_to_value(entry), ++ xa_to_value(entry), entry); ++ else if (xa_is_zero(entry)) ++ fprintf(fp, "zero (%ld)\n", xa_to_internal(entry)); ++ else if (mt_is_reserved(entry)) ++ fprintf(fp, "UNKNOWN ENTRY (0x%lx)\n", entry); ++ else ++ fprintf(fp, "0x%lx\n", entry); ++} ++ ++static void dump_mt_node(ulong maple_node, char *node_data, uint type, ++ ulong min, ulong max, uint depth) ++{ ++ mt_dump_range(min, max, depth); ++ ++ fprintf(fp, "node 0x%lx depth %d type %d parent %p", ++ maple_node, depth, type, ++ maple_node ? VOID_PTR(node_data + OFFSET(maple_node_parent)) : ++ NULL); ++} ++ ++static void do_mt_range64(ulong entry, ulong min, ulong max, ++ uint depth, char *path, ulong *global_index, ++ struct maple_tree_ops *ops) ++{ ++ ulong maple_node_m_node = mte_to_node(entry); ++ char node_buf[MAPLE_BUFSIZE]; ++ bool leaf = mte_is_leaf(entry); ++ ulong first = min, last; ++ int i; ++ int len = strlen(path); ++ struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; ++ char *mr64_buf; ++ ++ if (SIZE(maple_node) > MAPLE_BUFSIZE) ++ error(FATAL, "MAPLE_BUFSIZE should be larger than maple_node struct"); ++ ++ readmem(maple_node_m_node, KVADDR, node_buf, SIZE(maple_node), ++ "mt_dump_range64 read maple_node", FAULT_ON_ERROR); ++ ++ mr64_buf = node_buf + OFFSET(maple_node_mr64); ++ ++ for (i = 0; i < mt_slots[maple_range_64]; i++) { ++ last = max; ++ ++ if (i < (mt_slots[maple_range_64] - 1)) ++ last = ULONG(mr64_buf + OFFSET(maple_range_64_pivot) + ++ sizeof(ulong) * i); ++ ++ else if (!VOID_PTR(mr64_buf + OFFSET(maple_range_64_slot) + ++ sizeof(void *) * i) && ++ max != mt_max[mte_node_type(entry)]) ++ break; ++ if (last == 0 && i > 0) ++ break; ++ if (leaf) ++ do_mt_entry(mt_slot((void **)(mr64_buf + ++ OFFSET(maple_range_64_slot)), i), ++ first, last, depth + 1, i, path, global_index, ops); ++ else if (VOID_PTR(mr64_buf + OFFSET(maple_range_64_slot) + ++ sizeof(void *) * i)) { ++ sprintf(path + len, "/%d", i); ++ do_mt_node(mt_slot((void **)(mr64_buf + ++ OFFSET(maple_range_64_slot)), i), ++ first, last, depth + 1, path, global_index, ops); ++ } ++ ++ if (last == max) ++ break; ++ if (last > max) { ++ fprintf(fp, "node %p last (%lu) > max (%lu) at pivot %d!\n", ++ mr64_buf, last, max, i); ++ break; ++ } ++ first = last + 1; ++ } ++} ++ ++static void do_mt_arange64(ulong entry, ulong min, ulong max, ++ uint depth, char *path, ulong *global_index, ++ struct maple_tree_ops *ops) ++{ ++ ulong maple_node_m_node = mte_to_node(entry); ++ char node_buf[MAPLE_BUFSIZE]; ++ bool leaf = mte_is_leaf(entry); ++ ulong first = min, last; ++ int i; ++ int len = strlen(path); ++ struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; ++ char *ma64_buf; ++ ++ if (SIZE(maple_node) > MAPLE_BUFSIZE) ++ error(FATAL, "MAPLE_BUFSIZE should be larger than maple_node struct"); ++ ++ readmem(maple_node_m_node, KVADDR, node_buf, SIZE(maple_node), ++ "mt_dump_arange64 read maple_node", FAULT_ON_ERROR); ++ ++ ma64_buf = node_buf + OFFSET(maple_node_ma64); ++ ++ for (i = 0; i < mt_slots[maple_arange_64]; i++) { ++ last = max; ++ ++ if (i < (mt_slots[maple_arange_64] - 1)) ++ last = ULONG(ma64_buf + OFFSET(maple_arange_64_pivot) + ++ sizeof(ulong) * i); ++ else if (!VOID_PTR(ma64_buf + OFFSET(maple_arange_64_slot) + ++ sizeof(void *) * i)) ++ break; ++ if (last == 0 && i > 0) ++ break; ++ ++ if (leaf) ++ do_mt_entry(mt_slot((void **)(ma64_buf + ++ OFFSET(maple_arange_64_slot)), i), ++ first, last, depth + 1, i, path, global_index, ops); ++ else if (VOID_PTR(ma64_buf + OFFSET(maple_arange_64_slot) + ++ sizeof(void *) * i)) { ++ sprintf(path + len, "/%d", i); ++ do_mt_node(mt_slot((void **)(ma64_buf + ++ OFFSET(maple_arange_64_slot)), i), ++ first, last, depth + 1, path, global_index, ops); ++ } ++ ++ if (last == max) ++ break; ++ if (last > max) { ++ fprintf(fp, "node %p last (%lu) > max (%lu) at pivot %d!\n", ++ ma64_buf, last, max, i); ++ break; ++ } ++ first = last + 1; ++ } ++} ++ ++static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth, ++ uint index, char *path, ulong *global_index, ++ struct maple_tree_ops *ops) ++{ ++ int print_radix = 0, i; ++ static struct req_entry **e = NULL; ++ struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; ++ ++ if (!td) ++ return; ++} ++ ++static void do_mt_node(ulong entry, ulong min, ulong max, ++ uint depth, char *path, ulong *global_index, ++ struct maple_tree_ops *ops) ++{ ++ ulong maple_node = mte_to_node(entry); ++ uint type = mte_node_type(entry); ++ uint i; ++ char node_buf[MAPLE_BUFSIZE]; ++ struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; ++ ++ if (SIZE(maple_node) > MAPLE_BUFSIZE) ++ error(FATAL, "MAPLE_BUFSIZE should be larger than maple_node struct"); ++ ++ readmem(maple_node, KVADDR, node_buf, SIZE(maple_node), ++ "mt_dump_node read maple_node", FAULT_ON_ERROR); ++ ++ switch (type) { ++ case maple_dense: ++ for (i = 0; i < mt_slots[maple_dense]; i++) { ++ if (min + i > max) ++ fprintf(fp, "OUT OF RANGE: "); ++ do_mt_entry(mt_slot((void **)(node_buf + OFFSET(maple_node_slot)), i), ++ min + i, min + i, depth, i, path, global_index, ops); ++ } ++ break; ++ case maple_leaf_64: ++ case maple_range_64: ++ do_mt_range64(entry, min, max, depth, path, global_index, ops); ++ break; ++ case maple_arange_64: ++ do_mt_arange64(entry, min, max, depth, path, global_index, ops); ++ break; ++ default: ++ fprintf(fp, " UNKNOWN TYPE\n"); ++ } ++} ++ ++static int do_maple_tree_traverse(ulong ptr, int is_root, ++ struct maple_tree_ops *ops) ++{ ++ char path[BUFSIZE] = {0}; ++ char tree_buf[MAPLE_BUFSIZE]; ++ ulong entry; ++ struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; ++ ulong global_index = 0; ++ ++ if (SIZE(maple_tree) > MAPLE_BUFSIZE) ++ error(FATAL, "MAPLE_BUFSIZE should be larger than maple_tree struct"); ++ ++ if (!is_root) { ++ strcpy(path, "direct"); ++ do_mt_node(ptr, 0, mt_max[mte_node_type(ptr)], ++ 0, path, &global_index, ops); ++ } else { ++ readmem(ptr, KVADDR, tree_buf, SIZE(maple_tree), ++ "mt_dump read maple_tree", FAULT_ON_ERROR); ++ entry = ULONG(tree_buf + OFFSET(maple_tree_ma_root)); ++ ++ if (!xa_is_node(entry)) ++ do_mt_entry(entry, 0, 0, 0, 0, path, &global_index, ops); ++ else if (entry) { ++ strcpy(path, "root"); ++ do_mt_node(entry, 0, mt_max[mte_node_type(entry)], 0, ++ path, &global_index, ops); ++ } ++ } ++ return 0; ++} ++ ++int do_mptree(struct tree_data *td) ++{ ++ struct maple_tree_ops ops = { ++ .entry = NULL, ++ .private = td, ++ .is_td = true, ++ }; ++ ++ int is_root = !(td->flags & TREE_NODE_POINTER); ++ ++ do_maple_tree_traverse(td->start, is_root, &ops); ++ ++ return 0; ++} ++ ++/***********************************************/ ++void maple_init(void) ++{ ++ int array_len; ++ ++ STRUCT_SIZE_INIT(maple_tree, "maple_tree"); ++ STRUCT_SIZE_INIT(maple_node, "maple_node"); ++ ++ MEMBER_OFFSET_INIT(maple_tree_ma_root, "maple_tree", "ma_root"); ++ MEMBER_OFFSET_INIT(maple_tree_ma_flags, "maple_tree", "ma_flags"); ++ ++ MEMBER_OFFSET_INIT(maple_node_parent, "maple_node", "parent"); ++ MEMBER_OFFSET_INIT(maple_node_ma64, "maple_node", "ma64"); ++ MEMBER_OFFSET_INIT(maple_node_mr64, "maple_node", "mr64"); ++ MEMBER_OFFSET_INIT(maple_node_slot, "maple_node", "slot"); ++ ++ MEMBER_OFFSET_INIT(maple_arange_64_pivot, "maple_arange_64", "pivot"); ++ MEMBER_OFFSET_INIT(maple_arange_64_slot, "maple_arange_64", "slot"); ++ MEMBER_OFFSET_INIT(maple_arange_64_gap, "maple_arange_64", "gap"); ++ MEMBER_OFFSET_INIT(maple_arange_64_meta, "maple_arange_64", "meta"); ++ ++ MEMBER_OFFSET_INIT(maple_range_64_pivot, "maple_range_64", "pivot"); ++ MEMBER_OFFSET_INIT(maple_range_64_slot, "maple_range_64", "slot"); ++ ++ MEMBER_OFFSET_INIT(maple_metadata_end, "maple_metadata", "end"); ++ MEMBER_OFFSET_INIT(maple_metadata_gap, "maple_metadata", "gap"); ++ ++ array_len = get_array_length("mt_slots", NULL, sizeof(char)); ++ mt_slots = calloc(array_len, sizeof(char)); ++ readmem(symbol_value("mt_slots"), KVADDR, mt_slots, ++ array_len * sizeof(char), "maple_init read mt_slots", ++ RETURN_ON_ERROR); ++ ++ array_len = get_array_length("mt_pivots", NULL, sizeof(char)); ++ mt_pivots = calloc(array_len, sizeof(char)); ++ readmem(symbol_value("mt_pivots"), KVADDR, mt_pivots, ++ array_len * sizeof(char), "maple_init read mt_pivots", ++ RETURN_ON_ERROR); ++ ++ mt_max[maple_dense] = mt_slots[maple_dense]; ++ mt_max[maple_leaf_64] = ULONG_MAX; ++ mt_max[maple_range_64] = ULONG_MAX; ++ mt_max[maple_arange_64] = ULONG_MAX; ++} +diff --git a/maple_tree.h b/maple_tree.h +new file mode 100644 +index 000000000000..f53d5aaffd2e +--- /dev/null ++++ b/maple_tree.h +@@ -0,0 +1,82 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++#ifndef _MAPLE_TREE_H ++#define _MAPLE_TREE_H ++/* ++ * Maple Tree - An RCU-safe adaptive tree for storing ranges ++ * Copyright (c) 2018-2022 Oracle ++ * Authors: Liam R. Howlett ++ * Matthew Wilcox ++ * ++ * eXtensible Arrays ++ * Copyright (c) 2017 Microsoft Corporation ++ * Author: Matthew Wilcox ++ * ++ * See Documentation/core-api/xarray.rst for how to use the XArray. ++ */ ++#include ++#include ++#include ++ ++/* ++ * The following are copied and modified from include/linux/maple_tree.h ++ */ ++ ++enum maple_type { ++ maple_dense, ++ maple_leaf_64, ++ maple_range_64, ++ maple_arange_64, ++}; ++ ++#define MAPLE_NODE_MASK 255UL ++ ++#define MT_FLAGS_HEIGHT_OFFSET 0x02 ++#define MT_FLAGS_HEIGHT_MASK 0x7C ++ ++#define MAPLE_NODE_TYPE_MASK 0x0F ++#define MAPLE_NODE_TYPE_SHIFT 0x03 ++ ++#define MAPLE_RESERVED_RANGE 4096 ++ ++/* ++ * The following are copied and modified from include/linux/xarray.h ++ */ ++ ++#define XA_ZERO_ENTRY xa_mk_internal(257) ++ ++static inline ulong xa_mk_internal(ulong v) ++{ ++ return (v << 2) | 2; ++} ++ ++static inline bool xa_is_internal(ulong entry) ++{ ++ return (entry & 3) == 2; ++} ++ ++static inline bool xa_is_node(ulong entry) ++{ ++ return xa_is_internal(entry) && entry > 4096; ++} ++ ++static inline bool xa_is_value(ulong entry) ++{ ++ return entry & 1; ++} ++ ++static inline bool xa_is_zero(ulong entry) ++{ ++ return entry == XA_ZERO_ENTRY; ++} ++ ++static inline unsigned long xa_to_internal(ulong entry) ++{ ++ return entry >> 2; ++} ++ ++static inline unsigned long xa_to_value(ulong entry) ++{ ++ return entry >> 1; ++} ++ ++#endif /* _MAPLE_TREE_H */ +-- +2.37.1 + diff --git a/SOURCES/0066-Add-maple-tree-support-to-tree-command.patch b/SOURCES/0066-Add-maple-tree-support-to-tree-command.patch new file mode 100644 index 0000000..d4bafea --- /dev/null +++ b/SOURCES/0066-Add-maple-tree-support-to-tree-command.patch @@ -0,0 +1,335 @@ +From 4a6aba5dc85a2f491f752fb37dd2838c1141375d Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Tue, 10 Jan 2023 14:56:28 +0800 +Subject: [PATCH 66/89] Add maple tree support to "tree" command + +The maple tree is a new data structure for crash, so "tree" command +needs to support it for users to dump and view the content of maple +trees. This patch achieves this by using ported mt_dump() and its +related functions from kernel and adapting them with "tree" command. + +Also introduce a new -v arg specifically for dumping the complete +content of a maple tree: + + crash> tree -t maple 0xffff9034c006aec0 -v + + maple_tree(ffff9034c006aec0) flags 309, height 2 root 0xffff9034de70041e + + 0-18446744073709551615: node 0xffff9034de700400 depth 0 type 3 parent 0xffff9034c006aec1 contents:... + 0-140112331583487: node 0xffff9034c01e8800 depth 1 type 1 parent 0xffff9034de700406 contents:... + 0-94643156942847: (nil) + 94643156942848-94643158024191: 0xffff9035131754c0 + 94643158024192-94643160117247: (nil) + ... + +The existing options of "tree" command can work as well: + + crash> tree -t maple -r mm_struct.mm_mt 0xffff9034c006aec0 -p + ffff9035131754c0 + index: 1 position: root/0/1 + ffff9035131751c8 + index: 2 position: root/0/3 + ffff9035131757b8 + index: 3 position: root/0/4 + ... + + crash> tree -t maple 0xffff9034c006aec0 -p -x -s vm_area_struct.vm_start,vm_end + ffff9035131754c0 + index: 1 position: root/0/1 + vm_start = 0x5613d3c00000, + vm_end = 0x5613d3d08000, + ffff9035131751c8 + index: 2 position: root/0/3 + vm_start = 0x5613d3f07000, + vm_end = 0x5613d3f0b000, + ffff9035131757b8 + index: 3 position: root/0/4 + vm_start = 0x5613d3f0b000, + vm_end = 0x5613d3f14000, + .... + +Signed-off-by: Tao Liu +Signed-off-by: Lianbo Jiang +--- + defs.h | 1 + + maple_tree.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ + tools.c | 67 +++++++++++++++++++++++++++++++++++++++------------- + 3 files changed, 114 insertions(+), 17 deletions(-) + +diff --git a/defs.h b/defs.h +index 46ed10e17cd2..cc9af21a6b64 100644 +--- a/defs.h ++++ b/defs.h +@@ -2713,6 +2713,7 @@ struct tree_data { + #define TREE_PARSE_MEMBER (VERBOSE << 7) + #define TREE_READ_MEMBER (VERBOSE << 8) + #define TREE_LINEAR_ORDER (VERBOSE << 9) ++#define TREE_STRUCT_VERBOSE (VERBOSE << 10) + + #define ALIAS_RUNTIME (1) + #define ALIAS_RCLOCAL (2) +diff --git a/maple_tree.c b/maple_tree.c +index 474faeda6252..471136f3eb1d 100644 +--- a/maple_tree.c ++++ b/maple_tree.c +@@ -173,6 +173,10 @@ static void do_mt_range64(ulong entry, ulong min, ulong max, + + mr64_buf = node_buf + OFFSET(maple_node_mr64); + ++ if (td && td->flags & TREE_STRUCT_VERBOSE) { ++ dump_mt_range64(mr64_buf); ++ } ++ + for (i = 0; i < mt_slots[maple_range_64]; i++) { + last = max; + +@@ -230,6 +234,10 @@ static void do_mt_arange64(ulong entry, ulong min, ulong max, + + ma64_buf = node_buf + OFFSET(maple_node_ma64); + ++ if (td && td->flags & TREE_STRUCT_VERBOSE) { ++ dump_mt_arange64(ma64_buf); ++ } ++ + for (i = 0; i < mt_slots[maple_arange_64]; i++) { + last = max; + +@@ -275,6 +283,51 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth, + + if (!td) + return; ++ ++ if (!td->count && td->structname_args) { ++ /* ++ * Retrieve all members' info only once (count == 0) ++ * After last iteration all memory will be freed up ++ */ ++ e = (struct req_entry **)GETBUF(sizeof(*e) * td->structname_args); ++ for (i = 0; i < td->structname_args; i++) ++ e[i] = fill_member_offsets(td->structname[i]); ++ } ++ ++ td->count++; ++ ++ if (td->flags & TREE_STRUCT_VERBOSE) { ++ dump_mt_entry(entry, min, max, depth); ++ } else if (td->flags & VERBOSE && entry) ++ fprintf(fp, "%lx\n", entry); ++ if (td->flags & TREE_POSITION_DISPLAY && entry) ++ fprintf(fp, " index: %ld position: %s/%u\n", ++ ++(*global_index), path, index); ++ ++ if (td->structname) { ++ if (td->flags & TREE_STRUCT_RADIX_10) ++ print_radix = 10; ++ else if (td->flags & TREE_STRUCT_RADIX_16) ++ print_radix = 16; ++ else ++ print_radix = 0; ++ ++ for (i = 0; i < td->structname_args; i++) { ++ switch (count_chars(td->structname[i], '.')) { ++ case 0: ++ dump_struct(td->structname[i], entry, print_radix); ++ break; ++ default: ++ if (td->flags & TREE_PARSE_MEMBER) ++ dump_struct_members_for_tree(td, i, entry); ++ else if (td->flags & TREE_READ_MEMBER) ++ dump_struct_members_fast(e[i], print_radix, entry); ++ } ++ } ++ } ++ ++ if (e) ++ FREEBUF(e); + } + + static void do_mt_node(ulong entry, ulong min, ulong max, +@@ -293,6 +346,10 @@ static void do_mt_node(ulong entry, ulong min, ulong max, + readmem(maple_node, KVADDR, node_buf, SIZE(maple_node), + "mt_dump_node read maple_node", FAULT_ON_ERROR); + ++ if (td && td->flags & TREE_STRUCT_VERBOSE) { ++ dump_mt_node(maple_node, node_buf, type, min, max, depth); ++ } ++ + switch (type) { + case maple_dense: + for (i = 0; i < mt_slots[maple_dense]; i++) { +@@ -335,6 +392,12 @@ static int do_maple_tree_traverse(ulong ptr, int is_root, + "mt_dump read maple_tree", FAULT_ON_ERROR); + entry = ULONG(tree_buf + OFFSET(maple_tree_ma_root)); + ++ if (td && td->flags & TREE_STRUCT_VERBOSE) { ++ fprintf(fp, "maple_tree(%lx) flags %X, height %u root 0x%lx\n\n", ++ ptr, UINT(tree_buf + OFFSET(maple_tree_ma_flags)), ++ mt_height(tree_buf), entry); ++ } ++ + if (!xa_is_node(entry)) + do_mt_entry(entry, 0, 0, 0, 0, path, &global_index, ops); + else if (entry) { +diff --git a/tools.c b/tools.c +index 7f64bd6328cf..cc5c3448b93e 100644 +--- a/tools.c ++++ b/tools.c +@@ -30,7 +30,7 @@ static void dealloc_hq_entry(struct hq_entry *); + static void show_options(void); + static void dump_struct_members(struct list_data *, int, ulong); + static void rbtree_iteration(ulong, struct tree_data *, char *); +-static void dump_struct_members_for_tree(struct tree_data *, int, ulong); ++void dump_struct_members_for_tree(struct tree_data *, int, ulong); + + struct req_entry { + char *arg, *name, **member; +@@ -40,8 +40,8 @@ struct req_entry { + }; + + static void print_value(struct req_entry *, unsigned int, ulong, unsigned int); +-static struct req_entry *fill_member_offsets(char *); +-static void dump_struct_members_fast(struct req_entry *, int, ulong); ++struct req_entry *fill_member_offsets(char *); ++void dump_struct_members_fast(struct req_entry *, int, ulong); + + FILE * + set_error(char *target) +@@ -3666,7 +3666,7 @@ dump_struct_members_fast(struct req_entry *e, int radix, ulong p) + } + } + +-static struct req_entry * ++struct req_entry * + fill_member_offsets(char *arg) + { + int j; +@@ -4307,6 +4307,7 @@ dump_struct_members(struct list_data *ld, int idx, ulong next) + #define RADIXTREE_REQUEST (0x1) + #define RBTREE_REQUEST (0x2) + #define XARRAY_REQUEST (0x4) ++#define MAPLE_REQUEST (0x8) + + void + cmd_tree() +@@ -4317,6 +4318,7 @@ cmd_tree() + struct datatype_member struct_member, *sm; + struct syment *sp; + ulong value; ++ char *type_name = NULL; + + type_flag = 0; + root_offset = 0; +@@ -4324,25 +4326,33 @@ cmd_tree() + td = &tree_data; + BZERO(td, sizeof(struct tree_data)); + +- while ((c = getopt(argcnt, args, "xdt:r:o:s:S:plN")) != EOF) { ++ while ((c = getopt(argcnt, args, "xdt:r:o:s:S:plNv")) != EOF) { + switch (c) + { + case 't': +- if (type_flag & (RADIXTREE_REQUEST|RBTREE_REQUEST|XARRAY_REQUEST)) { ++ if (type_flag & (RADIXTREE_REQUEST|RBTREE_REQUEST|XARRAY_REQUEST|MAPLE_REQUEST)) { + error(INFO, "multiple tree types may not be entered\n"); + cmd_usage(pc->curcmd, SYNOPSIS); + } + + if (STRNEQ(optarg, "ra")) +- if (MEMBER_EXISTS("radix_tree_root", "xa_head")) ++ if (MEMBER_EXISTS("radix_tree_root", "xa_head")) { + type_flag = XARRAY_REQUEST; +- else ++ type_name = "Xarrays"; ++ } else { + type_flag = RADIXTREE_REQUEST; +- else if (STRNEQ(optarg, "rb")) ++ type_name = "radix trees"; ++ } ++ else if (STRNEQ(optarg, "rb")) { + type_flag = RBTREE_REQUEST; +- else if (STRNEQ(optarg, "x")) ++ type_name = "rbtrees"; ++ } else if (STRNEQ(optarg, "x")) { + type_flag = XARRAY_REQUEST; +- else { ++ type_name = "Xarrays"; ++ } else if (STRNEQ(optarg, "m")) { ++ type_flag = MAPLE_REQUEST; ++ type_name = "maple trees"; ++ } else { + error(INFO, "invalid tree type: %s\n", optarg); + cmd_usage(pc->curcmd, SYNOPSIS); + } +@@ -4417,6 +4427,9 @@ cmd_tree() + "-d and -x are mutually exclusive\n"); + td->flags |= TREE_STRUCT_RADIX_10; + break; ++ case 'v': ++ td->flags |= TREE_STRUCT_VERBOSE; ++ break; + default: + argerrs++; + break; +@@ -4426,13 +4439,17 @@ cmd_tree() + if (argerrs) + cmd_usage(pc->curcmd, SYNOPSIS); + +- if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST)) && (td->flags & TREE_LINEAR_ORDER)) +- error(FATAL, "-l option is not applicable to %s\n", +- type_flag & RADIXTREE_REQUEST ? "radix trees" : "Xarrays"); ++ if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST|MAPLE_REQUEST)) && ++ (td->flags & TREE_LINEAR_ORDER)) ++ error(FATAL, "-l option is not applicable to %s\n", type_name); + +- if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST)) && (td->flags & TREE_NODE_OFFSET_ENTERED)) +- error(FATAL, "-o option is not applicable to %s\n", +- type_flag & RADIXTREE_REQUEST ? "radix trees" : "Xarrays"); ++ if ((type_flag & (XARRAY_REQUEST|RADIXTREE_REQUEST|MAPLE_REQUEST)) && ++ (td->flags & TREE_NODE_OFFSET_ENTERED)) ++ error(FATAL, "-o option is not applicable to %s\n", type_name); ++ ++ if ((type_flag & (RBTREE_REQUEST|XARRAY_REQUEST|RADIXTREE_REQUEST)) && ++ (td->flags & TREE_STRUCT_VERBOSE)) ++ error(FATAL, "-v option is not applicable to %s\n", type_name); + + if ((td->flags & TREE_ROOT_OFFSET_ENTERED) && + (td->flags & TREE_NODE_POINTER)) +@@ -4506,12 +4523,26 @@ next_arg: + if (td->flags & TREE_STRUCT_RADIX_16) + fprintf(fp, "%sTREE_STRUCT_RADIX_16", + others++ ? "|" : ""); ++ if (td->flags & TREE_PARSE_MEMBER) ++ fprintf(fp, "%sTREE_PARSE_MEMBER", ++ others++ ? "|" : ""); ++ if (td->flags & TREE_READ_MEMBER) ++ fprintf(fp, "%sTREE_READ_MEMBER", ++ others++ ? "|" : ""); ++ if (td->flags & TREE_LINEAR_ORDER) ++ fprintf(fp, "%sTREE_LINEAR_ORDER", ++ others++ ? "|" : ""); ++ if (td->flags & TREE_STRUCT_VERBOSE) ++ fprintf(fp, "%sTREE_STRUCT_VERBOSE", ++ others++ ? "|" : ""); + fprintf(fp, ")\n"); + fprintf(fp, " type: "); + if (type_flag & RADIXTREE_REQUEST) + fprintf(fp, "radix\n"); + else if (type_flag & XARRAY_REQUEST) + fprintf(fp, "xarray\n"); ++ else if (type_flag & MAPLE_REQUEST) ++ fprintf(fp, "maple\n"); + else + fprintf(fp, "red-black%s", + type_flag & RBTREE_REQUEST ? +@@ -4532,6 +4563,8 @@ next_arg: + do_rdtree(td); + else if (type_flag & XARRAY_REQUEST) + do_xatree(td); ++ else if (type_flag & MAPLE_REQUEST) ++ do_mptree(td); + else + do_rbtree(td); + hq_close(); +-- +2.37.1 + diff --git a/SOURCES/0067-Add-do_maple_tree-for-maple-tree-operations.patch b/SOURCES/0067-Add-do_maple_tree-for-maple-tree-operations.patch new file mode 100644 index 0000000..ab5c346 --- /dev/null +++ b/SOURCES/0067-Add-do_maple_tree-for-maple-tree-operations.patch @@ -0,0 +1,205 @@ +From 7955002f1292f0c0d02076440b441ab7ebaf650d Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Tue, 10 Jan 2023 14:56:29 +0800 +Subject: [PATCH 67/89] Add do_maple_tree() for maple tree operations + +do_maple_tree() is similar to do_radix_tree() and do_xarray(), which +takes the same do_maple_tree_traverse entry as tree command. + +Signed-off-by: Tao Liu +Signed-off-by: Lianbo Jiang +--- + defs.h | 6 +++ + maple_tree.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 151 insertions(+) + +diff --git a/defs.h b/defs.h +index cc9af21a6b64..b2389cd82fae 100644 +--- a/defs.h ++++ b/defs.h +@@ -5750,6 +5750,12 @@ int cleanup_memory_driver(void); + + void maple_init(void); + int do_mptree(struct tree_data *); ++ulong do_maple_tree(ulong, int, struct list_pair *); ++#define MAPLE_TREE_COUNT (1) ++#define MAPLE_TREE_SEARCH (2) ++#define MAPLE_TREE_DUMP (3) ++#define MAPLE_TREE_GATHER (4) ++#define MAPLE_TREE_DUMP_CB (5) + + /* + * help.c +diff --git a/maple_tree.c b/maple_tree.c +index 471136f3eb1d..807c17f7dfa0 100644 +--- a/maple_tree.c ++++ b/maple_tree.c +@@ -40,6 +40,12 @@ static inline bool ma_is_leaf(const enum maple_type type) + + /*************** For cmd_tree ********************/ + ++struct do_maple_tree_info { ++ ulong maxcount; ++ ulong count; ++ void *data; ++}; ++ + struct maple_tree_ops { + void (*entry)(ulong node, ulong slot, const char *path, + ulong index, void *private); +@@ -281,6 +287,9 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth, + static struct req_entry **e = NULL; + struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL; + ++ if (ops->entry) ++ ops->entry(entry, entry, path, max, ops->private); ++ + if (!td) + return; + +@@ -424,6 +433,142 @@ int do_mptree(struct tree_data *td) + return 0; + } + ++/************* For do_maple_tree *****************/ ++static void do_maple_tree_count(ulong node, ulong slot, const char *path, ++ ulong index, void *private) ++{ ++ struct do_maple_tree_info *info = private; ++ info->count++; ++} ++ ++static void do_maple_tree_search(ulong node, ulong slot, const char *path, ++ ulong index, void *private) ++{ ++ struct do_maple_tree_info *info = private; ++ struct list_pair *lp = info->data; ++ ++ if (lp->index == index) { ++ lp->value = (void *)slot; ++ info->count = 1; ++ } ++} ++ ++static void do_maple_tree_dump(ulong node, ulong slot, const char *path, ++ ulong index, void *private) ++{ ++ struct do_maple_tree_info *info = private; ++ fprintf(fp, "[%lu] %lx\n", index, slot); ++ info->count++; ++} ++ ++static void do_maple_tree_gather(ulong node, ulong slot, const char *path, ++ ulong index, void *private) ++{ ++ struct do_maple_tree_info *info = private; ++ struct list_pair *lp = info->data; ++ ++ if (info->maxcount) { ++ lp[info->count].index = index; ++ lp[info->count].value = (void *)slot; ++ ++ info->count++; ++ info->maxcount--; ++ } ++} ++ ++static void do_maple_tree_dump_cb(ulong node, ulong slot, const char *path, ++ ulong index, void *private) ++{ ++ struct do_maple_tree_info *info = private; ++ struct list_pair *lp = info->data; ++ int (*cb)(ulong) = lp->value; ++ ++ /* Caller defined operation */ ++ if (!cb(slot)) { ++ error(FATAL, "do_maple_tree: callback " ++ "operation failed: entry: %ld item: %lx\n", ++ info->count, slot); ++ } ++ info->count++; ++} ++ ++/* ++ * do_maple_tree argument usage: ++ * ++ * root: Address of a maple_tree_root structure ++ * ++ * flag: MAPLE_TREE_COUNT - Return the number of entries in the tree. ++ * MAPLE_TREE_SEARCH - Search for an entry at lp->index; if found, ++ * store the entry in lp->value and return a count of 1; otherwise ++ * return a count of 0. ++ * MAPLE_TREE_DUMP - Dump all existing index/value pairs. ++ * MAPLE_TREE_GATHER - Store all existing index/value pairs in the ++ * passed-in array of list_pair structs starting at lp, ++ * returning the count of entries stored; the caller can/should ++ * limit the number of returned entries by putting the array size ++ * (max count) in the lp->index field of the first structure ++ * in the passed-in array. ++ * MAPLE_TREE_DUMP_CB - Similar with MAPLE_TREE_DUMP, but for each ++ * maple tree entry, a user defined callback at lp->value will ++ * be invoked. ++ * ++ * lp: Unused by MAPLE_TREE_COUNT and MAPLE_TREE_DUMP. ++ * A pointer to a list_pair structure for MAPLE_TREE_SEARCH. ++ * A pointer to an array of list_pair structures for ++ * MAPLE_TREE_GATHER; the dimension (max count) of the array may ++ * be stored in the index field of the first structure to avoid ++ * any chance of an overrun. ++ * For MAPLE_TREE_DUMP_CB, the lp->value must be initialized as a ++ * callback function. The callback prototype must be: int (*)(ulong); ++ */ ++ulong ++do_maple_tree(ulong root, int flag, struct list_pair *lp) ++{ ++ struct do_maple_tree_info info = { ++ .count = 0, ++ .data = lp, ++ }; ++ struct maple_tree_ops ops = { ++ .private = &info, ++ .is_td = false, ++ }; ++ ++ switch (flag) ++ { ++ case MAPLE_TREE_COUNT: ++ ops.entry = do_maple_tree_count; ++ break; ++ ++ case MAPLE_TREE_SEARCH: ++ ops.entry = do_maple_tree_search; ++ break; ++ ++ case MAPLE_TREE_DUMP: ++ ops.entry = do_maple_tree_dump; ++ break; ++ ++ case MAPLE_TREE_GATHER: ++ if (!(info.maxcount = lp->index)) ++ info.maxcount = (ulong)(-1); /* caller beware */ ++ ++ ops.entry = do_maple_tree_gather; ++ break; ++ ++ case MAPLE_TREE_DUMP_CB: ++ if (lp->value == NULL) { ++ error(FATAL, "do_maple_tree: need set callback function"); ++ } ++ ops.entry = do_maple_tree_dump_cb; ++ break; ++ ++ default: ++ error(FATAL, "do_maple_tree: invalid flag: %lx\n", flag); ++ } ++ ++ do_maple_tree_traverse(root, true, &ops); ++ return info.count; ++} ++ + /***********************************************/ + void maple_init(void) + { +-- +2.37.1 + diff --git a/SOURCES/0068-Introduce-maple-tree-vma-iteration-to-vm_area_dump.patch b/SOURCES/0068-Introduce-maple-tree-vma-iteration-to-vm_area_dump.patch new file mode 100644 index 0000000..a5efc12 --- /dev/null +++ b/SOURCES/0068-Introduce-maple-tree-vma-iteration-to-vm_area_dump.patch @@ -0,0 +1,455 @@ +From 77e9fc571e2782b0eafe1d376cfd7f30fb08fecf Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Tue, 10 Jan 2023 14:56:30 +0800 +Subject: [PATCH 68/89] Introduce maple tree vma iteration to vm_area_dump() + +Since memory.c:vm_area_dump() will iterate all vma, this patch mainly +introduces maple tree vma iteration to it. + +We extract the code which handles each vma into a function. If +mm_struct_mmap exist, aka the linked list of vma iteration available, +we goto the original way; if not and mm_struct_mm_mt exist, aka +maple tree is available, then we goto the maple tree vma iteration. + +Signed-off-by: Tao Liu +Signed-off-by: Lianbo Jiang +--- + Makefile | 2 +- + memory.c | 321 +++++++++++++++++++++++++++++++++---------------------- + 2 files changed, 193 insertions(+), 130 deletions(-) + +diff --git a/Makefile b/Makefile +index b290836ffc83..2af4dd0ae904 100644 +--- a/Makefile ++++ b/Makefile +@@ -364,7 +364,7 @@ filesys.o: ${GENERIC_HFILES} filesys.c + help.o: ${GENERIC_HFILES} help.c + ${CC} -c ${CRASH_CFLAGS} help.c ${WARNING_OPTIONS} ${WARNING_ERROR} + +-memory.o: ${GENERIC_HFILES} memory.c ++memory.o: ${GENERIC_HFILES} ${MAPLE_TREE_HFILES} memory.c + ${CC} -c ${CRASH_CFLAGS} memory.c ${WARNING_OPTIONS} ${WARNING_ERROR} + + test.o: ${GENERIC_HFILES} test.c +diff --git a/memory.c b/memory.c +index 156de2f7b5a3..5141fbea4b40 100644 +--- a/memory.c ++++ b/memory.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include "maple_tree.h" + + struct meminfo { /* general purpose memory information structure */ + ulong cache; /* used by the various memory searching/dumping */ +@@ -137,6 +138,27 @@ struct searchinfo { + char buf[BUFSIZE]; + }; + ++struct handle_each_vm_area_args { ++ ulong task; ++ ulong flag; ++ ulong vaddr; ++ struct reference *ref; ++ char *vma_header; ++ char *buf1; ++ char *buf2; ++ char *buf3; ++ char *buf4; ++ char *buf5; ++ ulong vma; ++ char **vma_buf; ++ struct task_mem_usage *tm; ++ int *found; ++ int *single_vma_found; ++ unsigned int radix; ++ struct task_context *tc; ++ ulong *single_vma; ++}; ++ + static char *memtype_string(int, int); + static char *error_handle_string(ulong); + static void collect_page_member_data(char *, struct meminfo *); +@@ -299,6 +321,7 @@ static void dump_page_flags(ulonglong); + static ulong kmem_cache_nodelists(ulong); + static void dump_hstates(void); + static ulong freelist_ptr(struct meminfo *, ulong, ulong); ++static ulong handle_each_vm_area(struct handle_each_vm_area_args *); + + /* + * Memory display modes specific to this file. +@@ -363,6 +386,10 @@ vm_init(void) + + MEMBER_OFFSET_INIT(task_struct_mm, "task_struct", "mm"); + MEMBER_OFFSET_INIT(mm_struct_mmap, "mm_struct", "mmap"); ++ MEMBER_OFFSET_INIT(mm_struct_mm_mt, "mm_struct", "mm_mt"); ++ if (VALID_MEMBER(mm_struct_mm_mt)) { ++ maple_init(); ++ } + MEMBER_OFFSET_INIT(mm_struct_pgd, "mm_struct", "pgd"); + MEMBER_OFFSET_INIT(mm_struct_rss, "mm_struct", "rss"); + if (!VALID_MEMBER(mm_struct_rss)) +@@ -3874,7 +3901,7 @@ bailout: + * for references -- and only then does a display + */ + +-#define PRINT_VM_DATA() \ ++#define PRINT_VM_DATA(buf4, buf5, tm) \ + { \ + fprintf(fp, "%s %s ", \ + mkstring(buf4, VADDR_PRLEN, CENTER|LJUST, "MM"), \ +@@ -3896,9 +3923,9 @@ bailout: + mkstring(buf5, 8, CENTER|LJUST, NULL)); \ + } + +-#define PRINT_VMA_DATA() \ ++#define PRINT_VMA_DATA(buf1, buf2, buf3, buf4, vma) \ + fprintf(fp, "%s%s%s%s%s %6llx%s%s\n", \ +- mkstring(buf4, VADDR_PRLEN, CENTER|LJUST|LONG_HEX, MKSTR(vma)), \ ++ mkstring(buf4, VADDR_PRLEN, CENTER|LJUST|LONG_HEX, MKSTR(vma)),\ + space(MINSPACE), \ + mkstring(buf2, UVADDR_PRLEN, RJUST|LONG_HEX, MKSTR(vm_start)), \ + space(MINSPACE), \ +@@ -3925,18 +3952,137 @@ bailout: + (DO_REF_SEARCH(X) && (string_exists(S)) && FILENAME_COMPONENT((S),(X)->str)) + #define VM_REF_FOUND(X) ((X) && ((X)->cmdflags & VM_REF_HEADER)) + +-ulong +-vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) ++static ulong handle_each_vm_area(struct handle_each_vm_area_args *args) + { +- struct task_context *tc; +- ulong vma; ++ char *dentry_buf, *file_buf; + ulong vm_start; + ulong vm_end; +- ulong vm_next, vm_mm; +- char *dentry_buf, *vma_buf, *file_buf; ++ ulong vm_mm; + ulonglong vm_flags; + ulong vm_file, inode; + ulong dentry, vfsmnt; ++ ++ if ((args->flag & PHYSADDR) && !DO_REF_SEARCH(args->ref)) ++ fprintf(fp, "%s", args->vma_header); ++ ++ inode = 0; ++ BZERO(args->buf1, BUFSIZE); ++ *(args->vma_buf) = fill_vma_cache(args->vma); ++ ++ vm_mm = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_mm)); ++ vm_end = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_end)); ++ vm_start = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_start)); ++ vm_flags = get_vm_flags(*(args->vma_buf)); ++ vm_file = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_file)); ++ ++ if (args->flag & PRINT_SINGLE_VMA) { ++ if (args->vma != *(args->single_vma)) ++ return 0; ++ fprintf(fp, "%s", args->vma_header); ++ *(args->single_vma_found) = TRUE; ++ } ++ ++ if (args->flag & PRINT_VMA_STRUCTS) { ++ dump_struct("vm_area_struct", args->vma, args->radix); ++ return 0; ++ } ++ ++ if (vm_file && !(args->flag & VERIFY_ADDR)) { ++ file_buf = fill_file_cache(vm_file); ++ dentry = ULONG(file_buf + OFFSET(file_f_dentry)); ++ dentry_buf = NULL; ++ if (dentry) { ++ dentry_buf = fill_dentry_cache(dentry); ++ if (VALID_MEMBER(file_f_vfsmnt)) { ++ vfsmnt = ULONG(file_buf + OFFSET(file_f_vfsmnt)); ++ get_pathname(dentry, args->buf1, BUFSIZE, 1, vfsmnt); ++ } else ++ get_pathname(dentry, args->buf1, BUFSIZE, 1, 0); ++ } ++ if ((args->flag & PRINT_INODES) && dentry) ++ inode = ULONG(dentry_buf + OFFSET(dentry_d_inode)); ++ } ++ ++ if (!(args->flag & UVADDR) || ((args->flag & UVADDR) && ++ ((args->vaddr >= vm_start) && (args->vaddr < vm_end)))) { ++ *(args->found) = TRUE; ++ ++ if (args->flag & VERIFY_ADDR) ++ return args->vma; ++ ++ if (DO_REF_SEARCH(args->ref)) { ++ if (VM_REF_CHECK_HEXVAL(args->ref, args->vma) || ++ VM_REF_CHECK_HEXVAL(args->ref, (ulong)vm_flags) || ++ VM_REF_CHECK_STRING(args->ref, args->buf1)) { ++ if (!(args->ref->cmdflags & VM_REF_HEADER)) { ++ print_task_header(fp, args->tc, 0); ++ PRINT_VM_DATA(args->buf4, args->buf5, args->tm); ++ args->ref->cmdflags |= VM_REF_HEADER; ++ } ++ if (!(args->ref->cmdflags & VM_REF_VMA) || ++ (args->ref->cmdflags & VM_REF_PAGE)) { ++ fprintf(fp, "%s", args->vma_header); ++ args->ref->cmdflags |= VM_REF_VMA; ++ args->ref->cmdflags &= ~VM_REF_PAGE; ++ args->ref->ref1 = args->vma; ++ } ++ PRINT_VMA_DATA(args->buf1, args->buf2, ++ args->buf3, args->buf4, args->vma); ++ } ++ ++ if (vm_area_page_dump(args->vma, args->task, ++ vm_start, vm_end, vm_mm, args->ref)) { ++ if (!(args->ref->cmdflags & VM_REF_HEADER)) { ++ print_task_header(fp, args->tc, 0); ++ PRINT_VM_DATA(args->buf4, args->buf5, args->tm); ++ args->ref->cmdflags |= VM_REF_HEADER; ++ } ++ if (!(args->ref->cmdflags & VM_REF_VMA) || ++ (args->ref->ref1 != args->vma)) { ++ fprintf(fp, "%s", args->vma_header); ++ PRINT_VMA_DATA(args->buf1, args->buf2, ++ args->buf3, args->buf4, args->vma); ++ args->ref->cmdflags |= VM_REF_VMA; ++ args->ref->ref1 = args->vma; ++ } ++ ++ args->ref->cmdflags |= VM_REF_DISPLAY; ++ vm_area_page_dump(args->vma, args->task, ++ vm_start, vm_end, vm_mm, args->ref); ++ args->ref->cmdflags &= ~VM_REF_DISPLAY; ++ } ++ ++ return 0; ++ } ++ ++ if (inode) { ++ fprintf(fp, "%lx%s%s%s%s%s%6llx%s%lx %s\n", ++ args->vma, space(MINSPACE), ++ mkstring(args->buf2, UVADDR_PRLEN, RJUST|LONG_HEX, ++ MKSTR(vm_start)), space(MINSPACE), ++ mkstring(args->buf3, UVADDR_PRLEN, RJUST|LONG_HEX, ++ MKSTR(vm_end)), space(MINSPACE), ++ vm_flags, space(MINSPACE), inode, args->buf1); ++ } else { ++ PRINT_VMA_DATA(args->buf1, args->buf2, ++ args->buf3, args->buf4, args->vma); ++ ++ if (args->flag & (PHYSADDR|PRINT_SINGLE_VMA)) ++ vm_area_page_dump(args->vma, args->task, ++ vm_start, vm_end, vm_mm, args->ref); ++ } ++ ++ if (args->flag & UVADDR) ++ return args->vma; ++ } ++ return 0; ++} ++ ++ulong ++vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) ++{ ++ struct task_context *tc; ++ ulong vma; + ulong single_vma; + unsigned int radix; + int single_vma_found; +@@ -3948,6 +4094,10 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) + char buf4[BUFSIZE]; + char buf5[BUFSIZE]; + char vma_header[BUFSIZE]; ++ char *vma_buf; ++ int i; ++ ulong mm_mt, entry_num; ++ struct list_pair *entry_list; + + tc = task_to_context(task); + tm = &task_mem_usage; +@@ -3981,14 +4131,14 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) + if (VM_REF_CHECK_HEXVAL(ref, tm->mm_struct_addr) || + VM_REF_CHECK_HEXVAL(ref, tm->pgd_addr)) { + print_task_header(fp, tc, 0); +- PRINT_VM_DATA(); ++ PRINT_VM_DATA(buf4, buf5, tm); + fprintf(fp, "\n"); + return (ulong)NULL; + } + + if (!(flag & (UVADDR|PRINT_MM_STRUCT|PRINT_VMA_STRUCTS|PRINT_SINGLE_VMA)) && + !DO_REF_SEARCH(ref)) +- PRINT_VM_DATA(); ++ PRINT_VM_DATA(buf4, buf5, tm); + + if (!tm->mm_struct_addr) { + if (pc->curcmd_flags & MM_STRUCT_FORCE) { +@@ -4012,9 +4162,6 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) + return (ulong)NULL; + } + +- readmem(tm->mm_struct_addr + OFFSET(mm_struct_mmap), KVADDR, +- &vma, sizeof(void *), "mm_struct mmap", FAULT_ON_ERROR); +- + sprintf(vma_header, "%s%s%s%s%s FLAGS%sFILE\n", + mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "VMA"), + space(MINSPACE), +@@ -4027,125 +4174,41 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) + !DO_REF_SEARCH(ref)) + fprintf(fp, "%s", vma_header); + +- for (found = FALSE; vma; vma = vm_next) { +- +- if ((flag & PHYSADDR) && !DO_REF_SEARCH(ref)) +- fprintf(fp, "%s", vma_header); +- +- inode = 0; +- BZERO(buf1, BUFSIZE); +- vma_buf = fill_vma_cache(vma); +- +- vm_mm = ULONG(vma_buf + OFFSET(vm_area_struct_vm_mm)); +- vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end)); +- vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next)); +- vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start)); +- vm_flags = get_vm_flags(vma_buf); +- vm_file = ULONG(vma_buf + OFFSET(vm_area_struct_vm_file)); +- +- if (flag & PRINT_SINGLE_VMA) { +- if (vma != single_vma) +- continue; +- fprintf(fp, "%s", vma_header); +- single_vma_found = TRUE; +- } +- +- if (flag & PRINT_VMA_STRUCTS) { +- dump_struct("vm_area_struct", vma, radix); +- continue; +- } ++ found = FALSE; + +- if (vm_file && !(flag & VERIFY_ADDR)) { +- file_buf = fill_file_cache(vm_file); +- dentry = ULONG(file_buf + OFFSET(file_f_dentry)); +- dentry_buf = NULL; +- if (dentry) { +- dentry_buf = fill_dentry_cache(dentry); +- if (VALID_MEMBER(file_f_vfsmnt)) { +- vfsmnt = ULONG(file_buf + +- OFFSET(file_f_vfsmnt)); +- get_pathname(dentry, buf1, BUFSIZE, +- 1, vfsmnt); +- } else { +- get_pathname(dentry, buf1, BUFSIZE, +- 1, 0); +- } +- } +- if ((flag & PRINT_INODES) && dentry) { +- inode = ULONG(dentry_buf + +- OFFSET(dentry_d_inode)); ++ struct handle_each_vm_area_args args = { ++ .task = task, .flag = flag, .vaddr = vaddr, ++ .ref = ref, .tc = tc, .radix = radix, ++ .tm = tm, .buf1 = buf1, .buf2 = buf2, ++ .buf3 = buf3, .buf4 = buf4, .buf5 = buf5, ++ .vma_header = vma_header, .single_vma = &single_vma, ++ .single_vma_found = &single_vma_found, .found = &found, ++ .vma_buf = &vma_buf, ++ }; ++ ++ if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) { ++ mm_mt = tm->mm_struct_addr + 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 (!!(args.vma = (ulong)entry_list[i].value) && ++ handle_each_vm_area(&args)) { ++ FREEBUF(entry_list); ++ return args.vma; + } + } +- +- if (!(flag & UVADDR) || ((flag & UVADDR) && +- ((vaddr >= vm_start) && (vaddr < vm_end)))) { +- found = TRUE; +- +- if (flag & VERIFY_ADDR) +- return vma; +- +- if (DO_REF_SEARCH(ref)) { +- if (VM_REF_CHECK_HEXVAL(ref, vma) || +- VM_REF_CHECK_HEXVAL(ref, (ulong)vm_flags) || +- VM_REF_CHECK_STRING(ref, buf1)) { +- if (!(ref->cmdflags & VM_REF_HEADER)) { +- print_task_header(fp, tc, 0); +- PRINT_VM_DATA(); +- ref->cmdflags |= VM_REF_HEADER; +- } +- if (!(ref->cmdflags & VM_REF_VMA) || +- (ref->cmdflags & VM_REF_PAGE)) { +- fprintf(fp, "%s", vma_header); +- ref->cmdflags |= VM_REF_VMA; +- ref->cmdflags &= ~VM_REF_PAGE; +- ref->ref1 = vma; +- } +- PRINT_VMA_DATA(); +- } +- +- if (vm_area_page_dump(vma, task, +- vm_start, vm_end, vm_mm, ref)) { +- if (!(ref->cmdflags & VM_REF_HEADER)) { +- print_task_header(fp, tc, 0); +- PRINT_VM_DATA(); +- ref->cmdflags |= VM_REF_HEADER; +- } +- if (!(ref->cmdflags & VM_REF_VMA) || +- (ref->ref1 != vma)) { +- fprintf(fp, "%s", vma_header); +- PRINT_VMA_DATA(); +- ref->cmdflags |= VM_REF_VMA; +- ref->ref1 = vma; +- } +- +- ref->cmdflags |= VM_REF_DISPLAY; +- vm_area_page_dump(vma, task, +- vm_start, vm_end, vm_mm, ref); +- ref->cmdflags &= ~VM_REF_DISPLAY; +- } +- +- continue; +- } +- +- if (inode) { +- fprintf(fp, "%lx%s%s%s%s%s%6llx%s%lx %s\n", +- vma, space(MINSPACE), +- mkstring(buf2, UVADDR_PRLEN, RJUST|LONG_HEX, +- MKSTR(vm_start)), space(MINSPACE), +- mkstring(buf3, UVADDR_PRLEN, RJUST|LONG_HEX, +- MKSTR(vm_end)), space(MINSPACE), +- vm_flags, space(MINSPACE), inode, buf1); +- } else { +- PRINT_VMA_DATA(); +- +- if (flag & (PHYSADDR|PRINT_SINGLE_VMA)) +- vm_area_page_dump(vma, task, +- vm_start, vm_end, vm_mm, ref); +- } +- +- if (flag & UVADDR) ++ FREEBUF(entry_list); ++ } else { ++ readmem(tm->mm_struct_addr + OFFSET(mm_struct_mmap), KVADDR, ++ &vma, sizeof(void *), "mm_struct mmap", FAULT_ON_ERROR); ++ while (vma) { ++ args.vma = vma; ++ if (handle_each_vm_area(&args)) + return vma; +- } ++ vma = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next)); ++ } + } + + if (flag & VERIFY_ADDR) +-- +2.37.1 + diff --git a/SOURCES/0069-Update-the-help-text-of-tree-command-for-maple-tree.patch b/SOURCES/0069-Update-the-help-text-of-tree-command-for-maple-tree.patch new file mode 100644 index 0000000..fb525ba --- /dev/null +++ b/SOURCES/0069-Update-the-help-text-of-tree-command-for-maple-tree.patch @@ -0,0 +1,135 @@ +From a3dbd5c455992baf6bfc196b9059a2b485823b83 Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Tue, 10 Jan 2023 14:56:31 +0800 +Subject: [PATCH 69/89] Update the help text of "tree" command for maple tree + +Signed-off-by: Tao Liu +Signed-off-by: Lianbo Jiang +--- + help.c | 86 +++++++++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 64 insertions(+), 22 deletions(-) + +diff --git a/help.c b/help.c +index bfba43f6e9fd..7ceefa06732b 100644 +--- a/help.c ++++ b/help.c +@@ -6313,19 +6313,20 @@ NULL + + char *help_tree[] = { + "tree", +-"display radix tree, XArray or red-black tree", +-"[-t [radix|xarray|rbtree]] [-r offset] [-[s|S] struct[.member[,member]]]\n -[x|d] [-o offset] [-l] [-p] [-N] start", +-" This command dumps the contents of a radix tree, an XAarray, or a red-black", +-" tree. The arguments are as follows:\n", ++"display radix tree, XArray, red-black tree or maple tree", ++"[-t [radix|xarray|rbtree|maple]] [-r offset] [-[s|S] struct[.member[,member]]]\n" ++" -[x|d] [-o offset] [-l] [-p] [-v] [-N] start", ++" This command dumps the contents of a radix tree, an XAarray, a red-black", ++" tree, or a maple tree. The arguments are as follows:\n", + " -t type The type of tree to dump; the type string can be one of ", +-" \"radix\", \"rbtree\", or \"xarray\", or alternatively, \"ra\",", +-" \"rb\" or \"x\" are acceptable. If not specified, rbtree is the", +-" default type.", ++" \"radix\", \"rbtree\", \"xarray\", or \"maple\", or alternatively,", ++" \"ra\", \"rb\", \"x\" or \"m\" are acceptable. If not specified,", ++" rbtree is the default type.", + " -r offset If the \"start\" argument is the address of a data structure that", +-" contains an radix_tree_root, xarray or rb_root structure, then this", +-" is the offset to that structure member. If the offset is non-zero,", +-" then this option is required. The offset may be entered in either", +-" of two manners:", ++" contains an radix_tree_root, maple_tree, xarray or rb_root", ++" structure, then this is the offset to that structure member. If", ++" the offset is non-zero, then this option is required. The offset", ++" may be entered in either of two manners:", + " 1. In \"structure.member\" format.", + " 2. A number of bytes.", + " -o offset For red-black trees only, the offset of the rb_node within its ", +@@ -6354,25 +6355,26 @@ char *help_tree[] = { + " -p Display the node's position information, showing the relationship", + " between it and the root. For red-black trees, a position that", + " indicates \"root/l/r\" means that the node is the right child", +-" of the left child of the root node. For radix trees and xarrays,", +-" the index, the height, and the slot index values are shown with", +-" respect to the root.", ++" of the left child of the root node. For radix trees, xarrays and", ++" maple trees, the index, the height, and the slot index values are", ++" shown with respect to the root.", + " -x Override default output format with hexadecimal format.", + " -d Override default output format with decimal format.", ++" -v For maple trees only, dump the contents of each maple tree node.", + " ", + " The meaning of the \"start\" argument, which can be expressed either in", + " hexadecimal format or symbolically, depends upon whether the -N option", + " is prepended:", + " ", +-" start The address of a radix_tree_root, xarray or rb_root structure, or", +-" the address of a structure containing the radix_tree_root, xarray", +-" or rb_root structure; if the latter, then the \"-r offset\" option", +-" must be used if the member offset of the root structure is ", +-" non-zero.", ++" start The address of a radix_tree_root, maple_tree, xarray or rb_root", ++" structure, or the address of a structure containing the", ++" radix_tree_root, maple_tree, xarray or rb_root structure; if the", ++" latter, then the \"-r offset\" option must be used if the member", ++" offset of the root structure is non-zero.", + " ", +-" -N start The address of a radix_tree_node, xa_node or rb_node structure,", +-" bypassing the radix_tree_root, xarray, or rb_root that points", +-" to it.", ++" -N start The address of a radix_tree_node, maple_node, xa_node or rb_node", ++" structure, bypassing the radix_tree_root, maple_tree, xarray, or", ++" rb_root that points to it.", + "", + "\nEXAMPLES", + " The vmap_area_root is a standalone rb_root structure. Display the ", +@@ -6709,6 +6711,46 @@ char *help_tree[] = { + " _refcount = {", + " counter = 0x1", + " }", ++"", ++" The -v option is introduced specifically for dumping the complete content of", ++" maple tree:", ++"", ++" %s> tree -t maple 0xffff9034c006aec0 -v", ++"", ++" maple_tree(ffff9034c006aec0) flags 309, height 2 root 0xffff9034de70041e", ++"", ++" 0-18446744073709551615: node 0xffff9034de700400 depth 0 type 3 parent ...", ++" 0-140112331583487: node 0xffff9034c01e8800 depth 1 type 1 parent ...", ++" 0-94643156942847: 0x0", ++" 94643156942848-94643158024191: 0xffff9035131754c0", ++" 94643158024192-94643160117247: 0x0", ++" ...", ++"", ++" The existing options can work as well for maple tree:", ++"", ++" %s> tree -t maple -r mm_struct.mm_mt 0xffff9034c006aec0 -p", ++" ffff9035131754c0", ++" index: 1 position: root/0/1", ++" ffff9035131751c8", ++" index: 2 position: root/0/3", ++" ffff9035131757b8", ++" index: 3 position: root/0/4", ++" ...", ++"", ++" %s> tree -t maple 0xffff9034c006aec0 -p -x -s vm_area_struct.vm_start,vm_end", ++" ffff9035131754c0", ++" index: 1 position: root/0/1", ++" vm_start = 0x5613d3c00000,", ++" vm_end = 0x5613d3d08000,", ++" ffff9035131751c8", ++" index: 2 position: root/0/3", ++" vm_start = 0x5613d3f07000,", ++" vm_end = 0x5613d3f0b000,", ++" ffff9035131757b8", ++" index: 3 position: root/0/4", ++" vm_start = 0x5613d3f0b000,", ++" vm_end = 0x5613d3f14000,", ++" ....", + NULL + }; + +-- +2.37.1 + diff --git a/SOURCES/0070-Dump-maple-tree-offset-variables-by-help-o.patch b/SOURCES/0070-Dump-maple-tree-offset-variables-by-help-o.patch new file mode 100644 index 0000000..9edc727 --- /dev/null +++ b/SOURCES/0070-Dump-maple-tree-offset-variables-by-help-o.patch @@ -0,0 +1,52 @@ +From 198ce92c480baa71e3c70694b7049432f8a5a6ec Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Tue, 10 Jan 2023 14:56:32 +0800 +Subject: [PATCH 70/89] Dump maple tree offset variables by "help -o" + +In the previous patches, some variables are added to offset_table and +size_table, print them out with "help -o" command. + +Signed-off-by: Tao Liu +Signed-off-by: Lianbo Jiang +--- + symbols.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/symbols.c b/symbols.c +index 9e6fca73eaf9..20bfac35c1f6 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -10778,6 +10778,21 @@ dump_offset_table(char *spec, ulong makestruct) + OFFSET(sbq_wait_state_wait_cnt)); + fprintf(fp, " sbq_wait_state_wait: %ld\n", + OFFSET(sbq_wait_state_wait)); ++ fprintf(fp, " mm_struct_mm_mt: %ld\n", OFFSET(mm_struct_mm_mt)); ++ fprintf(fp, " maple_tree_ma_root: %ld\n", OFFSET(maple_tree_ma_root)); ++ fprintf(fp, " maple_tree_ma_flags: %ld\n", OFFSET(maple_tree_ma_flags)); ++ fprintf(fp, " maple_node_parent: %ld\n", OFFSET(maple_node_parent)); ++ fprintf(fp, " maple_node_ma64: %ld\n", OFFSET(maple_node_ma64)); ++ fprintf(fp, " maple_node_mr64: %ld\n", OFFSET(maple_node_mr64)); ++ fprintf(fp, " maple_node_slot: %ld\n", OFFSET(maple_node_slot)); ++ fprintf(fp, " maple_arange_64_pivot: %ld\n", OFFSET(maple_arange_64_pivot)); ++ fprintf(fp, " maple_arange_64_slot: %ld\n", OFFSET(maple_arange_64_slot)); ++ fprintf(fp, " maple_arange_64_gap: %ld\n", OFFSET(maple_arange_64_gap)); ++ fprintf(fp, " maple_arange_64_meta: %ld\n", OFFSET(maple_arange_64_meta)); ++ fprintf(fp, " maple_range_64_pivot: %ld\n", OFFSET(maple_range_64_pivot)); ++ fprintf(fp, " maple_range_64_slot: %ld\n", OFFSET(maple_range_64_slot)); ++ fprintf(fp, " maple_metadata_end: %ld\n", OFFSET(maple_metadata_end)); ++ fprintf(fp, " maple_metadata_gap: %ld\n", OFFSET(maple_metadata_gap)); + + fprintf(fp, "\n size_table:\n"); + fprintf(fp, " page: %ld\n", SIZE(page)); +@@ -11050,6 +11065,8 @@ dump_offset_table(char *spec, ulong makestruct) + fprintf(fp, " sbitmap_queue: %ld\n", SIZE(sbitmap_queue)); + fprintf(fp, " sbq_wait_state: %ld\n", SIZE(sbq_wait_state)); + fprintf(fp, " blk_mq_tags: %ld\n", SIZE(blk_mq_tags)); ++ fprintf(fp, " maple_tree: %ld\n", SIZE(maple_tree)); ++ fprintf(fp, " maple_node: %ld\n", SIZE(maple_node)); + + fprintf(fp, " percpu_counter: %ld\n", SIZE(percpu_counter)); + +-- +2.37.1 + diff --git a/SOURCES/0071-Fix-for-bt-command-printing-bogus-exception-frame-wa.patch b/SOURCES/0071-Fix-for-bt-command-printing-bogus-exception-frame-wa.patch new file mode 100644 index 0000000..a840abb --- /dev/null +++ b/SOURCES/0071-Fix-for-bt-command-printing-bogus-exception-frame-wa.patch @@ -0,0 +1,80 @@ +From a39b03603eba70d630121390f50abbc186bc8f56 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Mon, 13 Feb 2023 11:12:12 +0800 +Subject: [PATCH 71/89] Fix for "bt" command printing "bogus exception frame" + warning + +Currently, the "bt" command may print a bogus exception frame +and the remaining frame will be truncated on x86_64 when using the +"virsh send-key KEY_LEFTALT KEY_SYSRQ KEY_C" command +to trigger a panic from the KVM host. For example: + + crash> bt + PID: 0 TASK: ffff9e7a47e32f00 CPU: 3 COMMAND: "swapper/3" + #0 [ffffba7900118bb8] machine_kexec at ffffffff87e5c2c7 + #1 [ffffba7900118c08] __crash_kexec at ffffffff87f9500d + #2 [ffffba7900118cd0] panic at ffffffff87edfff9 + #3 [ffffba7900118d50] sysrq_handle_crash at ffffffff883ce2c1 + ... + #16 [ffffba7900118fd8] handle_edge_irq at ffffffff87f559f2 + #17 [ffffba7900118ff0] asm_call_on_stack at ffffffff88800fa2 + --- --- + #18 [ffffba790008bda0] asm_call_on_stack at ffffffff88800fa2 + RIP: ffffffffffffffff RSP: 0000000000000124 RFLAGS: 00000003 + RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000000 + RDX: ffffffff88800c1e RSI: 0000000000000000 RDI: 0000000000000000 + RBP: 0000000000000001 R8: 0000000000000000 R9: 0000000000000000 + R10: 0000000000000000 R11: ffffffff88760555 R12: ffffba790008be08 + R13: ffffffff87f18002 R14: ffff9e7a47e32f00 R15: ffff9e7bb6198e00 + ORIG_RAX: 0000000000000000 CS: 0003 SS: 0000 + bt: WARNING: possibly bogus exception frame + crash> + +The following related kernel commits cause the current issue, crash +needs to adjust the value of irq_eframe_link. + +Related kernel commits: +[1] v5.8: 931b94145981 ("x86/entry: Provide helpers for executing on the irqstack") +[2] v5.8: fa5e5c409213 ("x86/entry: Use idtentry for interrupts") +[3] v5.12: 52d743f3b712 ("x86/softirq: Remove indirection in do_softirq_own_stack()") + +Signed-off-by: Lianbo Jiang +Signed-off-by: Kazuhito Hagio +--- + x86_64.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/x86_64.c b/x86_64.c +index 1113a1055f77..27b1167ec630 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -3935,6 +3935,11 @@ in_exception_stack: + if (irq_eframe) { + bt->flags |= BT_EXCEPTION_FRAME; + i = (irq_eframe - bt->stackbase)/sizeof(ulong); ++ if (symbol_exists("asm_common_interrupt")) { ++ i -= 1; ++ up = (ulong *)(&bt->stackbuf[i*sizeof(ulong)]); ++ bt->instptr = *up; ++ } + x86_64_print_stack_entry(bt, ofp, level, i, bt->instptr); + bt->flags &= ~(ulonglong)BT_EXCEPTION_FRAME; + cs = x86_64_exception_frame(EFRAME_PRINT|EFRAME_CS, 0, +@@ -6513,6 +6518,14 @@ x86_64_irq_eframe_link_init(void) + else + return; + ++ if (symbol_exists("asm_common_interrupt")) { ++ if (symbol_exists("asm_call_on_stack")) ++ machdep->machspec->irq_eframe_link = -64; ++ else ++ machdep->machspec->irq_eframe_link = -32; ++ return; ++ } ++ + if (THIS_KERNEL_VERSION < LINUX(2,6,9)) + return; + +-- +2.37.1 + diff --git a/SOURCES/0072-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch b/SOURCES/0072-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch new file mode 100644 index 0000000..2e2e72b --- /dev/null +++ b/SOURCES/0072-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch @@ -0,0 +1,144 @@ +From 3c9c16c545319958d7fa14ef5ab8934fc5449d83 Mon Sep 17 00:00:00 2001 +From: "Aureau, Georges (Kernel Tools ERT)" +Date: Wed, 8 Feb 2023 12:09:03 +0000 +Subject: [PATCH 72/89] Fix "kmem -s|-S" not working properly on RHEL8.6 and + later + +For CONFIG_SLAB_FREELIST_HARDENED, the crash memory.c:freelist_ptr() +code is checking for an additional bswap using a simple release test eg. +THIS_KERNEL_VERSION >= LINUX(5,7,0), basically checking for RHEL9 and +beyond. + +However, for RHEL8.6 and later, we have CONFIG_SLAB_FREELIST_HARDENED=y, +and we also have the additional bswap, but the current crash is not +handling this case, hence "kmem -s|-S" will not work properly, and free +objects will not be counted nor reported properly. + +An example from a RHEL8.6 x86_64 kdump, a kmem cache with a single slab +having 42 objects, only the freelist head is seen as free as crash can't +walk freelist next pointers, and crash is wrongly reporting 41 allocated +objects: + + crash> sys | grep RELEASE + RELEASE: 4.18.0-372.9.1.el8.x86_64 + crash> kmem -s nfs_commit_data + CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME + ffff9ad40c7cb2c0 728 41 42 1 32k nfs_commit_data + +When properly accounting for the additional bswap, we can walk the +freelist and find 38 free objects, and crash is now reporting only 4 +allocated objects: + + crash> kmem -s nfs_commit_data + CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME + ffff9ad40c7cb2c0 728 4 42 1 32k nfs_commit_data + +Signed-off-by: Georges Aureau +Signed-off-by: Lianbo Jiang +--- + defs.h | 1 + + memory.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 49 insertions(+), 1 deletion(-) + +diff --git a/defs.h b/defs.h +index b2389cd82fae..ae5d1244e8b3 100644 +--- a/defs.h ++++ b/defs.h +@@ -2638,6 +2638,7 @@ struct vm_table { /* kernel VM-related data */ + #define SLAB_OVERLOAD_PAGE (0x8000000) + #define SLAB_CPU_CACHE (0x10000000) + #define SLAB_ROOT_CACHES (0x20000000) ++#define FREELIST_PTR_BSWAP (0x40000000) + + #define IS_FLATMEM() (vt->flags & FLATMEM) + #define IS_DISCONTIGMEM() (vt->flags & DISCONTIGMEM) +diff --git a/memory.c b/memory.c +index 5141fbea4b40..e0742c1bd3a4 100644 +--- a/memory.c ++++ b/memory.c +@@ -320,6 +320,7 @@ static void dump_per_cpu_offsets(void); + static void dump_page_flags(ulonglong); + static ulong kmem_cache_nodelists(ulong); + static void dump_hstates(void); ++static void freelist_ptr_init(void); + static ulong freelist_ptr(struct meminfo *, ulong, ulong); + static ulong handle_each_vm_area(struct handle_each_vm_area_args *); + +@@ -789,6 +790,8 @@ vm_init(void) + MEMBER_OFFSET_INIT(kmem_cache_name, "kmem_cache", "name"); + MEMBER_OFFSET_INIT(kmem_cache_flags, "kmem_cache", "flags"); + MEMBER_OFFSET_INIT(kmem_cache_random, "kmem_cache", "random"); ++ if (VALID_MEMBER(kmem_cache_random)) ++ freelist_ptr_init(); + MEMBER_OFFSET_INIT(kmem_cache_cpu_freelist, "kmem_cache_cpu", "freelist"); + MEMBER_OFFSET_INIT(kmem_cache_cpu_page, "kmem_cache_cpu", "page"); + if (INVALID_MEMBER(kmem_cache_cpu_page)) +@@ -13932,6 +13935,8 @@ dump_vm_table(int verbose) + fprintf(fp, "%sSLAB_CPU_CACHE", others++ ? "|" : "");\ + if (vt->flags & SLAB_ROOT_CACHES) + fprintf(fp, "%sSLAB_ROOT_CACHES", others++ ? "|" : "");\ ++ if (vt->flags & FREELIST_PTR_BSWAP) ++ fprintf(fp, "%sFREELIST_PTR_BSWAP", others++ ? "|" : "");\ + if (vt->flags & USE_VMAP_AREA) + fprintf(fp, "%sUSE_VMAP_AREA", others++ ? "|" : "");\ + if (vt->flags & CONFIG_NUMA) +@@ -19519,13 +19524,55 @@ count_free_objects(struct meminfo *si, ulong freelist) + return c; + } + ++/* ++ * With CONFIG_SLAB_FREELIST_HARDENED, freelist_ptr's are crypted with xor's, ++ * and for recent release with an additionnal bswap. Some releases prio to 5.7.0 ++ * may be using the additionnal bswap. The only easy and reliable way to tell is ++ * to inspect assembly code (eg. "__slab_free") for a bswap instruction. ++ */ ++static int ++freelist_ptr_bswap_x86(void) ++{ ++ char buf1[BUFSIZE]; ++ char buf2[BUFSIZE]; ++ char *arglist[MAXARGS]; ++ int found; ++ ++ sprintf(buf1, "disassemble __slab_free"); ++ open_tmpfile(); ++ if (!gdb_pass_through(buf1, pc->tmpfile, GNU_RETURN_ON_ERROR)) { ++ close_tmpfile(); ++ return FALSE; ++ } ++ rewind(pc->tmpfile); ++ found = FALSE; ++ while (fgets(buf2, BUFSIZE, pc->tmpfile)) { ++ if (parse_line(buf2, arglist) < 3) ++ continue; ++ if (STREQ(arglist[2], "bswap")) { ++ found = TRUE; ++ break; ++ } ++ } ++ close_tmpfile(); ++ return found; ++} ++ ++static void ++freelist_ptr_init(void) ++{ ++ if (THIS_KERNEL_VERSION >= LINUX(5,7,0) || ++ ((machine_type("X86_64") || machine_type("X86")) && freelist_ptr_bswap_x86())) ++ vt->flags |= FREELIST_PTR_BSWAP; ++} ++ + static ulong + freelist_ptr(struct meminfo *si, ulong ptr, ulong ptr_addr) + { + if (VALID_MEMBER(kmem_cache_random)) { + /* CONFIG_SLAB_FREELIST_HARDENED */ + +- if (THIS_KERNEL_VERSION >= LINUX(5,7,0)) ++ if (vt->flags & FREELIST_PTR_BSWAP) + ptr_addr = (sizeof(long) == 8) ? bswap_64(ptr_addr) + : bswap_32(ptr_addr); + return (ptr ^ si->random ^ ptr_addr); +-- +2.37.1 + diff --git a/SOURCES/0073-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch b/SOURCES/0073-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch new file mode 100644 index 0000000..bd54148 --- /dev/null +++ b/SOURCES/0073-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch @@ -0,0 +1,106 @@ +From 49f689eda0bc3331beb70df17ac4990034460f2b Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Thu, 9 Feb 2023 20:15:46 +0800 +Subject: [PATCH 73/89] Fix for "net -s" option to show IPv6 addresses on Linux + 3.13 and later + +Currently, the "net -s" option fails to show IPv6 addresses and ports +for the SOURCE-PORT and DESTINATION-PORT columns on Linux 3.13 and later +kernels, which have kernel commit efe4208f47f907 ("ipv6: make lookups +simpler and faster"). For example: + + crash> net -s + PID: 305524 TASK: ffff9bc449895580 CPU: 6 COMMAND: "sshd" + FD SOCKET SOCK FAMILY:TYPE SOURCE-PORT DESTINATION-PORT + 3 ffff9bc446e9a680 ffff9bc4455b5940 UNIX:DGRAM + 4 ffff9bc446e9c600 ffff9bc3b2b24e00 INET6:STREAM + +With the patch: + + crash> net -s + PID: 305524 TASK: ffff9bc449895580 CPU: 6 COMMAND: "sshd" + FD SOCKET SOCK FAMILY:TYPE SOURCE-PORT DESTINATION-PORT + 3 ffff9bc446e9a680 ffff9bc4455b5940 UNIX:DGRAM + 4 ffff9bc446e9c600 ffff9bc3b2b24e00 INET6:STREAM xxxx:xx:x:xxxx:xxxx:xxxx:xxxx:xxxx-22 yyyy:yy:y:yyyy:yyyy:yyyy:yyyy:yyyy-44870 + +Reported-by: Buland Kumar Singh +Signed-off-by: Lianbo Jiang +Signed-off-by: Kazuhito Hagio +--- + defs.h | 3 +++ + net.c | 20 +++++++++++++++----- + symbols.c | 3 +++ + 3 files changed, 21 insertions(+), 5 deletions(-) + +diff --git a/defs.h b/defs.h +index ae5d1244e8b3..801781749666 100644 +--- a/defs.h ++++ b/defs.h +@@ -2204,6 +2204,9 @@ struct offset_table { /* stash of commonly-used offsets */ + long maple_range_64_slot; + long maple_metadata_end; + long maple_metadata_gap; ++ long sock_sk_common; ++ long sock_common_skc_v6_daddr; ++ long sock_common_skc_v6_rcv_saddr; + }; + + struct size_table { /* stash of commonly-used sizes */ +diff --git a/net.c b/net.c +index 7c9c8bd9c98d..aa445ab7ee13 100644 +--- a/net.c ++++ b/net.c +@@ -199,6 +199,9 @@ net_init(void) + MEMBER_OFFSET_INIT(sock_common_skc_family, + "sock_common", "skc_family"); + MEMBER_OFFSET_INIT(sock_sk_type, "sock", "sk_type"); ++ MEMBER_OFFSET_INIT(sock_sk_common, "sock", "__sk_common"); ++ MEMBER_OFFSET_INIT(sock_common_skc_v6_daddr, "sock_common", "skc_v6_daddr"); ++ MEMBER_OFFSET_INIT(sock_common_skc_v6_rcv_saddr, "sock_common", "skc_v6_rcv_saddr"); + /* + * struct inet_sock { + * struct sock sk; +@@ -1104,12 +1107,19 @@ get_sock_info(ulong sock, char *buf) + break; + + case SOCK_V2: +- if (INVALID_MEMBER(ipv6_pinfo_rcv_saddr) || +- INVALID_MEMBER(ipv6_pinfo_daddr)) ++ if (VALID_MEMBER(ipv6_pinfo_rcv_saddr) && ++ VALID_MEMBER(ipv6_pinfo_daddr)) { ++ ipv6_rcv_saddr = ipv6_pinfo + OFFSET(ipv6_pinfo_rcv_saddr); ++ ipv6_daddr = ipv6_pinfo + OFFSET(ipv6_pinfo_daddr); ++ } else if (VALID_MEMBER(sock_sk_common) && ++ VALID_MEMBER(sock_common_skc_v6_daddr) && ++ VALID_MEMBER(sock_common_skc_v6_rcv_saddr)) { ++ ipv6_rcv_saddr = sock + OFFSET(sock_sk_common) + OFFSET(sock_common_skc_v6_rcv_saddr); ++ ipv6_daddr = sock + OFFSET(sock_sk_common) + OFFSET(sock_common_skc_v6_daddr); ++ } else { ++ sprintf(&buf[strlen(buf)], "%s", "(cannot get IPv6 addresses)"); + break; +- +- ipv6_rcv_saddr = ipv6_pinfo + OFFSET(ipv6_pinfo_rcv_saddr); +- ipv6_daddr = ipv6_pinfo + OFFSET(ipv6_pinfo_daddr); ++ } + + if (!readmem(ipv6_rcv_saddr, KVADDR, u6_addr16_src, SIZE(in6_addr), + "ipv6_rcv_saddr buffer", QUIET|RETURN_ON_ERROR)) +diff --git a/symbols.c b/symbols.c +index 20bfac35c1f6..54115d753601 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -9830,8 +9830,11 @@ dump_offset_table(char *spec, ulong makestruct) + + fprintf(fp, " sock_sk_type: %ld\n", + OFFSET(sock_sk_type)); ++ fprintf(fp, " sock_sk_common: %ld\n", OFFSET(sock_sk_common)); + fprintf(fp, " sock_common_skc_family: %ld\n", + OFFSET(sock_common_skc_family)); ++ fprintf(fp, " sock_common_skc_v6_daddr: %ld\n", OFFSET(sock_common_skc_v6_daddr)); ++ fprintf(fp, " sock_common_skc_v6_rcv_saddr: %ld\n", OFFSET(sock_common_skc_v6_rcv_saddr)); + fprintf(fp, " socket_alloc_vfs_inode: %ld\n", + OFFSET(socket_alloc_vfs_inode)); + fprintf(fp, " inet_sock_inet: %ld\n", +-- +2.37.1 + diff --git a/SOURCES/0074-Fix-for-kmem-i-option-to-not-print-invalid-values-fo.patch b/SOURCES/0074-Fix-for-kmem-i-option-to-not-print-invalid-values-fo.patch new file mode 100644 index 0000000..a4350aa --- /dev/null +++ b/SOURCES/0074-Fix-for-kmem-i-option-to-not-print-invalid-values-fo.patch @@ -0,0 +1,56 @@ +From b13a2f3c2885bc638d1e413ef9e7c59a8ec8f81d Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Tue, 14 Feb 2023 22:37:08 +0800 +Subject: [PATCH 74/89] Fix for "kmem -i" option to not print invalid values + for CACHED + +The "kmem -i" option may output a bogus statistics for CACHED, which +might be observed when some extreme situations occur in kernel, such as +OOM, disk IO errors, etc. + +The following result of calculation may be a negative value, refer to +the dump_kmeminfo(): + page_cache_size = nr_file_pages - swapper_space_nrpages - buffer_pages; + +As a result, the negative value will be converted to unsigned long +integer, eventually it overflows and is printed as big integers. + + crash> kmem -i + PAGES TOTAL PERCENTAGE + TOTAL MEM 255314511 973.9 GB ---- + FREE 533574 2 GB 0% of TOTAL MEM + USED 254780937 971.9 GB 99% of TOTAL MEM + SHARED 1713 6.7 MB 0% of TOTAL MEM + BUFFERS 374 1.5 MB 0% of TOTAL MEM + CACHED -114 70368744177664 GB 72251060080% of TOTAL MEM + ^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^ + ... + +Let's normalize it to zero with an info message to fix such cornor cases. + +Reported-by: Buland Kumar Singh +Signed-off-by: Lianbo Jiang +Signed-off-by: Kazuhito Hagio +--- + memory.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/memory.c b/memory.c +index e0742c1bd3a4..d9cd616f19de 100644 +--- a/memory.c ++++ b/memory.c +@@ -8615,6 +8615,11 @@ dump_kmeminfo(void) + page_cache_size = 0; + + ++ if (page_cache_size < 0) { ++ error(INFO, "page_cache_size went negative (%ld), setting to 0\n", ++ page_cache_size); ++ page_cache_size = 0; ++ } + pct = (page_cache_size * 100)/totalram_pages; + fprintf(fp, "%13s %7ld %11s %3ld%% of TOTAL MEM\n", + "CACHED", page_cache_size, +-- +2.37.1 + diff --git a/SOURCES/0075-Fix-for-bt-command-unnecessarily-printing-an-excepti.patch b/SOURCES/0075-Fix-for-bt-command-unnecessarily-printing-an-excepti.patch new file mode 100644 index 0000000..cc5c2cf --- /dev/null +++ b/SOURCES/0075-Fix-for-bt-command-unnecessarily-printing-an-excepti.patch @@ -0,0 +1,78 @@ +From cce90e242f74ab81e411f2f65f5d5a9fb5022416 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Wed, 15 Feb 2023 16:24:57 +0800 +Subject: [PATCH 75/89] Fix for "bt" command unnecessarily printing an + exception frame + +Kernel commit 7d65f4a65532 ("irq: Consolidate do_softirq() arch overriden +implementations") renamed the call_softirq to do_softirq_own_stack, and +there is no exception frame also when coming from do_softirq_own_stack. +Without the patch, crash may unnecessarily output an exception frame with +a warning as below: + + crash> foreach bt + ... + PID: 0 TASK: ffff914f820a8000 CPU: 25 COMMAND: "swapper/25" + #0 [fffffe0000504e48] crash_nmi_callback at ffffffffa665d763 + #1 [fffffe0000504e50] nmi_handle at ffffffffa662a423 + #2 [fffffe0000504ea8] default_do_nmi at ffffffffa6fe7dc9 + #3 [fffffe0000504ec8] do_nmi at ffffffffa662a97f + #4 [fffffe0000504ef0] end_repeat_nmi at ffffffffa70015e8 + [exception RIP: clone_endio+172] + RIP: ffffffffc005c1ec RSP: ffffa1d403d08e98 RFLAGS: 00000246 + RAX: 0000000000000000 RBX: ffff915326fba230 RCX: 0000000000000018 + RDX: ffffffffc0075400 RSI: 0000000000000000 RDI: ffff915326fba230 + RBP: ffff915326fba1c0 R8: 0000000000001000 R9: ffff915308d6d2a0 + R10: 000000a97dfe5e10 R11: ffffa1d40038fe98 R12: ffff915302babc40 + R13: ffff914f94360000 R14: 0000000000000000 R15: 0000000000000000 + ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 + --- --- + #5 [ffffa1d403d08e98] clone_endio at ffffffffc005c1ec [dm_mod] + #6 [ffffa1d403d08ed0] blk_update_request at ffffffffa6a96954 + #7 [ffffa1d403d08f10] scsi_end_request at ffffffffa6c9b968 + #8 [ffffa1d403d08f48] scsi_io_completion at ffffffffa6c9bb3e + #9 [ffffa1d403d08f90] blk_complete_reqs at ffffffffa6aa0e95 + #10 [ffffa1d403d08fa0] __softirqentry_text_start at ffffffffa72000dc + #11 [ffffa1d403d08ff0] do_softirq_own_stack at ffffffffa7000f9a + --- --- + #12 [ffffa1d40038fe70] do_softirq_own_stack at ffffffffa7000f9a + [exception RIP: unknown or invalid address] + RIP: 0000000000000000 RSP: 0000000000000000 RFLAGS: 00000000 + RAX: ffffffffa672eae5 RBX: ffffffffa83b34e0 RCX: ffffffffa672eb12 + RDX: 0000000000000010 RSI: 8b7d6c8869010c00 RDI: 0000000000000085 + RBP: 0000000000000286 R8: ffff914f820a8000 R9: ffffffffa67a94e0 + R10: 0000000000000286 R11: ffffffffa66fb4c5 R12: ffffffffa67a898b + R13: 0000000000000000 R14: fffffffffffffff8 R15: ffffffffa67a1e68 + ORIG_RAX: 0000000000000000 CS: 0000 SS: ffffffffa672edff + bt: WARNING: possibly bogus exception frame + #13 [ffffa1d40038ff30] start_secondary at ffffffffa665fa2c + #14 [ffffa1d40038ff50] secondary_startup_64_no_verify at ffffffffa6600116 + ... + +Reported-by: Marco Patalano +Signed-off-by: Lianbo Jiang +--- + x86_64.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/x86_64.c b/x86_64.c +index 27b1167ec630..31c249699066 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -3822,10 +3822,11 @@ in_exception_stack: + up -= 1; + bt->instptr = *up; + /* +- * No exception frame when coming from call_softirq. ++ * No exception frame when coming from do_softirq_own_stack ++ * or call_softirq. + */ + if ((sp = value_search(bt->instptr, &offset)) && +- STREQ(sp->name, "call_softirq")) ++ (STREQ(sp->name, "do_softirq_own_stack") || STREQ(sp->name, "call_softirq"))) + irq_eframe = 0; + bt->frameptr = 0; + done = FALSE; +-- +2.37.1 + diff --git a/SOURCES/0076-Fix-for-dis-command-to-correctly-display-the-offset-.patch b/SOURCES/0076-Fix-for-dis-command-to-correctly-display-the-offset-.patch new file mode 100644 index 0000000..5867e3c --- /dev/null +++ b/SOURCES/0076-Fix-for-dis-command-to-correctly-display-the-offset-.patch @@ -0,0 +1,63 @@ +From 39a938a62d0153a98ab3d1115d845b904192a832 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Tue, 21 Feb 2023 11:03:26 +0800 +Subject: [PATCH 76/89] Fix for "dis" command to correctly display the offset + of disassembly code + +For gdb-10.2, the disassembly code may start with "=>", which needs to +be stripped when calculating the address. Otherwise, parsing the address +will fail because the current code always assumes that it starts with the +"0x". For example: + + crash> gdb disassemble 0xffffffffa2317add + Dump of assembler code for function native_queued_spin_lock_slowpath: + ... + 0xffffffffa2317ad3 <+35>: mov %edx,%eax + 0xffffffffa2317ad5 <+37>: lock cmpxchg %ecx,(%rdi) + => 0xffffffffa2317ad9 <+41>: cmp %eax,%edx + 0xffffffffa2317adb <+43>: jne 0xffffffffa2317ac0 ... + 0xffffffffa2317add <+45>: pop %rbp + ... + +Without the patch: + crash> dis 0xffffffffa2317add -r | tail -5 + 0xffffffffa2317ad3 : mov %edx,%eax + 0xffffffffa2317ad5 : lock cmpxchg %ecx,(%rdi) + 0xffffffffa2317ad5 : cmp %eax,%edx + ^^ + 0xffffffffa2317adb : jne 0xffffffffa2317ac0 ... + 0xffffffffa2317add : pop %rbp + +With the patch: + + crash> dis 0xffffffffa2317add -r | tail -5 + 0xffffffffa2317ad3 : mov %edx,%eax + 0xffffffffa2317ad5 : lock cmpxchg %ecx,(%rdi) + 0xffffffffa2317ad9 : cmp %eax,%edx + 0xffffffffa2317adb : jne 0xffffffffa2317ac0 ... + 0xffffffffa2317add : pop %rbp + +Reported-by: Vernon Lovejoy +Signed-off-by: Lianbo Jiang +--- + kernel.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel.c b/kernel.c +index 3ca513962970..3f2d9a15a78d 100644 +--- a/kernel.c ++++ b/kernel.c +@@ -2113,6 +2113,10 @@ cmd_dis(void) + rewind(pc->tmpfile); + + while (fgets(buf2, BUFSIZE, pc->tmpfile)) { ++ ++ if (STRNEQ(buf2, "=>")) ++ shift_string_left(buf2, 2); ++ + strip_beginning_whitespace(buf2); + + if (do_load_module_filter) +-- +2.37.1 + diff --git a/SOURCES/0077-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch b/SOURCES/0077-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch new file mode 100644 index 0000000..2b43122 --- /dev/null +++ b/SOURCES/0077-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch @@ -0,0 +1,300 @@ +From 04a84a7071b34958f80633ea7bf96652810dadba Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Mon, 20 Feb 2023 10:28:53 +0900 +Subject: [PATCH 77/89] x86_64: Fix "bt" command on kernels with + random_kstack_offset=on + +On kernels configured with CONFIG_RANDOMIZE_KSTACK_OFFSET=y and +random_kstack_offset=on, a random offset is added to task stacks with +__kstack_alloca() at the beginning of do_syscall_64() and other syscall +entry functions. This eventually does the following instruction. + + : sub %rax,%rsp + +On the other hand, crash uses only a part of data for ORC unwinder to +unwind stacks and if an ip value doesn't have a usable ORC data, it +caluculates the frame size with parsing the assembly of the function. + +However, crash cannot calculate the frame size correctly with the +instruction above, and prints stale return addresses like this: + + crash> bt 1 + PID: 1 TASK: ffff9c250023b880 CPU: 0 COMMAND: "systemd" + #0 [ffffb7e5c001fc80] __schedule at ffffffff91ae2b16 + #1 [ffffb7e5c001fd00] schedule at ffffffff91ae2ed3 + #2 [ffffb7e5c001fd18] schedule_hrtimeout_range_clock at ffffffff91ae7ed8 + #3 [ffffb7e5c001fda8] ep_poll at ffffffff913ef828 + #4 [ffffb7e5c001fe48] do_epoll_wait at ffffffff913ef943 + #5 [ffffb7e5c001fe80] __x64_sys_epoll_wait at ffffffff913f0130 + #6 [ffffb7e5c001fed0] do_syscall_64 at ffffffff91ad7169 + #7 [ffffb7e5c001fef0] do_syscall_64 at ffffffff91ad7179 << + #8 [ffffb7e5c001ff10] syscall_exit_to_user_mode at ffffffff91adaab2 << stale entries + #9 [ffffb7e5c001ff20] do_syscall_64 at ffffffff91ad7179 << + #10 [ffffb7e5c001ff50] entry_SYSCALL_64_after_hwframe at ffffffff91c0009b + RIP: 00007f258d9427ae RSP: 00007fffda631d60 RFLAGS: 00000293 + ... + +To fix this, enhance the use of ORC data. The ORC unwinder often uses +%rbp value, so keep it from exception frames and inactive task stacks. + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 1 + + symbols.c | 1 + + x86_64.c | 118 ++++++++++++++++++++++++++++++++++++++---------------- + 3 files changed, 85 insertions(+), 35 deletions(-) + +diff --git a/defs.h b/defs.h +index 801781749666..3c6fa3b0d228 100644 +--- a/defs.h ++++ b/defs.h +@@ -2207,6 +2207,7 @@ struct offset_table { /* stash of commonly-used offsets */ + long sock_sk_common; + long sock_common_skc_v6_daddr; + long sock_common_skc_v6_rcv_saddr; ++ long inactive_task_frame_bp; + }; + + struct size_table { /* stash of commonly-used sizes */ +diff --git a/symbols.c b/symbols.c +index 54115d753601..fc55da678ecd 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -8834,6 +8834,7 @@ dump_offset_table(char *spec, ulong makestruct) + OFFSET(task_struct_tss_ksp)); + fprintf(fp, " task_struct_thread_eip: %ld\n", + OFFSET(task_struct_thread_eip)); ++ fprintf(fp, " inactive_task_frame_bp: %ld\n", OFFSET(inactive_task_frame_bp)); + fprintf(fp, " inactive_task_frame_ret_addr: %ld\n", + OFFSET(inactive_task_frame_ret_addr)); + fprintf(fp, " task_struct_thread_esp: %ld\n", +diff --git a/x86_64.c b/x86_64.c +index 31c249699066..86abea00c9d6 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -122,7 +122,7 @@ static int x86_64_do_not_cache_framesize(struct syment *, ulong); + static int x86_64_framesize_cache_func(int, ulong, int *, int, struct syment *); + static ulong x86_64_get_framepointer(struct bt_info *, ulong); + int search_for_eframe_target_caller(struct bt_info *, ulong, int *); +-static int x86_64_get_framesize(struct bt_info *, ulong, ulong); ++static int x86_64_get_framesize(struct bt_info *, ulong, ulong, char *); + static void x86_64_framesize_debug(struct bt_info *); + static void x86_64_get_active_set(void); + static int x86_64_get_kvaddr_ranges(struct vaddr_range *); +@@ -3639,7 +3639,7 @@ in_exception_stack: + bt, ofp); + rsp += SIZE(pt_regs); /* guaranteed kernel mode */ + if (bt->eframe_ip && ((framesize = x86_64_get_framesize(bt, +- bt->eframe_ip, rsp)) >= 0)) ++ bt->eframe_ip, rsp, NULL)) >= 0)) + rsp += framesize; + level++; + irq_eframe = 0; +@@ -3671,7 +3671,7 @@ in_exception_stack: + case BACKTRACE_ENTRY_DISPLAYED: + level++; + if ((framesize = x86_64_get_framesize(bt, +- bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) { ++ bt->eframe_ip ? bt->eframe_ip : *up, rsp, NULL)) >= 0) { + rsp += framesize; + i += framesize/sizeof(ulong); + } +@@ -3744,7 +3744,7 @@ in_exception_stack: + } + + level++; +- if ((framesize = x86_64_get_framesize(bt, bt->instptr, rsp)) >= 0) ++ if ((framesize = x86_64_get_framesize(bt, bt->instptr, rsp, NULL)) >= 0) + rsp += framesize; + } + } +@@ -3796,7 +3796,7 @@ in_exception_stack: + case BACKTRACE_ENTRY_DISPLAYED: + level++; + if ((framesize = x86_64_get_framesize(bt, +- bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) { ++ bt->eframe_ip ? bt->eframe_ip : *up, rsp, NULL)) >= 0) { + rsp += framesize; + i += framesize/sizeof(ulong); + } +@@ -3906,24 +3906,34 @@ in_exception_stack: + (STREQ(rip_symbol, "thread_return") || + STREQ(rip_symbol, "schedule") || + STREQ(rip_symbol, "__schedule"))) { +- if (STREQ(rip_symbol, "__schedule")) { +- i = (rsp - bt->stackbase)/sizeof(ulong); +- x86_64_print_stack_entry(bt, ofp, level, +- i, bt->instptr); +- level++; +- rsp = __schedule_frame_adjust(rsp, bt); +- if (STREQ(closest_symbol(bt->instptr), "schedule")) ++ if ((machdep->flags & ORC) && VALID_MEMBER(inactive_task_frame_ret_addr)) { ++ /* ++ * %rsp should have the address of inactive_task_frame, so ++ * skip the registers before ret_addr to adjust rsp. ++ */ ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "rsp: %lx rbp: %lx\n", rsp, bt->bptr); ++ rsp += OFFSET(inactive_task_frame_ret_addr); ++ } else { ++ if (STREQ(rip_symbol, "__schedule")) { ++ i = (rsp - bt->stackbase)/sizeof(ulong); ++ x86_64_print_stack_entry(bt, ofp, level, ++ i, bt->instptr); ++ level++; ++ rsp = __schedule_frame_adjust(rsp, bt); ++ if (STREQ(closest_symbol(bt->instptr), "schedule")) ++ bt->flags |= BT_SCHEDULE; ++ } else + bt->flags |= BT_SCHEDULE; +- } else +- bt->flags |= BT_SCHEDULE; +- +- if (bt->flags & BT_SCHEDULE) { +- i = (rsp - bt->stackbase)/sizeof(ulong); +- x86_64_print_stack_entry(bt, ofp, level, +- i, bt->instptr); +- bt->flags &= ~(ulonglong)BT_SCHEDULE; +- rsp += sizeof(ulong); +- level++; ++ ++ if (bt->flags & BT_SCHEDULE) { ++ i = (rsp - bt->stackbase)/sizeof(ulong); ++ x86_64_print_stack_entry(bt, ofp, level, ++ i, bt->instptr); ++ bt->flags &= ~(ulonglong)BT_SCHEDULE; ++ rsp += sizeof(ulong); ++ level++; ++ } + } + } + +@@ -3954,7 +3964,7 @@ in_exception_stack: + irq_eframe = 0; + bt->flags |= BT_EFRAME_TARGET; + if (bt->eframe_ip && ((framesize = x86_64_get_framesize(bt, +- bt->eframe_ip, rsp)) >= 0)) ++ bt->eframe_ip, rsp, NULL)) >= 0)) + rsp += framesize; + bt->flags &= ~BT_EFRAME_TARGET; + } +@@ -4041,7 +4051,7 @@ in_exception_stack: + case BACKTRACE_ENTRY_DISPLAYED: + level++; + if ((framesize = x86_64_get_framesize(bt, +- bt->eframe_ip ? bt->eframe_ip : *up, rsp)) >= 0) { ++ bt->eframe_ip ? bt->eframe_ip : *up, rsp, (char *)up)) >= 0) { + rsp += framesize; + i += framesize/sizeof(ulong); + } +@@ -4752,7 +4762,8 @@ x86_64_exception_frame(ulong flags, ulong kvaddr, char *local, + bt->instptr = rip; + bt->stkptr = rsp; + bt->bptr = rbp; +- } ++ } else if (machdep->flags & ORC) ++ bt->bptr = rbp; + + if (kvaddr) + FREEBUF(pt_regs_buf); +@@ -5312,6 +5323,10 @@ x86_64_get_sp(struct bt_info *bt) + OFFSET(thread_struct_rsp), KVADDR, + &rsp, sizeof(void *), + "thread_struct rsp", FAULT_ON_ERROR); ++ if ((machdep->flags & ORC) && VALID_MEMBER(inactive_task_frame_bp)) { ++ readmem(rsp + OFFSET(inactive_task_frame_bp), KVADDR, &bt->bptr, ++ sizeof(void *), "inactive_task_frame.bp", FAULT_ON_ERROR); ++ } + return rsp; + } + +@@ -6418,6 +6433,9 @@ x86_64_ORC_init(void) + orc->__stop_orc_unwind = symbol_value("__stop_orc_unwind"); + orc->orc_lookup = symbol_value("orc_lookup"); + ++ MEMBER_OFFSET_INIT(inactive_task_frame_bp, "inactive_task_frame", "bp"); ++ MEMBER_OFFSET_INIT(inactive_task_frame_ret_addr, "inactive_task_frame", "ret_addr"); ++ + machdep->flags |= ORC; + } + +@@ -8480,7 +8498,7 @@ search_for_eframe_target_caller(struct bt_info *bt, ulong stkptr, int *framesize + (BT_OLD_BACK_TRACE|BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_ALL|BT_FRAMESIZE_DISABLE) + + static int +-x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp) ++x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp, char *stack_ptr) + { + int c, framesize, instr, arg, max; + struct syment *sp; +@@ -8581,19 +8599,49 @@ x86_64_get_framesize(struct bt_info *bt, ulong textaddr, ulong rsp) + if ((machdep->flags & ORC) && (korc = orc_find(textaddr))) { + if (CRASHDEBUG(1)) { + fprintf(fp, +- "rsp: %lx textaddr: %lx framesize: %d -> spo: %d bpo: %d spr: %d bpr: %d type: %d %s", +- rsp, textaddr, framesize, korc->sp_offset, korc->bp_offset, +- korc->sp_reg, korc->bp_reg, korc->type, +- (korc->type == ORC_TYPE_CALL) && (korc->sp_reg == ORC_REG_SP) ? "" : "(UNUSED)"); ++ "rsp: %lx textaddr: %lx -> spo: %d bpo: %d spr: %d bpr: %d type: %d", ++ rsp, textaddr, korc->sp_offset, korc->bp_offset, ++ korc->sp_reg, korc->bp_reg, korc->type); + if (MEMBER_EXISTS("orc_entry", "end")) + fprintf(fp, " end: %d", korc->end); + fprintf(fp, "\n"); + } + +- if ((korc->type == ORC_TYPE_CALL) && (korc->sp_reg == ORC_REG_SP)) { +- framesize = (korc->sp_offset - 8); +- return (x86_64_framesize_cache_func(FRAMESIZE_ENTER, textaddr, +- &framesize, exception, NULL)); ++ if (korc->type == ORC_TYPE_CALL) { ++ ulong prev_sp = 0, prev_bp = 0; ++ framesize = -1; ++ ++ if (korc->sp_reg == ORC_REG_SP) { ++ framesize = (korc->sp_offset - 8); ++ ++ /* rsp points to a return address, so +8 to use sp_offset */ ++ prev_sp = (rsp + 8) + korc->sp_offset; ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "rsp: %lx prev_sp: %lx framesize: %d\n", ++ rsp, prev_sp, framesize); ++ } else if ((korc->sp_reg == ORC_REG_BP) && bt->bptr) { ++ prev_sp = bt->bptr + korc->sp_offset; ++ framesize = (prev_sp - (rsp + 8) - 8); ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "rsp: %lx rbp: %lx prev_sp: %lx framesize: %d\n", ++ rsp, bt->bptr, prev_sp, framesize); ++ } ++ ++ if ((korc->bp_reg == ORC_REG_PREV_SP) && prev_sp) { ++ prev_bp = prev_sp + korc->bp_offset; ++ if (stack_ptr && INSTACK(prev_bp, bt)) { ++ bt->bptr = ULONG(stack_ptr + (prev_bp - rsp)); ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "rsp: %lx prev_sp: %lx prev_bp: %lx -> %lx\n", ++ rsp, prev_sp, prev_bp, bt->bptr); ++ } else ++ bt->bptr = 0; ++ } else if ((korc->bp_reg != ORC_REG_UNDEFINED)) ++ bt->bptr = 0; ++ ++ if (framesize >= 0) ++ /* Do not cache this, possibly it may be variable. */ ++ return framesize; + } + } + +@@ -8749,7 +8797,7 @@ x86_64_framesize_debug(struct bt_info *bt) + if (!bt->hp->eip) + error(INFO, "x86_64_framesize_debug: ignoring command\n"); + else +- x86_64_get_framesize(bt, bt->hp->eip, 0); ++ x86_64_get_framesize(bt, bt->hp->eip, 0, NULL); + break; + + case -3: +-- +2.37.1 + diff --git a/SOURCES/0078-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch b/SOURCES/0078-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch new file mode 100644 index 0000000..c81b3a9 --- /dev/null +++ b/SOURCES/0078-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch @@ -0,0 +1,169 @@ +From dbc45587f2c0024f0bc801a967bed9bd8d9f218c Mon Sep 17 00:00:00 2001 +From: Tao Liu +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 +Signed-off-by: Lianbo Jiang +--- + 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 + diff --git a/SOURCES/0079-Enhance-net-command-to-display-IPv6-address-of-netwo.patch b/SOURCES/0079-Enhance-net-command-to-display-IPv6-address-of-netwo.patch new file mode 100644 index 0000000..fd9dfcd --- /dev/null +++ b/SOURCES/0079-Enhance-net-command-to-display-IPv6-address-of-netwo.patch @@ -0,0 +1,258 @@ +From f4acc0e222aedf720e796fd386f2dc15bbb665e9 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Tue, 7 Mar 2023 17:14:25 +0800 +Subject: [PATCH 79/89] Enhance "net" command to display IPv6 address of + network interface + +Currently, the "net" command displays only the IPv4 address of a network +interface. Support outputting IPv6 addresses. For example: + +Without the patch: + crash> net + NET_DEVICE NAME IP ADDRESS(ES) + ffff8d01b1205000 lo 127.0.0.1 + ffff8d0087e40000 eno1 192.168.122.2 + +With the patch: + crash> net + NET_DEVICE NAME IP ADDRESS(ES) + ffff8d01b1205000 lo 127.0.0.1, ::1 + ffff8d0087e40000 eno1 192.168.122.2, xxxx:xx:x:xxxx:xxxx:xxx:xxxx:xxxx, yyyy::yyyy:yyy:yyyy:yyyy + +Also align with longer device names. + +Related kernel commit: +502a2ffd7376 ("ipv6: convert idev_list to list macros") + +Reported-by: Buland Kumar Singh +Signed-off-by: Lianbo Jiang +Signed-off-by: Kazuhito Hagio +--- + defs.h | 6 +++ + net.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++----- + symbols.c | 6 +++ + 3 files changed, 112 insertions(+), 9 deletions(-) + +diff --git a/defs.h b/defs.h +index 3c6fa3b0d228..6cfc21487497 100644 +--- a/defs.h ++++ b/defs.h +@@ -2208,6 +2208,12 @@ struct offset_table { /* stash of commonly-used offsets */ + long sock_common_skc_v6_daddr; + long sock_common_skc_v6_rcv_saddr; + long inactive_task_frame_bp; ++ long net_device_ip6_ptr; ++ long inet6_dev_addr_list; ++ long inet6_ifaddr_addr; ++ long inet6_ifaddr_if_list; ++ long inet6_ifaddr_if_next; ++ long in6_addr_in6_u; + }; + + struct size_table { /* stash of commonly-used sizes */ +diff --git a/net.c b/net.c +index aa445ab7ee13..987dc8934942 100644 +--- a/net.c ++++ b/net.c +@@ -71,6 +71,7 @@ static void print_neighbour_q(ulong, int); + static void get_netdev_info(ulong, struct devinfo *); + static void get_device_name(ulong, char *); + static long get_device_address(ulong, char **, long); ++static void get_device_ip6_address(ulong, char **, long); + static void get_sock_info(ulong, char *); + static void dump_arp(void); + static void arp_state_to_flags(unsigned char); +@@ -114,6 +115,13 @@ net_init(void) + net->dev_ip_ptr = MEMBER_OFFSET_INIT(net_device_ip_ptr, + "net_device", "ip_ptr"); + MEMBER_OFFSET_INIT(net_device_dev_list, "net_device", "dev_list"); ++ MEMBER_OFFSET_INIT(net_device_ip6_ptr, "net_device", "ip6_ptr"); ++ MEMBER_OFFSET_INIT(inet6_dev_addr_list, "inet6_dev", "addr_list"); ++ MEMBER_OFFSET_INIT(inet6_ifaddr_addr, "inet6_ifaddr", "addr"); ++ MEMBER_OFFSET_INIT(inet6_ifaddr_if_list, "inet6_ifaddr", "if_list"); ++ MEMBER_OFFSET_INIT(inet6_ifaddr_if_next, "inet6_ifaddr", "if_next"); ++ MEMBER_OFFSET_INIT(in6_addr_in6_u, "in6_addr", "in6_u"); ++ + MEMBER_OFFSET_INIT(net_dev_base_head, "net", "dev_base_head"); + ARRAY_LENGTH_INIT(net->net_device_name_index, + net_device_name, "net_device.name", NULL, sizeof(char)); +@@ -466,7 +474,7 @@ show_net_devices(ulong task) + buf = GETBUF(buflen); + flen = MAX(VADDR_PRLEN, strlen(net->netdevice)); + +- fprintf(fp, "%s NAME IP ADDRESS(ES)\n", ++ fprintf(fp, "%s NAME IP ADDRESS(ES)\n", + mkstring(upper_case(net->netdevice, buf), + flen, CENTER|LJUST, NULL)); + +@@ -475,9 +483,10 @@ show_net_devices(ulong task) + mkstring(buf, flen, CENTER|RJUST|LONG_HEX, MKSTR(next))); + + get_device_name(next, buf); +- fprintf(fp, "%-6s ", buf); ++ fprintf(fp, "%-10s ", buf); + +- buflen = get_device_address(next, &buf, buflen); ++ get_device_address(next, &buf, buflen); ++ get_device_ip6_address(next, &buf, buflen); + fprintf(fp, "%s\n", buf); + + readmem(next+net->dev_next, KVADDR, &next, +@@ -503,7 +512,7 @@ show_net_devices_v2(ulong task) + buf = GETBUF(buflen); + flen = MAX(VADDR_PRLEN, strlen(net->netdevice)); + +- fprintf(fp, "%s NAME IP ADDRESS(ES)\n", ++ fprintf(fp, "%s NAME IP ADDRESS(ES)\n", + mkstring(upper_case(net->netdevice, buf), + flen, CENTER|LJUST, NULL)); + +@@ -528,9 +537,10 @@ show_net_devices_v2(ulong task) + MKSTR(ld->list_ptr[i]))); + + get_device_name(ld->list_ptr[i], buf); +- fprintf(fp, "%-6s ", buf); ++ fprintf(fp, "%-10s ", buf); + +- buflen = get_device_address(ld->list_ptr[i], &buf, buflen); ++ get_device_address(ld->list_ptr[i], &buf, buflen); ++ get_device_ip6_address(ld->list_ptr[i], &buf, buflen); + fprintf(fp, "%s\n", buf); + } + +@@ -556,7 +566,7 @@ show_net_devices_v3(ulong task) + buf = GETBUF(buflen); + flen = MAX(VADDR_PRLEN, strlen(net->netdevice)); + +- fprintf(fp, "%s NAME IP ADDRESS(ES)\n", ++ fprintf(fp, "%s NAME IP ADDRESS(ES)\n", + mkstring(upper_case(net->netdevice, buf), + flen, CENTER|LJUST, NULL)); + +@@ -591,9 +601,10 @@ show_net_devices_v3(ulong task) + MKSTR(ld->list_ptr[i]))); + + get_device_name(ld->list_ptr[i], buf); +- fprintf(fp, "%-6s ", buf); ++ fprintf(fp, "%-10s ", buf); + +- buflen = get_device_address(ld->list_ptr[i], &buf, buflen); ++ get_device_address(ld->list_ptr[i], &buf, buflen); ++ get_device_ip6_address(ld->list_ptr[i], &buf, buflen); + fprintf(fp, "%s\n", buf); + } + +@@ -925,6 +936,86 @@ get_device_address(ulong devaddr, char **bufp, long buflen) + return buflen; + } + ++static void ++get_device_ip6_address(ulong devaddr, char **bufp, long buflen) ++{ ++ ulong ip6_ptr = 0, pos = 0, bufsize = buflen, addr = 0; ++ struct in6_addr ip6_addr; ++ char *buf; ++ char str[INET6_ADDRSTRLEN] = {0}; ++ char buffer[INET6_ADDRSTRLEN + 2] = {0}; ++ uint len = 0; ++ ++ buf = *bufp; ++ pos = strlen(buf); ++ ++ readmem(devaddr + OFFSET(net_device_ip6_ptr), KVADDR, ++ &ip6_ptr, sizeof(ulong), "ip6_ptr", FAULT_ON_ERROR); ++ ++ if (!ip6_ptr) ++ return; ++ ++ /* ++ * 502a2ffd7376 ("ipv6: convert idev_list to list macros") ++ * v2.6.35-rc1~473^2~733 ++ */ ++ if (VALID_MEMBER(inet6_ifaddr_if_list)) { ++ struct list_data list_data, *ld; ++ ulong cnt = 0, i; ++ ++ ld = &list_data; ++ BZERO(ld, sizeof(struct list_data)); ++ ld->flags |= LIST_ALLOCATE; ++ ld->start = ip6_ptr + OFFSET(inet6_dev_addr_list); ++ ld->list_head_offset = OFFSET(inet6_ifaddr_if_list); ++ cnt = do_list(ld); ++ ++ for (i = 1; i < cnt; i++) { ++ ++ addr = ld->list_ptr[i] + OFFSET(inet6_ifaddr_addr); ++ readmem(addr + OFFSET(in6_addr_in6_u), KVADDR, &ip6_addr, ++ sizeof(struct in6_addr), "in6_addr.in6_u", FAULT_ON_ERROR); ++ ++ inet_ntop(AF_INET6, (void*)&ip6_addr, str, INET6_ADDRSTRLEN); ++ sprintf(buffer, "%s%s", pos ? ", " : "", str); ++ len = strlen(buffer); ++ if (pos + len >= bufsize) { ++ RESIZEBUF(*bufp, bufsize, bufsize + buflen); ++ buf = *bufp; ++ BZERO(buf + bufsize, buflen); ++ bufsize += buflen; ++ } ++ BCOPY(buffer, &buf[pos], len); ++ pos += len; ++ } ++ ++ FREEBUF(ld->list_ptr); ++ return; ++ } ++ ++ readmem(ip6_ptr + OFFSET(inet6_dev_addr_list), KVADDR, ++ &addr, sizeof(void *), "inet6_dev.addr_list", FAULT_ON_ERROR); ++ ++ while (addr) { ++ readmem(addr + OFFSET(in6_addr_in6_u), KVADDR, &ip6_addr, ++ sizeof(struct in6_addr), "in6_addr.in6_u", FAULT_ON_ERROR); ++ inet_ntop(AF_INET6, (void*)&ip6_addr, str, INET6_ADDRSTRLEN); ++ sprintf(buffer, "%s%s", pos ? ", " : "", str); ++ len = strlen(buffer); ++ ++ if (pos + len >= bufsize) { ++ RESIZEBUF(*bufp, bufsize, bufsize + buflen); ++ buf = *bufp; ++ BZERO(buf + bufsize, buflen); ++ bufsize += buflen; ++ } ++ BCOPY(buffer, &buf[pos], len); ++ pos += len; ++ readmem(addr + OFFSET(inet6_ifaddr_if_next), KVADDR, &addr, ++ sizeof(void *), "inet6_ifaddr.if_next", FAULT_ON_ERROR); ++ } ++} ++ + /* + * Get the family, type, local and destination address/port pairs. + */ +diff --git a/symbols.c b/symbols.c +index fc55da678ecd..158c95459bec 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -9799,6 +9799,7 @@ dump_offset_table(char *spec, ulong makestruct) + OFFSET(net_device_addr_len)); + fprintf(fp, " net_device_ip_ptr: %ld\n", + OFFSET(net_device_ip_ptr)); ++ fprintf(fp, " net_device_ip6_ptr: %ld\n", OFFSET(net_device_ip6_ptr)); + fprintf(fp, " net_device_dev_list: %ld\n", + OFFSET(net_device_dev_list)); + fprintf(fp, " net_dev_base_head: %ld\n", +@@ -9851,6 +9852,11 @@ dump_offset_table(char *spec, ulong makestruct) + fprintf(fp, " inet_opt_num: %ld\n", + OFFSET(inet_opt_num)); + ++ fprintf(fp, " inet6_dev_addr_list: %ld\n", OFFSET(inet6_dev_addr_list)); ++ fprintf(fp, " inet6_ifaddr_addr: %ld\n", OFFSET(inet6_ifaddr_addr)); ++ fprintf(fp, " inet6_ifaddr_if_list: %ld\n", OFFSET(inet6_ifaddr_if_list)); ++ fprintf(fp, " inet6_ifaddr_if_next: %ld\n", OFFSET(inet6_ifaddr_if_next)); ++ fprintf(fp, " in6_addr_in6_u: %ld\n", OFFSET(in6_addr_in6_u)); + fprintf(fp, " ipv6_pinfo_rcv_saddr: %ld\n", + OFFSET(ipv6_pinfo_rcv_saddr)); + fprintf(fp, " ipv6_pinfo_daddr: %ld\n", +-- +2.37.1 + diff --git a/SOURCES/0080-Fix-for-net-n-option-to-properly-deal-with-an-invali.patch b/SOURCES/0080-Fix-for-net-n-option-to-properly-deal-with-an-invali.patch new file mode 100644 index 0000000..759e26a --- /dev/null +++ b/SOURCES/0080-Fix-for-net-n-option-to-properly-deal-with-an-invali.patch @@ -0,0 +1,44 @@ +From 0f2e551ef1f9bb10b2fef0c3ac27e9d32488cc47 Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Wed, 8 Mar 2023 20:22:02 +0800 +Subject: [PATCH 80/89] Fix for "net -n" option to properly deal with an + invalid argument + +The help/man page of the "net" command suggests that "-n" option can +accept two kinds of argument: PID or task_struct pointer. However, +the "net -n" command accepts an invalid argument and shows the +namespace of the current context silently. For example: + + crash> net -n 1000000000 + NET_DEVICE NAME IP ADDRESS(ES) + ffff949dc11d7000 lo 127.0.0.1 + ffff949dcc01c000 eno49 192.168.122.17 + +With the patch, emit an error expectedly. + + crash> net -n 1000000000 + net: invalid task or pid value: 1000000000 + +Reported-by: Buland Kumar Singh +Signed-off-by: Lianbo Jiang +--- + net.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net.c b/net.c +index 987dc8934942..18c238be346d 100644 +--- a/net.c ++++ b/net.c +@@ -420,6 +420,9 @@ cmd_net(void) + case STR_PID: + case STR_TASK: + task = tc->task; ++ break; ++ case STR_INVALID: ++ error(FATAL, "invalid task or pid value: %s\n", args[optind]); + } + } + break; +-- +2.37.1 + diff --git a/SOURCES/0081-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch b/SOURCES/0081-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch new file mode 100644 index 0000000..db281af --- /dev/null +++ b/SOURCES/0081-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch @@ -0,0 +1,160 @@ +From b29bd2b531502ca0274ad9c4531417920102fb26 Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Fri, 10 Mar 2023 02:38:26 +0000 +Subject: [PATCH 81/89] Fix "kmem -n" option to display memory blocks on Linux + 6.3-rc1 and later + +Kernel commit d2bf38c088e0 ("driver core: remove private pointer from +struct bus_type") removed the bus_type.p member, and the "kmem -n" +option fails with the following error before displaying memory block +information on Linux 6.3-rc1 and later kernels. + + kmem: invalid structure member offset: bus_type_p + FILE: memory.c LINE: 17852 FUNCTION: init_memory_block() + +Search bus_kset.list instead for subsys_private of memory subsys. + +Signed-off-by: Kazuhito Hagio +Signed-off-by: Lianbo Jiang +--- + defs.h | 2 ++ + memory.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++------ + symbols.c | 2 ++ + 3 files changed, 61 insertions(+), 6 deletions(-) + +diff --git a/defs.h b/defs.h +index 6cfc21487497..9091397a7012 100644 +--- a/defs.h ++++ b/defs.h +@@ -2214,6 +2214,8 @@ struct offset_table { /* stash of commonly-used offsets */ + long inet6_ifaddr_if_list; + long inet6_ifaddr_if_next; + long in6_addr_in6_u; ++ long kset_kobj; ++ long subsys_private_subsys; + }; + + struct size_table { /* stash of commonly-used sizes */ +diff --git a/memory.c b/memory.c +index c4a6ecd18004..592a5ef49d50 100644 +--- a/memory.c ++++ b/memory.c +@@ -17822,6 +17822,13 @@ static void + init_memory_block_offset(void) + { + MEMBER_OFFSET_INIT(bus_type_p, "bus_type", "p"); ++ if (INVALID_MEMBER(bus_type_p)) { ++ MEMBER_OFFSET_INIT(kset_list, "kset", "list"); ++ MEMBER_OFFSET_INIT(kset_kobj, "kset", "kobj"); ++ MEMBER_OFFSET_INIT(kobject_name, "kobject", "name"); ++ MEMBER_OFFSET_INIT(kobject_entry, "kobject", "entry"); ++ MEMBER_OFFSET_INIT(subsys_private_subsys, "subsys_private", "subsys"); ++ } + MEMBER_OFFSET_INIT(subsys_private_klist_devices, + "subsys_private", "klist_devices"); + MEMBER_OFFSET_INIT(klist_k_list, "klist", "k_list"); +@@ -17842,15 +17849,60 @@ init_memory_block_offset(void) + } + + static void +-init_memory_block(struct list_data *ld, int *klistcnt, ulong **klistbuf) ++init_memory_block(int *klistcnt, ulong **klistbuf) + { +- ulong memory_subsys = symbol_value("memory_subsys"); + ulong private, klist, start; ++ struct list_data list_data, *ld; ++ ++ ld = &list_data; ++ private = 0; + + init_memory_block_offset(); + +- readmem(memory_subsys + OFFSET(bus_type_p), KVADDR, &private, +- sizeof(void *), "memory_subsys.private", FAULT_ON_ERROR); ++ /* ++ * v6.3-rc1 ++ * d2bf38c088e0 driver core: remove private pointer from struct bus_type ++ */ ++ if (INVALID_MEMBER(bus_type_p)) { ++ int i, cnt; ++ char buf[32]; ++ ulong bus_kset, list, name; ++ ++ BZERO(ld, sizeof(struct list_data)); ++ ++ get_symbol_data("bus_kset", sizeof(ulong), &bus_kset); ++ readmem(bus_kset + OFFSET(kset_list), KVADDR, &list, ++ sizeof(ulong), "bus_kset.list", FAULT_ON_ERROR); ++ ++ ld->flags |= LIST_ALLOCATE; ++ ld->start = list; ++ ld->end = bus_kset + OFFSET(kset_list); ++ ld->list_head_offset = OFFSET(kobject_entry); ++ ++ cnt = do_list(ld); ++ for (i = 0; i < cnt; i++) { ++ readmem(ld->list_ptr[i] + OFFSET(kobject_name), KVADDR, &name, ++ sizeof(ulong), "kobject.name", FAULT_ON_ERROR); ++ read_string(name, buf, sizeof(buf)-1); ++ if (CRASHDEBUG(1)) ++ fprintf(fp, "kobject: %lx name: %s\n", ld->list_ptr[i], buf); ++ if (STREQ(buf, "memory")) { ++ /* entry is subsys_private.subsys.kobj. See bus_to_subsys(). */ ++ private = ld->list_ptr[i] - OFFSET(kset_kobj) ++ - OFFSET(subsys_private_subsys); ++ break; ++ } ++ } ++ FREEBUF(ld->list_ptr); ++ } else { ++ ulong memory_subsys = symbol_value("memory_subsys"); ++ readmem(memory_subsys + OFFSET(bus_type_p), KVADDR, &private, ++ sizeof(void *), "memory_subsys.private", FAULT_ON_ERROR); ++ } ++ ++ if (!private) ++ error(FATAL, "cannot determine subsys_private for memory.\n"); ++ + klist = private + OFFSET(subsys_private_klist_devices) + + OFFSET(klist_k_list); + BZERO(ld, sizeof(struct list_data)); +@@ -17875,7 +17927,6 @@ dump_memory_blocks(int initialize) + ulong memory_block, device; + ulong *klistbuf; + int klistcnt, i; +- struct list_data list_data; + char mb_hdr[BUFSIZE]; + char paddr_hdr[BUFSIZE]; + char buf1[BUFSIZE]; +@@ -17892,7 +17943,7 @@ dump_memory_blocks(int initialize) + if (initialize) + return; + +- init_memory_block(&list_data, &klistcnt, &klistbuf); ++ init_memory_block(&klistcnt, &klistbuf); + + if ((symbol_exists("memory_block_size_probed")) || + (MEMBER_EXISTS("memory_block", "end_section_nr"))) +diff --git a/symbols.c b/symbols.c +index 158c95459bec..1d083b876f87 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -10416,6 +10416,7 @@ dump_offset_table(char *spec, ulong makestruct) + OFFSET(kobject_entry)); + fprintf(fp, " kset_list: %ld\n", + OFFSET(kset_list)); ++ fprintf(fp, " kset_kobj: %ld\n", OFFSET(kset_kobj)); + fprintf(fp, " request_list_count: %ld\n", + OFFSET(request_list_count)); + fprintf(fp, " request_cmd_flags: %ld\n", +@@ -10453,6 +10454,7 @@ dump_offset_table(char *spec, ulong makestruct) + fprintf(fp, " blk_mq_tags_rqs: %ld\n", + OFFSET(blk_mq_tags_rqs)); + ++ fprintf(fp, " subsys_private_subsys: %ld\n", OFFSET(subsys_private_subsys)); + fprintf(fp, " subsys_private_klist_devices: %ld\n", + OFFSET(subsys_private_klist_devices)); + fprintf(fp, " subsystem_kset: %ld\n", +-- +2.37.1 + diff --git a/SOURCES/0082-xen-fix-stacksize.patch b/SOURCES/0082-xen-fix-stacksize.patch new file mode 100644 index 0000000..f9627af --- /dev/null +++ b/SOURCES/0082-xen-fix-stacksize.patch @@ -0,0 +1,33 @@ +From ba48bd462728515dd3eed562f1a97125e3417ceb Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Wed, 15 Mar 2023 12:18:48 +0100 +Subject: [PATCH 82/89] xen: fix stacksize + +The size of the percpu stack area of Xen on x86_64 is 8 pages, not 2. +This is the case since Xen commit 0b630aa340ec in 2007. + +While not really critical in its current usage, it should be corrected +nevertheless. + +Signed-off-by: Juergen Gross +Signed-off-by: Lianbo Jiang +--- + x86_64.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/x86_64.c b/x86_64.c +index 86abea00c9d6..619b9f566613 100644 +--- a/x86_64.c ++++ b/x86_64.c +@@ -8104,7 +8104,7 @@ x86_64_init_hyper(int when) + machdep->pageshift = ffs(machdep->pagesize) - 1; + machdep->pageoffset = machdep->pagesize - 1; + machdep->pagemask = ~((ulonglong)machdep->pageoffset); +- machdep->stacksize = machdep->pagesize * 2; ++ machdep->stacksize = machdep->pagesize * 8; + if ((machdep->pgd = (char *)malloc(PAGESIZE())) == NULL) + error(FATAL, "cannot malloc pgd space."); + if ((machdep->pud = (char *)malloc(PAGESIZE())) == NULL) +-- +2.37.1 + diff --git a/SOURCES/0083-xen-get-stack-address-via-stack_base-array-if-availa.patch b/SOURCES/0083-xen-get-stack-address-via-stack_base-array-if-availa.patch new file mode 100644 index 0000000..4e811ea --- /dev/null +++ b/SOURCES/0083-xen-get-stack-address-via-stack_base-array-if-availa.patch @@ -0,0 +1,111 @@ +From 907516256dd60ed20feaa2a8fd9e2bf148099ec3 Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Wed, 15 Mar 2023 12:18:49 +0100 +Subject: [PATCH 83/89] xen: get stack address via stack_base array if + available + +Since many years now the stack address of each percpu stack is +available via the stack_base[] array (Xen commit 3cb68d2b59ab made +it visible). Use that instead of the indirect method via the percpu +variables tss_init or tss_page, especially as the layout of tss_page +has changed in Xen 4.16 (Xen commit 91d26ed304ff5), resulting in the +stack no longer to be found. + +Signed-off-by: Juergen Gross +Signed-off-by: Lianbo Jiang +--- + xen_hyper.c | 56 ++++++++++++++++++++++++++++++----------------------- + 1 file changed, 32 insertions(+), 24 deletions(-) + +diff --git a/xen_hyper.c b/xen_hyper.c +index 1030c0ae25d7..19501de94f4b 100644 +--- a/xen_hyper.c ++++ b/xen_hyper.c +@@ -324,7 +324,7 @@ void + xen_hyper_x86_pcpu_init(void) + { + ulong cpu_info; +- ulong init_tss_base, init_tss; ++ ulong init_tss_base, init_tss, stack_base = 0; + ulong sp; + struct xen_hyper_pcpu_context *pcc; + char *buf, *bp; +@@ -340,34 +340,40 @@ xen_hyper_x86_pcpu_init(void) + } + /* get physical cpu context */ + xen_hyper_alloc_pcpu_context_space(XEN_HYPER_MAX_CPUS()); +- if (symbol_exists("per_cpu__init_tss")) { ++ if (symbol_exists("stack_base")) { ++ stack_base = symbol_value("stack_base"); ++ flag = 0; ++ } else if (symbol_exists("per_cpu__init_tss")) { + init_tss_base = symbol_value("per_cpu__init_tss"); +- flag = TRUE; ++ flag = 1; + } else if (symbol_exists("per_cpu__tss_page")) { +- init_tss_base = symbol_value("per_cpu__tss_page"); +- flag = TRUE; ++ init_tss_base = symbol_value("per_cpu__tss_page"); ++ flag = 1; + } else { + init_tss_base = symbol_value("init_tss"); +- flag = FALSE; ++ flag = 2; + } +- buf = GETBUF(XEN_HYPER_SIZE(tss)); ++ if (flag) ++ buf = GETBUF(XEN_HYPER_SIZE(tss)); + for_cpu_indexes(i, cpuid) + { +- if (flag) +- init_tss = xen_hyper_per_cpu(init_tss_base, cpuid); +- else +- init_tss = init_tss_base + +- XEN_HYPER_SIZE(tss) * cpuid; +- if (!readmem(init_tss, KVADDR, buf, +- XEN_HYPER_SIZE(tss), "init_tss", RETURN_ON_ERROR)) { +- error(FATAL, "cannot read init_tss.\n"); +- } +- if (machine_type("X86")) { +- sp = ULONG(buf + XEN_HYPER_OFFSET(tss_esp0)); +- } else if (machine_type("X86_64")) { +- sp = ULONG(buf + XEN_HYPER_OFFSET(tss_rsp0)); +- } else +- sp = 0; ++ if (flag) { ++ if (flag == 1) ++ init_tss = xen_hyper_per_cpu(init_tss_base, cpuid); ++ else ++ init_tss = init_tss_base + XEN_HYPER_SIZE(tss) * cpuid; ++ readmem(init_tss, KVADDR, buf, ++ XEN_HYPER_SIZE(tss), "init_tss", FAULT_ON_ERROR); ++ if (machine_type("X86")) { ++ sp = ULONG(buf + XEN_HYPER_OFFSET(tss_esp0)); ++ } else if (machine_type("X86_64")) { ++ sp = ULONG(buf + XEN_HYPER_OFFSET(tss_rsp0)); ++ } else ++ sp = 0; ++ } else { ++ readmem(stack_base + sizeof(ulong) * cpuid, KVADDR, &sp, ++ sizeof(ulong), "stack_base", FAULT_ON_ERROR); ++ } + cpu_info = XEN_HYPER_GET_CPU_INFO(sp); + if (CRASHDEBUG(1)) { + fprintf(fp, "sp=%lx, cpu_info=%lx\n", sp, cpu_info); +@@ -377,9 +383,11 @@ xen_hyper_x86_pcpu_init(void) + } + pcc = &xhpct->context_array[cpuid]; + xen_hyper_store_pcpu_context(pcc, cpu_info, bp); +- xen_hyper_store_pcpu_context_tss(pcc, init_tss, buf); ++ if (flag) ++ xen_hyper_store_pcpu_context_tss(pcc, init_tss, buf); + } +- FREEBUF(buf); ++ if (flag) ++ FREEBUF(buf); + } + + #elif defined(IA64) +-- +2.37.1 + diff --git a/SOURCES/0084-xen-adjust-to-new-scheduler-structures.patch b/SOURCES/0084-xen-adjust-to-new-scheduler-structures.patch new file mode 100644 index 0000000..e7c8192 --- /dev/null +++ b/SOURCES/0084-xen-adjust-to-new-scheduler-structures.patch @@ -0,0 +1,178 @@ +From 9e8155297e16f8d8804d151dd75cc489447c1fe7 Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Wed, 15 Mar 2023 12:18:50 +0100 +Subject: [PATCH 84/89] xen: adjust to new scheduler structures + +There has been a significant modification regarding scheduler data in +the Xen hypervisor (Xen commit d62fefa4d459). Adapt to new structures +and removed fields. + +Note that this is only the bare minimum to not let crash error out when +opening a vmcore in Xen mode with a recent Xen version. + +Signed-off-by: Juergen Gross +Signed-off-by: Lianbo Jiang +--- + xen_hyper.c | 63 +++++++++++++++++++++++++++-------------- + xen_hyper_defs.h | 4 ++- + xen_hyper_dump_tables.c | 4 +++ + 3 files changed, 49 insertions(+), 22 deletions(-) + +diff --git a/xen_hyper.c b/xen_hyper.c +index 19501de94f4b..dbbfdaa3c154 100644 +--- a/xen_hyper.c ++++ b/xen_hyper.c +@@ -415,13 +415,21 @@ void + xen_hyper_misc_init(void) + { + XEN_HYPER_STRUCT_SIZE_INIT(schedule_data, "schedule_data"); +- XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_schedule_lock, "schedule_data", "schedule_lock"); +- XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_curr, "schedule_data", "curr"); +- if (MEMBER_EXISTS("schedule_data", "idle")) +- XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_idle, "schedule_data", "idle"); +- XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_sched_priv, "schedule_data", "sched_priv"); +- XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_s_timer, "schedule_data", "s_timer"); +- XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_tick, "schedule_data", "tick"); ++ XEN_HYPER_STRUCT_SIZE_INIT(sched_resource, "sched_resource"); ++ if (XEN_HYPER_VALID_SIZE(schedule_data)) { ++ XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_schedule_lock, "schedule_data", "schedule_lock"); ++ XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_curr, "schedule_data", "curr"); ++ if (MEMBER_EXISTS("schedule_data", "idle")) ++ XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_idle, "schedule_data", "idle"); ++ XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_sched_priv, "schedule_data", "sched_priv"); ++ XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_s_timer, "schedule_data", "s_timer"); ++ XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_tick, "schedule_data", "tick"); ++ } else if (XEN_HYPER_VALID_SIZE(sched_resource)) { ++ XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_schedule_lock, "sched_resource", "schedule_lock"); ++ XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_curr, "sched_resource", "curr"); ++ XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_sched_priv, "sched_resource", "sched_priv"); ++ XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_s_timer, "sched_resource", "s_timer"); ++ } + + XEN_HYPER_STRUCT_SIZE_INIT(scheduler, "scheduler"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_name, "scheduler", "name"); +@@ -465,6 +473,7 @@ xen_hyper_schedule_init(void) + long *schedulers_buf; + int nr_schedulers; + struct xen_hyper_sched_context *schc; ++ long buf_size; + char *buf; + char opt_name_buf[XEN_HYPER_OPT_SCHED_SIZE]; + int i, cpuid, flag; +@@ -559,28 +568,39 @@ xen_hyper_schedule_init(void) + } + BZERO(xhscht->sched_context_array, + sizeof(struct xen_hyper_sched_context) * XEN_HYPER_MAX_CPUS()); +- buf = GETBUF(XEN_HYPER_SIZE(schedule_data)); +- if (symbol_exists("per_cpu__schedule_data")) { ++ if (symbol_exists("per_cpu__sched_res")) { ++ addr = symbol_value("per_cpu__sched_res"); ++ buf_size = XEN_HYPER_SIZE(sched_resource); ++ flag = 0; ++ } else if (symbol_exists("per_cpu__schedule_data")) { + addr = symbol_value("per_cpu__schedule_data"); +- flag = TRUE; ++ buf_size = XEN_HYPER_SIZE(schedule_data); ++ flag = 1; + } else { + addr = symbol_value("schedule_data"); +- flag = FALSE; ++ buf_size = XEN_HYPER_SIZE(schedule_data); ++ flag = 2; + } ++ buf = GETBUF(buf_size); + for_cpu_indexes(i, cpuid) + { + schc = &xhscht->sched_context_array[cpuid]; + if (flag) { +- schc->schedule_data = +- xen_hyper_per_cpu(addr, i); ++ if (flag == 1) { ++ schc->schedule_data = ++ xen_hyper_per_cpu(addr, i); ++ } else { ++ schc->schedule_data = addr + ++ XEN_HYPER_SIZE(schedule_data) * i; ++ } ++ readmem(schc->schedule_data, ++ KVADDR, buf, XEN_HYPER_SIZE(schedule_data), ++ "schedule_data", FAULT_ON_ERROR); + } else { +- schc->schedule_data = addr + +- XEN_HYPER_SIZE(schedule_data) * i; +- } +- if (!readmem(schc->schedule_data, +- KVADDR, buf, XEN_HYPER_SIZE(schedule_data), +- "schedule_data", RETURN_ON_ERROR)) { +- error(FATAL, "cannot read schedule_data.\n"); ++ schc->sched_resource = xen_hyper_per_cpu(addr, i); ++ readmem(schc->sched_resource, ++ KVADDR, buf, XEN_HYPER_SIZE(sched_resource), ++ "sched_resource", FAULT_ON_ERROR); + } + schc->cpu_id = cpuid; + schc->curr = ULONG(buf + XEN_HYPER_OFFSET(schedule_data_curr)); +@@ -1597,7 +1617,8 @@ xen_hyper_store_vcpu_context(struct xen_hyper_vcpu_context *vcc, + vcc->next_in_list = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_next_in_list)); + if (XEN_HYPER_VALID_MEMBER(vcpu_sleep_tick)) + vcc->sleep_tick = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_sleep_tick)); +- vcc->sched_priv = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_sched_priv)); ++ if (XEN_HYPER_VALID_MEMBER(vcpu_sched_priv)) ++ vcc->sched_priv = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_sched_priv)); + vcc->state = INT(vcp + XEN_HYPER_OFFSET(vcpu_runstate) + + XEN_HYPER_OFFSET(vcpu_runstate_info_state)); + vcc->state_entry_time = ULONGLONG(vcp + +diff --git a/xen_hyper_defs.h b/xen_hyper_defs.h +index acf910abe15e..dccc6ebff109 100644 +--- a/xen_hyper_defs.h ++++ b/xen_hyper_defs.h +@@ -551,6 +551,7 @@ struct xen_hyper_sched_context { + ulong idle; + ulong sched_priv; + ulong tick; ++ ulong sched_resource; + }; + + struct xen_hyper_sched_table { +@@ -602,6 +603,7 @@ struct xen_hyper_size_table { + long vcpu; + long vcpu_runstate_info; + long xen_crash_xen_regs_t; /* elf note v2 */ ++ long sched_resource; + }; + + struct xen_hyper_offset_table { +@@ -692,7 +694,7 @@ struct xen_hyper_offset_table { + /* mm_struct */ + long mm_struct_pgd; + #endif +- /* schedule_data */ ++ /* schedule_data or sched_resource */ + long schedule_data_schedule_lock; + long schedule_data_curr; + long schedule_data_idle; +diff --git a/xen_hyper_dump_tables.c b/xen_hyper_dump_tables.c +index 0360d25740ac..227ffc4ae4e4 100644 +--- a/xen_hyper_dump_tables.c ++++ b/xen_hyper_dump_tables.c +@@ -558,6 +558,8 @@ xen_hyper_dump_xen_hyper_sched_table(int verbose) + flag, (buf, "%d]\n", i)); + XEN_HYPER_PRI(fp, len, "schedule_data: ", buf, flag, + (buf, "%lx\n", schc->schedule_data)); ++ XEN_HYPER_PRI(fp, len, "sched_resource: ", buf, flag, ++ (buf, "%lx\n", schc->sched_resource)); + XEN_HYPER_PRI(fp, len, "curr: ", buf, flag, + (buf, "%lx\n", schc->curr)); + XEN_HYPER_PRI(fp, len, "idle: ", buf, flag, +@@ -630,6 +632,8 @@ xen_hyper_dump_xen_hyper_size_table(char *spec, ulong makestruct) + (buf, "%ld\n", xen_hyper_size_table.note_buf_t)); + XEN_HYPER_PRI(fp, len, "schedule_data: ", buf, flag, + (buf, "%ld\n", xen_hyper_size_table.schedule_data)); ++ XEN_HYPER_PRI(fp, len, "sched_resource: ", buf, flag, ++ (buf, "%ld\n", xen_hyper_size_table.sched_resource)); + XEN_HYPER_PRI(fp, len, "scheduler: ", buf, flag, + (buf, "%ld\n", xen_hyper_size_table.scheduler)); + XEN_HYPER_PRI(fp, len, "shared_info: ", buf, flag, +-- +2.37.1 + diff --git a/SOURCES/0085-Fix-vm-M-option-to-properly-deal-with-an-invalid-arg.patch b/SOURCES/0085-Fix-vm-M-option-to-properly-deal-with-an-invalid-arg.patch new file mode 100644 index 0000000..801d2f6 --- /dev/null +++ b/SOURCES/0085-Fix-vm-M-option-to-properly-deal-with-an-invalid-arg.patch @@ -0,0 +1,70 @@ +From 1cebb3d75b45fedc734dac8563782a3e6d86f23b Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Thu, 23 Mar 2023 13:18:07 +0800 +Subject: [PATCH 85/89] Fix "vm -M" option to properly deal with an invalid + argument + +The "vm -M" option can accept an invalid address and print the virtual +memory data of a task without an error like this: + + crash> vm -M 0xdeadbeef + PID: 92960 TASK: ffff99157976cc80 CPU: 0 COMMAND: "crash" + MM PGD RSS TOTAL_VM + ffff991573bfdf00 ffff9915857f2000 449020k 2427076k + VMA START END FLAGS FILE + ffff99158718d1c8 400000 4de000 8000071 /home/crash/crash + ... + +The reasons are +- htoll() only converts a hexadecimal string to an unsigned long long + value and does not evaluate whether it's a valid kernel virtual + address or not, and +- The specified value is used only when the task's mm_struct is NULL. + +Also, this behavior is not described enough in its help text, so it's +confusing for users. + +Let's add a check on the converted value regardless of the task's +mm_struct and add a description of the behavior to its help text. + +With the patch: + crash> vm -M 0xdeadbeef + vm: invalid mm_struct address: 0xdeadbeef + +Reported-by: Buland Kumar Singh +Signed-off-by: Lianbo Jiang +[ kh: rewrote commit message ] +Signed-off-by: Kazuhito Hagio +--- + help.c | 1 + + memory.c | 2 ++ + 2 files changed, 3 insertions(+) + +diff --git a/help.c b/help.c +index 7ceefa06732b..738bbca2e563 100644 +--- a/help.c ++++ b/help.c +@@ -4701,6 +4701,7 @@ char *help_vm[] = { + " However, if the address can be determined from the kernel stack,", + " it can be entered manually in order to try to resurrect the", + " virtual memory data of the task.", ++" NOTE: this option is only used when the task's mm_struct is NULL.", + " -R reference search for references to this number or filename.", + " -m dump the mm_struct associated with the task.", + " -v dump all of the vm_area_structs associated with the task.", +diff --git a/memory.c b/memory.c +index 592a5ef49d50..0568f18eb9b7 100644 +--- a/memory.c ++++ b/memory.c +@@ -3559,6 +3559,8 @@ cmd_vm(void) + case 'M': + pc->curcmd_private = htoll(optarg, FAULT_ON_ERROR, NULL); + pc->curcmd_flags |= MM_STRUCT_FORCE; ++ if (!IS_KVADDR(pc->curcmd_private)) ++ error(FATAL, "invalid mm_struct address: %s\n", optarg); + break; + + case 'f': +-- +2.37.1 + diff --git a/SOURCES/0086-Fix-fuser-command-to-properly-deal-with-an-invalid-a.patch b/SOURCES/0086-Fix-fuser-command-to-properly-deal-with-an-invalid-a.patch new file mode 100644 index 0000000..a45d85a --- /dev/null +++ b/SOURCES/0086-Fix-fuser-command-to-properly-deal-with-an-invalid-a.patch @@ -0,0 +1,81 @@ +From a83349d6ce9773f151a7f88e032c259f94a2fbde Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Mon, 10 Apr 2023 11:41:16 +0800 +Subject: [PATCH 86/89] Fix "fuser" command to properly deal with an invalid + argument + +The man page of the "fuser" command suggests that the argument can be a +full pathname or inode address. However, the "fuser" command accepts an +invalid argument and prints a bogus result as below: + + crash> fuser x + PID TASK COMM USAGE + 100507 ffff9914431f4c80 "packagekitd" fd + 100508 ffff991574e59980 "gmain" fd + 100509 ffff9914431f3300 "gdbus" fd + 102020 ffff991574400000 "sshd" fd + 102043 ffff991441d19980 "sshd" fd + +The current fuser command has no checking mechanism to determine if an +argument is valid or not. Let's add it to handle such cases. + +With the patch: + crash> fuser x + fuser: invalid argument: x + +In addition, also add a note that fuser does not expect an argument other +than an inode address and full pathname, and if others are specified, the +output can be an unexpected result. + +Reported-by: Buland Kumar Singh +Signed-off-by: Lianbo Jiang +Signed-off-by: Kazuhito Hagio +--- + filesys.c | 8 +++++++- + help.c | 4 ++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/filesys.c b/filesys.c +index d64b54a9b822..1d0ee7f0b24a 100644 +--- a/filesys.c ++++ b/filesys.c +@@ -3398,6 +3398,7 @@ cmd_fuser(void) + char fuser_header[BUFSIZE]; + int doing_fds, doing_mmap, len; + int fuser_header_printed, lockd_header_printed; ++ ulong spec_addr; + + while ((c = getopt(argcnt, args, "")) != EOF) { + switch(c) +@@ -3421,7 +3422,12 @@ cmd_fuser(void) + + doing_fds = doing_mmap = 0; + while (args[optind]) { +- spec_string = args[optind]; ++ spec_string = args[optind]; ++ spec_addr = htol(spec_string, RETURN_ON_ERROR|QUIET, NULL); ++ if ((spec_addr == BADADDR || !IS_KVADDR(spec_addr)) && ++ spec_string[0] != '/') ++ error(FATAL, "invalid argument: %s\n", args[optind]); ++ + if (STRNEQ(spec_string, "0x") && hexadecimal(spec_string, 0)) + shift_string_left(spec_string, 2); + len = strlen(spec_string); +diff --git a/help.c b/help.c +index 738bbca2e563..26f0d75b8699 100644 +--- a/help.c ++++ b/help.c +@@ -7996,6 +7996,10 @@ char *help_fuser[] = { + " listed.\n", + " pathname the full pathname of the file.", + " inode the hexadecimal inode address for the file.", ++"", ++" NOTE: This commmand does not expect arguments other than inode address", ++" or full pathname. If others are specified, the command may accept them,", ++" but an unexpected output can be displayed.", + "\nEXAMPLES", + " Display the tasks using file /usr/lib/libkfm.so.2.0.0\n", + " %s> fuser /usr/lib/libkfm.so.2.0.0", +-- +2.37.1 + diff --git a/SOURCES/0087-Replace-lseek-read-into-pread-for-kcore-and-vmcore-r.patch b/SOURCES/0087-Replace-lseek-read-into-pread-for-kcore-and-vmcore-r.patch new file mode 100644 index 0000000..48072e5 --- /dev/null +++ b/SOURCES/0087-Replace-lseek-read-into-pread-for-kcore-and-vmcore-r.patch @@ -0,0 +1,115 @@ +From a447ef800c93ab5bbde91a1e7751cf13c2e831fb Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Thu, 20 Apr 2023 18:25:22 +0800 +Subject: [PATCH 87/89] Replace lseek/read into pread for kcore and vmcore + reading + +Previously crash uses lseek/read for kcore and vmcore reading, this involves +2 syscalls. And we can replace them with pread, only 1 syscall is needed for +kcore/vmcore reading, and we can have a better performance. Please note there +are plenty of places in crash using lseek/read, this patch doesn't modify all +of them, just the most commonly used kcore and diskdump vmcore reading. + +Signed-off-by: Tao Liu +Signed-off-by: Lianbo Jiang +--- + diskdump.c | 25 +++++++++++++++++++------ + netdump.c | 15 ++++++++++----- + 2 files changed, 29 insertions(+), 11 deletions(-) + +diff --git a/diskdump.c b/diskdump.c +index 90e67d7df1db..1f3685cea89e 100644 +--- a/diskdump.c ++++ b/diskdump.c +@@ -515,16 +515,22 @@ arm_kdump_header_adjust(int header_version) + static int + read_pd(int fd, off_t offset, page_desc_t *pd) + { +- const off_t failed = (off_t)-1; ++ int ret; + + if (FLAT_FORMAT()) { + if (!read_flattened_format(fd, offset, pd, sizeof(*pd))) + return READ_ERROR; + } else { +- if (lseek(fd, offset, SEEK_SET) == failed) ++ if (offset < 0) { ++ if (CRASHDEBUG(8)) ++ fprintf(fp, "read_pd: invalid offset: %lx\n", offset); + return SEEK_ERROR; +- if (read(fd, pd, sizeof(*pd)) != sizeof(*pd)) ++ } ++ if ((ret = pread(fd, pd, sizeof(*pd), offset)) != sizeof(*pd)) { ++ if (ret == -1 && CRASHDEBUG(8)) ++ fprintf(fp, "read_pd: pread error: %s\n", strerror(errno)); + return READ_ERROR; ++ } + } + + return 0; +@@ -1125,7 +1131,6 @@ cache_page(physaddr_t paddr) + off_t seek_offset; + page_desc_t pd; + const int block_size = dd->block_size; +- const off_t failed = (off_t)-1; + ulong retlen; + #ifdef ZSTD + static ZSTD_DCtx *dctx = NULL; +@@ -1190,10 +1195,18 @@ cache_page(physaddr_t paddr) + return PAGE_INCOMPLETE; + } + } else { +- if (lseek(dd->dfd, pd.offset, SEEK_SET) == failed) ++ if (pd.offset < 0) { ++ if (CRASHDEBUG(8)) ++ fprintf(fp, "read_diskdump/cache_page: invalid offset: %lx\n", ++ pd.offset); + return SEEK_ERROR; +- if (read(dd->dfd, dd->compressed_page, pd.size) != pd.size) ++ } ++ if ((ret = pread(dd->dfd, dd->compressed_page, pd.size, pd.offset)) != pd.size) { ++ if (ret == -1 && CRASHDEBUG(8)) ++ fprintf(fp, "read_diskdump/cache_page: pread error: %s\n", ++ strerror(errno)); + return READ_ERROR; ++ } + } + + if (pd.flags & DUMP_DH_COMPRESSED_ZLIB) { +diff --git a/netdump.c b/netdump.c +index 4ef5807a641b..04a49e5515bb 100644 +--- a/netdump.c ++++ b/netdump.c +@@ -4336,7 +4336,7 @@ no_nt_prstatus_exists: + int + read_proc_kcore(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr) + { +- int i; ++ int i, ret; + size_t readcnt; + ulong kvaddr; + Elf32_Phdr *lp32; +@@ -4436,11 +4436,16 @@ read_proc_kcore(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr) + if (offset == UNINITIALIZED) + return SEEK_ERROR; + +- if (lseek(fd, offset, SEEK_SET) != offset) +- perror("lseek"); +- +- if (read(fd, bufptr, readcnt) != readcnt) ++ if (offset < 0) { ++ if (CRASHDEBUG(8)) ++ fprintf(fp, "read_proc_kcore: invalid offset: %lx\n", offset); ++ return SEEK_ERROR; ++ } ++ if ((ret = pread(fd, bufptr, readcnt, offset)) != readcnt) { ++ if (ret == -1 && CRASHDEBUG(8)) ++ fprintf(fp, "read_proc_kcore: pread error: %s\n", strerror(errno)); + return READ_ERROR; ++ } + + return cnt; + } +-- +2.37.1 + diff --git a/SOURCES/0088-Fix-net-command-on-kernel-configured-with-CONFIG_IPV.patch b/SOURCES/0088-Fix-net-command-on-kernel-configured-with-CONFIG_IPV.patch new file mode 100644 index 0000000..26dfc8a --- /dev/null +++ b/SOURCES/0088-Fix-net-command-on-kernel-configured-with-CONFIG_IPV.patch @@ -0,0 +1,36 @@ +From a1d0ff0e0d113ada3b4baac25c583be7c96b0950 Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Tue, 25 Apr 2023 09:31:04 +0900 +Subject: [PATCH 88/89] Fix "net" command on kernel configured with + CONFIG_IPV6=m + +On a kernel configured with CONFIG_IPV6=m, struct inet6_ifaddr is not +defined in kernel. Without the patch, the "net" command fails with the +following error. + + net: invalid structure member offset: inet6_ifaddr_if_next + FILE: net.c LINE: 1017 FUNCTION: get_device_ip6_address() + +Signed-off-by: Lianbo Jiang +Signed-off-by: Kazuhito Hagio +--- + net.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net.c b/net.c +index 18c238be346d..31d3f2bf7c2f 100644 +--- a/net.c ++++ b/net.c +@@ -996,6 +996,9 @@ get_device_ip6_address(ulong devaddr, char **bufp, long buflen) + return; + } + ++ if (INVALID_MEMBER(inet6_ifaddr_if_next)) ++ return; ++ + readmem(ip6_ptr + OFFSET(inet6_dev_addr_list), KVADDR, + &addr, sizeof(void *), "inet6_dev.addr_list", FAULT_ON_ERROR); + +-- +2.37.1 + diff --git a/SOURCES/0089-gdb-7.6-fix-for-whatis-command-causes-crash-coredump.patch b/SOURCES/0089-gdb-7.6-fix-for-whatis-command-causes-crash-coredump.patch new file mode 100644 index 0000000..d349d8e --- /dev/null +++ b/SOURCES/0089-gdb-7.6-fix-for-whatis-command-causes-crash-coredump.patch @@ -0,0 +1,38 @@ +From 8986cceb699a27c720b42a9b2456f8e19d5422cd Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Mon, 8 May 2023 17:05:49 +0800 +Subject: [PATCH 89/89] gdb-7.6: fix for whatis command causes crash coredump + +8ecb59f85679 ("Print non-Ada unions without crashing") +* cp-abi.c (value_rtti_type): Check HAVE_CPLUS_STRUCT. + +This is a RHEL-Only patch. + +Signed-off-by: Lianbo Jiang +--- + gdb-7.6.patch | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/gdb-7.6.patch b/gdb-7.6.patch +index d0becd055666..f25f5f159e50 100644 +--- a/gdb-7.6.patch ++++ b/gdb-7.6.patch +@@ -2601,3 +2601,15 @@ diff -up gdb-7.6/opcodes/configure.orig gdb-7.6/opcodes/configure + + /* If the nearest symbol is too far away, don't print anything symbolic. */ + ++--- gdb-7.6/gdb/cp-abi.c.orig +++++ gdb-7.6/gdb/cp-abi.c ++@@ -113,7 +113,8 @@ value_rtti_type (struct value *v, int *full, ++ struct type *ret = NULL; ++ volatile struct gdb_exception e; ++ ++- if ((current_cp_abi.rtti_type) == NULL) +++ if ((current_cp_abi.rtti_type) == NULL || +++ !HAVE_CPLUS_STRUCT (check_typedef (value_type (v)))) ++ return NULL; ++ TRY_CATCH (e, RETURN_MASK_ERROR) ++ { +-- +2.37.1 + diff --git a/SOURCES/rhel8-freepointer.patch b/SOURCES/rhel8-freepointer.patch new file mode 100644 index 0000000..eebd657 --- /dev/null +++ b/SOURCES/rhel8-freepointer.patch @@ -0,0 +1,31 @@ +From d39b714d36c12e17c9e3359dd283adbb0693458e Mon Sep 17 00:00:00 2001 +From: Lianbo Jiang +Date: Mon, 8 May 2023 21:51:02 +0800 +Subject: [PATCH] rhel8 freepointer + +CONFIG_SLAB_FREELIST_HARDENED=y + +This is a RHEL-Only patch. + +Signed-off-by: Lianbo Jiang +--- + memory.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/memory.c b/memory.c +index 0568f18eb9b7..82d4214be066 100644 +--- a/memory.c ++++ b/memory.c +@@ -19671,7 +19671,8 @@ freelist_ptr(struct meminfo *si, ulong ptr, ulong ptr_addr) + if (VALID_MEMBER(kmem_cache_random)) { + /* CONFIG_SLAB_FREELIST_HARDENED */ + +- if (vt->flags & FREELIST_PTR_BSWAP) ++ if ((vt->flags & FREELIST_PTR_BSWAP) || machine_type("PPC64") ++ || machine_type("ARM64") || machine_type("S390X")) + ptr_addr = (sizeof(long) == 8) ? bswap_64(ptr_addr) + : bswap_32(ptr_addr); + return (ptr ^ si->random ^ ptr_addr); +-- +2.37.1 + diff --git a/SOURCES/rhel8_freepointer.patch b/SOURCES/rhel8_freepointer.patch deleted file mode 100644 index 235e532..0000000 --- a/SOURCES/rhel8_freepointer.patch +++ /dev/null @@ -1,16 +0,0 @@ ---- crash-7.3.2/memory.c.orig -+++ crash-7.3.2/memory.c -@@ -19412,9 +19412,8 @@ freelist_ptr(struct meminfo *si, ulong ptr, ulong ptr_addr) - if (VALID_MEMBER(kmem_cache_random)) { - /* CONFIG_SLAB_FREELIST_HARDENED */ - -- if (THIS_KERNEL_VERSION >= LINUX(5,7,0)) -- ptr_addr = (sizeof(long) == 8) ? bswap_64(ptr_addr) -- : bswap_32(ptr_addr); -+ ptr_addr = (sizeof(long) == 8) ? bswap_64(ptr_addr) -+ : bswap_32(ptr_addr); - return (ptr ^ si->random ^ ptr_addr); - } else - return ptr; --- -fix freepointer issue diff --git a/SPECS/crash.spec b/SPECS/crash.spec index 56ae42c..a22f1e3 100644 --- a/SPECS/crash.spec +++ b/SPECS/crash.spec @@ -4,7 +4,7 @@ Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles Name: crash Version: 7.3.2 -Release: 4%{?dist} +Release: 8%{?dist} License: GPLv3 Group: Development/Debuggers Source0: https://github.com/crash-utility/crash/archive/crash-%{version}.tar.gz @@ -16,53 +16,109 @@ Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n) BuildRequires: ncurses-devel zlib-devel lzo-devel bison snappy-devel wget patch libzstd-devel Requires: binutils Provides: bundled(gdb) = 7.6 -Patch0: lzo_snappy_zstd.patch -Patch1: rhel8_build.patch -Patch2: rhel8_freepointer.patch -Patch3: 0001-ppc64-update-the-NR_CPUS-to-8192.patch -Patch4: 0002-sbitmapq-remove-struct-and-member-validation-in-sbit.patch -Patch5: 0003-sbitmapq-fix-invalid-offset-for-sbitmap_queue_alloc_.patch -Patch6: 0004-sbitmapq-fix-invalid-offset-for-sbitmap_queue_round_.patch -Patch7: 0005-sbitmapq-fix-invalid-offset-for-sbitmap_word_depth-o.patch -Patch8: 0007-bt-x86_64-filter-out-idle-task-stack.patch -Patch9: 0008-bt-arm64-add-support-for-bt-n-idle.patch -Patch10: 0010-Enhance-dev-d-D-options-to-support-blk-mq-sbitmap.patch -Patch11: 0011-Fix-for-dev-d-D-options-to-support-blk-mq-change-on-.patch -Patch12: 0012-Doc-update-man-page-for-the-bpf-and-sbitmapq-command.patch -Patch13: 0013-sbitmapq-Fix-for-sbitmap_queue-without-ws_active-mem.patch -Patch14: 0014-sbitmapq-Fix-for-sbitmap_word-without-cleared-member.patch -Patch15: 0015-sbitmapq-Fix-for-sbitmap_queue-without-min_shallow_d.patch -Patch16: 0016-Make-dev-d-D-options-parse-sbitmap-on-Linux-4.18-and.patch -Patch17: 0017-sbitmapq-Fix-for-kernels-without-struct-wait_queue_h.patch -Patch18: 0018-sbitmapq-Limit-kernels-without-sbitmap-again.patch -Patch19: 0001-Fix-for-dev-command-on-Linux-5.11-and-later.patch -Patch20: 0002-Extend-field-length-of-task-attributes.patch -Patch21: 0003-ppc64-fix-bt-for-S-case.patch -Patch22: 0004-ppc64-dynamically-allocate-h-w-interrupt-stack.patch -Patch23: 0005-ppc64-rename-ppc64_paca_init-to-ppc64_paca_percpu_of.patch -Patch24: 0006-ppc64-handle-backtrace-when-CPU-is-in-an-emergency-s.patch -Patch25: 0007-ppc64-print-emergency-stacks-info-with-mach-command.patch -Patch26: 0008-ppc64-use-a-variable-for-machdep-machspec.patch -Patch27: 0009-arm64-Fix-for-st-_stext_vmlinux-not-initialized-when.patch -Patch28: 0010-Fix-gcc-11-compiler-warnings-on-filesys.c.patch -Patch29: 0011-Fix-gcc-11-compiler-warning-on-symbols.c.patch -Patch30: 0012-Fix-gcc-11-compiler-warning-on-makedumpfile.c.patch -Patch31: 0013-Fix-gcc-11-compiler-warning-on-kvmdump.c.patch -Patch32: 0014-x86_64-Fix-for-AMD-SME-issue.patch -Patch33: 0015-Makefile-Fix-unnecessary-re-patching-with-coreutils-.patch -Patch34: 0016-arm64-use-TCR_EL1_T1SZ-to-get-the-correct-info-if-va.patch -Patch35: 0017-Fix-task-R-by-adding-end-identifier-for-union-in-tas.patch -Patch36: 0018-Let-gdb-get-kernel-module-symbols-info-from-crash.patch -Patch37: 0019-x86_64-Correct-the-identifier-when-locating-the-call.patch -Patch38: 0020-Add-debian-ubuntu-vmlinux-location-to-default-search.patch -Patch39: 0021-Fix-gcc-12-compiler-warnings-on-lkcd_-.c.patch -Patch40: 0022-Fix-for-the-invalid-linux_banner-pointer-issue.patch -Patch41: 0023-Fix-kmem-failing-to-print-task-context-when-address-.patch -Patch42: 0024-Fix-page-offset-issue-when-converting-physical-to-vi.patch -Patch43: 0025-Let-kmem-print-task-context-with-physical-address.patch -Patch44: 0026-ppc64-still-allow-to-move-on-if-the-emergency-stacks.patch -Patch45: 0027-Fix-segmentation-fault-in-page_flags_init_from_pagef.patch -Patch46: 0028-Fix-for-ps-vm-commands-to-display-correct-MEM-and-RS.patch +Patch0: 0001-ppc64-update-the-NR_CPUS-to-8192.patch +Patch1: 0002-sbitmapq-remove-struct-and-member-validation-in-sbit.patch +Patch2: 0003-sbitmapq-fix-invalid-offset-for-sbitmap_queue_alloc_.patch +Patch3: 0004-sbitmapq-fix-invalid-offset-for-sbitmap_queue_round_.patch +Patch4: 0005-sbitmapq-fix-invalid-offset-for-sbitmap_word_depth-o.patch +Patch5: 0006-bt-x86_64-filter-out-idle-task-stack.patch +Patch6: 0007-bt-arm64-add-support-for-bt-n-idle.patch +Patch7: 0008-Enhance-dev-d-D-options-to-support-blk-mq-sbitmap.patch +Patch8: 0009-Fix-for-dev-d-D-options-to-support-blk-mq-change-on-.patch +Patch9: 0010-Doc-update-man-page-for-the-bpf-and-sbitmapq-command.patch +Patch10: 0011-sbitmapq-Fix-for-sbitmap_queue-without-ws_active-mem.patch +Patch11: 0012-sbitmapq-Fix-for-sbitmap_word-without-cleared-member.patch +Patch12: 0013-sbitmapq-Fix-for-sbitmap_queue-without-min_shallow_d.patch +Patch13: 0014-Make-dev-d-D-options-parse-sbitmap-on-Linux-4.18-and.patch +Patch14: 0015-sbitmapq-Fix-for-kernels-without-struct-wait_queue_h.patch +Patch15: 0016-sbitmapq-Limit-kernels-without-sbitmap-again.patch +Patch16: 0017-Fix-for-dev-command-on-Linux-5.11-and-later.patch +Patch17: 0018-Extend-field-length-of-task-attributes.patch +Patch18: 0019-ppc64-fix-bt-for-S-case.patch +Patch19: 0020-ppc64-dynamically-allocate-h-w-interrupt-stack.patch +Patch20: 0021-ppc64-rename-ppc64_paca_init-to-ppc64_paca_percpu_of.patch +Patch21: 0022-ppc64-handle-backtrace-when-CPU-is-in-an-emergency-s.patch +Patch22: 0023-ppc64-print-emergency-stacks-info-with-mach-command.patch +Patch23: 0024-ppc64-use-a-variable-for-machdep-machspec.patch +Patch24: 0025-arm64-Fix-for-st-_stext_vmlinux-not-initialized-when.patch +Patch25: 0026-Fix-gcc-11-compiler-warnings-on-filesys.c.patch +Patch26: 0027-Fix-gcc-11-compiler-warning-on-symbols.c.patch +Patch27: 0028-Fix-gcc-11-compiler-warning-on-makedumpfile.c.patch +Patch28: 0029-Fix-gcc-11-compiler-warning-on-kvmdump.c.patch +Patch29: 0030-x86_64-Fix-for-AMD-SME-issue.patch +Patch30: 0031-Makefile-Fix-unnecessary-re-patching-with-coreutils-.patch +Patch31: 0032-arm64-use-TCR_EL1_T1SZ-to-get-the-correct-info-if-va.patch +Patch32: 0033-Fix-task-R-by-adding-end-identifier-for-union-in-tas.patch +Patch33: 0034-Let-gdb-get-kernel-module-symbols-info-from-crash.patch +Patch34: 0035-x86_64-Correct-the-identifier-when-locating-the-call.patch +Patch35: 0036-Add-debian-ubuntu-vmlinux-location-to-default-search.patch +Patch36: 0037-Fix-gcc-12-compiler-warnings-on-lkcd_-.c.patch +Patch37: 0038-Fix-for-the-invalid-linux_banner-pointer-issue.patch +Patch38: 0039-Fix-kmem-failing-to-print-task-context-when-address-.patch +Patch39: 0040-Fix-page-offset-issue-when-converting-physical-to-vi.patch +Patch40: 0041-Let-kmem-print-task-context-with-physical-address.patch +Patch41: 0042-ppc64-still-allow-to-move-on-if-the-emergency-stacks.patch +Patch42: 0043-Fix-segmentation-fault-in-page_flags_init_from_pagef.patch +Patch43: 0044-Fix-for-ps-vm-commands-to-display-correct-MEM-and-RS.patch +Patch44: 0045-ps-Provide-an-option-to-display-no-header-line.patch +Patch45: 0046-arm64-fix-backtraces-of-KASAN-kernel-dumpfile-trunca.patch +Patch46: 0047-arm64-handle-vabits_actual-symbol-missing-case.patch +Patch47: 0048-x86_64-Fix-for-move-of-per-cpu-variables-into-struct.patch +Patch48: 0049-Fix-for-mm_struct.rss_stat-conversion-into-percpu_co.patch +Patch49: 0050-Fix-mount-command-to-appropriately-display-the-mount.patch +Patch50: 0051-Add-RISCV64-framework-code-support.patch +Patch51: 0052-RISCV64-Make-crash-tool-enter-command-line-and-suppo.patch +Patch52: 0053-RISCV64-Add-dis-command-support.patch +Patch53: 0054-RISCV64-Add-irq-command-support.patch +Patch54: 0055-RISCV64-Add-bt-command-support.patch +Patch55: 0056-RISCV64-Add-help-r-command-support.patch +Patch56: 0057-RISCV64-Add-help-m-M-command-support.patch +Patch57: 0058-RISCV64-Add-mach-command-support.patch +Patch58: 0059-RISCV64-Add-the-implementation-of-symbol-verify.patch +Patch59: 0060-SLUB-Fix-for-offset-change-of-struct-slab-members-on.patch +Patch60: 0061-Fix-for-kmem-i-to-display-correct-SLAB-statistics-on.patch +Patch61: 0062-Fix-build-failure-due-to-no-EM_RISCV-with-glibc-2.23.patch +Patch62: 0063-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.1-and-later.patch +Patch63: 0064-SLAB-Fix-for-kmem-s-S-options-on-Linux-6.2-rc1-and-l.patch +Patch64: 0065-Port-the-maple-tree-data-structures-and-functions.patch +Patch65: 0066-Add-maple-tree-support-to-tree-command.patch +Patch66: 0067-Add-do_maple_tree-for-maple-tree-operations.patch +Patch67: 0068-Introduce-maple-tree-vma-iteration-to-vm_area_dump.patch +Patch68: 0069-Update-the-help-text-of-tree-command-for-maple-tree.patch +Patch69: 0070-Dump-maple-tree-offset-variables-by-help-o.patch +Patch70: 0071-Fix-for-bt-command-printing-bogus-exception-frame-wa.patch +Patch71: 0072-Fix-kmem-s-S-not-working-properly-on-RHEL8.6-and-lat.patch +Patch72: 0073-Fix-for-net-s-option-to-show-IPv6-addresses-on-Linux.patch +Patch73: 0074-Fix-for-kmem-i-option-to-not-print-invalid-values-fo.patch +Patch74: 0075-Fix-for-bt-command-unnecessarily-printing-an-excepti.patch +Patch75: 0076-Fix-for-dis-command-to-correctly-display-the-offset-.patch +Patch76: 0077-x86_64-Fix-bt-command-on-kernels-with-random_kstack_.patch +Patch77: 0078-Fix-for-search-u-option-failing-in-maple-tree-kernel.patch +Patch78: 0079-Enhance-net-command-to-display-IPv6-address-of-netwo.patch +Patch79: 0080-Fix-for-net-n-option-to-properly-deal-with-an-invali.patch +Patch80: 0081-Fix-kmem-n-option-to-display-memory-blocks-on-Linux-.patch +Patch81: 0082-xen-fix-stacksize.patch +Patch82: 0083-xen-get-stack-address-via-stack_base-array-if-availa.patch +Patch83: 0084-xen-adjust-to-new-scheduler-structures.patch +Patch84: 0085-Fix-vm-M-option-to-properly-deal-with-an-invalid-arg.patch +Patch85: 0086-Fix-fuser-command-to-properly-deal-with-an-invalid-a.patch +Patch86: 0087-Replace-lseek-read-into-pread-for-kcore-and-vmcore-r.patch +Patch87: 0088-Fix-net-command-on-kernel-configured-with-CONFIG_IPV.patch +Patch88: 0089-gdb-7.6-fix-for-whatis-command-causes-crash-coredump.patch +Patch89: 0001-Fix-kernel-version-macros-for-revision-numbers-over-.patch +Patch90: 0002-Fix-failure-of-dev-d-D-options-on-Linux-6.4-and-late.patch +Patch91: 0003-Fix-kmem-v-option-displaying-no-regions-on-Linux-6.3.patch +Patch92: 0004-arm64-x86_64-Enhance-vtop-command-to-show-zero_pfn-i.patch +Patch93: 0005-diskdump-netdump-fix-segmentation-fault-caused-by-fa.patch +Patch94: 0006-Fix-segfault-in-arm64_is_kernel_exception_frame-when.patch +Patch95: 0001-Output-prompt-when-stdin-is-not-a-TTY.patch +Patch96: 0002-x86_64-Fix-bt-command-printing-stale-entries-on-Linu.patch +Patch97: 0003-Fix-invalid-structure-size-error-during-crash-startu.patch +Patch98: 0004-Revert-Fix-segfault-in-arm64_is_kernel_exception_fra.patch +Patch99: 0005-arm64-Fix-again-segfault-in-arm64_is_kernel_exceptio.patch +Patch100: lzo_snappy_zstd.patch +Patch101: rhel8_build.patch +Patch102: rhel8-freepointer.patch %description The core analysis suite is a self-contained tool that can be used to @@ -83,9 +139,9 @@ offered by Mission Critical Linux, or the LKCD kernel patch. %prep %setup -n %{name}-%{version} -q -%patch0 -p1 -b lzo_snappy_zstd.patch -%patch1 -p1 -b rhel8_build.patch -%patch2 -p1 -b rhel8_freepointer.patch +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 %patch3 -p1 %patch4 -p1 %patch5 -p1 @@ -130,6 +186,62 @@ offered by Mission Critical Linux, or the LKCD kernel patch. %patch44 -p1 %patch45 -p1 %patch46 -p1 +%patch47 -p1 +%patch48 -p1 +%patch49 -p1 +%patch50 -p1 +%patch51 -p1 +%patch52 -p1 +%patch53 -p1 +%patch54 -p1 +%patch55 -p1 +%patch56 -p1 +%patch57 -p1 +%patch58 -p1 +%patch59 -p1 +%patch60 -p1 +%patch61 -p1 +%patch62 -p1 +%patch63 -p1 +%patch64 -p1 +%patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 +%patch71 -p1 +%patch72 -p1 +%patch73 -p1 +%patch74 -p1 +%patch75 -p1 +%patch76 -p1 +%patch77 -p1 +%patch78 -p1 +%patch79 -p1 +%patch80 -p1 +%patch81 -p1 +%patch82 -p1 +%patch83 -p1 +%patch84 -p1 +%patch85 -p1 +%patch86 -p1 +%patch87 -p1 +%patch88 -p1 +%patch89 -p1 +%patch90 -p1 +%patch91 -p1 +%patch92 -p1 +%patch93 -p1 +%patch94 -p1 +%patch95 -p1 +%patch96 -p1 +%patch97 -p1 +%patch98 -p1 +%patch99 -p1 +%patch100 -p1 +%patch101 -p1 +%patch102 -p1 %build cp %{SOURCE1} . @@ -160,6 +272,20 @@ rm -rf %{buildroot} %{_includedir}/* %changelog +* Thu Jun 15 2023 Lianbo Jiang - 7.3.2-8 +- arm64: Fix again segfault in arm64_is_kernel_exception_frame() +- Fix invalid structure size error during crash startup on ppc64 + +* Wed Jun 07 2023 Lianbo Jiang - 7.3.2-7 +- Fix segfault caused by failure of stopping CPUs + +* Mon May 08 2023 Lianbo Jiang - 7.3.2-6 +- Fix for freelist pointer on PPC64le, ARM64 and S390x + +* Mon May 08 2023 Lianbo Jiang - 7.3.2-5 +- Update to the latest upstream commit 47216437e79a +- ("Fix "net" command on kernel configured with CONFIG_IPV6=m") + * Mon Nov 21 2022 Lianbo Jiang - 7.3.2-4 - Fix for commit 2145b2bb79c5, there are different behaviors between gdb-7.6 and gdb-10.2