Release: crash-7.3.2-5

Update to the latest upstream commit 47216437e79a ("Fix "net" command on
kernel configured with CONFIG_IPV6=m")

Resolves: rhbz#2166880
Resolves: rhbz#2161133
Resolves: rhbz#2158721
Resolves: rhbz#2156904
Resolves: rhbz#2156898
Resolves: rhbz#2156892
Resolves: rhbz#2156889
Resolves: rhbz#2156885
Resolves: rhbz#2152619

Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
This commit is contained in:
Lianbo Jiang 2023-05-08 15:00:14 +08:00
parent 6fdeb6efe3
commit b6407a85f0
91 changed files with 8181 additions and 209 deletions

View File

@ -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 <sourabhjain@linux.ibm.com>
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 <lijiang@redhat.com>
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

View File

@ -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 <lijiang@redhat.com>
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

View File

@ -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 <lijiang@redhat.com>
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 <lijiang@redhat.com>
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

View File

@ -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 <lijiang@redhat.com>
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 <lijiang@redhat.com>
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

View File

@ -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 <lijiang@redhat.com>
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

View File

@ -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 <zhengqi.arch@bytedance.com>
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 <lijiang@redhat.com>
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

View File

@ -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 <zhengqi.arch@bytedance.com>
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

View File

@ -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 <lijiang@redhat.com>
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 <k-hagio-ab@nec.com>
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

View File

@ -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 <lijiang@redhat.com>
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 <lijiang@redhat.com>
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

View File

@ -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 <lijiang@redhat.com>
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

View File

@ -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 <k-hagio-ab@nec.com>
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

View File

@ -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 <k-hagio-ab@nec.com>
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

View File

@ -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 <k-hagio-ab@nec.com>
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

View File

@ -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 <k-hagio-ab@nec.com>
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

View File

@ -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 <k-hagio-ab@nec.com>
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

View File

@ -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 <k-hagio-ab@nec.com>
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

View File

@ -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 <k-hagio-ab@nec.com>
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:

View File

@ -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 <k-hagio-ab@nec.com>
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.

View File

@ -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 <hbathini@linux.ibm.com>
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

View File

@ -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 <hbathini@linux.ibm.com>
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

View File

@ -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 <hbathini@linux.ibm.com>
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

View File

@ -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 <hbathini@linux.ibm.com>
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

View File

@ -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 <hbathini@linux.ibm.com>
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.

View File

@ -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 <hbathini@linux.ibm.com>
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

View File

@ -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 <qianli.zhao@horizon.ai>
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"

View File

@ -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 <k-hagio-ab@nec.com>
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:

View File

@ -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 <k-hagio-ab@nec.com>
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:

View File

@ -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 <k-hagio-ab@nec.com>
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:

View File

@ -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 <k-hagio-ab@nec.com>
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:

View File

@ -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 <lijiang@redhat.com>
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:

View File

@ -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 <k-hagio-ab@nec.com>
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 <lijiang@redhat.com>
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:

View File

@ -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 <shijie@os.amperecomputing.com>
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

View File

@ -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 <ltao@redhat.com>
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

View File

@ -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 <ltao@redhat.com>
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)

View File

@ -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 <ltao@redhat.com>
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

View File

@ -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" <chunguang.xu@shopee.com>
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

View File

@ -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 <k-hagio-ab@nec.com>
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:

View File

@ -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 <lijiang@redhat.com>
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:

View File

@ -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 <ltao@redhat.com>
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 <lijiang@redhat.com>
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)

View File

@ -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 <ltao@redhat.com>
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 <lijiang@redhat.com>
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)

View File

@ -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 <ltao@redhat.com>
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 <lijiang@redhat.com>
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)

View File

@ -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 <lijiang@redhat.com>
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

View File

@ -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 <matiasevara@gmail.com>
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 <lijiang@redhat.com>
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)

View File

@ -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 <lijiang@redhat.com>
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 <lijiang@redhat.com>
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)

View File

