import crash-7.2.3-18.el8

This commit is contained in:
CentOS Sources 2019-05-07 09:44:18 -04:00
commit 6087332729
27 changed files with 5842 additions and 0 deletions

1
.crash.metadata Normal file
View File

@ -0,0 +1 @@
1a9fa8cd6869da42314ec47df6a750e053f4bece SOURCES/crash-7.2.3.tar.gz

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/crash-7.2.3.tar.gz

View File

@ -0,0 +1,154 @@
commit 0f65ae0c36bf04e22219f28c32c3ae0cdee5acfe
Author: Dave Anderson <anderson@redhat.com>
Date: Fri Dec 7 15:17:37 2018 -0500
Implemented a new plugin function for the readline library's tab
completion feature. Without the patch, the use of the default plugin
from the embedded gdb module has been seen to cause segmentation
violations or other fatal malloc/free/corruption assertions. The new
plugin takes gdb out of the picture entirely, and also restricts the
matching options to just symbol names, so as not to clutter the
results with irrelevant filenames.
(anderson@redhat.com)
diff --git a/cmdline.c b/cmdline.c
index cf3e150..665f48c 100644
--- a/cmdline.c
+++ b/cmdline.c
@@ -40,6 +40,8 @@ int shell_command(char *);
static void modify_orig_line(char *, struct args_input_file *);
static void modify_expression_arg(char *, char **, struct args_input_file *);
static int verify_args_input_file(char *);
+static char *crash_readline_completion_generator(const char *, int);
+static char **crash_readline_completer(const char *, int, int);
#define READLINE_LIBRARY
@@ -2073,6 +2075,9 @@ readline_init(void)
if (STREQ(pc->editing_mode, "emacs")) {
rl_editing_mode = emacs_mode;
}
+
+ rl_attempted_completion_function = crash_readline_completer;
+ rl_attempted_completion_over = 1;
}
/*
@@ -2610,3 +2615,27 @@ exec_args_input_file(struct command_table_entry *ct, struct args_input_file *aif
fclose(pc->args_ifile);
pc->args_ifile = NULL;
}
+
+static char *
+crash_readline_completion_generator(const char *match, int state)
+{
+ static struct syment *sp_match;
+
+ if (state == 0)
+ sp_match = NULL;
+
+ sp_match = symbol_complete_match(match, sp_match);
+
+ if (sp_match)
+ return(strdup(sp_match->name));
+ else
+ return NULL;
+}
+
+static char **
+crash_readline_completer(const char *match, int start, int end)
+{
+ rl_attempted_completion_over = 1;
+ return rl_completion_matches(match, crash_readline_completion_generator);
+}
+
diff --git a/defs.h b/defs.h
index 9ce32c1..a3cb5a4 100644
--- a/defs.h
+++ b/defs.h
@@ -5153,6 +5153,7 @@ void parse_for_member_extended(struct datatype_member *, ulong);
void add_to_downsized(char *);
int is_downsized(char *);
int is_string(char *, char *);
+struct syment *symbol_complete_match(const char *, struct syment *);
/*
* memory.c
diff --git a/symbols.c b/symbols.c
index 05628ff..0769294 100644
--- a/symbols.c
+++ b/symbols.c
@@ -13108,3 +13108,73 @@ is_downsized(char *name)
return FALSE;
}
+
+struct syment *
+symbol_complete_match(const char *match, struct syment *sp_last)
+{
+ int i;
+ struct syment *sp, *sp_end, *sp_start;
+ struct load_module *lm;
+ int search_init;
+
+ if (sp_last) {
+ sp_start = next_symbol(NULL, sp_last);
+ if (!sp_start)
+ return NULL;
+ } else
+ sp_start = st->symtable;
+
+ if ((sp_start >= st->symtable) && (sp_start < st->symend)) {
+ for (sp = sp_start; sp < st->symend; sp++) {
+ if (STRNEQ(sp->name, match))
+ return sp;
+ }
+ sp_start = NULL;
+ }
+
+ search_init = FALSE;
+
+ for (i = 0; i < st->mods_installed; i++) {
+ lm = &st->load_modules[i];
+ if (lm->mod_flags & MOD_INIT)
+ search_init = TRUE;
+ sp_end = lm->mod_symend;
+ if (!sp_start)
+ sp_start = lm->mod_symtable;
+
+ if ((sp_start >= lm->mod_symtable) && (sp_start < sp_end)) {
+ for (sp = sp_start; sp < sp_end; sp++) {
+ if (MODULE_START(sp))
+ continue;
+
+ if (STRNEQ(sp->name, match))
+ return sp;
+ }
+ sp_start = NULL;
+ }
+ }
+
+ if (!search_init)
+ return NULL;
+
+ for (i = 0; i < st->mods_installed; i++) {
+ lm = &st->load_modules[i];
+ if (!lm->mod_init_symtable)
+ continue;
+ sp_end = lm->mod_init_symend;
+ if (!sp_start)
+ sp_start = lm->mod_init_symtable;
+
+ if ((sp_start >= lm->mod_init_symtable) && (sp_start < sp_end)) {
+ for (sp = sp_start; sp < sp_end; sp++) {
+ if (MODULE_START(sp))
+ continue;
+
+ if (STRNEQ(sp->name, match))
+ return sp;
+ }
+ }
+ }
+
+ return NULL;
+}

View File

@ -0,0 +1,27 @@
commit 1926150ee350e17fee2aeabb8ef781222d94366e
Author: Dave Anderson <anderson@redhat.com>
Date: Mon Jun 11 13:46:41 2018 -0400
Fix for the ppc64/ppc64le "bt" command on Linux 4.7 and later kernels
that contain commit d8bff643d81a58181356c0aa3ab771ac10da6894,
titled "[x86] asm: Make sure verify_cpu() has a good stack", which
inadvertently breaks the ppc64/ppc64le kernel stack size calculation
when running with crash-7.2.2 or later. Without the patch, "bt" may
fail with a filtered kdump dumpfile with the two error messages
"bt: page excluded: kernel virtual address: <address> type: stack
contents" and "bt: read of stack at <address> failed".
(anderson@redhat.com)
diff --git a/task.c b/task.c
index f6956d5..1b32629 100644
--- a/task.c
+++ b/task.c
@@ -440,7 +440,7 @@ task_init(void)
} else if (VALID_SIZE(thread_union) &&
((len = SIZE(thread_union)) != STACKSIZE())) {
machdep->stacksize = len;
- } else {
+ } else if (!VALID_SIZE(thread_union) && !VALID_SIZE(task_union)) {
if (kernel_symbol_exists("__start_init_task") &&
kernel_symbol_exists("__end_init_task")) {
len = symbol_value("__end_init_task");

View File

@ -0,0 +1,412 @@
commit 27a6ebd0cda386b1dfb7b0fffb4d8b489b391ccf
Author: Dave Anderson <anderson@redhat.com>
Date: Mon Sep 24 16:33:57 2018 -0400
Resurrection of the the "dev -p" option for displaying PCI device
data on Linux 2.6.26 and later kernels. The option was deprecated
as of Linux 2.6.26, and without the patch, the option would indicate
"dev: -p option not supported or applicable on this architecture
or kernel" when running against the newer kernel versions. PCI Bus
information will also be displayed with this patch.
(m.mizuma@jp.fujitsu.com)
diff --git a/defs.h b/defs.h
index d6492c5..80c61ef 100644
--- a/defs.h
+++ b/defs.h
@@ -2032,6 +2032,17 @@ struct offset_table {
long bpf_prog_aux_user;
long user_struct_uid;
long idr_cur;
+ long pci_dev_dev;
+ long pci_dev_hdr_type;
+ long pci_dev_pcie_flags_reg;
+ long pci_bus_node;
+ long pci_bus_devices;
+ long pci_bus_dev;
+ long pci_bus_children;
+ long pci_bus_parent;
+ long pci_bus_self;
+ long device_kobj;
+ long kobject_name;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/dev.c b/dev.c
index 3db898a..7ce2422 100644
--- a/dev.c
+++ b/dev.c
@@ -24,6 +24,7 @@ static void dump_blkdevs_v3(ulong);
static ulong search_cdev_map_probes(char *, int, int, ulong *);
static ulong search_bdev_map_probes(char *, int, int, ulong *);
static void do_pci(void);
+static void do_pci2(void);
static void do_io(void);
static void do_resource_list(ulong, char *, int);
@@ -51,11 +52,23 @@ dev_init(void)
MEMBER_OFFSET_INIT(pci_dev_global_list, "pci_dev", "global_list");
MEMBER_OFFSET_INIT(pci_dev_next, "pci_dev", "next");
MEMBER_OFFSET_INIT(pci_dev_bus, "pci_dev", "bus");
+ MEMBER_OFFSET_INIT(pci_dev_dev, "pci_dev", "dev");
MEMBER_OFFSET_INIT(pci_dev_devfn, "pci_dev", "devfn");
MEMBER_OFFSET_INIT(pci_dev_class, "pci_dev", "class");
MEMBER_OFFSET_INIT(pci_dev_device, "pci_dev", "device");
+ MEMBER_OFFSET_INIT(pci_dev_hdr_type, "pci_dev", "hdr_type");
+ MEMBER_OFFSET_INIT(pci_dev_pcie_flags_reg, "pci_dev", "pcie_flags_reg");
MEMBER_OFFSET_INIT(pci_dev_vendor, "pci_dev", "vendor");
MEMBER_OFFSET_INIT(pci_bus_number, "pci_bus", "number");
+ MEMBER_OFFSET_INIT(pci_bus_node, "pci_bus", "node");
+ MEMBER_OFFSET_INIT(pci_bus_devices, "pci_bus", "devices");
+ MEMBER_OFFSET_INIT(pci_bus_dev, "pci_bus", "dev");
+ MEMBER_OFFSET_INIT(pci_bus_children, "pci_bus", "children");
+ MEMBER_OFFSET_INIT(pci_bus_parent, "pci_bus", "parent");
+ MEMBER_OFFSET_INIT(pci_bus_self, "pci_bus", "self");
+
+ MEMBER_OFFSET_INIT(device_kobj, "device", "kobj");
+ MEMBER_OFFSET_INIT(kobject_name, "kobject", "name");
STRUCT_SIZE_INIT(resource, "resource");
if ((VALID_STRUCT(resource) && symbol_exists("do_resource_list")) ||
@@ -114,10 +127,14 @@ cmd_dev(void)
return;
case 'p':
- if (machine_type("S390X") ||
- (THIS_KERNEL_VERSION >= LINUX(2,6,26)))
+ if (machine_type("S390X"))
+ option_not_supported(c);
+ if (symbol_exists("pci_devices"))
+ do_pci();
+ else if (symbol_exists("pci_root_buses"))
+ do_pci2();
+ else
option_not_supported(c);
- do_pci();
return;
default:
@@ -2217,6 +2234,313 @@ do_resource_list(ulong first_entry, char *resource_buf, int size)
#endif /* USE_2_2_17_PCI_H */
+#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */
+#define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */
+#define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */
+#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */
+#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */
+#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
+#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCIe to PCI/PCI-X Bridge */
+#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIe Bridge */
+#define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */
+#define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */
+
+static void
+fill_dev_name(ulong pci_dev, char *name)
+{
+ ulong kobj, value;
+
+ memset(name, 0, sizeof(*name) * BUFSIZE);
+
+ kobj = pci_dev + OFFSET(pci_dev_dev) + OFFSET(device_kobj);
+
+ readmem(kobj + OFFSET(kobject_name),
+ KVADDR, &value, sizeof(void *), "kobject name",
+ FAULT_ON_ERROR);
+
+ read_string(value, name, BUFSIZE-1);
+}
+
+static void
+fill_bus_name(ulong pci_bus, char *name)
+{
+ ulong kobj, value;
+
+ memset(name, 0, sizeof(*name) * BUFSIZE);
+
+ kobj = pci_bus + OFFSET(pci_bus_dev) + OFFSET(device_kobj);
+
+ readmem(kobj + OFFSET(kobject_name),
+ KVADDR, &value, sizeof(void *), "kobject name",
+ FAULT_ON_ERROR);
+
+ read_string(value, name, BUFSIZE-1);
+}
+
+static void
+fill_dev_id(ulong pci_dev, char *id)
+{
+ unsigned short device, vendor;
+
+ memset(id, 0, sizeof(*id) * BUFSIZE);
+
+ readmem(pci_dev + OFFSET(pci_dev_device),
+ KVADDR, &device, sizeof(short), "pci dev device",
+ FAULT_ON_ERROR);
+ readmem(pci_dev + OFFSET(pci_dev_vendor), KVADDR,
+ &vendor, sizeof(short), "pci dev vendor", FAULT_ON_ERROR);
+
+ sprintf(id, "%x:%x", vendor, device);
+}
+
+static void
+fill_dev_class(ulong pci_dev, char *c)
+{
+ unsigned int class;
+
+ memset(c, 0, sizeof(*c) * BUFSIZE);
+ readmem(pci_dev + OFFSET(pci_dev_class), KVADDR,
+ &class, sizeof(int), "pci class", FAULT_ON_ERROR);
+
+ class >>= 8;
+
+ sprintf(c, "%04x", class);
+}
+
+static int
+pci_pcie_type(ulong cap)
+{
+ return (cap & PCI_EXP_FLAGS_TYPE) >> 4;
+}
+
+static int
+pci_is_bridge(unsigned char hdr_type)
+{
+ return hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+ hdr_type == PCI_HEADER_TYPE_CARDBUS;
+}
+
+static void
+fill_pcie_type(ulong pcidev, char *t)
+{
+ int type, bufidx = 0;
+ unsigned short pciecap;
+ unsigned char hdr_type;
+
+ memset(t, 0, sizeof(*t) * BUFSIZE);
+
+ readmem(pcidev + OFFSET(pci_dev_hdr_type), KVADDR, &hdr_type,
+ sizeof(char), "pci dev hdr_type", FAULT_ON_ERROR);
+
+ if (!VALID_MEMBER(pci_dev_pcie_flags_reg))
+ goto bridge_chk;
+
+ readmem(pcidev + OFFSET(pci_dev_pcie_flags_reg), KVADDR, &pciecap,
+ sizeof(unsigned short), "pci dev pcie_flags_reg", FAULT_ON_ERROR);
+
+ type = pci_pcie_type(pciecap);
+
+ if (type == PCI_EXP_TYPE_ENDPOINT)
+ bufidx = sprintf(t, "ENDPOINT");
+ else if (type == PCI_EXP_TYPE_LEG_END)
+ bufidx = sprintf(t, "LEG_END");
+ else if (type == PCI_EXP_TYPE_ROOT_PORT)
+ bufidx = sprintf(t, "ROOT_PORT");
+ else if (type == PCI_EXP_TYPE_UPSTREAM)
+ bufidx = sprintf(t, "UPSTREAM");
+ else if (type == PCI_EXP_TYPE_DOWNSTREAM)
+ bufidx = sprintf(t, "DOWNSTREAM");
+ else if (type == PCI_EXP_TYPE_PCI_BRIDGE)
+ bufidx = sprintf(t, "PCI_BRIDGE");
+ else if (type == PCI_EXP_TYPE_PCIE_BRIDGE)
+ bufidx = sprintf(t, "PCIE_BRIDGE");
+ else if (type == PCI_EXP_TYPE_RC_END)
+ bufidx = sprintf(t, "RC_END");
+ else if (type == PCI_EXP_TYPE_RC_EC)
+ bufidx = sprintf(t, "RC_EC");
+
+bridge_chk:
+ if (pci_is_bridge(hdr_type))
+ sprintf(t + bufidx, " [BRIDGE]");
+}
+
+static void
+walk_devices(ulong pci_bus)
+{
+ struct list_data list_data, *ld;
+ int devcnt, i;
+ ulong *devlist, self;
+ char name[BUFSIZE], class[BUFSIZE], id[BUFSIZE], type[BUFSIZE];
+ char pcidev_hdr[BUFSIZE];
+ char buf1[BUFSIZE];
+ char buf2[BUFSIZE];
+ char buf3[BUFSIZE];
+ char buf4[BUFSIZE];
+ char buf5[BUFSIZE];
+
+ ld = &list_data;
+
+ BZERO(ld, sizeof(struct list_data));
+
+ readmem(pci_bus + OFFSET(pci_bus_devices), KVADDR,
+ &ld->start, sizeof(void *), "pci bus devices",
+ FAULT_ON_ERROR);
+
+ if (VALID_MEMBER(pci_dev_pcie_flags_reg))
+ snprintf(pcidev_hdr, sizeof(pcidev_hdr), "%s %s %s %s %s\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PCI DEV"),
+ mkstring(buf2, strlen("0000:00:00.0"), CENTER, "DO:BU:SL.FN"),
+ mkstring(buf3, strlen("0000") + 2, CENTER, "CLASS"),
+ mkstring(buf4, strlen("0000:0000"), CENTER, "PCI_ID"),
+ mkstring(buf5, 10, CENTER, "TYPE"));
+ else
+ snprintf(pcidev_hdr, sizeof(pcidev_hdr), "%s %s %s %s\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PCI DEV"),
+ mkstring(buf2, strlen("0000:00:00.0"), CENTER, "DO:BU:SL.FN"),
+ mkstring(buf3, strlen("0000") + 2, CENTER, "CLASS"),
+ mkstring(buf4, strlen("0000:0000"), CENTER, "PCI_ID"));
+
+ fprintf(fp, " %s", pcidev_hdr);
+
+ readmem(pci_bus + OFFSET(pci_bus_self), KVADDR, &self,
+ sizeof(void *), "pci bus self", FAULT_ON_ERROR);
+ if (self) {
+ fill_dev_name(self, name);
+ fill_dev_class(self, class);
+ fill_dev_id(self, id);
+ fill_pcie_type(self, type);
+ fprintf(fp, " %s %s %s %s %s\n",
+ mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX,
+ MKSTR(self)),
+ mkstring(buf2, strlen("0000:00:00.0"), CENTER, name),
+ mkstring(buf3, strlen("0000") + 2, CENTER, class),
+ mkstring(buf4, strlen("0000:0000"), CENTER, id),
+ mkstring(buf5, 10, CENTER, type));
+ }
+
+ if (ld->start == (pci_bus + OFFSET(pci_bus_devices)))
+ return;
+
+ ld->end = pci_bus + OFFSET(pci_bus_devices);
+ hq_open();
+ devcnt = do_list(ld);
+ devlist = (ulong *)GETBUF(devcnt * sizeof(ulong));
+ devcnt = retrieve_list(devlist, devcnt);
+ hq_close();
+
+ for (i = 0; i < devcnt; i++) {
+ fill_dev_name(devlist[i], name);
+ fill_dev_class(devlist[i], class);
+ fill_dev_id(devlist[i], id);
+ fill_pcie_type(devlist[i], type);
+ fprintf(fp, " %s %s %s %s %s\n",
+ mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX,
+ MKSTR(devlist[i])),
+ mkstring(buf2, strlen("0000:00:00.0"), CENTER, name),
+ mkstring(buf3, strlen("0000") + 2, CENTER, class),
+ mkstring(buf4, strlen("0000:0000"), CENTER, id),
+ mkstring(buf5, 10, CENTER, type));
+ }
+ FREEBUF(devlist);
+}
+
+static void
+walk_buses(ulong pci_bus)
+{
+ struct list_data list_data, *ld;
+ int buscnt, i;
+ ulong *buslist, parent;
+ char pcibus_hdr[BUFSIZE];
+ char buf1[BUFSIZE];
+ char buf2[BUFSIZE];
+
+ ld = &list_data;
+
+ BZERO(ld, sizeof(struct list_data));
+
+ readmem(pci_bus + OFFSET(pci_bus_children), KVADDR,
+ &ld->start, sizeof(void *), "pci bus children",
+ FAULT_ON_ERROR);
+
+ if (ld->start == (pci_bus + OFFSET(pci_bus_children)))
+ return;
+
+ ld->end = pci_bus + OFFSET(pci_bus_children);
+ hq_open();
+ buscnt = do_list(ld);
+ buslist = (ulong *)GETBUF(buscnt * sizeof(ulong));
+ buscnt = retrieve_list(buslist, buscnt);
+ hq_close();
+
+ snprintf(pcibus_hdr, sizeof(pcibus_hdr), "%s %s\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PCI BUS"),
+ mkstring(buf2, VADDR_PRLEN, CENTER, "PARENT BUS"));
+
+ for (i = 0; i < buscnt; i++) {
+ readmem(buslist[i] + OFFSET(pci_bus_parent), KVADDR, &parent,
+ sizeof(void *), "pci bus parent", FAULT_ON_ERROR);
+
+ fprintf(fp, " %s", pcibus_hdr);
+
+ fprintf(fp, " %s %s\n",
+ mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX,
+ MKSTR(buslist[i])),
+ mkstring(buf2, VADDR_PRLEN, LJUST|LONG_HEX,
+ MKSTR(parent)));
+ walk_devices(buslist[i]);
+ fprintf(fp, "\n");
+ walk_buses(buslist[i]);
+ }
+ FREEBUF(buslist);
+}
+
+static void
+do_pci2(void)
+{
+ struct list_data list_data, *ld;
+ int rootbuscnt, i;
+ ulong *rootbuslist;
+ unsigned long pci_root_bus_addr = symbol_value("pci_root_buses");
+ char name[BUFSIZE];
+ char pcirootbus_hdr[BUFSIZE];
+ char buf1[BUFSIZE];
+ char buf2[BUFSIZE];
+
+ ld = &list_data;
+ BZERO(ld, sizeof(struct list_data));
+
+ get_symbol_data("pci_root_buses", sizeof(void *), &ld->start);
+
+ if (ld->start == pci_root_bus_addr)
+ error(FATAL, "no PCI devices found on this system.\n");
+
+ ld->end = pci_root_bus_addr;
+
+ hq_open();
+ rootbuscnt = do_list(ld);
+ rootbuslist = (ulong *)GETBUF(rootbuscnt * sizeof(ulong));
+ rootbuscnt = retrieve_list(rootbuslist, rootbuscnt);
+ hq_close();
+
+ snprintf(pcirootbus_hdr, sizeof(pcirootbus_hdr), "%s %s\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "ROOT BUS"),
+ mkstring(buf2, strlen("0000:00"), CENTER, "BUSNAME"));
+
+ for (i = 0; i < rootbuscnt; i++) {
+ fprintf(fp, "%s", pcirootbus_hdr);
+ fill_bus_name(rootbuslist[i], name);
+ fprintf(fp, "%s %s\n",
+ mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX,
+ MKSTR(rootbuslist[i])),
+ mkstring(buf2, strlen("0000:00"), CENTER, name));
+ walk_devices(rootbuslist[i]);
+ walk_buses(rootbuslist[i]);
+
+ fprintf(fp, "\n");
+ }
+ FREEBUF(rootbuslist);
+}
+
static void
do_pci(void)
{
@@ -2230,9 +2554,6 @@ do_pci(void)
char buf2[BUFSIZE];
char buf3[BUFSIZE];
- if (!symbol_exists("pci_devices"))
- error(FATAL, "no PCI devices found on this system.\n");
-
BZERO(&pcilist_data, sizeof(struct list_data));
if (VALID_MEMBER(pci_dev_global_list)) {

View File

@ -0,0 +1,174 @@
commit 28fa7bd09013455b5ddc020dea4706278cda0d65
Author: Dave Anderson <anderson@redhat.com>
Date: Tue Jun 19 16:31:54 2018 -0400
Fix for PPC64 kernel virtual address translation in Linux 4.17 and
later kernels with commit c2b4d8b7417a59b7f9a52d0d8402f5257cbbd398,
titled "powerpc/mm/hash64: Increase the VA range", in which the
maximum virtual address value has been increased to 4PB. Without
the patch, the translation/access of high vmalloc space addresses
fails; for example, the "kmem -[sS]" option fails the translation
of per-cpu kmem_cache_cpu addresses located in vmalloc space, with
the error messages "kmem: invalid kernel virtual address: <address>
type: kmem_cache_cpu.freelist" and "kmem: invalid kernel virtual
address: <address> type: kmem_cache_cpu.page", and the "vtop"
command shows the addresses as "(not mapped)".
(hbathini@linux.ibm.com)
diff --git a/defs.h b/defs.h
index 6e6f6be..e6e3850 100644
--- a/defs.h
+++ b/defs.h
@@ -3977,6 +3977,7 @@ struct efi_memory_desc_t {
#define PMD_INDEX_SIZE_L4_64K_4_12 10
#define PUD_INDEX_SIZE_L4_64K_4_12 7
#define PGD_INDEX_SIZE_L4_64K_4_12 8
+#define PUD_INDEX_SIZE_L4_64K_4_17 10
#define PTE_INDEX_SIZE_RADIX_64K 5
#define PMD_INDEX_SIZE_RADIX_64K 9
#define PUD_INDEX_SIZE_RADIX_64K 9
diff --git a/ppc64.c b/ppc64.c
index 0dd8a2a..f5d0dac 100644
--- a/ppc64.c
+++ b/ppc64.c
@@ -451,7 +451,10 @@ ppc64_init(int when)
if (THIS_KERNEL_VERSION >= LINUX(4,12,0)) {
m->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_12;
- m->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_12;
+ if (THIS_KERNEL_VERSION >= LINUX(4,17,0))
+ m->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_17;
+ else
+ m->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_12;
m->l4_index_size = PGD_INDEX_SIZE_L4_64K_4_12;
} else {
m->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_6;
commit e5df29d54bbdb8b84cb1661233ed186b153be746
Author: Dave Anderson <anderson@redhat.com>
Date: Wed Jun 20 11:15:38 2018 -0400
Fix for the x86_64 "bt" command in which a legitimate exception
frame is appended with the message "bt: WARNING: possibly bogus
exception frame". This only happens in KASLR-enabled kernels when
the text address that was executing when the exception occurred
is marked as a "weak" symbol (type "W") instead of a text symbol
(type "T" or "t"). As a result, the exception frame's RIP is not
recognized as a text symbol, and the warning message is displayed.
(anderson@redhat.com)
diff --git a/symbols.c b/symbols.c
index bb4ae3a..bf55319 100644
--- a/symbols.c
+++ b/symbols.c
@@ -2755,9 +2755,14 @@ is_kernel_text(ulong value)
section);
end = start + (ulong)bfd_section_size(st->bfd,
section);
+
+ if (kt->flags2 & KASLR) {
+ start += (kt->relocate * -1);
+ end += (kt->relocate * -1);
+ }
- if ((value >= start) && (value < end))
- return TRUE;
+ if ((value >= start) && (value < end))
+ return TRUE;
}
}
}
@@ -2833,7 +2838,16 @@ is_kernel_text_offset(ulong value)
int
is_symbol_text(struct syment *sp)
{
- return ((sp->type == 'T') || (sp->type == 't'));
+ if ((sp->type == 'T') || (sp->type == 't'))
+ return TRUE;
+
+ if ((sp->type == 'W') || (sp->type == 'w')) {
+ if ((sp->value >= kt->stext) &&
+ (sp->value < kt->etext))
+ return TRUE;
+ }
+
+ return FALSE;
}
/*
commit a7e5b90757bb41ad5e148177c5b3aaf5d892243d
Author: Dave Anderson <anderson@redhat.com>
Date: Wed Jun 20 16:33:43 2018 -0400
Fix for the x86_64 "bt" command in Linux 4.16 and later kernels
containing commit 3aa99fc3e708b9cd9b4cfe2df0b7a66cf293e3cf, titled
"x86/entry/64: Remove 'interrupt' macro". Without the patch, the
exception frame display generated by an interrupt exception will
show incorrect contents, and be followed by the message "bt: WARNING:
possibly bogus exception frame".
(anderson@redhat.com)
diff --git a/x86_64.c b/x86_64.c
index e01082b..6d1ae2f 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -4285,6 +4285,12 @@ x86_64_exception_frame(ulong flags, ulong kvaddr, char *local,
long err;
char buf[BUFSIZE];
+ if (flags == EFRAME_VERIFY) {
+ if (!accessible(kvaddr) ||
+ !accessible(kvaddr + SIZE(pt_regs) - sizeof(long)))
+ return FALSE;
+ }
+
ms = machdep->machspec;
sp = NULL;
@@ -6283,6 +6289,9 @@ x86_64_irq_eframe_link(ulong stkref, struct bt_info *bt, FILE *ofp)
{
ulong irq_eframe;
+ if (x86_64_exception_frame(EFRAME_VERIFY, stkref, 0, bt, ofp))
+ return stkref;
+
irq_eframe = stkref - machdep->machspec->irq_eframe_link;
if (x86_64_exception_frame(EFRAME_VERIFY, irq_eframe, 0, bt, ofp))
commit 02efd0838f05ef8a7fe21b0b8ba6cad729270645
Author: Dave Anderson <anderson@redhat.com>
Date: Fri Jun 22 11:00:01 2018 -0400
Fix for the failure of several "kmem" command options, most notably
seen if the command is piped directly into a crash session, or if
the command is contained in an input file. For examples:
$ echo "kmem -i" | crash ...
$ crash -i <input-file> ...
Without the patch, the kmem command may fail with the error message
"<segmentation violation in gdb>". While the bug is due to a buffer
overflow that has always existed, it only is triggered by certain
kernel configurations.
(anderson@redhat.com)
diff --git a/memory.c b/memory.c
index 2f568d5..5c0a853 100644
--- a/memory.c
+++ b/memory.c
@@ -17498,13 +17498,12 @@ vm_stat_init(void)
STREQ(arglist[0], "NR_VM_ZONE_STAT_ITEMS")) {
continue;
} else {
- stringlen += strlen(arglist[0]);
+ stringlen += strlen(arglist[0]) + 1;
count++;
}
}
- total = stringlen + vt->nr_vm_stat_items +
- (sizeof(void *) * vt->nr_vm_stat_items);
+ total = stringlen + (sizeof(void *) * vt->nr_vm_stat_items);
if (!(vt->vm_stat_items = (char **)malloc(total))) {
close_tmpfile();
error(FATAL, "cannot malloc vm_stat_items cache\n");

View File

@ -0,0 +1,58 @@
commit 2f57a96ce27d8b121c2822de2a66c71b83bdad21
Author: Dave Anderson <anderson@redhat.com>
Date: Tue Sep 4 14:29:45 2018 -0400
Fix for the "files" command in Linux 4.17 and later kernels that
contain commit b93b016313b3ba8003c3b8bb71f569af91f19fc7, titled
"page cache: use xa_lock". Without the patch, the "files -c" option
fails with the message "files: -c option not supported or applicable
on this architecture or kernel", and the "files -p &lt;inode>" option
fails in a similar manner.
(k-hagio@ab.jp.nec.com)
diff --git a/filesys.c b/filesys.c
index 47f5a24..32daa5a 100644
--- a/filesys.c
+++ b/filesys.c
@@ -2207,6 +2207,11 @@ dump_inode_page_cache_info(ulong inode)
RJUST|LONG_DEC,
MKSTR(nrpages)));
+ FREEBUF(inode_buf);
+
+ if (!nrpages)
+ return;
+
root_rnode = i_mapping + OFFSET(address_space_page_tree);
rtp.index = 0;
rtp.value = (void *)&dump_inode_page;
@@ -2217,7 +2222,6 @@ dump_inode_page_cache_info(ulong inode)
error(INFO, "page_tree count: %ld nrpages: %ld\n",
count, nrpages);
- FREEBUF(inode_buf);
return;
}
@@ -2275,7 +2279,7 @@ cmd_files(void)
return;
case 'c':
- if (VALID_MEMBER(address_space_page_tree) &&
+ if (VALID_MEMBER(address_space_nrpages) &&
VALID_MEMBER(inode_i_mapping))
open_flags |= PRINT_NRPAGES;
else
diff --git a/memory.c b/memory.c
index 24fce5e..ea25047 100644
--- a/memory.c
+++ b/memory.c
@@ -485,6 +485,8 @@ vm_init(void)
MEMBER_OFFSET_INIT(block_device_bd_disk, "block_device", "bd_disk");
MEMBER_OFFSET_INIT(inode_i_mapping, "inode", "i_mapping");
MEMBER_OFFSET_INIT(address_space_page_tree, "address_space", "page_tree");
+ if (INVALID_MEMBER(address_space_page_tree))
+ MEMBER_OFFSET_INIT(address_space_page_tree, "address_space", "i_pages");
MEMBER_OFFSET_INIT(address_space_nrpages, "address_space", "nrpages");
if (INVALID_MEMBER(address_space_nrpages))
MEMBER_OFFSET_INIT(address_space_nrpages, "address_space", "__nrpages");

View File

@ -0,0 +1,45 @@
commit 3141bba98af302e2a7c5e2a19203bb8a40b6aa63
Author: Dave Anderson <anderson@redhat.com>
Date: Wed Oct 10 09:15:42 2018 -0400
Fix the calculation of the vmalloc memory region size to account for
Linux 4.17 commit a7412546d8cb5ad578805060b4006f2a021b5868, titled
"x86/mm: Adjust vmalloc base and size at boot-time", which increases
the region's size from 32TB to 1280TB when 5-level pagetables are
enabled. Also presume that virtual addresses above the end of the
vmalloc space up to the beginning of vmemmap space are translatable
via 5-level page tables. Without the patch, mapped virtual addresses
may fail translation in whatever command accesses them, with errors
indicating "seek error: kernel virtual address: <mapped-address>
type: <type-string>"
(anderson@redhat.com)
diff --git a/x86_64.c b/x86_64.c
index 6f547e8..345122c 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -393,8 +393,12 @@ x86_64_init(int when)
readmem(symbol_value("vmalloc_base"), KVADDR,
&machdep->machspec->vmalloc_start_addr,
sizeof(ulong), "vmalloc_base", FAULT_ON_ERROR);
- machdep->machspec->vmalloc_end =
- machdep->machspec->vmalloc_start_addr + TERABYTES(32) - 1;
+ if (machdep->flags & VM_5LEVEL)
+ machdep->machspec->vmalloc_end =
+ machdep->machspec->vmalloc_start_addr + TERABYTES(1280) - 1;
+ else
+ machdep->machspec->vmalloc_end =
+ machdep->machspec->vmalloc_start_addr + TERABYTES(32) - 1;
if (kernel_symbol_exists("vmemmap_base")) {
readmem(symbol_value("vmemmap_base"), KVADDR,
&machdep->machspec->vmemmap_vaddr, sizeof(ulong),
@@ -1626,7 +1630,8 @@ x86_64_IS_VMALLOC_ADDR(ulong vaddr)
(vaddr >= VSYSCALL_START && vaddr < VSYSCALL_END) ||
(machdep->machspec->cpu_entry_area_start &&
vaddr >= machdep->machspec->cpu_entry_area_start &&
- vaddr <= machdep->machspec->cpu_entry_area_end));
+ vaddr <= machdep->machspec->cpu_entry_area_end) ||
+ ((machdep->flags & VM_5LEVEL) && vaddr > VMALLOC_END && vaddr < VMEMMAP_VADDR));
}
static int

View File

@ -0,0 +1,196 @@
commit 361f050e3148c6188afb45942e06d4a509852b86
Author: Dave Anderson <anderson@redhat.com>
Date: Mon Jan 7 13:56:15 2019 -0500
Fix for the "dev -[dD]" options in kernels containing Linux 5.0-rc1
commit 7ff4f8035695984c513598e2d49c8277d5d234ca, titled "block:
remove dead queue members", in which the number of I/Os issued to
a disk driver are no longer stored in the request_queue structure.
Without the patch, the options indicate "dev: -d option not supported
or applicable on this architecture or kernel". With the patch, the
"DRV" column is not shown.
(m.mizuma@jp.fujitsu.com)
diff --git a/defs.h b/defs.h
index a3cb5a4..9ebdde6 100644
--- a/defs.h
+++ b/defs.h
@@ -2043,6 +2043,8 @@ struct offset_table {
long pci_bus_self;
long device_kobj;
long kobject_name;
+ long hd_struct_dkstats;
+ long disk_stats_in_flight;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/dev.c b/dev.c
index 7ce2422..24efea2 100644
--- a/dev.c
+++ b/dev.c
@@ -3974,7 +3974,7 @@ struct iter {
* this function reads request_list.count[2], and the first argument
* is the address of request_queue.
*/
- void (*get_diskio)(unsigned long , struct diskio *);
+ void (*get_diskio)(unsigned long , unsigned long, struct diskio *);
/*
* check if device.type == &disk_type
@@ -4187,24 +4187,55 @@ get_mq_diskio(unsigned long q, unsigned long *mq_count)
}
}
+static void
+get_one_diskio_from_dkstats(unsigned long dkstats, unsigned long *count)
+{
+ int cpu;
+ unsigned long dkstats_addr;
+ unsigned long in_flight[2];
+
+ for (cpu = 0; cpu < kt->cpus; cpu++) {
+ if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) {
+ dkstats_addr = dkstats + kt->__per_cpu_offset[cpu];
+ readmem(dkstats_addr + OFFSET(disk_stats_in_flight),
+ KVADDR, in_flight, sizeof(long) * 2,
+ "disk_stats.in_flight", FAULT_ON_ERROR);
+ count[0] += in_flight[0];
+ count[1] += in_flight[1];
+ }
+ }
+}
+
+
/* read request_queue.rq.count[2] */
static void
-get_diskio_1(unsigned long rq, struct diskio *io)
+get_diskio_1(unsigned long rq, unsigned long gendisk, struct diskio *io)
{
int count[2];
- unsigned long mq_count[2] = { 0 };
+ unsigned long io_counts[2] = { 0 };
+ unsigned long dkstats;
if (!use_mq_interface(rq)) {
- readmem(rq + OFFSET(request_queue_rq) +
- OFFSET(request_list_count), KVADDR, count,
- sizeof(int) * 2, "request_list.count", FAULT_ON_ERROR);
+ if (VALID_MEMBER(request_queue_rq)) {
+ readmem(rq + OFFSET(request_queue_rq) +
+ OFFSET(request_list_count), KVADDR, count,
+ sizeof(int) * 2, "request_list.count", FAULT_ON_ERROR);
+
+ io->read = count[0];
+ io->write = count[1];
+ } else {
+ readmem(gendisk + OFFSET(gendisk_part0) +
+ OFFSET(hd_struct_dkstats), KVADDR, &dkstats,
+ sizeof(ulong), "gendisk.part0.dkstats", FAULT_ON_ERROR);
+ get_one_diskio_from_dkstats(dkstats, io_counts);
- io->read = count[0];
- io->write = count[1];
+ io->read = io_counts[0];
+ io->write = io_counts[1];
+ }
} else {
- get_mq_diskio(rq, mq_count);
- io->read = mq_count[0];
- io->write = mq_count[1];
+ get_mq_diskio(rq, io_counts);
+ io->read = io_counts[0];
+ io->write = io_counts[1];
}
}
@@ -4250,9 +4281,6 @@ init_iter(struct iter *i)
i->get_in_flight = get_in_flight_1;
} else if (SIZE(rq_in_flight) == sizeof(int) * 2) {
i->get_in_flight = get_in_flight_2;
- } else {
- option_not_supported('d');
- return;
}
i->get_diskio = get_diskio_1;
@@ -4354,7 +4382,7 @@ display_one_diskio(struct iter *i, unsigned long gendisk, ulong flags)
sizeof(ulong), "gen_disk.queue", FAULT_ON_ERROR);
readmem(gendisk + OFFSET(gendisk_major), KVADDR, &major, sizeof(int),
"gen_disk.major", FAULT_ON_ERROR);
- i->get_diskio(queue_addr, &io);
+ i->get_diskio(queue_addr, gendisk, &io);
if ((flags & DIOF_NONZERO)
&& (io.read + io.write == 0))
@@ -4379,11 +4407,14 @@ display_one_diskio(struct iter *i, unsigned long gendisk, ulong flags)
(char *)(unsigned long)io.write),
space(MINSPACE));
- if (!use_mq_interface(queue_addr)) {
- in_flight = i->get_in_flight(queue_addr);
- fprintf(fp, "%5u\n", in_flight);
+ if (VALID_MEMBER(request_queue_in_flight)) {
+ if (!use_mq_interface(queue_addr)) {
+ in_flight = i->get_in_flight(queue_addr);
+ fprintf(fp, "%5u\n", in_flight);
+ } else
+ fprintf(fp, "%s\n", "N/A(MQ)");
} else
- fprintf(fp, "%s\n", "N/A(MQ)");
+ fprintf(fp, "\n");
}
static void
@@ -4418,7 +4449,7 @@ display_all_diskio(ulong flags)
i.sync_count ? mkstring(buf4, 5, RJUST, "SYNC") :
mkstring(buf4, 5, RJUST, "WRITE"),
space(MINSPACE),
- mkstring(buf5, 5, RJUST, "DRV"));
+ VALID_MEMBER(request_queue_in_flight) ? mkstring(buf5, 5, RJUST, "DRV") : "");
while ((gendisk = i.next_disk(&i)) != 0)
display_one_diskio(&i, gendisk, flags);
@@ -4446,6 +4477,7 @@ void diskio_init(void)
MEMBER_OFFSET_INIT(gendisk_part0, "gendisk", "part0");
MEMBER_OFFSET_INIT(gendisk_queue, "gendisk", "queue");
MEMBER_OFFSET_INIT(hd_struct_dev, "hd_struct", "__dev");
+ MEMBER_OFFSET_INIT(hd_struct_dkstats, "hd_struct", "dkstats");
MEMBER_OFFSET_INIT(klist_k_list, "klist", "k_list");
MEMBER_OFFSET_INIT(klist_node_n_klist, "klist_node", "n_klist");
MEMBER_OFFSET_INIT(klist_node_n_node, "klist_node", "n_node");
@@ -4476,6 +4508,7 @@ void diskio_init(void)
MEMBER_SIZE_INIT(rq_in_flight, "request_queue", "in_flight");
MEMBER_SIZE_INIT(class_private_devices, "class_private",
"class_devices");
+ MEMBER_OFFSET_INIT(disk_stats_in_flight, "disk_stats", "in_flight");
dt->flags |= DISKIO_INIT;
}
diff --git a/help.c b/help.c
index aadd2ed..1593e82 100644
--- a/help.c
+++ b/help.c
@@ -3218,7 +3218,7 @@ char *help_dev[] = {
" WRITE: I/O requests that are writes (older kernels)",
" DRV: I/O requests that are in-flight in the device driver.",
" If the device driver uses blk-mq interface, this field",
-" shows N/A(MQ).",
+" shows N/A(MQ). If not available, this column is not shown.",
" -D same as -d, but filter out disks with no in-progress I/O requests.",
"\nEXAMPLES",
" Display character and block device data:\n",
diff --git a/symbols.c b/symbols.c
index ef6f934..5f77e27 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10021,6 +10021,10 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(gendisk_queue));
fprintf(fp, " hd_struct_dev: %ld\n",
OFFSET(hd_struct_dev));
+ fprintf(fp, " hd_struct_dkstats: %ld\n",
+ OFFSET(hd_struct_dkstats));
+ fprintf(fp, " disk_stats_in_flight: %ld\n",
+ OFFSET(disk_stats_in_flight));
fprintf(fp, " klist_k_list: %ld\n",
OFFSET(klist_k_list));
fprintf(fp, " klist_node_n_klist: %ld\n",

View File

@ -0,0 +1,414 @@
commit 46d2121960d81354facf4e2558c81f82257b740e
Author: Dave Anderson <anderson@redhat.com>
Date: Tue May 29 14:04:03 2018 -0400
Fix for the "timer -r" command on Linux 4.10 and later kernels that
contain commit 2456e855354415bfaeb7badaa14e11b3e02c8466, titled
"ktime: Get rid of the union". Without the patch, the command fails
with the error message "timer: invalid structure member offset:
ktime_t_sec".
(k-hagio@ab.jp.nec.com)
diff --git a/kernel.c b/kernel.c
index b1886ce..138a47f 100644
--- a/kernel.c
+++ b/kernel.c
@@ -7740,7 +7740,7 @@ ktime_to_ns(const void *ktime)
if (VALID_MEMBER(ktime_t_tv64)) {
readmem((ulong)ktime + OFFSET(ktime_t_tv64), KVADDR, &ns,
sizeof(ns), "ktime_t tv64", QUIET|RETURN_ON_ERROR);
- } else {
+ } else if (VALID_MEMBER(ktime_t_sec) && VALID_MEMBER(ktime_t_nsec)) {
uint32_t sec, nsec;
sec = 0;
@@ -7753,6 +7753,9 @@ ktime_to_ns(const void *ktime)
sizeof(nsec), "ktime_t nsec", QUIET|RETURN_ON_ERROR);
ns = sec * 1000000000L + nsec;
+ } else {
+ readmem((ulong)ktime, KVADDR, &ns,
+ sizeof(ns), "ktime_t", QUIET|RETURN_ON_ERROR);
}
return ns;
commit a6cd8408d1d214a67ed0c4b09343fec77a8e2ae7
Author: Dave Anderson <anderson@redhat.com>
Date: Thu May 31 11:43:14 2018 -0400
Fix for the x86 and x86_64 "mach -m" option on Linux 4.12 and later
kernels to account for the structure name changes "e820map" to
"e820_table", and "e820entry" to "e820_entry", and for the symbol
name change from "e820" to "e820_table". Also updated the display
output to properly translate E820_PRAM and E820_RESERVED_KERN entries.
Without the patch on all kernels, E820_PRAM and E820_RESERVED_KERN
entries show "type 12" and "type 128" respectively. Without the
patch on Linux 4.12 and later kernels, the command fails with the
error message "mach: cannot resolve e820".
(anderson@redhat.com)
diff --git a/x86.c b/x86.c
index 47767b6..88562b6 100644
--- a/x86.c
+++ b/x86.c
@@ -1,8 +1,8 @@
/* x86.c - core analysis suite
*
* Portions Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
- * Copyright (C) 2002-2014,2017 David Anderson
- * Copyright (C) 2002-2014,2017 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2002-2014,2017-2018 David Anderson
+ * Copyright (C) 2002-2014,2017-2018 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
@@ -1967,15 +1967,27 @@ x86_init(int when)
}
MEMBER_OFFSET_INIT(thread_struct_cr3, "thread_struct", "cr3");
STRUCT_SIZE_INIT(cpuinfo_x86, "cpuinfo_x86");
- STRUCT_SIZE_INIT(e820map, "e820map");
- STRUCT_SIZE_INIT(e820entry, "e820entry");
STRUCT_SIZE_INIT(irq_ctx, "irq_ctx");
+ if (STRUCT_EXISTS("e820map")) {
+ STRUCT_SIZE_INIT(e820map, "e820map");
+ MEMBER_OFFSET_INIT(e820map_nr_map, "e820map", "nr_map");
+ } else {
+ STRUCT_SIZE_INIT(e820map, "e820_table");
+ MEMBER_OFFSET_INIT(e820map_nr_map, "e820_table", "nr_entries");
+ }
+ if (STRUCT_EXISTS("e820entry")) {
+ STRUCT_SIZE_INIT(e820entry, "e820entry");
+ MEMBER_OFFSET_INIT(e820entry_addr, "e820entry", "addr");
+ MEMBER_OFFSET_INIT(e820entry_size, "e820entry", "size");
+ MEMBER_OFFSET_INIT(e820entry_type, "e820entry", "type");
+ } else {
+ STRUCT_SIZE_INIT(e820entry, "e820_entry");
+ MEMBER_OFFSET_INIT(e820entry_addr, "e820_entry", "addr");
+ MEMBER_OFFSET_INIT(e820entry_size, "e820_entry", "size");
+ MEMBER_OFFSET_INIT(e820entry_type, "e820_entry", "type");
+ }
if (!VALID_STRUCT(irq_ctx))
STRUCT_SIZE_INIT(irq_ctx, "irq_stack");
- MEMBER_OFFSET_INIT(e820map_nr_map, "e820map", "nr_map");
- MEMBER_OFFSET_INIT(e820entry_addr, "e820entry", "addr");
- MEMBER_OFFSET_INIT(e820entry_size, "e820entry", "size");
- MEMBER_OFFSET_INIT(e820entry_type, "e820entry", "type");
if (KVMDUMP_DUMPFILE())
set_kvm_iohole(NULL);
if (symbol_exists("irq_desc"))
@@ -4415,33 +4427,54 @@ static char *e820type[] = {
static void
x86_display_memmap(void)
{
- ulong e820;
- int nr_map, i;
- char *buf, *e820entry_ptr;
- ulonglong addr, size;
- ulong type;
+ ulong e820;
+ int nr_map, i;
+ char *buf, *e820entry_ptr;
+ ulonglong addr, size;
+ uint type;
+
+ if (kernel_symbol_exists("e820")) {
+ if (get_symbol_type("e820", NULL, NULL) == TYPE_CODE_PTR)
+ get_symbol_data("e820", sizeof(void *), &e820);
+ else
+ e820 = symbol_value("e820");
+
+ } else if (kernel_symbol_exists("e820_table"))
+ get_symbol_data("e820_table", sizeof(void *), &e820);
+ else
+ error(FATAL, "neither e820 or e820_table symbols exist\n");
- e820 = symbol_value("e820");
- buf = (char *)GETBUF(SIZE(e820map));
+ if (CRASHDEBUG(1)) {
+ if (STRUCT_EXISTS("e820map"))
+ dump_struct("e820map", e820, RADIX(16));
+ else if (STRUCT_EXISTS("e820_table"))
+ dump_struct("e820_table", e820, RADIX(16));
+ }
+ buf = (char *)GETBUF(SIZE(e820map));
- readmem(e820, KVADDR, &buf[0], SIZE(e820map),
- "e820map", FAULT_ON_ERROR);
+ readmem(e820, KVADDR, &buf[0], SIZE(e820map),
+ "e820map", FAULT_ON_ERROR);
- nr_map = INT(buf + OFFSET(e820map_nr_map));
+ nr_map = INT(buf + OFFSET(e820map_nr_map));
- fprintf(fp, " PHYSICAL ADDRESS RANGE TYPE\n");
+ fprintf(fp, " PHYSICAL ADDRESS RANGE TYPE\n");
- for (i = 0; i < nr_map; i++) {
- e820entry_ptr = buf + sizeof(int) + (SIZE(e820entry) * i);
- addr = ULONGLONG(e820entry_ptr + OFFSET(e820entry_addr));
- size = ULONGLONG(e820entry_ptr + OFFSET(e820entry_size));
- type = ULONG(e820entry_ptr + OFFSET(e820entry_type));
+ for (i = 0; i < nr_map; i++) {
+ e820entry_ptr = buf + sizeof(int) + (SIZE(e820entry) * i);
+ addr = ULONGLONG(e820entry_ptr + OFFSET(e820entry_addr));
+ size = ULONGLONG(e820entry_ptr + OFFSET(e820entry_size));
+ type = UINT(e820entry_ptr + OFFSET(e820entry_type));
fprintf(fp, "%016llx - %016llx ", addr, addr+size);
- if (type >= (sizeof(e820type)/sizeof(char *)))
- fprintf(fp, "type %ld\n", type);
- else
+ if (type >= (sizeof(e820type)/sizeof(char *))) {
+ if (type == 12)
+ fprintf(fp, "E820_PRAM\n");
+ else if (type == 128)
+ fprintf(fp, "E820_RESERVED_KERN\n");
+ else
+ fprintf(fp, "type %d\n", type);
+ } else
fprintf(fp, "%s\n", e820type[type]);
- }
+ }
}
/*
diff --git a/x86_64.c b/x86_64.c
index 921552b..1d5e155 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -415,12 +415,26 @@ x86_64_init(int when)
STRUCT_SIZE_INIT(gate_struct, "gate_desc");
else
STRUCT_SIZE_INIT(gate_struct, "gate_struct");
- STRUCT_SIZE_INIT(e820map, "e820map");
- STRUCT_SIZE_INIT(e820entry, "e820entry");
- MEMBER_OFFSET_INIT(e820map_nr_map, "e820map", "nr_map");
- MEMBER_OFFSET_INIT(e820entry_addr, "e820entry", "addr");
- MEMBER_OFFSET_INIT(e820entry_size, "e820entry", "size");
- MEMBER_OFFSET_INIT(e820entry_type, "e820entry", "type");
+
+ if (STRUCT_EXISTS("e820map")) {
+ STRUCT_SIZE_INIT(e820map, "e820map");
+ MEMBER_OFFSET_INIT(e820map_nr_map, "e820map", "nr_map");
+ } else {
+ STRUCT_SIZE_INIT(e820map, "e820_table");
+ MEMBER_OFFSET_INIT(e820map_nr_map, "e820_table", "nr_entries");
+ }
+ if (STRUCT_EXISTS("e820entry")) {
+ STRUCT_SIZE_INIT(e820entry, "e820entry");
+ MEMBER_OFFSET_INIT(e820entry_addr, "e820entry", "addr");
+ MEMBER_OFFSET_INIT(e820entry_size, "e820entry", "size");
+ MEMBER_OFFSET_INIT(e820entry_type, "e820entry", "type");
+ } else {
+ STRUCT_SIZE_INIT(e820entry, "e820_entry");
+ MEMBER_OFFSET_INIT(e820entry_addr, "e820_entry", "addr");
+ MEMBER_OFFSET_INIT(e820entry_size, "e820_entry", "size");
+ MEMBER_OFFSET_INIT(e820entry_type, "e820_entry", "type");
+ }
+
if (KVMDUMP_DUMPFILE())
set_kvm_iohole(NULL);
MEMBER_OFFSET_INIT(thread_struct_rip, "thread_struct", "rip");
@@ -5643,12 +5657,23 @@ x86_64_display_memmap(void)
ulonglong addr, size;
uint type;
- if (get_symbol_type("e820", NULL, NULL) == TYPE_CODE_PTR)
- get_symbol_data("e820", sizeof(void *), &e820);
+ if (kernel_symbol_exists("e820")) {
+ if (get_symbol_type("e820", NULL, NULL) == TYPE_CODE_PTR)
+ get_symbol_data("e820", sizeof(void *), &e820);
+ else
+ e820 = symbol_value("e820");
+
+ } else if (kernel_symbol_exists("e820_table"))
+ get_symbol_data("e820_table", sizeof(void *), &e820);
else
- e820 = symbol_value("e820");
- if (CRASHDEBUG(1))
- dump_struct("e820map", e820, RADIX(16));
+ error(FATAL, "neither e820 or e820_table symbols exist\n");
+
+ if (CRASHDEBUG(1)) {
+ if (STRUCT_EXISTS("e820map"))
+ dump_struct("e820map", e820, RADIX(16));
+ else if (STRUCT_EXISTS("e820_table"))
+ dump_struct("e820_table", e820, RADIX(16));
+ }
buf = (char *)GETBUF(SIZE(e820map));
readmem(e820, KVADDR, &buf[0], SIZE(e820map),
@@ -5664,9 +5689,14 @@ x86_64_display_memmap(void)
size = ULONGLONG(e820entry_ptr + OFFSET(e820entry_size));
type = UINT(e820entry_ptr + OFFSET(e820entry_type));
fprintf(fp, "%016llx - %016llx ", addr, addr+size);
- if (type >= (sizeof(e820type)/sizeof(char *)))
- fprintf(fp, "type %d\n", type);
- else
+ if (type >= (sizeof(e820type)/sizeof(char *))) {
+ if (type == 12)
+ fprintf(fp, "E820_PRAM\n");
+ else if (type == 128)
+ fprintf(fp, "E820_RESERVED_KERN\n");
+ else
+ fprintf(fp, "type %d\n", type);
+ } else
fprintf(fp, "%s\n", e820type[type]);
}
}
commit da49e2010b3cb88b4755d69d38fe90af6ba218b2
Author: Dave Anderson <anderson@redhat.com>
Date: Fri Jun 1 10:58:00 2018 -0400
Update for the recognition of the new x86_64 CPU_ENTRY_AREA virtual
address range introduced in Linux 4.15. The memory range exists
above the vmemmap range and below the mapped kernel static text/data
region, and where all of the x86_64 exception stacks have been moved.
Without the patch, reads from the new memory region fail because the
address range is not recognized as a legitimate virtual address.
Most notable is the failure of "bt" on tasks whose backtraces
originate from any of the exception stacks, which fail with the two
error messages "bt: seek error: kernel virtual address: <address>
type: stack contents" followed by "bt: read of stack at <address>
failed".
(anderson@redhat.com)
diff --git a/defs.h b/defs.h
index 931be07..6e6f6be 100644
--- a/defs.h
+++ b/defs.h
@@ -3391,6 +3391,9 @@ struct arm64_stackframe {
#define VSYSCALL_START 0xffffffffff600000
#define VSYSCALL_END 0xffffffffff601000
+#define CPU_ENTRY_AREA_START 0xfffffe0000000000
+#define CPU_ENTRY_AREA_END 0xfffffe7fffffffff
+
#define PTOV(X) ((unsigned long)(X)+(machdep->kvbase))
#define VTOP(X) x86_64_VTOP((ulong)(X))
#define IS_VMALLOC_ADDR(X) x86_64_IS_VMALLOC_ADDR((ulong)(X))
@@ -5829,6 +5832,8 @@ struct machine_specific {
ulong kpti_entry_stack;
ulong kpti_entry_stack_size;
ulong ptrs_per_pgd;
+ ulong cpu_entry_area_start;
+ ulong cpu_entry_area_end;
};
#define KSYMS_START (0x1)
diff --git a/x86_64.c b/x86_64.c
index 1d5e155..54b6539 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -407,6 +407,11 @@ x86_64_init(int when)
machdep->machspec->modules_end = MODULES_END_2_6_31;
}
}
+ if (STRUCT_EXISTS("cpu_entry_area")) {
+ machdep->machspec->cpu_entry_area_start = CPU_ENTRY_AREA_START;
+ machdep->machspec->cpu_entry_area_end = CPU_ENTRY_AREA_END;
+ }
+
STRUCT_SIZE_INIT(cpuinfo_x86, "cpuinfo_x86");
/*
* Before 2.6.25 the structure was called gate_struct
@@ -879,20 +884,21 @@ x86_64_dump_machdep_table(ulong arg)
/* pml4 and upml is legacy for extension modules */
if (ms->pml4) {
- fprintf(fp, " pml4: %lx\n", (ulong)ms->pml4);
- fprintf(fp, " last_pml4_read: %lx\n", (ulong)ms->last_pml4_read);
+ fprintf(fp, " pml4: %lx\n", (ulong)ms->pml4);
+ fprintf(fp, " last_pml4_read: %lx\n", (ulong)ms->last_pml4_read);
} else {
- fprintf(fp, " pml4: (unused)\n");
- fprintf(fp, " last_pml4_read: (unused)\n");
+ fprintf(fp, " pml4: (unused)\n");
+ fprintf(fp, " last_pml4_read: (unused)\n");
}
if (ms->upml) {
- fprintf(fp, " upml: %lx\n", (ulong)ms->upml);
- fprintf(fp, " last_upml_read: %lx\n", (ulong)ms->last_upml_read);
+ fprintf(fp, " upml: %lx\n", (ulong)ms->upml);
+ fprintf(fp, " last_upml_read: %lx\n", (ulong)ms->last_upml_read);
} else {
- fprintf(fp, " upml: (unused)\n");
- fprintf(fp, " last_upml_read: (unused)\n");
+ fprintf(fp, " GART_end: %lx\n", ms->GART_end);
+ fprintf(fp, " upml: (unused)\n");
+ fprintf(fp, " last_upml_read: (unused)\n");
}
if (ms->p4d) {
@@ -1016,10 +1022,14 @@ x86_64_dump_machdep_table(ulong arg)
fprintf(fp, "\n ");
fprintf(fp, "%016lx ", ms->stkinfo.ibase[c]);
}
- fprintf(fp, "\n kpti_entry_stack_size: %ld", ms->kpti_entry_stack_size);
- fprintf(fp, "\n kpti_entry_stack: ");
+ fprintf(fp, "\n kpti_entry_stack_size: ");
+ if (ms->kpti_entry_stack_size)
+ fprintf(fp, "%ld", ms->kpti_entry_stack_size);
+ else
+ fprintf(fp, "(unused)");
+ fprintf(fp, "\n kpti_entry_stack: ");
if (machdep->flags & KPTI) {
- fprintf(fp, "%lx\n ", ms->kpti_entry_stack);
+ fprintf(fp, "(percpu: %lx):\n ", ms->kpti_entry_stack);
for (c = 0; c < cpus; c++) {
if (c && !(c%4))
fprintf(fp, "\n ");
@@ -1028,6 +1038,16 @@ x86_64_dump_machdep_table(ulong arg)
fprintf(fp, "\n");
} else
fprintf(fp, "(unused)\n");
+ fprintf(fp, " cpu_entry_area_start: ");
+ if (ms->cpu_entry_area_start)
+ fprintf(fp, "%016lx\n", (ulong)ms->cpu_entry_area_start);
+ else
+ fprintf(fp, "(unused)\n");
+ fprintf(fp, " cpu_entry_area_end: ");
+ if (ms->cpu_entry_area_end)
+ fprintf(fp, "%016lx\n", (ulong)ms->cpu_entry_area_end);
+ else
+ fprintf(fp, "(unused)\n");
}
/*
@@ -1586,7 +1606,10 @@ x86_64_IS_VMALLOC_ADDR(ulong vaddr)
((machdep->flags & VMEMMAP) &&
(vaddr >= VMEMMAP_VADDR && vaddr <= VMEMMAP_END)) ||
(vaddr >= MODULES_VADDR && vaddr <= MODULES_END) ||
- (vaddr >= VSYSCALL_START && vaddr < VSYSCALL_END));
+ (vaddr >= VSYSCALL_START && vaddr < VSYSCALL_END) ||
+ (machdep->machspec->cpu_entry_area_start &&
+ vaddr >= machdep->machspec->cpu_entry_area_start &&
+ vaddr <= machdep->machspec->cpu_entry_area_end));
}
static int
commit 9446958fe211825ed5524317b05d5ea020bb00d6
Author: Dave Anderson <anderson@redhat.com>
Date: Fri Jun 1 14:01:01 2018 -0400
Fix to address a "__builtin___snprintf_chk" compiler warning if bpf.c
is compiled with -D_FORTIFY_SOURCE=2.
(anderson@redhat.com)
diff --git a/bpf.c b/bpf.c
index 305d49f..ee1986f 100644
--- a/bpf.c
+++ b/bpf.c
@@ -362,7 +362,7 @@ do_bpf(ulong flags, ulong prog_id, ulong map_id, int radix)
fprintf(fp, " LOAD_TIME: ");
if (VALID_MEMBER(bpf_prog_aux_load_time)) {
load_time = ULONGLONG(bpf->bpf_prog_aux_buf + OFFSET(bpf_prog_aux_load_time));
- print_boot_time(load_time, buf5, BUFSIZE);
+ print_boot_time(load_time, buf5, BUFSIZE/2);
fprintf(fp, "%s\n", buf5);
} else
fprintf(fp, "(unknown)\n");

View File

@ -0,0 +1,34 @@
commit 64dad6d0d60514498252e6071738fa1b4c12db8c
Author: Dave Anderson <anderson@redhat.com>
Date: Thu Nov 29 14:21:19 2018 -0500
Fix for the "ps -s" option on ARM64 if the number of tasks exceeds
2000. Without the patch, the command ultimately fails with a
dump of the internal buffer allocation stats, followed by the
message "ps: cannot allocate any more memory!".
(anderson@redhat.com)
diff -up crash-7.2.3/task.c.orig crash-7.2.3/task.c
--- crash-7.2.3/task.c.orig 2018-11-29 13:54:39.108320730 -0500
+++ crash-7.2.3/task.c 2018-11-29 13:54:48.598279086 -0500
@@ -4133,6 +4133,10 @@ task_pointer_string(struct task_context
readmem(tc->task + OFFSET(task_struct_thread_ksp),
KVADDR, &bt->stkptr, sizeof(void *),
"thread_struct ksp", FAULT_ON_ERROR);
+ } else if (VALID_MEMBER(task_struct_thread_context_sp)) {
+ readmem(tc->task + OFFSET(task_struct_thread_context_sp),
+ KVADDR, &bt->stkptr, sizeof(void *),
+ "cpu_context sp", FAULT_ON_ERROR);
} else {
if ((bt->stackbase = GET_STACKBASE(tc->task))) {
bt->stacktop = GET_STACKTOP(tc->task);
@@ -4140,6 +4144,8 @@ task_pointer_string(struct task_context
bt->tc = tc;
bt->flags |= BT_KSTACKP;
back_trace(bt);
+ if (bt->stackbuf)
+ FREEBUF(bt->stackbuf);
} else
bt->stkptr = 0;
}

View File

@ -0,0 +1,39 @@
commit 6b93714b83d59ae4147b8ec3887261aca7fd6f65
Author: Dave Anderson <anderson@redhat.com>
Date: Mon Jan 7 10:44:29 2019 -0500
Prevent a SIGSEGV if a user attempts to input a command line that
exceeds the maximum length of 1500 bytes. The patch displays an
error message and ignores the command line.
(anderson@redhat.com)
diff --git a/cmdline.c b/cmdline.c
index 665f48c..796f7c5 100644
--- a/cmdline.c
+++ b/cmdline.c
@@ -1,8 +1,8 @@
/* cmdline.c - core analysis suite
*
* Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
- * Copyright (C) 2002-2015,2018 David Anderson
- * Copyright (C) 2002-2015,2018 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2002-2015,2019 David Anderson
+ * Copyright (C) 2002-2015,2019 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
@@ -121,9 +121,11 @@ process_command_line(void)
args[0] = NULL;
fprintf(fp, "\n");
return;
- }
-
- strcpy(pc->command_line, pc->readline);
+ }
+ if (strlen(pc->readline) >= BUFSIZE)
+ error(FATAL, "input line exceeds maximum of 1500 bytes\n");
+ else
+ strcpy(pc->command_line, pc->readline);
free(pc->readline);
clean_line(pc->command_line);

View File

@ -0,0 +1,212 @@
commit 8618ddd817621c40c1f44f0ab6df7c7805234416
Author: Dave Anderson <anderson@redhat.com>
Date: Fri Feb 1 15:01:29 2019 -0500
First phase of support for ARM64 kernels that are configured with
CONFIG_ARM64_USER_VA_BITS_52, which causes the PTRS_PER_PGD count
to increase from 64 to 1024. Without the patch, "WARNING: cannot
access vmalloc'd module memory" will be displayed during session
initialization, and the translation of any mapped kernel virtual
address that requires a page table walk will fail, leading to a
myriad of other errors.
(anderson@redhat.com)
diff --git a/arm64.c b/arm64.c
index 45c7313..2308612 100644
--- a/arm64.c
+++ b/arm64.c
@@ -1,8 +1,8 @@
/*
* arm64.c - core analysis suite
*
- * Copyright (C) 2012-2018 David Anderson
- * Copyright (C) 2012-2018 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2019 David Anderson
+ * Copyright (C) 2012-2019 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
@@ -209,6 +209,8 @@ arm64_init(int when)
ms->page_offset = ARM64_PAGE_OFFSET;
machdep->identity_map_base = ARM64_PAGE_OFFSET;
machdep->kvbase = ARM64_VA_START;
+ machdep->is_kvaddr = generic_is_kvaddr;
+ machdep->kvtop = arm64_kvtop;
ms->userspace_top = ARM64_USERSPACE_TOP;
if (machdep->flags & NEW_VMEMMAP) {
struct syment *sp;
@@ -262,11 +264,17 @@ arm64_init(int when)
break;
case 65536:
+ if (kernel_symbol_exists("idmap_ptrs_per_pgd") &&
+ readmem(symbol_value("idmap_ptrs_per_pgd"), KVADDR,
+ &value, sizeof(ulong), "idmap_ptrs_per_pgd", RETURN_ON_ERROR))
+ machdep->ptrs_per_pgd = value;
+
if (machdep->machspec->VA_BITS > PGDIR_SHIFT_L3_64K) {
machdep->flags |= VM_L3_64K;
- machdep->ptrs_per_pgd = PTRS_PER_PGD_L3_64K;
+ if (!machdep->ptrs_per_pgd)
+ machdep->ptrs_per_pgd = PTRS_PER_PGD_L3_64K;
if ((machdep->pgd =
- (char *)malloc(PTRS_PER_PGD_L3_64K * 8)) == NULL)
+ (char *)malloc(machdep->ptrs_per_pgd * 8)) == NULL)
error(FATAL, "cannot malloc pgd space.");
if ((machdep->pmd =
(char *)malloc(PTRS_PER_PMD_L3_64K * 8)) == NULL)
@@ -276,9 +284,10 @@ arm64_init(int when)
error(FATAL, "cannot malloc ptbl space.");
} else {
machdep->flags |= VM_L2_64K;
- machdep->ptrs_per_pgd = PTRS_PER_PGD_L2_64K;
+ if (!machdep->ptrs_per_pgd)
+ machdep->ptrs_per_pgd = PTRS_PER_PGD_L2_64K;
if ((machdep->pgd =
- (char *)malloc(PTRS_PER_PGD_L2_64K * 8)) == NULL)
+ (char *)malloc(machdep->ptrs_per_pgd * 8)) == NULL)
error(FATAL, "cannot malloc pgd space.");
if ((machdep->ptbl =
(char *)malloc(PTRS_PER_PTE_L2_64K * 8)) == NULL)
@@ -306,9 +315,11 @@ arm64_init(int when)
machdep->flags |= VMEMMAP;
machdep->uvtop = arm64_uvtop;
- machdep->kvtop = arm64_kvtop;
- machdep->is_kvaddr = generic_is_kvaddr;
machdep->is_uvaddr = arm64_is_uvaddr;
+ if (kernel_symbol_exists("vabits_user") &&
+ readmem(symbol_value("vabits_user"), KVADDR,
+ &value, sizeof(ulong), "vabits_user", RETURN_ON_ERROR))
+ machdep->machspec->vabits_user = value;
machdep->eframe_search = arm64_eframe_search;
machdep->back_trace = arm64_back_trace_cmd;
machdep->in_alternate_stack = arm64_in_alternate_stack;
@@ -350,10 +361,14 @@ arm64_init(int when)
case POST_GDB:
arm64_calc_virtual_memory_ranges();
machdep->section_size_bits = _SECTION_SIZE_BITS;
- if (THIS_KERNEL_VERSION >= LINUX(3,17,0))
- machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_3_17;
- else
- machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
+ if (!machdep->max_physmem_bits) {
+ if (machdep->machspec->VA_BITS == 52) /* guess */
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_52;
+ else if (THIS_KERNEL_VERSION >= LINUX(3,17,0))
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_3_17;
+ else
+ machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
+ }
ms = machdep->machspec;
if (THIS_KERNEL_VERSION >= LINUX(4,0,0)) {
@@ -601,6 +616,11 @@ arm64_dump_machdep_table(ulong arg)
fprintf(fp, " machspec: %lx\n", (ulong)ms);
fprintf(fp, " VA_BITS: %ld\n", ms->VA_BITS);
+ fprintf(fp, " vabits_user: ");
+ if (ms->vabits_user)
+ fprintf(fp, "%ld\n", ms->vabits_user);
+ else
+ fprintf(fp, "(unused)\n");
fprintf(fp, " userspace_top: %016lx\n", ms->userspace_top);
fprintf(fp, " page_offset: %016lx\n", ms->page_offset);
fprintf(fp, " vmalloc_start_addr: %016lx\n", ms->vmalloc_start_addr);
@@ -691,6 +711,8 @@ arm64_parse_machdep_arg_l(char *argstring, char *param, ulong *value)
*value = dtol(p, flags, &err);
if (!err)
*value = MEGABYTES(*value);
+ } else if (STRNEQ(argstring, "max_physmem_bits")) {
+ *value = dtol(p, flags, &err);
} else {
*value = htol(p, flags, &err);
}
@@ -750,6 +772,12 @@ arm64_parse_cmdline_args(void)
"setting kimage_voffset to: 0x%lx\n\n",
machdep->machspec->kimage_voffset);
continue;
+ } else if (arm64_parse_machdep_arg_l(arglist[i], "max_physmem_bits",
+ &machdep->max_physmem_bits)) {
+ error(NOTE,
+ "setting max_physmem_bits to: %ld\n\n",
+ machdep->max_physmem_bits);
+ continue;
}
error(WARNING, "ignoring --machdep option: %s\n",
@@ -1065,8 +1093,8 @@ arm64_vtop_2level_64k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, "PAGE DIRECTORY: %lx\n", pgd);
pgd_base = (ulong *)pgd;
- FILL_PGD(pgd_base, KVADDR, PTRS_PER_PGD_L2_64K * sizeof(ulong));
- pgd_ptr = pgd_base + (((vaddr) >> PGDIR_SHIFT_L2_64K) & (PTRS_PER_PGD_L2_64K - 1));
+ FILL_PGD(pgd_base, KVADDR, machdep->ptrs_per_pgd * sizeof(ulong));
+ pgd_ptr = pgd_base + (((vaddr) >> PGDIR_SHIFT_L2_64K) & (machdep->ptrs_per_pgd - 1));
pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr));
if (verbose)
fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
@@ -1129,8 +1157,8 @@ arm64_vtop_3level_64k(ulong pgd, ulong vaddr, physaddr_t *paddr, int verbose)
fprintf(fp, "PAGE DIRECTORY: %lx\n", pgd);
pgd_base = (ulong *)pgd;
- FILL_PGD(pgd_base, KVADDR, PTRS_PER_PGD_L3_64K * sizeof(ulong));
- pgd_ptr = pgd_base + (((vaddr) >> PGDIR_SHIFT_L3_64K) & (PTRS_PER_PGD_L3_64K - 1));
+ FILL_PGD(pgd_base, KVADDR, machdep->ptrs_per_pgd * sizeof(ulong));
+ pgd_ptr = pgd_base + (((vaddr) >> PGDIR_SHIFT_L3_64K) & (machdep->ptrs_per_pgd - 1));
pgd_val = ULONG(machdep->pgd + PGDIR_OFFSET_L3_64K(pgd_ptr));
if (verbose)
fprintf(fp, " PGD: %lx => %lx\n", (ulong)pgd_ptr, pgd_val);
diff --git a/crash.8 b/crash.8
index 8c11615..f9de36d 100644
--- a/crash.8
+++ b/crash.8
@@ -278,6 +278,7 @@ ARM:
ARM64:
phys_offset=<physical-address>
kimage_voffset=<kimage_voffset-value>
+ max_physmem_bits=<value>
X86:
page_offset=<CONFIG_PAGE_OFFSET-value>
.fi
diff --git a/defs.h b/defs.h
index b473972..05f2d17 100644
--- a/defs.h
+++ b/defs.h
@@ -3049,7 +3049,7 @@ typedef signed int s32;
#define PMD_SHIFT_L3_64K (29)
#define PMD_SIZE_L3_64K (1UL << PMD_SHIFT_L3_64K)
#define PMD_MASK_L3_64K (~(PMD_SIZE_L3_64K-1))
-#define PGDIR_OFFSET_L3_64K(X) (((ulong)(X)) & ((PTRS_PER_PGD_L3_64K * 8) - 1))
+#define PGDIR_OFFSET_L3_64K(X) (((ulong)(X)) & ((machdep->ptrs_per_pgd * 8) - 1))