[PATCH] log: output logs of printk safe buffers
by shogo.matsumoto@fujitsu.com
We sometimes overlook logs written to printk safe buffers
(safe_print_seq/nmi_print_seq) which have not been flushed yet.
This patch will output unflushed logs of the safe buffers
at the bottom of log command output as follows:
[nmi_print_seq] CPU: 0 BUFFER: ffff888063c18ac0 LEN: 28
nmi print seq test message
[safe_print_seq] CPU: 1 BUFFER: ffff888063d19ae0 LEN: 30
safe print seq test message
Note that the safe buffer (struct printk_safe_seq_buf) was introduced
in kernel-4.11 and removed in kernel-5.15.
Signed-off-by: Shogo Matsumoto <shogo.matsumoto(a)fujitsu.com>
---
defs.h | 3 +++
kernel.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+)
diff --git a/defs.h b/defs.h
index 7e2a16e..3ee51e0 100644
--- a/defs.h
+++ b/defs.h
@@ -2146,6 +2146,8 @@ struct offset_table { /* stash of commonly-used offsets */
long wait_queue_entry_private;
long wait_queue_head_head;
long wait_queue_entry_entry;
+ long printk_safe_seq_buf_len;
+ long printk_safe_seq_buf_buffer;
};
struct size_table { /* stash of commonly-used sizes */
@@ -2310,6 +2312,7 @@ struct size_table { /* stash of commonly-used sizes */
long prb_desc;
long wait_queue_entry;
long task_struct_state;
+ long printk_safe_seq_buf_buffer;
};
struct array_table {
diff --git a/kernel.c b/kernel.c
index f4598ea..cc97176 100644
--- a/kernel.c
+++ b/kernel.c
@@ -93,6 +93,7 @@ static void source_tree_init(void);
static ulong dump_audit_skb_queue(ulong);
static ulong __dump_audit(char *);
static void dump_audit(void);
+static void dump_printk_safe_seq_buf(void);
static char *vmcoreinfo_read_string(const char *);
static void check_vmcoreinfo(void);
static int is_pvops_xen(void);
@@ -5048,6 +5049,7 @@ cmd_log(void)
}
dump_log(msg_flags);
+ dump_printk_safe_seq_buf();
}
@@ -11534,6 +11536,62 @@ dump_audit(void)
error(INFO, "kernel audit log is empty\n");
}
+static void
+__dump_printk_safe_seq_buf(char *buf_name)
+{
+ int cpu, buffer_size;
+ char *buffer;
+
+ if (!symbol_exists(buf_name)) {
+ return;
+ }
+
+ buffer_size = SIZE(printk_safe_seq_buf_buffer);
+ buffer = GETBUF(buffer_size);
+ for (cpu = 0; cpu < kt->cpus; cpu++) {
+ ulong len_addr, buffer_addr;
+ int len;
+
+ len_addr = symbol_value(buf_name) + kt->__per_cpu_offset[cpu] + OFFSET(printk_safe_seq_buf_len);
+ buffer_addr = symbol_value(buf_name) + kt->__per_cpu_offset[cpu] + OFFSET(printk_safe_seq_buf_buffer);
+ readmem(len_addr, KVADDR, &len, STRUCT_SIZE("atomic_t"), "printk_safe_seq_buf len", FAULT_ON_ERROR);
+ readmem(buffer_addr, KVADDR, buffer, buffer_size, "printk_safe_seq_buf buffer", FAULT_ON_ERROR);
+
+ if (len > 0) {
+ int i, n;
+ char *p;
+ fprintf(fp, "[%s] CPU: %d BUFFER: %lx LEN: %d\n", buf_name, cpu, buffer_addr, len);
+ n = (len <= buffer_size) ? len : buffer_size;
+ for (i = 0, p = buffer; i < n; i++, p++) {
+ if (*p == 0x1) { //SOH
+ i++; p++;
+ continue;
+ } else {
+ fputc(ascii(*p) ? *p : '.', fp);
+ }
+ }
+ fputc('\n', fp);
+ }
+ }
+ FREEBUF(buffer);
+}
+
+static void
+dump_printk_safe_seq_buf(void)
+{
+ if (!STRUCT_EXISTS("printk_safe_seq_buf"))
+ return;
+
+ if (INVALID_SIZE(printk_safe_seq_buf_buffer)) {
+ MEMBER_OFFSET_INIT(printk_safe_seq_buf_len, "printk_safe_seq_buf", "len");
+ MEMBER_OFFSET_INIT(printk_safe_seq_buf_buffer, "printk_safe_seq_buf", "buffer");
+ MEMBER_SIZE_INIT(printk_safe_seq_buf_buffer, "printk_safe_seq_buf", "buffer");
+ }
+
+ __dump_printk_safe_seq_buf("nmi_print_seq");
+ __dump_printk_safe_seq_buf("safe_print_seq");
+}
+
/*
* Reads a string value from the VMCOREINFO data stored in (live) memory.
*
--
2.29.2
2 years, 11 months
Re: [Crash-utility] [PATCH] log: output logs of printk safe buffers
by lijiang
Hi, shogo
Thank you for the patch.
On Thu, Dec 16, 2021 at 4:01 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Thu, 16 Dec 2021 07:39:42 +0000
> From: "shogo.matsumoto(a)fujitsu.com" <shogo.matsumoto(a)fujitsu.com>
> To: "'crash-utility(a)redhat.com'" <crash-utility(a)redhat.com>
> Subject: [Crash-utility] [PATCH] log: output logs of printk safe
> buffers
> Message-ID:
> <TYAPR01MB62191B03B637D36487695277E2779(a)TYAPR01MB6219.jpnprd01.prod.outlook.com>
>
> Content-Type: text/plain; charset="iso-2022-jp"
>
> We sometimes overlook logs written to printk safe buffers
> (safe_print_seq/nmi_print_seq) which have not been flushed yet.
>
> This patch will output unflushed logs of the safe buffers
> at the bottom of log command output as follows:
>
> [nmi_print_seq] CPU: 0 BUFFER: ffff888063c18ac0 LEN: 28
> nmi print seq test message
> [safe_print_seq] CPU: 1 BUFFER: ffff888063d19ae0 LEN: 30
> safe print seq test message
>
> Note that the safe buffer (struct printk_safe_seq_buf) was introduced
> in kernel-4.11 and removed in kernel-5.15.
>
Although the safe buffer has been deprecated from the latest kernel
with the printk ringbuffer feature, it seems to be still helpful for
the old kernel.
> Signed-off-by: Shogo Matsumoto <shogo.matsumoto(a)fujitsu.com>
> ---
> defs.h | 3 +++
> kernel.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 61 insertions(+)
>
> diff --git a/defs.h b/defs.h
> index 7e2a16e..3ee51e0 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -2146,6 +2146,8 @@ struct offset_table { /* stash of commonly-used offsets */
> long wait_queue_entry_private;
> long wait_queue_head_head;
> long wait_queue_entry_entry;
> + long printk_safe_seq_buf_len;
> + long printk_safe_seq_buf_buffer;
> };
>
> struct size_table { /* stash of commonly-used sizes */
> @@ -2310,6 +2312,7 @@ struct size_table { /* stash of commonly-used sizes */
> long prb_desc;
> long wait_queue_entry;
> long task_struct_state;
> + long printk_safe_seq_buf_buffer;
> };
>
Can you help to add all new variables mentioned above to the dump table?
> struct array_table {
> diff --git a/kernel.c b/kernel.c
> index f4598ea..cc97176 100644
> --- a/kernel.c
> +++ b/kernel.c
> @@ -93,6 +93,7 @@ static void source_tree_init(void);
> static ulong dump_audit_skb_queue(ulong);
> static ulong __dump_audit(char *);
> static void dump_audit(void);
> +static void dump_printk_safe_seq_buf(void);
> static char *vmcoreinfo_read_string(const char *);
> static void check_vmcoreinfo(void);
> static int is_pvops_xen(void);
> @@ -5048,6 +5049,7 @@ cmd_log(void)
> }
>
> dump_log(msg_flags);
> + dump_printk_safe_seq_buf();
> }
>
This does not support dumping with the crash --log command, right?
Thanks.
Lianbo
>
> @@ -11534,6 +11536,62 @@ dump_audit(void)
> error(INFO, "kernel audit log is empty\n");
> }
>
> +static void
> +__dump_printk_safe_seq_buf(char *buf_name)
> +{
> + int cpu, buffer_size;
> + char *buffer;
> +
> + if (!symbol_exists(buf_name)) {
> + return;
> + }
> +
> + buffer_size = SIZE(printk_safe_seq_buf_buffer);
> + buffer = GETBUF(buffer_size);
> + for (cpu = 0; cpu < kt->cpus; cpu++) {
> + ulong len_addr, buffer_addr;
> + int len;
> +
> + len_addr = symbol_value(buf_name) + kt->__per_cpu_offset[cpu] + OFFSET(printk_safe_seq_buf_len);
> + buffer_addr = symbol_value(buf_name) + kt->__per_cpu_offset[cpu] + OFFSET(printk_safe_seq_buf_buffer);
> + readmem(len_addr, KVADDR, &len, STRUCT_SIZE("atomic_t"), "printk_safe_seq_buf len", FAULT_ON_ERROR);
> + readmem(buffer_addr, KVADDR, buffer, buffer_size, "printk_safe_seq_buf buffer", FAULT_ON_ERROR);
> +
> + if (len > 0) {
> + int i, n;
> + char *p;
> + fprintf(fp, "[%s] CPU: %d BUFFER: %lx LEN: %d\n", buf_name, cpu, buffer_addr, len);
> + n = (len <= buffer_size) ? len : buffer_size;
> + for (i = 0, p = buffer; i < n; i++, p++) {
> + if (*p == 0x1) { //SOH
> + i++; p++;
> + continue;
> + } else {
> + fputc(ascii(*p) ? *p : '.', fp);
> + }
> + }
> + fputc('\n', fp);
> + }
> + }
> + FREEBUF(buffer);
> +}
> +
> +static void
> +dump_printk_safe_seq_buf(void)
> +{
> + if (!STRUCT_EXISTS("printk_safe_seq_buf"))
> + return;
> +
> + if (INVALID_SIZE(printk_safe_seq_buf_buffer)) {
> + MEMBER_OFFSET_INIT(printk_safe_seq_buf_len, "printk_safe_seq_buf", "len");
> + MEMBER_OFFSET_INIT(printk_safe_seq_buf_buffer, "printk_safe_seq_buf", "buffer");
> + MEMBER_SIZE_INIT(printk_safe_seq_buf_buffer, "printk_safe_seq_buf", "buffer");
> + }
> +
> + __dump_printk_safe_seq_buf("nmi_print_seq");
> + __dump_printk_safe_seq_buf("safe_print_seq");
> +}
> +
> /*
> * Reads a string value from the VMCOREINFO data stored in (live) memory.
> *
> --
> 2.29.2
2 years, 11 months
[PATCH v2] Handle blk_mq_ctx member changes for kernels v5.16-rc1~75^2~44
by Lianbo Jiang
Kernel commit <9a14d6ce4135> ("block: remove debugfs blk_mq_ctx
dispatched/merged/completed attributes") removed the member
rq_dispatched and rq_completed from struct blk_mq_ctx. Without
this patch, crash will fail with the following error:
crash> dev -d
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL ASYNC SYNC
dev: invalid structure member offset: blk_mq_ctx_rq_dispatched
FILE: dev.c LINE: 4229 FUNCTION: get_one_mctx_diskio()
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
change since v1:
[1] display prompt information "(not supported)" instead of the
statistical result if kernel does not support it
dev.c | 56 ++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 38 insertions(+), 18 deletions(-)
diff --git a/dev.c b/dev.c
index effe789f38d8..c5e38e1c5376 100644
--- a/dev.c
+++ b/dev.c
@@ -4246,6 +4246,10 @@ get_mq_diskio(unsigned long q, unsigned long *mq_count)
unsigned long mctx_addr;
struct diskio tmp;
+ if (!MEMBER_EXISTS("blk_mq_ctx", "rq_dispatched") &&
+ !MEMBER_EXISTS("blk_mq_ctx", "rq_completed"))
+ return;
+
memset(&tmp, 0x00, sizeof(struct diskio));
readmem(q + OFFSET(request_queue_queue_ctx), KVADDR, &queue_ctx,
@@ -4475,24 +4479,40 @@ display_one_diskio(struct iter *i, unsigned long gendisk, ulong flags)
&& (io.read + io.write == 0))
return;
- fprintf(fp, "%s%s%s %s%s%s%s %s%5d%s%s%s%s%s",
- mkstring(buf0, 5, RJUST|INT_DEC, (char *)(unsigned long)major),
- space(MINSPACE),
- mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, (char *)gendisk),
- space(MINSPACE),
- mkstring(buf2, 10, LJUST, disk_name),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN <= 11 ? 11 : VADDR_PRLEN,
- LJUST|LONG_HEX, (char *)queue_addr),
- space(MINSPACE),
- io.read + io.write,
- space(MINSPACE),
- mkstring(buf4, 5, RJUST|INT_DEC,
- (char *)(unsigned long)io.read),
- space(MINSPACE),
- mkstring(buf5, 5, RJUST|INT_DEC,
- (char *)(unsigned long)io.write),
- space(MINSPACE));
+ if (!MEMBER_EXISTS("blk_mq_ctx", "rq_dispatched") &&
+ !MEMBER_EXISTS("blk_mq_ctx", "rq_completed"))
+ fprintf(fp, "%s%s%s %s%s%s%s %s%s%s",
+ mkstring(buf0, 5, RJUST|INT_DEC, (char *)(unsigned long)major),
+ space(MINSPACE),
+ mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, (char *)gendisk),
+ space(MINSPACE),
+ mkstring(buf2, 10, LJUST, disk_name),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN <= 11 ? 11 : VADDR_PRLEN,
+ LJUST|LONG_HEX, (char *)queue_addr),
+ space(MINSPACE),
+ mkstring(buf4, 16, LJUST, "(not supported)"),
+ space(MINSPACE));
+
+ else
+ fprintf(fp, "%s%s%s %s%s%s%s %s%5d%s%s%s%s%s",
+ mkstring(buf0, 5, RJUST|INT_DEC, (char *)(unsigned long)major),
+ space(MINSPACE),
+ mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, (char *)gendisk),
+ space(MINSPACE),
+ mkstring(buf2, 10, LJUST, disk_name),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN <= 11 ? 11 : VADDR_PRLEN,
+ LJUST|LONG_HEX, (char *)queue_addr),
+ space(MINSPACE),
+ io.read + io.write,
+ space(MINSPACE),
+ mkstring(buf4, 5, RJUST|INT_DEC,
+ (char *)(unsigned long)io.read),
+ space(MINSPACE),
+ mkstring(buf5, 5, RJUST|INT_DEC,
+ (char *)(unsigned long)io.write),
+ space(MINSPACE));
if (VALID_MEMBER(request_queue_in_flight)) {
if (!use_mq_interface(queue_addr)) {
--
2.20.1
3 years
[PATCH] Handle blk_mq_ctx member changes for kernels v5.16-rc1~75^2~44
by Lianbo Jiang
Kernel commit <9a14d6ce4135> ("block: remove debugfs blk_mq_ctx
dispatched/merged/completed attributes") removed the member
rq_dispatched and rq_completed from struct blk_mq_ctx. Without
this patch, crash will fail with the following error:
crash> dev -d
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL ASYNC SYNC
dev: invalid structure member offset: blk_mq_ctx_rq_dispatched
FILE: dev.c LINE: 4229 FUNCTION: get_one_mctx_diskio()
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
dev.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/dev.c b/dev.c
index effe789f38d8..dd21511e5dfc 100644
--- a/dev.c
+++ b/dev.c
@@ -4246,6 +4246,10 @@ get_mq_diskio(unsigned long q, unsigned long *mq_count)
unsigned long mctx_addr;
struct diskio tmp;
+ if (!MEMBER_EXISTS("blk_mq_ctx", "rq_dispatched") &&
+ !MEMBER_EXISTS("blk_mq_ctx", "rq_completed"))
+ return;
+
memset(&tmp, 0x00, sizeof(struct diskio));
readmem(q + OFFSET(request_queue_queue_ctx), KVADDR, &queue_ctx,
--
2.20.1
3 years
[PATCH] New sbitmap command
by Sergey Samoylenko
Patch adds new 'sbitmap' command. This command dumps
the contents of the sbitmap_queue structure and the used
bits in the bitmap. Also, it shows the dump of a structure
array associated with the sbitmap_queue.
Signed-off-by: Sergey Samoylenko <s.samoylenko(a)yadro.com>
---
Makefile | 7 +-
defs.h | 2 +
global_data.c | 1 +
help.c | 89 ++++++++
sbitmap.c | 591 ++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 688 insertions(+), 2 deletions(-)
create mode 100644 sbitmap.c
diff --git a/Makefile b/Makefile
index ece1306..c116177 100644
--- a/Makefile
+++ b/Makefile
@@ -72,7 +72,7 @@ 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
+ xen_dom0.c kaslr_helper.c sbitmap.c
SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \
${REDHAT_CFILES} ${REDHAT_HFILES} ${UNWIND_HFILES} \
@@ -92,7 +92,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
+ xen_dom0.o kaslr_helper.o sbitmap.o
MEMORY_DRIVER_FILES=memory_driver/Makefile memory_driver/crash.c memory_driver/README
@@ -346,6 +346,9 @@ cmdline.o: ${GENERIC_HFILES} cmdline.c
tools.o: ${GENERIC_HFILES} tools.c
${CC} -c ${CRASH_CFLAGS} tools.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+sbitmap.o: ${GENERIC_HFILES} sbitmap.c
+ ${CC} -c ${CRASH_CFLAGS} sbitmap.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+
global_data.o: ${GENERIC_HFILES} global_data.c
${CC} -c ${CRASH_CFLAGS} global_data.c ${WARNING_OPTIONS} ${WARNING_ERROR}
diff --git a/defs.h b/defs.h
index eb1c71b..1fa5c21 100644
--- a/defs.h
+++ b/defs.h
@@ -4956,6 +4956,7 @@ void cmd_mach(void); /* main.c */
void cmd_help(void); /* help.c */
void cmd_test(void); /* test.c */
void cmd_ascii(void); /* tools.c */
+void cmd_sbitmap(void); /* sbitmap.c */
void cmd_bpf(void); /* bfp.c */
void cmd_set(void); /* tools.c */
void cmd_eval(void); /* tools.c */
@@ -5543,6 +5544,7 @@ void display_help_screen(char *);
extern char *help_pointer[];
extern char *help_alias[];
extern char *help_ascii[];
+extern char *help_sbitmap[];
extern char *help_bpf[];
extern char *help_bt[];
extern char *help_btop[];
diff --git a/global_data.c b/global_data.c
index a316d1c..55524e3 100644
--- a/global_data.c
+++ b/global_data.c
@@ -105,6 +105,7 @@ struct command_table_entry linux_command_table[] = {
{"rd", cmd_rd, help_rd, MINIMAL},
{"repeat", cmd_repeat, help_repeat, 0},
{"runq", cmd_runq, help_runq, REFRESH_TASK_TABLE},
+ {"sbitmap", cmd_sbitmap, help_sbitmap, 0},
{"search", cmd_search, help_search, 0},
{"set", cmd_set, help_set, REFRESH_TASK_TABLE | MINIMAL},
{"sig", cmd_sig, help_sig, REFRESH_TASK_TABLE},
diff --git a/help.c b/help.c
index 6c262a3..b946745 100644
--- a/help.c
+++ b/help.c
@@ -967,6 +967,95 @@ char *help_ascii[] = {
NULL
};
+char *help_sbitmap[] = {
+"sbitmap",
+"sbitmap_queue struct contents",
+"[-s struct[.member[,member]] -p address [-v]] address",
+" This command dumps the contents of the sbitmap_queue structure and",
+" the used bits in the bitmap. Also, it shows the dump of a structure",
+" array associated with the sbitmap_queue.",
+"",
+" The arguments are as follows:",
+"",
+" -s struct - name of a C-code structure, that is stored in an array",
+" sssociated with sbitmap_queue structure. Use the",
+" \"struct.member\" format in order to display a particular",
+" member of the structure. -s option requires -p option",
+"",
+" -p address - address of a structure array associated with sbitmap_queue",
+" structure. The set bits in sbitmap are used for the index",
+" in an associated array.",
+"",
+" -x - override default output format with hexadecimal format.",
+"",
+" -d - override default output format with decimal format.",
+"",
+" -v - By default, the sbitmap command shows only a used sbitmap",
+" index and a structure address in the associated array.",
+" This flag says to print of a formatted display of the",
+" contents of a structure in an associated array. -v option",
+" requires of -s.",
+"",
+"EXAMPLES",
+"",
+" Display the common sbitmap information:",
+"",
+" %s> sbitmap ffffffffc06b9420",
+" depth = 256",
+" busy = 15",
+" cleared = 1",
+" bits_per_word = 64",
+" map_nr = 4",
+" alloc_hint = {193, 78}",
+" wake_batch = 8",
+" wake_index = 0",
+" ws_active = 0",
+" ws = {",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" }",
+" round_robin = 0",
+" min_shallow_depth = 4294967295",
+"",
+" 00000000: 0000 0000 0000 0000 ffbf 0000 0000 0000",
+" 00000010: 0000 0000 0000 0000 0000 0000 0000 0000",
+"",
+" Display the structure address is associated with sbitmap_queue:",
+"",
+" %s> sbitmap -s test_data -p ffff973422dac000 ffffffffc06b9420",
+" 64: 0xffff973422dac200",
+" 65: 0xffff973422dac208",
+" 66: 0xffff973422dac210",
+" ...",
+"",
+" Display a formatted content of a structures:",
+"",
+" %s> sbitmap -s test_data -p ffff973422dac000 -v ffffffffc06b9420",
+" 64 (0xffff973422dac200):",
+" struct test_data {",
+" tag = 64,",
+" cpu = 1",
+" }",
+" 65 (0xffff973422dac208):",
+" struct test_data {",
+" tag = 65,",
+" cpu = 1",
+" }",
+" 66 (0xffff973422dac210):",
+" struct test_data {",
+" tag = 66,",
+" cpu = 1",
+" }",
+" ...",
+NULL
+};
+
char *help_quit[] = {
"quit",
"exit this session",
diff --git a/sbitmap.c b/sbitmap.c
new file mode 100644
index 0000000..71522f8
--- /dev/null
+++ b/sbitmap.c
@@ -0,0 +1,591 @@
+/* sbitmap.c - core analysis suite
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
+ * Copyright (C) 2002-2020 David Anderson
+ * Copyright (C) 2002-2020 Red Hat, Inc. All rights reserved.
+ *
+ * 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"
+#include <stdbool.h>
+
+#define SBQ_WAIT_QUEUES 8
+
+static inline unsigned int __const_hweight8(unsigned long w)
+{
+ return
+ (!!((w) & (1ULL << 0))) +
+ (!!((w) & (1ULL << 1))) +
+ (!!((w) & (1ULL << 2))) +
+ (!!((w) & (1ULL << 3))) +
+ (!!((w) & (1ULL << 4))) +
+ (!!((w) & (1ULL << 5))) +
+ (!!((w) & (1ULL << 6))) +
+ (!!((w) & (1ULL << 7)));
+}
+
+#define __const_hweight16(w) (__const_hweight8(w) + __const_hweight8((w) >> 8))
+#define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16))
+#define __const_hweight64(w) (__const_hweight32(w) + __const_hweight32((w) >> 32))
+
+#define hweight32(w) __const_hweight32(w)
+#define hweight64(w) __const_hweight64(w)
+
+#define BIT(nr) (1UL << (nr))
+
+/* sbitmap and sbitmap_word structs context */
+struct sbitmap_context {
+ unsigned sb_depth;
+ unsigned sb_shift;
+ unsigned sb_map_nr;
+ ulong sb_map_addr;
+ unsigned sb_map_size;
+
+ int w_depth_off;
+ int w_word_off;
+ int w_cleared_off;
+};
+
+/* sbitmap_queue struct context */
+struct sbitmap_queue_context {
+ ulong sb_addr;
+ ulong alloc_hint;
+ unsigned int wake_batch;
+ int wake_index;
+ ulong ws_addr;
+ int ws_active;
+ bool round_robin;
+ unsigned int min_shallow_depth;
+
+};
+
+struct sbitmap_data {
+#define SD_FLAG_STRUCT_NAME (VERBOSE << 1)
+#define SD_FLAG_STRUCT_ADDR (VERBOSE << 2)
+#define SD_FLAG_STRUCT_MEMBER (VERBOSE << 3)
+ ulong flags;
+ int radix;
+ /* sbitmap_queue info */
+ ulong addr;
+ /* data array info */
+ char *data_name;
+ ulong data_addr;
+
+ struct sbitmap_queue_context sqc;
+ struct sbitmap_context sc;
+};
+
+static inline unsigned long min(unsigned long a, unsigned long b)
+{
+ return (a < b) ? a : b;
+}
+
+static void __readmem(ulong addr, void *buffer, size_t size)
+{
+ ulong flag = FAULT_ON_ERROR;
+
+ if (!readmem(addr, KVADDR, buffer, size, "__readmem", flag))
+ error(FATAL, "failed read memory: 0x%x\n", addr);
+}
+
+static ulong __read_ulong(ulong addr)
+{
+ ulong value;
+
+ __readmem(addr, &value, sizeof(value));
+ return value;
+}
+
+static long __struct_size(char *name)
+{
+ long size;
+
+ size = STRUCT_SIZE(name);
+ if (size < 0)
+ error(FATAL, "Invalid struct size: %s\n", name);
+
+ return size;
+}
+
+static long __member_offset(char *name, char *member)
+{
+ long offset;
+
+ offset = MEMBER_OFFSET(name, member);
+ if (offset == INVALID_OFFSET)
+ offset = ANON_MEMBER_OFFSET(name, member);
+ if (offset == INVALID_OFFSET)
+ error(FATAL, "Can't get offset of '%s.%s'\n", name, member);
+
+ return offset;
+}
+
+static unsigned long __last_word_mask(unsigned long nbits)
+{
+ return ~0UL >> (-(nbits) & (BITS_PER_LONG - 1));
+}
+
+static unsigned long bitmap_hweight_long(unsigned long w)
+{
+ return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
+}
+
+static unsigned long bitmap_weight(unsigned long bitmap, unsigned int bits)
+{
+ unsigned long w = 0;
+
+ w += bitmap_hweight_long(bitmap);
+ if (bits % BITS_PER_LONG)
+ w += bitmap_hweight_long(bitmap & __last_word_mask(bits));
+
+ return w;
+}
+
+static unsigned int __sbitmap_weight(const struct sbitmap_context *sc, bool set)
+{
+ unsigned int weight = 0;
+ ulong addr = sc->sb_map_addr;
+ unsigned long depth, word, cleared;
+ int i;
+
+ for (i = 0; i < sc->sb_map_nr; i++) {
+ depth = __read_ulong(addr + sc->w_depth_off);
+
+ if (set) {
+ word = __read_ulong(addr + sc->w_word_off);
+ weight += bitmap_weight(word, depth);
+ } else {
+ cleared = __read_ulong(addr + sc->w_cleared_off);
+ weight += bitmap_weight(cleared, depth);
+ }
+
+ addr += sc->sb_map_size;
+ }
+
+ return weight;
+}
+
+static unsigned int sbitmap_weight(const struct sbitmap_context *sc)
+{
+ return __sbitmap_weight(sc, true);
+}
+
+static unsigned int sbitmap_cleared(const struct sbitmap_context *sc)
+{
+ return __sbitmap_weight(sc, false);
+}
+
+static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
+ const struct sbitmap_context *sc)
+{
+ int cpus = get_cpus_possible();
+ int sbq_wait_state_size, wait_cnt_off, wait_off, list_head_off;
+ bool first;
+ int i;
+
+ fprintf(fp, "depth = %u\n", sc->sb_depth);
+ fprintf(fp, "busy = %u\n", sbitmap_weight(sc) - sbitmap_cleared(sc));
+ fprintf(fp, "cleared = %u\n", sbitmap_cleared(sc));
+ fprintf(fp, "bits_per_word = %u\n", 1U << sc->sb_shift);
+ fprintf(fp, "map_nr = %u\n", sc->sb_map_nr);
+
+ fputs("alloc_hint = {", fp);
+ first = true;
+ for (i = 0; i < cpus; i++) {
+ if (!first)
+ fprintf(fp, ", ");
+ first = false;
+
+ ulong ptr = kt->__per_cpu_offset[i] + sqc->alloc_hint;
+ fprintf(fp, "%lu", __read_ulong(ptr));
+ }
+ fputs("}\n", fp);
+
+ fprintf(fp, "wake_batch = %u\n", sqc->wake_batch);
+ fprintf(fp, "wake_index = %d\n", sqc->wake_index);
+ fprintf(fp, "ws_active = %d\n", sqc->ws_active);
+
+ sbq_wait_state_size = __struct_size("sbq_wait_state");
+ wait_cnt_off = __member_offset("sbq_wait_state", "wait_cnt");
+ wait_off = __member_offset("sbq_wait_state", "wait");
+ list_head_off = __member_offset("wait_queue_head", "head");
+
+ fputs("ws = {\n", fp);
+ for (i = 0; i < SBQ_WAIT_QUEUES; i++) {
+ ulong ws_addr = sqc->ws_addr + (sbq_wait_state_size * i);
+ struct kernel_list_head lh;
+ ulong wait_cnt_addr, list_head_addr;
+ ulong wait_cnt;
+
+ wait_cnt_addr = ws_addr + wait_cnt_off;
+ __readmem(wait_cnt_addr, &wait_cnt, sizeof(wait_cnt));
+
+ list_head_addr = ws_addr + wait_off + list_head_off;
+ __readmem(list_head_addr, &lh, sizeof(lh));
+
+ fprintf(fp, "\t{ .wait_cnt = %lu, .wait = %s },\n",
+ wait_cnt, (lh.next == lh.prev) ? "inactive" : "active");
+ }
+ fputs("}\n", fp);
+
+ fprintf(fp, "round_robin = %d\n", sqc->round_robin);
+ fprintf(fp, "min_shallow_depth = %u\n", sqc->min_shallow_depth);
+}
+
+static void sbitmap_emit_byte(unsigned int offset, uint8_t byte)
+{
+ if ((offset &0xf) == 0) {
+ if (offset != 0)
+ fputc('\n', fp);
+ fprintf(fp, "%08x:", offset);
+ }
+ if ((offset & 0x1) == 0)
+ fputc(' ', fp);
+ fprintf(fp, "%02x", byte);
+}
+
+static void sbitmap_bitmap_show(const struct sbitmap_context *sc)
+{
+ uint8_t byte = 0;
+ unsigned int byte_bits = 0;
+ unsigned int offset = 0;
+ int i;
+
+ for (i = 0; i < sc->sb_map_nr; i++) {
+ ulong addr = sc->sb_map_addr + (sc->sb_map_size * i);
+ unsigned long word = __read_ulong(addr + sc->w_word_off);
+ unsigned long cleared = __read_ulong(addr + sc->w_cleared_off);
+ unsigned long word_bits = __read_ulong(addr + sc->w_depth_off);
+
+ word &= ~cleared;
+
+ while (word_bits > 0) {
+ unsigned int bits = min(8 - byte_bits, word_bits);
+
+ byte |= (word & (BIT(bits) - 1)) << byte_bits;
+ byte_bits += bits;
+ if (byte_bits == 8) {
+ sbitmap_emit_byte(offset, byte);
+ byte = 0;
+ byte_bits = 0;
+ offset++;
+ }
+ word >>= bits;
+ word_bits -= bits;
+ }
+
+ }
+ if (byte_bits) {
+ sbitmap_emit_byte(offset, byte);
+ offset++;
+ }
+ if (offset)
+ fputc('\n', fp);
+}
+
+static void sbitmap_queue_dump(const struct sbitmap_data *sd)
+{
+ sbitmap_queue_show(&sd->sqc, &sd->sc);
+ fputc('\n', fp);
+ sbitmap_bitmap_show(&sd->sc);
+}
+
+static unsigned long sbitmap_find_next_bit(unsigned long word,
+ unsigned long size, unsigned long offset)
+{
+ if (size > BITS_PER_LONG)
+ error(FATAL, "%s: word size isn't correct\n", __func__);
+
+ for (; offset < size; offset++)
+ if (word & (1UL << offset))
+ return offset;
+
+ return size;
+}
+
+typedef bool (*sb_for_each_fn)(unsigned int, void *);
+
+static void __sbitmap_for_each_set(const struct sbitmap_context *sc,
+ unsigned int start, sb_for_each_fn fn, void *data)
+{
+ unsigned int index;
+ unsigned int nr;
+ unsigned int scanned = 0;
+
+ if (start >= sc->sb_map_nr)
+ start = 0;
+
+ index = start >> sc->sb_shift;
+ nr = start & ((1U << sc->sb_shift) - 1U);
+
+ while (scanned < sc->sb_depth) {
+ unsigned long w_addr = sc->sb_map_addr + (sc->sb_map_size * index);
+
+ unsigned long w_depth = __read_ulong(w_addr + sc->w_depth_off);
+ unsigned long w_word = __read_ulong(w_addr + sc->w_word_off);
+ unsigned long w_cleared = __read_ulong(w_addr + sc->w_cleared_off);
+
+ unsigned long word;
+ unsigned int depth = min(w_depth - nr, sc->sb_depth - scanned);
+
+ scanned += depth;
+ word = w_word & ~w_cleared;
+ if (!word)
+ goto next;
+
+ /*
+ * On the first iteration of the outer loop, we need to add the
+ * bit offset back to the size of the word for find_next_bit().
+ * On all other iterations, nr is zero, so this is a noop.
+ */
+ depth += nr;
+ while (1) {
+ nr = sbitmap_find_next_bit(word, depth, nr);
+ if (nr >= depth)
+ break;
+ if (!fn((index << sc->sb_shift) + nr, data))
+ return;
+
+ nr++;
+ }
+next:
+ nr = 0;
+ if (++index >= sc->sb_map_nr)
+ index = 0;
+ }
+}
+
+static void sbitmap_for_each_set(const struct sbitmap_context *sc,
+ sb_for_each_fn fn, void *data)
+{
+ __sbitmap_for_each_set(sc, 0, fn, data);
+}
+
+static void sbitmap_dump_struct_members(const char *s, ulong addr, unsigned radix)
+{
+ int i, argc;
+ char *p1, *p2;
+ char *structname, *members;
+ char *arglist[MAXARGS];
+
+ structname = GETBUF(strlen(s) + 1);
+ members = GETBUF(strlen(s) + 1);
+
+ strcpy(structname, s);
+ p1 = strstr(structname, ".") + 1;
+
+ p2 = strstr(s, ".") + 1;
+ strcpy(members, p2);
+ replace_string(members, ",", ' ');
+ argc = parse_line(members, arglist);
+
+ for (i = 0; i < argc; i++) {
+ *p1 = NULLCHAR;
+ strcat(structname, arglist[i]);
+ dump_struct_member(structname, addr, radix);
+ }
+
+ FREEBUF(structname);
+ FREEBUF(members);
+}
+
+struct data_info {
+ ulong addr;
+ int size;
+ char *name;
+ unsigned radix;
+ bool verbose;
+ bool members;
+};
+
+static bool sbitmap_data_print(unsigned int idx, void *data)
+{
+ const struct data_info *d = data;
+ ulong addr = d->addr + (d->size * idx);
+
+ if (d->verbose) {
+ fprintf(fp, "%d (0x%08lx):\n", idx, addr);
+ if (d->members)
+ sbitmap_dump_struct_members(d->name, addr, d->radix);
+ else
+ dump_struct(d->name, addr, d->radix);
+ } else
+ fprintf(fp, "%d: 0x%08lx\n", idx, addr);
+
+ return true;
+}
+
+static char *__get_struct_name(const char *s)
+{
+ char *name, *p;
+
+ name = GETBUF(strlen(s) + 1);
+ strcpy(name, s);
+
+ p = strstr(name, ".");
+ *p = NULLCHAR;
+
+ return name;
+}
+
+static void sbitmap_data_dump(const struct sbitmap_data *sd)
+{
+ struct data_info d = {0};
+
+ d.addr = sd->data_addr;
+ d.name = sd->data_name;
+ d.radix = sd->radix;
+ d.verbose = !!(sd->flags & VERBOSE);
+ d.members = !!(sd->flags & SD_FLAG_STRUCT_MEMBER);
+
+ if (d.members) {
+ char *name = __get_struct_name(d.name);
+ d.size = __struct_size(name);
+ FREEBUF(name);
+ } else
+ d.size = __struct_size(d.name);
+
+ sbitmap_for_each_set(&sd->sc, sbitmap_data_print, &d);
+}
+
+static void load_sbitmap_queue_context(ulong addr, struct sbitmap_queue_context *sqc)
+{
+ char *sb_q = "sbitmap_queue";
+
+ sqc->sb_addr = addr + __member_offset(sb_q, "sb");
+ __readmem(addr + __member_offset(sb_q, "alloc_hint"), &sqc->alloc_hint, sizeof(sqc->alloc_hint));
+ __readmem(addr + __member_offset(sb_q, "wake_batch"), &sqc->wake_batch, sizeof(sqc->wake_batch));
+ __readmem(addr + __member_offset(sb_q, "wake_index"), &sqc->wake_index, sizeof(sqc->wake_index));
+ __readmem(addr + __member_offset(sb_q, "ws"), &sqc->ws_addr, sizeof(sqc->ws_addr));
+ __readmem(addr + __member_offset(sb_q, "ws_active"), &sqc->ws_active, sizeof(sqc->ws_active));
+ __readmem(addr + __member_offset(sb_q, "round_robin"), &sqc->round_robin, sizeof(sqc->round_robin));
+ __readmem(addr + __member_offset(sb_q, "min_shallow_depth"), &sqc->min_shallow_depth, sizeof(sqc->min_shallow_depth));
+}
+
+static void load_sbitmap_context(ulong addr, struct sbitmap_context *sc)
+{
+ char *sb = "sbitmap";
+ char *map = "sbitmap_word";
+
+ __readmem(addr + __member_offset(sb, "depth"), &sc->sb_depth, sizeof(sc->sb_depth));
+ __readmem(addr + __member_offset(sb, "shift"), &sc->sb_shift, sizeof(sc->sb_shift));
+ __readmem(addr + __member_offset(sb, "map_nr"), &sc->sb_map_nr, sizeof(sc->sb_map_nr));
+ __readmem(addr + __member_offset(sb, "map"), &sc->sb_map_addr, sizeof(sc->sb_map_addr));
+ sc->sb_map_size = __struct_size(map);
+ sc->w_depth_off = __member_offset(map, "depth");
+ sc->w_word_off = __member_offset(map, "word");
+ sc->w_cleared_off = __member_offset(map, "cleared");
+}
+
+void cmd_sbitmap(void)
+{
+ struct sbitmap_data sd = {0};
+ int c;
+
+ while ((c = getopt(argcnt, args, "s:p:xdv")) != EOF) {
+ switch (c) {
+ case 's':
+ if (sd.flags & SD_FLAG_STRUCT_NAME)
+ error(FATAL, "-s option (%s) already entered\n", sd.data_name);
+
+ sd.data_name = optarg;
+ sd.flags |= SD_FLAG_STRUCT_NAME;
+
+ break;
+
+ case 'p':
+ if (sd.flags & SD_FLAG_STRUCT_ADDR)
+ error(FATAL, "-m option (0x%lx) already entered\n", sd.data_addr);
+ else if (!IS_A_NUMBER(optarg))
+ error(FATAL, "invalid -m option: %s\n", optarg);
+
+ sd.data_addr = htol(optarg, FAULT_ON_ERROR, NULL);
+ if (!IS_KVADDR(sd.data_addr))
+ error(FATAL, "invalid kernel virtual address: %s\n", optarg);
+ sd.flags |= SD_FLAG_STRUCT_ADDR;
+
+ break;
+
+ case 'v':
+ sd.flags |= VERBOSE;
+ break;
+
+ case 'x':
+ if (sd.radix == 10)
+ error(FATAL, "-d and -x are mutually exclusive\n");
+ sd.radix = 16;
+ break;
+
+ case 'd':
+ if (sd.radix == 16)
+ error(FATAL, "-d and -x are mutually exclusive\n");
+ sd.radix = 10;
+ break;
+
+ default:
+ argerrs++;
+ break;
+ }
+ }
+
+ if (argerrs)
+ cmd_usage(pc->curcmd, SYNOPSIS);
+
+ if (!args[optind]) {
+ error(INFO, "command argument is required\n");
+ cmd_usage(pc->curcmd, SYNOPSIS);
+ } else if (args[optind] && args[optind + 1]) {
+ error(INFO, "too many arguments\n");
+ cmd_usage(pc->curcmd, SYNOPSIS);
+ } else if (!IS_A_NUMBER(args[optind])) {
+ error(FATAL, "invalid command argument: %s\n", args[optind]);
+ }
+
+ sd.addr = htol(args[optind], FAULT_ON_ERROR, NULL);
+ if (!IS_KVADDR(sd.addr))
+ error(FATAL, "invalid kernel virtual address: %s\n", args[optind]);
+
+ if ((sd.flags & SD_FLAG_STRUCT_NAME) && !(sd.flags & SD_FLAG_STRUCT_ADDR)) {
+ error(INFO, "-s option requires -m option");
+ cmd_usage(pc->curcmd, SYNOPSIS);
+ } else if ((sd.flags & SD_FLAG_STRUCT_ADDR) && !(sd.flags & SD_FLAG_STRUCT_NAME)) {
+ error(FATAL, "-m option is used with -s option only\n");
+ cmd_usage(pc->curcmd, SYNOPSIS);
+ }
+
+ if (sd.flags & SD_FLAG_STRUCT_NAME) {
+ bool error_flag = false;
+
+ if (count_chars(sd.data_name, '.') > 0)
+ sd.flags |= SD_FLAG_STRUCT_MEMBER;
+
+ if (sd.flags & SD_FLAG_STRUCT_MEMBER) {
+ char *data_name = __get_struct_name(sd.data_name);
+ if (!STRUCT_EXISTS(data_name))
+ error_flag = true;
+ FREEBUF(data_name);
+ } else {
+ if (!STRUCT_EXISTS(sd.data_name))
+ error_flag = true;
+ }
+ if (error_flag)
+ error(FATAL, "invalid data structure reference: %s\n", sd.data_name);
+ }
+
+ load_sbitmap_queue_context(sd.addr, &sd.sqc);
+ load_sbitmap_context(sd.sqc.sb_addr, &sd.sc);
+
+ if (sd.flags & SD_FLAG_STRUCT_NAME)
+ sbitmap_data_dump(&sd);
+ else
+ sbitmap_queue_dump(&sd);
+}
--
2.25.1
3 years
Re: [Crash-utility] [PATCH v2 4/4] make: replace make by $(MAKE)
by lijiang
On Thu, Dec 23, 2021 at 5:14 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Thu, 23 Dec 2021 00:33:16 +0000
> From: HAGIO KAZUHITO(?????) <k-hagio-ab(a)nec.com>
> To: Sven Schnelle <svens(a)linux.ibm.com>
> Cc: "Discussion list for crash utility usage, maintenance and
> development" <crash-utility(a)redhat.com>
> Subject: Re: [Crash-utility] [PATCH v2 4/4] make: replace make by
> $(MAKE)
> Message-ID:
> <OS3PR01MB677601D042591DF6451F477DDD7E9(a)OS3PR01MB6776.jpnprd01.prod.outlook.com>
>
> Content-Type: text/plain; charset="iso-2022-jp"
>
> Hi Sven,
>
> thank you for the update.
>
> -----Original Message-----
> > diff --git a/gdb-10.2.patch b/gdb-10.2.patch
> > index 1280d0688e83..afdbe99eae0d 100644
> > --- a/gdb-10.2.patch
> > +++ b/gdb-10.2.patch
> > @@ -73,7 +73,7 @@
> > # Removing the old gdb first works better if it is running, at least on SunOS.
> > gdb$(EXEEXT): gdb.o $(LIBGDB_OBS) $(CDEPS) $(TDEPLIBS)
> > $(SILENCE) rm -f gdb$(EXEEXT)
> > -+ @make -C ../.. GDB_FLAGS=-DGDB_10_2 library
> > ++ @$(MAKE) -C ../.. GDB_FLAGS=-DGDB_10_2 library
> > $(ECHO_CXXLD) $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \
> > - -o gdb$(EXEEXT) gdb.o $(LIBGDB_OBS) \
> > - $(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES)
>
> When detecting any change of the gdb patch, it tries to re-apply the new one
> using "patch -N --fuzz=0" in order to update the gdb. Please refer to
> Makefile::rebuild and the head of the gdb-10.2.patch.
>
> So I think that, to make a change to the gdb sources,
>
> 1. we have to "add" patches to the end of the gdb patch, and
> 2. if there are multiple patches for a gdb file, the "patch -N" doesn't work,
> so we have to revert the gdb file to the original one.
>
> (I will add this custom to crash guidelines later..)
>
Good point, Kazu.
Thanks.
Lianbo
3 years
[PATCH v2 0/4] A few makefile cleanups
by Sven Schnelle
Hi List,
i was looking into why crash doesn't compile with multiple jobs
and prepared a few patches to make that work. While doing that,
i also changed a few other things along the way.
Changes in v2:
- remove one missed --no-print-directory occurrence
- also fix extensions/Makefile
Sven Schnelle (4):
make: set --no-print-directory once
extensions: fix defs.h dependency
make: use -C instead of (cd x; make)
make: replace make by $(MAKE)
Makefile | 61 +++++++++++++++++++++++----------------------
extensions/Makefile | 10 ++++----
gdb-10.2.patch | 2 +-
3 files changed, 37 insertions(+), 36 deletions(-)
--
2.32.0
3 years
Re: [Crash-utility] [PATCH v3] Fix pvops Xen detection for arm machine
by lijiang
Thank you for the update, Qi.
For v3: Acked-by: Lianbo Jiang <lijiang(a)redhat.com>
On Tue, Dec 21, 2021 at 3:41 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Tue, 21 Dec 2021 15:40:31 +0800
> From: Qi Zheng <zhengqi.arch(a)bytedance.com>
> To: lijiang(a)redhat.com, k-hagio-ab(a)nec.com
> Cc: Qi Zheng <zhengqi.arch(a)bytedance.com>, crash-utility(a)redhat.com
> Subject: [Crash-utility] [PATCH v3] Fix pvops Xen detection for arm
> machine
> Message-ID: <20211221074031.51379-1-zhengqi.arch(a)bytedance.com>
> Content-Type: text/plain; charset="US-ASCII"
>
> Since the xen_start_info on the arm/arm64 platform is static defined:
>
> ./arm/xen/enlighten.c:40:static struct start_info _xen_start_info;
> ./arm/xen/enlighten.c:41:struct start_info *xen_start_info = &_xen_start_info;
> ./arm/xen/enlighten.c:42:EXPORT_SYMBOL(xen_start_info);
>
> The is_pvops_xen() in commit 4badc6229c69f5cd9da7eb7bdf400a53ec6db01a
> ("Fix pvops Xen detection for kernels >= v4.20") always return TRUE.
> Then the following error will be reported because p2m_mid_missing
> and xen_p2m_addr are not defined:
>
> crash: cannot resolve "p2m_top"
>
> For the arm/arm64 platform, fix it by using xen_vcpu_info instead of
> xen_start_info to detect Xen dumps.
>
> And considering that xen_start_info is only defined on x86 and arm
> platform, use machine_type() to explicitly narrow the scope of the
> xen_start_info check to x86.
>
> Signed-off-by: Qi Zheng <zhengqi.arch(a)bytedance.com>
> Acked-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
> ---
> kernel.c | 20 +++++++++++++++-----
> 1 file changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/kernel.c b/kernel.c
> index f4598ea..37b7af7 100644
> --- a/kernel.c
> +++ b/kernel.c
> @@ -10757,11 +10757,21 @@ is_pvops_xen(void)
> STREQ(sym, "paravirt_patch_default")))
> return TRUE;
>
> - if (symbol_exists("xen_start_info") &&
> - readmem(symbol_value("xen_start_info"), KVADDR, &addr,
> - sizeof(void *), "xen_start_info", RETURN_ON_ERROR) &&
> - addr != 0)
> - return TRUE;
> + if (machine_type("X86") || machine_type("X86_64")) {
> + if (symbol_exists("xen_start_info") &&
> + readmem(symbol_value("xen_start_info"), KVADDR, &addr,
> + sizeof(void *), "xen_start_info", RETURN_ON_ERROR) &&
> + addr != 0)
> + return TRUE;
> + }
> +
> + if (machine_type("ARM") || machine_type("ARM64")) {
> + if (symbol_exists("xen_vcpu_info") &&
> + readmem(symbol_value("xen_vcpu_info"), KVADDR, &addr,
> + sizeof(void *), "xen_vcpu_info", RETURN_ON_ERROR) &&
> + addr != 0)
> + return TRUE;
> + }
>
> return FALSE;
> }
> --
> changes since [v2]:
> - use machine_type() to explicitly narrow the scope of the xen_start_info
> check to x86.
> - Collect Acked-by from Kazu.
>
> [v1]: https://listman.redhat.com/archives/crash-utility/2021-December/msg00007....
> [v2]: https://listman.redhat.com/archives/crash-utility/2021-December/msg00028....
> 2.11.0
3 years
Re: [Crash-utility] [PATCH v2 2/4] extensions: fix defs.h dependency
by lijiang
Hi, Sven
Thank you for the improvement.
On Mon, Dec 20, 2021 at 9:17 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Mon, 20 Dec 2021 14:16:49 +0100
> From: Sven Schnelle <svens(a)linux.ibm.com>
> To: crash-utility(a)redhat.com
> Subject: [Crash-utility] [PATCH v2 2/4] extensions: fix defs.h
> dependency
> Message-ID: <20211220131651.1291387-3-svens(a)linux.ibm.com>
> Content-Type: text/plain; charset="US-ASCII"
>
> defs.h must be a dependency on each source files, otherwise
> targets might be built before defs.h is linked into the directory.
>
> Signed-off-by: Sven Schnelle <svens(a)linux.ibm.com>
> ---
> extensions/Makefile | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/extensions/Makefile b/extensions/Makefile
> index 0ad625af37ce..2894b9aa5a08 100644
> --- a/extensions/Makefile
> +++ b/extensions/Makefile
> @@ -26,9 +26,9 @@
>
> CONTRIB_SO := $(patsubst %.c,%.so,$(wildcard *.c))
>
> -all: link_defs $(CONTRIB_SO)
> -
> -link_defs:
> +all: $(CONTRIB_SO)
> +
> +defs.h:
> @rm -f defs.h
> @ln ../defs.h
>
Could you please describe more details about the above changes or give
an example to prove that it has this risk?
I noticed that all object files(.so and .c) have the dependency of
defs.h, the following code was copied from Makefile:
all: link_defs $(CONTRIB_SO)
link_defs:
@rm -f defs.h
@ln ../defs.h
$(CONTRIB_SO): %.so: %.c defs.h
Thanks.
Lianbo
> --
> 2.32.0
3 years
[PATCH v3] Fix pvops Xen detection for arm machine
by Qi Zheng
Since the xen_start_info on the arm/arm64 platform is static defined:
./arm/xen/enlighten.c:40:static struct start_info _xen_start_info;
./arm/xen/enlighten.c:41:struct start_info *xen_start_info = &_xen_start_info;
./arm/xen/enlighten.c:42:EXPORT_SYMBOL(xen_start_info);
The is_pvops_xen() in commit 4badc6229c69f5cd9da7eb7bdf400a53ec6db01a
("Fix pvops Xen detection for kernels >= v4.20") always return TRUE.
Then the following error will be reported because p2m_mid_missing
and xen_p2m_addr are not defined:
crash: cannot resolve "p2m_top"
For the arm/arm64 platform, fix it by using xen_vcpu_info instead of
xen_start_info to detect Xen dumps.
And considering that xen_start_info is only defined on x86 and arm
platform, use machine_type() to explicitly narrow the scope of the
xen_start_info check to x86.
Signed-off-by: Qi Zheng <zhengqi.arch(a)bytedance.com>
Acked-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
kernel.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/kernel.c b/kernel.c
index f4598ea..37b7af7 100644
--- a/kernel.c
+++ b/kernel.c
@@ -10757,11 +10757,21 @@ is_pvops_xen(void)
STREQ(sym, "paravirt_patch_default")))
return TRUE;
- if (symbol_exists("xen_start_info") &&
- readmem(symbol_value("xen_start_info"), KVADDR, &addr,
- sizeof(void *), "xen_start_info", RETURN_ON_ERROR) &&
- addr != 0)
- return TRUE;
+ if (machine_type("X86") || machine_type("X86_64")) {
+ if (symbol_exists("xen_start_info") &&
+ readmem(symbol_value("xen_start_info"), KVADDR, &addr,
+ sizeof(void *), "xen_start_info", RETURN_ON_ERROR) &&
+ addr != 0)
+ return TRUE;
+ }
+
+ if (machine_type("ARM") || machine_type("ARM64")) {
+ if (symbol_exists("xen_vcpu_info") &&
+ readmem(symbol_value("xen_vcpu_info"), KVADDR, &addr,
+ sizeof(void *), "xen_vcpu_info", RETURN_ON_ERROR) &&
+ addr != 0)
+ return TRUE;
+ }
return FALSE;
}
--
changes since [v2]:
- use machine_type() to explicitly narrow the scope of the xen_start_info
check to x86.
- Collect Acked-by from Kazu.
[v1]: https://listman.redhat.com/archives/crash-utility/2021-December/msg00007....
[v2]: https://listman.redhat.com/archives/crash-utility/2021-December/msg00028....
2.11.0
3 years