@ -0,0 +1,72 @@
From acd2b8a54e4532f859173fe9f0d1b92b44cbc848 Mon Sep 17 00:00:00 2001
From: Aaron Tomlin <atomlin@redhat.com>
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 <atomlin@atomlin.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,150 @@
From 6122f0d067ed5c522ad11fb91b6db3ea1d34f355 Mon Sep 17 00:00:00 2001
From: Ding Hui <dinghui@sangfor.com.cn>
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 <machine_kexec>: stp x29, x30, [sp,#-208]!
0xffff2000200bff54 <machine_kexec+0x4>: mov x29, sp
0xffff2000200bff58 <machine_kexec+0x8>: stp x19, x20, [sp,#16]
0xffff2000200bff5c <machine_kexec+0xc>: str x24, [sp,#56]
0xffff2000200bff60 <machine_kexec+0x10>: str x26, [sp,#72]
0xffff2000200bff64 <machine_kexec+0x14>: mov x2, #0x8ab3
0xffff2000200bff68 <machine_kexec+0x18>: add x1, x29, #0x70
0xffff2000200bff6c <machine_kexec+0x1c>: lsr x1, x1, #3
0xffff2000200bff70 <machine_kexec+0x20>: movk x2, #0x41b5, lsl #16
0xffff2000200bff74 <machine_kexec+0x24>: mov x19, #0x200000000000
0xffff2000200bff78 <machine_kexec+0x28>: adrp x3, 0xffff2000224b0000
0xffff2000200bff7c <machine_kexec+0x2c>: movk x19, #0xdfff, lsl #48
0xffff2000200bff80 <machine_kexec+0x30>: add x3, x3, #0xcb0
0xffff2000200bff84 <machine_kexec+0x34>: add x4, x1, x19
0xffff2000200bff88 <machine_kexec+0x38>: stp x2, x3, [x29,#112]
0xffff2000200bff8c <machine_kexec+0x3c>: adrp x2, 0xffff2000200bf000 <swsusp_arch_resume+0x1e8>
0xffff2000200bff90 <machine_kexec+0x40>: add x2, x2, #0xf50
0xffff2000200bff94 <machine_kexec+0x44>: str x2, [x29,#128]
0xffff2000200bff98 <machine_kexec+0x48>: mov w2, #0xf1f1f1f1
0xffff2000200bff9c <machine_kexec+0x4c>: str w2, [x1,x19]
0xffff2000200bffa0 <machine_kexec+0x50>: mov w2, #0xf200
0xffff2000200bffa4 <machine_kexec+0x54>: mov w1, #0xf3f3f3f3
0xffff2000200bffa8 <machine_kexec+0x58>: movk w2, #0xf2f2, lsl #16
0xffff2000200bffac <machine_kexec+0x5c>: 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 <dinghui@sangfor.com.cn>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,37 @@
From 69786ee12c4842d2cbd39ea42df65c45fb043edd Mon Sep 17 00:00:00 2001
From: Pavankumar Kondeti <quic_pkondeti@quicinc.com>
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 <quic_pkondeti@quicinc.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,144 @@
From 1f6b58b323f669293b4ef8d497fe7867d1411143 Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
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
<segmentation violation in gdb>
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,163 @@
From c05bbb36fcb468bce384ee4b8e30a0f5748bc4ae Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
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 <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,48 @@
From 1c56f2a37c79fa07c64dce34605d7b4a8a903243 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <dwysocha@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,692 @@
From 8ac8ab4f0e2d81b51b79b30f410c09e394b17e9c Mon Sep 17 00:00:00 2001
From: Xianting Tian <xianting.tian@linux.alibaba.com>
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 <lifang_xia@linux.alibaba.com>
Signed-off-by: Xianting Tian <xianting.tian@linux.alibaba.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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 <anderson@redhat.com>\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 <elf.h>
+
+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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
From 4876c73ca54a8ee2e02032d1b10832e0de9adde3 Mon Sep 17 00:00:00 2001
From: Xianting Tian <xianting.tian@linux.alibaba.com>
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 <xianting.tian@linux.alibaba.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,36 @@
From b4d78e7f96564ecbdbfe4b4b70a1c6d65429bbb9 Mon Sep 17 00:00:00 2001
From: Xianting Tian <xianting.tian@linux.alibaba.com>
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 <xianting.tian@linux.alibaba.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,413 @@
From 75afbf54dd183b05a8b7363390df4a198155580a Mon Sep 17 00:00:00 2001
From: Xianting Tian <xianting.tian@linux.alibaba.com>
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 <xianting.tian@linux.alibaba.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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, &current, &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

View File

@ -0,0 +1,80 @@
From 15ac3968a929adebc27985be77fe90d3847abd57 Mon Sep 17 00:00:00 2001
From: Xianting Tian <xianting.tian@linux.alibaba.com>
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 <xianting.tian@linux.alibaba.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,141 @@
From 012c8ebc3d6d71c995522dcf8d8aad530cdb4d02 Mon Sep 17 00:00:00 2001
From: Xianting Tian <xianting.tian@linux.alibaba.com>
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 <xianting.tian@linux.alibaba.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,83 @@
From 7a942ad69e1a4270dba89de9bff4f93cd6d87578 Mon Sep 17 00:00:00 2001
From: Xianting Tian <xianting.tian@linux.alibaba.com>
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 <xianting.tian@linux.alibaba.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,45 @@
From ba2d96e12463157fe2ed9c134ad9cf42481427e8 Mon Sep 17 00:00:00 2001
From: Xianting Tian <xianting.tian@linux.alibaba.com>
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 <xianting.tian@linux.alibaba.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,149 @@
From 47d375ac822d413999c92520402c4868ce2275cc Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
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 <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,49 @@
From 699717c7720cb2a397ce59d0a0380c65d2693033 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <bsingh@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
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

View File

@ -0,0 +1,49 @@
From 4003c972c5ff0814847865a9f5487c8561a598ad Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
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 <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,46 @@
From 652681dd7fa37a20d7ef3a51a27afa7d6d3f1872 Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
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 <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,233 @@
From 4060546b051751e7e593100027d2a160723a17ee Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
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 <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,633 @@
From 5b61f450d213cda90dd0f50a02594a0b87151c89 Mon Sep 17 00:00:00 2001
From: Tao Liu <ltao@redhat.com>
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 <ltao@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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 <Liam.Howlett@oracle.com>
+ * Matthew Wilcox <willy@infradead.org>
+ *
+ * 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 <Liam.Howlett@Oracle.com>
+ * Matthew Wilcox <willy@infradead.org>
+ *
+ * eXtensible Arrays
+ * Copyright (c) 2017 Microsoft Corporation
+ * Author: Matthew Wilcox <willy@infradead.org>
+ *
+ * See Documentation/core-api/xarray.rst for how to use the XArray.
+ */
+#include <stdbool.h>
+#include <limits.h>
+#include <sys/types.h>
+
+/*
+ * 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

View File

@ -0,0 +1,335 @@
From 4a6aba5dc85a2f491f752fb37dd2838c1141375d Mon Sep 17 00:00:00 2001
From: Tao Liu <ltao@redhat.com>
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 <ltao@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,205 @@
From 7955002f1292f0c0d02076440b441ab7ebaf650d Mon Sep 17 00:00:00 2001
From: Tao Liu <ltao@redhat.com>
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 <ltao@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,455 @@
From 77e9fc571e2782b0eafe1d376cfd7f30fb08fecf Mon Sep 17 00:00:00 2001
From: Tao Liu <ltao@redhat.com>
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 <ltao@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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 <ctype.h>
#include <netinet/in.h>
#include <byteswap.h>
+#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

View File

@ -0,0 +1,135 @@
From a3dbd5c455992baf6bfc196b9059a2b485823b83 Mon Sep 17 00:00:00 2001
From: Tao Liu <ltao@redhat.com>
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 <ltao@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,52 @@
From 198ce92c480baa71e3c70694b7049432f8a5a6ec Mon Sep 17 00:00:00 2001
From: Tao Liu <ltao@redhat.com>
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 <ltao@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,80 @@
From a39b03603eba70d630121390f50abbc186bc8f56 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <kvm guest> 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
--- <IRQ stack> ---
#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 <lijiang@redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
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

View File

@ -0,0 +1,144 @@
From 3c9c16c545319958d7fa14ef5ab8934fc5449d83 Mon Sep 17 00:00:00 2001
From: "Aureau, Georges (Kernel Tools ERT)" <georges.aureau@hpe.com>
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 <georges.aureau@hpe.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,106 @@
From 49f689eda0bc3331beb70df17ac4990034460f2b Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <bsingh@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
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

View File

@ -0,0 +1,56 @@
From b13a2f3c2885bc638d1e413ef9e7c59a8ec8f81d Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <bsingh@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
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

View File

@ -0,0 +1,78 @@
From cce90e242f74ab81e411f2f65f5d5a9fb5022416 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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
--- <NMI exception stack> ---
#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
--- <IRQ stack> ---
#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 <mpatalan@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,63 @@
From 39a938a62d0153a98ab3d1115d845b904192a832 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <native_queued_spin_lock_slowpath+35>: mov %edx,%eax
0xffffffffa2317ad5 <native_queued_spin_lock_slowpath+37>: lock cmpxchg %ecx,(%rdi)
0xffffffffa2317ad5 <native_queued_spin_lock_slowpath+37>: cmp %eax,%edx
^^
0xffffffffa2317adb <native_queued_spin_lock_slowpath+43>: jne 0xffffffffa2317ac0 ...
0xffffffffa2317add <native_queued_spin_lock_slowpath+45>: pop %rbp
With the patch:
crash> dis 0xffffffffa2317add -r | tail -5
0xffffffffa2317ad3 <native_queued_spin_lock_slowpath+35>: mov %edx,%eax
0xffffffffa2317ad5 <native_queued_spin_lock_slowpath+37>: lock cmpxchg %ecx,(%rdi)
0xffffffffa2317ad9 <native_queued_spin_lock_slowpath+41>: cmp %eax,%edx
0xffffffffa2317adb <native_queued_spin_lock_slowpath+43>: jne 0xffffffffa2317ac0 ...
0xffffffffa2317add <native_queued_spin_lock_slowpath+45>: pop %rbp
Reported-by: Vernon Lovejoy <vlovejoy@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,300 @@
From 04a84a7071b34958f80633ea7bf96652810dadba Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
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.
<do_syscall_64+32>: 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 <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

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

View File

@ -0,0 +1,258 @@
From f4acc0e222aedf720e796fd386f2dc15bbb665e9 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <bsingh@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
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

View File

@ -0,0 +1,44 @@
From 0f2e551ef1f9bb10b2fef0c3ac27e9d32488cc47 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <bsingh@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,160 @@
From b29bd2b531502ca0274ad9c4531417920102fb26 Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
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 <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,33 @@
From ba48bd462728515dd3eed562f1a97125e3417ceb Mon Sep 17 00:00:00 2001
From: Juergen Gross <jgross@suse.com>
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 <jgross@suse.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,111 @@
From 907516256dd60ed20feaa2a8fd9e2bf148099ec3 Mon Sep 17 00:00:00 2001
From: Juergen Gross <jgross@suse.com>
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 <jgross@suse.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,178 @@
From 9e8155297e16f8d8804d151dd75cc489447c1fe7 Mon Sep 17 00:00:00 2001
From: Juergen Gross <jgross@suse.com>
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 <jgross@suse.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,70 @@
From 1cebb3d75b45fedc734dac8563782a3e6d86f23b Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <bsingh@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
[ kh: rewrote commit message ]
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
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

View File

@ -0,0 +1,81 @@
From a83349d6ce9773f151a7f88e032c259f94a2fbde Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <bsingh@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
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

View File

@ -0,0 +1,115 @@
From a447ef800c93ab5bbde91a1e7751cf13c2e831fb Mon Sep 17 00:00:00 2001
From: Tao Liu <ltao@redhat.com>
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 <ltao@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
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

View File

@ -0,0 +1,36 @@
From a1d0ff0e0d113ada3b4baac25c583be7c96b0950 Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
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 <lijiang@redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
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

View File

@ -0,0 +1,38 @@
From 8986cceb699a27c720b42a9b2456f8e19d5422cd Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
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 <lijiang@redhat.com>
---
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

View File

@ -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: 5%{?dist}
License: GPLv3
Group: Development/Debuggers
Source0: https://github.com/crash-utility/crash/archive/crash-%{version}.tar.gz
@ -16,53 +16,97 @@ 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: lzo_snappy_zstd.patch
Patch90: rhel8_build.patch
%description
The core analysis suite is a self-contained tool that can be used to
@ -83,9 +127,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 +174,50 @@ 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
%build
cp %{SOURCE1} .
@ -160,6 +248,10 @@ rm -rf %{buildroot}
%{_includedir}/*
%changelog
* Mon May 08 2023 Lianbo Jiang <lijiang@redhat.com> - 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 <lijiang@redhat.com> - 7.3.2-4
- Fix for commit 2145b2bb79c5, there are different behaviors between gdb-7.6 and gdb-10.2

View File

@ -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