diff --git a/.crash.metadata b/.crash.metadata
index 44d67c9..d966af7 100644
--- a/.crash.metadata
+++ b/.crash.metadata
@@ -1 +1 @@
-0179af8d08a36269d5ae41205ec98e0a6957ab5f SOURCES/crash-7.2.0.tar.gz
+1a9fa8cd6869da42314ec47df6a750e053f4bece SOURCES/crash-7.2.3.tar.gz
diff --git a/.gitignore b/.gitignore
index b708ec5..32212ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/crash-7.2.0.tar.gz
+SOURCES/crash-7.2.3.tar.gz
diff --git a/SOURCES/github_1926150e_ppc64_stacksize.patch b/SOURCES/github_1926150e_ppc64_stacksize.patch
new file mode 100644
index 0000000..5da09da
--- /dev/null
+++ b/SOURCES/github_1926150e_ppc64_stacksize.patch
@@ -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");
diff --git a/SOURCES/github_1e488cfe_to_1160ba19.patch b/SOURCES/github_1e488cfe_to_1160ba19.patch
deleted file mode 100644
index c018be5..0000000
--- a/SOURCES/github_1e488cfe_to_1160ba19.patch
+++ /dev/null
@@ -1,319 +0,0 @@
-commit 1e488cfefa1d9ca4ca626bc2a308b39f7404f5db
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Tue Jan 23 16:35:41 2018 -0500
-
-    Fix for the "bt" command and the "ps -s" option for zombie tasks
-    whose kernel stacks have been freed/detached.  Without the patch,
-    the "bt" command indicates "bt: invalid kernel virtual address: 0
-    type: stack contents" and "bt: read of stack at 0 failed"; it will
-    be changed to display "(no stack)".  The "ps -s" option would fail
-    prematurely upon reaching such a task, indicating "ps: invalid kernel
-    virtual address: 0  type: stack contents" and "ps: read of stack at 0
-    failed".
-    (anderson@redhat.com)
-
-diff --git a/kernel.c b/kernel.c
-index 4638495..1bf6251 100644
---- a/kernel.c
-+++ b/kernel.c
-@@ -1,8 +1,8 @@
- /* kernel.c - core analysis suite
-  *
-  * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
-- * Copyright (C) 2002-2017 David Anderson
-- * Copyright (C) 2002-2017 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2002-2018 David Anderson
-+ * Copyright (C) 2002-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
-@@ -2890,6 +2890,11 @@ back_trace(struct bt_info *bt)
- 			return;
-  	}
- 
-+	if (bt->stackbase == 0) {
-+		fprintf(fp, "(no stack)\n");
-+		return;
-+	}
-+
- 	fill_stackbuf(bt);
- 
- 	if (CRASHDEBUG(4)) {
-diff --git a/task.c b/task.c
-index b303ef7..db05ab4 100644
---- a/task.c
-+++ b/task.c
-@@ -1,8 +1,8 @@
- /* task.c - core analysis suite
-  *
-  * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
-- * Copyright (C) 2002-2017 David Anderson
-- * Copyright (C) 2002-2017 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2002-2018 David Anderson
-+ * Copyright (C) 2002-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
-@@ -4182,12 +4182,14 @@ task_pointer_string(struct task_context *tc, ulong do_kstackp, char *buf)
- 				KVADDR, &bt->stkptr, sizeof(void *),
-                 		"thread_struct ksp", FAULT_ON_ERROR);
- 		} else {
--               		bt->task = tc->task;
--               		bt->tc = tc;
--               		bt->stackbase = GET_STACKBASE(tc->task);
--               		bt->stacktop = GET_STACKTOP(tc->task);
--			bt->flags |= BT_KSTACKP;
--			back_trace(bt);
-+			if ((bt->stackbase = GET_STACKBASE(tc->task))) {
-+				bt->stacktop = GET_STACKTOP(tc->task);
-+				bt->task = tc->task;
-+				bt->tc = tc;
-+				bt->flags |= BT_KSTACKP;
-+				back_trace(bt);
-+			} else
-+				bt->stkptr = 0;
- 		}
- 
- 		if (bt->stkptr)
-
-commit 693e0fa8ea8b2791329a4197fafd8700afa14c3b
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Thu Jan 25 14:52:54 2018 -0500
-
-    Fix for running on live systems on 4.15-rc2 and later kernels that
-    are configured with CONFIG_RANDOMIZE_BASE and contain kernel commit
-    668533dc0764b30c9dd2baf3ca800156f688326b, titled "kallsyms: take
-    advantage of the new '%px' format".  Without the patch, a live crash
-    session does not show the "WARNING: kernel relocated ..." message
-    expected with KASLR, and then displays the message "crash: cannot set
-    context for pid: <pid>" prior to generating a SIGSEGV.
-    (anderson@redhat.com)
-
-diff --git a/symbols.c b/symbols.c
-index 2372887..9a3763c 100644
---- a/symbols.c
-+++ b/symbols.c
-@@ -1,8 +1,8 @@
- /* symbols.c - core analysis suite
-  *
-  * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
-- * Copyright (C) 2002-2017 David Anderson
-- * Copyright (C) 2002-2017 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2002-2018 David Anderson
-+ * Copyright (C) 2002-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
-@@ -1004,10 +1004,9 @@ symbol_value_from_proc_kallsyms(char *symname)
- 
- 	found = FALSE;
- 	while (!found && fgets(buf, BUFSIZE, kp) &&
--	    (parse_line(buf, kallsyms) == 3) && 
--	    hexadecimal(kallsyms[0], 0)) {
--
--		if (STREQ(kallsyms[2], symname)) {
-+	    (parse_line(buf, kallsyms) == 3)) {
-+		if (hexadecimal(kallsyms[0], 0) && 
-+		    STREQ(kallsyms[2], symname)) {
- 			kallsym = htol(kallsyms[0], RETURN_ON_ERROR, NULL);
- 			found = TRUE;
- 			break;
-
-commit 1af7813e0552ac93b39a44abffffc04600d3ed4c
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Thu Jan 25 15:17:26 2018 -0500
-
-    Fix for 4.15-rc5 and later x86_64 kernels that contain kernel commit
-    c482feefe1aeb150156248ba0fd3e029bc886605, titled "x86/entry/64: Make
-    cpu_entry_area.tss read-only".  Without the patch, the addresses and
-    sizes of the x86_64 exception stacks cannot be determined; therefore
-    if a backtrace starts on one of the exception stacks, then the "bt"
-    command will fail.
-    (anderson@redhat.com)
-
-diff --git a/x86_64.c b/x86_64.c
-index e924ca9..467b5d7 100644
---- a/x86_64.c
-+++ b/x86_64.c
-@@ -1245,8 +1245,10 @@ x86_64_ist_init(void)
- 	struct syment *boot_sp, *tss_sp, *ist_sp;
- 
-         ms = machdep->machspec;
--	if (!(tss_sp = per_cpu_symbol_search("per_cpu__init_tss")))
--		tss_sp = per_cpu_symbol_search("per_cpu__cpu_tss");
-+	if (!(tss_sp = per_cpu_symbol_search("per_cpu__init_tss"))) {
-+		if (!(tss_sp = per_cpu_symbol_search("per_cpu__cpu_tss")))
-+			tss_sp = per_cpu_symbol_search("per_cpu__cpu_tss_rw");
-+	}
- 	ist_sp = per_cpu_symbol_search("per_cpu__orig_ist");
- 
- 	x86_64_exception_stacks_init();
-
-commit 1160ba19884fed4420c334394cde7a40b113e09c
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Fri Jan 26 11:06:48 2018 -0500
-
-    Additional fix for support of KASLR enabled kernels captured by the
-    SADUMP dumpfile facility, where this patch fixes a problem when Page
-    Table Isolation(PTI) is enabled.  When PTI is enabled, bit 12 of CR3
-    register is used to split user space and kernel space.  Also bit 11:0
-    is used for Process Context IDentifiers(PCID).  To open an SADUMP
-    dumpfile, the value of CR3 is used to calculate KASLR offset and
-    phys_base; this patch masks the CR3 register value correctly for
-    a PTI enabled kernel.
-    (indou.takao@jp.fujitsu.com)
-
-diff --git a/defs.h b/defs.h
-index 4d2fb2f..92341d2 100644
---- a/defs.h
-+++ b/defs.h
-@@ -2605,6 +2605,8 @@ struct symbol_table_data {
- 	ulong divide_error_vmlinux;
- 	ulong idt_table_vmlinux;
- 	ulong saved_command_line_vmlinux;
-+	ulong pti_init_vmlinux;
-+	ulong kaiser_init_vmlinux;
- };
- 
- /* flags for st */
-diff --git a/sadump.c b/sadump.c
-index 6b912d4..25cefe9 100644
---- a/sadump.c
-+++ b/sadump.c
-@@ -1749,7 +1749,7 @@ static ulong memparse(char *ptr, char **retptr)
-  * of elfcorehdr.
-  */
- static ulong
--get_elfcorehdr(ulong cr3, ulong kaslr_offset)
-+get_elfcorehdr(ulong kaslr_offset)
- {
- 	char cmdline[BUFSIZE], *ptr;
- 	ulong cmdline_vaddr;
-@@ -1906,7 +1906,7 @@ get_vmcoreinfo(ulong elfcorehdr, ulong *addr, int *len)
-  *    using "elfcorehdr=" and retrieve kaslr_offset/phys_base from vmcoreinfo.
-  */
- static int
--get_kaslr_offset_from_vmcoreinfo(ulong cr3, ulong orig_kaslr_offset,
-+get_kaslr_offset_from_vmcoreinfo(ulong orig_kaslr_offset,
- 		                 ulong *kaslr_offset, ulong *phys_base)
- {
- 	ulong elfcorehdr_addr = 0;
-@@ -1916,7 +1916,7 @@ get_kaslr_offset_from_vmcoreinfo(ulong cr3, ulong orig_kaslr_offset,
- 	int ret = FALSE;
- 
- 	/* Find "elfcorehdr=" in the kernel boot parameter */
--	elfcorehdr_addr = get_elfcorehdr(cr3, orig_kaslr_offset);
-+	elfcorehdr_addr = get_elfcorehdr(orig_kaslr_offset);
- 	if (!elfcorehdr_addr)
- 		return FALSE;
- 
-@@ -1973,8 +1973,8 @@ quit:
-  * 1) Get IDTR and CR3 value from the dump header.
-  * 2) Get a virtual address of IDT from IDTR value
-  *    --- (A)
-- * 3) Translate (A) to physical address using CR3, which points a top of
-- *    page table.
-+ * 3) Translate (A) to physical address using CR3, the upper 52 bits
-+ *    of which points a top of page table.
-  *    --- (B)
-  * 4) Get an address of vector0 (Devide Error) interrupt handler from
-  *    IDT, which are pointed by (B).
-@@ -2023,12 +2023,15 @@ quit:
-  *    kernel. Retrieve vmcoreinfo from address of "elfcorehdr=" and
-  *    get kaslr_offset and phys_base from vmcoreinfo.
-  */
-+#define PTI_USER_PGTABLE_BIT	PAGE_SHIFT
-+#define PTI_USER_PGTABLE_MASK	(1 << PTI_USER_PGTABLE_BIT)
-+#define CR3_PCID_MASK		0xFFFull
- int
- sadump_calc_kaslr_offset(ulong *kaslr_offset)
- {
- 	ulong phys_base = 0;
- 	struct sadump_smram_cpu_state scs;
--	uint64_t idtr = 0, cr3 = 0, idtr_paddr;
-+	uint64_t idtr = 0, pgd = 0, idtr_paddr;
- 	ulong divide_error_vmcore;
- 	ulong kaslr_offset_kdump, phys_base_kdump;
- 	int ret = FALSE;
-@@ -2039,7 +2042,10 @@ sadump_calc_kaslr_offset(ulong *kaslr_offset)
- 
- 	memset(&scs, 0, sizeof(scs));
- 	get_sadump_smram_cpu_state_any(&scs);
--	cr3 = scs.Cr3;
-+	if (st->pti_init_vmlinux || st->kaiser_init_vmlinux)
-+		pgd = scs.Cr3 & ~(CR3_PCID_MASK|PTI_USER_PGTABLE_MASK);
-+	else
-+		pgd = scs.Cr3 & ~CR3_PCID_MASK;
- 	idtr = ((uint64_t)scs.IdtUpper)<<32 | (uint64_t)scs.IdtLower;
- 
- 	/*
-@@ -2050,12 +2056,12 @@ sadump_calc_kaslr_offset(ulong *kaslr_offset)
- 	 *
- 	 * TODO: XEN and 5-level is not supported
- 	 */
--	vt->kernel_pgd[0] = cr3;
-+	vt->kernel_pgd[0] = pgd;
- 	machdep->machspec->last_pml4_read = vt->kernel_pgd[0];
- 	machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_2_6;
- 	machdep->machspec->pgdir_shift = PGDIR_SHIFT;
--	if (!readmem(cr3, PHYSADDR, machdep->machspec->pml4, PAGESIZE(),
--			"cr3", RETURN_ON_ERROR))
-+	if (!readmem(pgd, PHYSADDR, machdep->machspec->pml4, PAGESIZE(),
-+			"pgd", RETURN_ON_ERROR))
- 		goto quit;
- 
- 	/* Convert virtual address of IDT table to physical address */
-@@ -2070,7 +2076,7 @@ sadump_calc_kaslr_offset(ulong *kaslr_offset)
- 
- 	if (CRASHDEBUG(1)) {
- 		fprintf(fp, "calc_kaslr_offset: idtr=%lx\n", idtr);
--		fprintf(fp, "calc_kaslr_offset: cr3=%lx\n", cr3);
-+		fprintf(fp, "calc_kaslr_offset: pgd=%lx\n", pgd);
- 		fprintf(fp, "calc_kaslr_offset: idtr(phys)=%lx\n", idtr_paddr);
- 		fprintf(fp, "calc_kaslr_offset: divide_error(vmlinux): %lx\n",
- 			st->divide_error_vmlinux);
-@@ -2084,9 +2090,12 @@ sadump_calc_kaslr_offset(ulong *kaslr_offset)
- 	 * from vmcoreinfo
- 	 */
- 	if (get_kaslr_offset_from_vmcoreinfo(
--		cr3, *kaslr_offset, &kaslr_offset_kdump, &phys_base_kdump)) {
-+		*kaslr_offset, &kaslr_offset_kdump, &phys_base_kdump)) {
- 		*kaslr_offset =  kaslr_offset_kdump;
- 		phys_base =  phys_base_kdump;
-+	} else if (CRASHDEBUG(1)) {
-+		fprintf(fp, "sadump: failed to determine which kernel was running at crash,\n");
-+		fprintf(fp, "sadump: asssuming the kdump 1st kernel.\n");
- 	}
- 
- 	if (CRASHDEBUG(1)) {
-diff --git a/symbols.c b/symbols.c
-index 9a3763c..4db9af7 100644
---- a/symbols.c
-+++ b/symbols.c
-@@ -3071,10 +3071,14 @@ dump_symbol_table(void)
- 		fprintf(fp, "divide_error_vmlinux: %lx\n", st->divide_error_vmlinux);
- 		fprintf(fp, "   idt_table_vmlinux: %lx\n", st->idt_table_vmlinux);
- 		fprintf(fp, "saved_command_line_vmlinux: %lx\n", st->saved_command_line_vmlinux);
-+		fprintf(fp, "    pti_init_vmlinux: %lx\n", st->pti_init_vmlinux);
-+		fprintf(fp, " kaiser_init_vmlinux: %lx\n", st->kaiser_init_vmlinux);
- 	} else {
- 		fprintf(fp, "divide_error_vmlinux: (unused)\n");
- 		fprintf(fp, "   idt_table_vmlinux: (unused)\n");
- 		fprintf(fp, "saved_command_line_vmlinux: (unused)\n");
-+		fprintf(fp, "    pti_init_vmlinux: (unused)\n");
-+		fprintf(fp, " kaiser_init_vmlinux: (unused)\n");
- 	}
- 
-         fprintf(fp, "    symval_hash[%d]: %lx\n", SYMVAL_HASH,
-@@ -12305,6 +12309,11 @@ numeric_forward(const void *P_x, const void *P_y)
- 			st->saved_command_line_vmlinux = valueof(x);
- 		else if (STREQ(y->name, "saved_command_line"))
- 			st->saved_command_line_vmlinux = valueof(y);
-+
-+		if (STREQ(x->name, "pti_init"))
-+			st->pti_init_vmlinux = valueof(x);
-+		else if (STREQ(y->name, "kaiser_init"))
-+			st->kaiser_init_vmlinux = valueof(y);
- 	}
- 
-   	xs = bfd_get_section(x);
diff --git a/SOURCES/github_28fa7bd0_ppc64_increase_VA_range.patch b/SOURCES/github_28fa7bd0_ppc64_increase_VA_range.patch
new file mode 100644
index 0000000..119ddf6
--- /dev/null
+++ b/SOURCES/github_28fa7bd0_ppc64_increase_VA_range.patch
@@ -0,0 +1,45 @@
+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
+@@ -3978,6 +3978,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;
diff --git a/SOURCES/github_46d21219.patch b/SOURCES/github_46d21219.patch
new file mode 100644
index 0000000..297cb84
--- /dev/null
+++ b/SOURCES/github_46d21219.patch
@@ -0,0 +1,34 @@
+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;
diff --git a/SOURCES/github_494a796e_to_63419fb9.patch b/SOURCES/github_494a796e_to_63419fb9.patch
deleted file mode 100644
index 88a808a..0000000
--- a/SOURCES/github_494a796e_to_63419fb9.patch
+++ /dev/null
@@ -1,1084 +0,0 @@
-commit 494a796e112869cf5df482dc7618868eca7cf2d5
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Tue Nov 28 09:24:39 2017 -0500
-
-    Fix to support Linux 4.15 and later kernels that contain kernel
-    commit e8cfbc245e24887e3c30235f71e9e9405e0cfc39, titled "pid: remove
-    pidhash".  The kernel's traditional usage of a pid_hash[] array to
-    store PIDs has been replaced by an IDR radix tree, requiring a new
-    crash plug-in function to gather the system's task set.  Without the
-    patch, the crash session fails during initialization with the error
-    message "crash: cannot resolve init_task_union".
-    (anderson@redhat.com)
-
-diff --git a/defs.h b/defs.h
-index 9132075..ba9abad 100644
---- a/defs.h
-+++ b/defs.h
-@@ -845,6 +845,8 @@ struct task_table {                      /* kernel/local task table data */
- 	long anonpages;
- 	ulong stack_end_magic;
- 	ulong pf_kthread;
-+	ulong pid_radix_tree;
-+	int callbacks;
- };
- 
- #define TASK_INIT_DONE       (0x1)
-@@ -864,6 +866,7 @@ struct task_table {                      /* kernel/local task table data */
- #define ACTIVE_ONLY       (0x4000)
- #define START_TIME_NSECS  (0x8000)
- #define THREAD_INFO_IN_TASK (0x10000)
-+#define PID_RADIX_TREE   (0x20000)
- 
- #define TASK_SLUSH (20)
- 
-@@ -1996,6 +1999,8 @@ struct offset_table {                    /* stash of commonly-used offsets */
- 	long mod_arch_specific_orc_unwind;
- 	long task_struct_policy;
- 	long kmem_cache_random;
-+	long pid_namespace_idr;
-+	long idr_idr_rt;
- };
- 
- struct size_table {         /* stash of commonly-used sizes */
-@@ -2146,6 +2151,7 @@ struct size_table {         /* stash of commonly-used sizes */
- 	long sk_buff_len;
- 	long orc_entry;
- 	long task_struct_policy;
-+	long pid;
- };
- 
- struct array_table {
-diff --git a/filesys.c b/filesys.c
-index f9a7797..1b44ad5 100644
---- a/filesys.c
-+++ b/filesys.c
-@@ -2083,38 +2083,6 @@ vfs_init(void)
- 	if (!(ft->inode_cache = (char *)malloc(SIZE(inode)*INODE_CACHE)))
- 		error(FATAL, "cannot malloc inode cache\n");
- 
--	if (symbol_exists("height_to_maxindex") ||
--	    symbol_exists("height_to_maxnodes")) {
--		int newver = symbol_exists("height_to_maxnodes");
--		int tmp ATTRIBUTE_UNUSED;
--		if (!newver) {
--			if (LKCD_KERNTYPES())
--				ARRAY_LENGTH_INIT_ALT(tmp, "height_to_maxindex",
--					"radix_tree_preload.nodes", NULL, 0);
--			else
--				ARRAY_LENGTH_INIT(tmp, height_to_maxindex,
--					"height_to_maxindex", NULL, 0);
--		} else {
--			if (LKCD_KERNTYPES())
--				ARRAY_LENGTH_INIT_ALT(tmp, "height_to_maxnodes",
--					"radix_tree_preload.nodes", NULL, 0);
--			else
--				ARRAY_LENGTH_INIT(tmp, height_to_maxnodes,
--					"height_to_maxnodes", NULL, 0);
--		}
--		STRUCT_SIZE_INIT(radix_tree_root, "radix_tree_root");
--		STRUCT_SIZE_INIT(radix_tree_node, "radix_tree_node");
--		MEMBER_OFFSET_INIT(radix_tree_root_height, 
--			"radix_tree_root","height");
--		MEMBER_OFFSET_INIT(radix_tree_root_rnode, 
--			"radix_tree_root","rnode");
--		MEMBER_OFFSET_INIT(radix_tree_node_slots, 
--			"radix_tree_node","slots");
--		MEMBER_OFFSET_INIT(radix_tree_node_height, 
--			"radix_tree_node","height");
--		MEMBER_OFFSET_INIT(radix_tree_node_shift,
--			"radix_tree_node","shift");
--	}
- 	MEMBER_OFFSET_INIT(rb_root_rb_node, 
- 		"rb_root","rb_node");
- 	MEMBER_OFFSET_INIT(rb_node_rb_left, 
-diff --git a/symbols.c b/symbols.c
-index 0d85ff7..2372887 100644
---- a/symbols.c
-+++ b/symbols.c
-@@ -8608,6 +8608,10 @@ dump_offset_table(char *spec, ulong makestruct)
- 	fprintf(fp, "            mnt_namespace_list: %ld\n",
- 		OFFSET(mnt_namespace_list));
- 
-+	fprintf(fp, "             pid_namespace_idr: %ld\n",
-+		OFFSET(pid_namespace_idr));
-+	fprintf(fp, "                    idr_idr_rt: %ld\n",
-+		OFFSET(idr_idr_rt));
-         fprintf(fp, "                  pid_link_pid: %ld\n",
-                 OFFSET(pid_link_pid));
-         fprintf(fp, "                pid_hash_chain: %ld\n",
-@@ -10349,6 +10353,8 @@ dump_offset_table(char *spec, ulong makestruct)
- 		SIZE(pid_link));
- 	fprintf(fp, "                          upid: %ld\n", 
- 		SIZE(upid));
-+	fprintf(fp, "                           pid: %ld\n",
-+		SIZE(pid));
- 	fprintf(fp, "                  unwind_table: %ld\n", 
- 		SIZE(unwind_table));
- 	fprintf(fp, "                        rlimit: %ld\n", 
-diff --git a/task.c b/task.c
-index 724532d..b303ef7 100644
---- a/task.c
-+++ b/task.c
-@@ -30,6 +30,8 @@ static void refresh_hlist_task_table(void);
- static void refresh_hlist_task_table_v2(void);
- static void refresh_hlist_task_table_v3(void);
- static void refresh_active_task_table(void);
-+static int radix_tree_task_callback(ulong);
-+static void refresh_radix_tree_task_table(void);
- static struct task_context *store_context(struct task_context *, ulong, char *);
- static void refresh_context(ulong, ulong);
- static ulong parent_of(ulong);
-@@ -439,12 +441,55 @@ task_init(void)
- 	    	((len = SIZE(thread_union)) != STACKSIZE())) 
- 		machdep->stacksize = len;
- 
-+	MEMBER_OFFSET_INIT(pid_namespace_idr, "pid_namespace", "idr");
-+	MEMBER_OFFSET_INIT(idr_idr_rt, "idr", "idr_rt");
-+
-+	if (symbol_exists("height_to_maxindex") ||
-+	    symbol_exists("height_to_maxnodes")) {
-+		int newver = symbol_exists("height_to_maxnodes");
-+		int tmp ATTRIBUTE_UNUSED;
-+		if (!newver) {
-+			if (LKCD_KERNTYPES())
-+				ARRAY_LENGTH_INIT_ALT(tmp, "height_to_maxindex",
-+					"radix_tree_preload.nodes", NULL, 0);
-+			else
-+				ARRAY_LENGTH_INIT(tmp, height_to_maxindex,
-+					"height_to_maxindex", NULL, 0);
-+		} else {
-+			if (LKCD_KERNTYPES())
-+				ARRAY_LENGTH_INIT_ALT(tmp, "height_to_maxnodes",
-+					"radix_tree_preload.nodes", NULL, 0);
-+			else
-+				ARRAY_LENGTH_INIT(tmp, height_to_maxnodes,
-+					"height_to_maxnodes", NULL, 0);
-+		}
-+		STRUCT_SIZE_INIT(radix_tree_root, "radix_tree_root");
-+		STRUCT_SIZE_INIT(radix_tree_node, "radix_tree_node");
-+		MEMBER_OFFSET_INIT(radix_tree_root_height,
-+			"radix_tree_root","height");
-+		MEMBER_OFFSET_INIT(radix_tree_root_rnode,
-+			"radix_tree_root","rnode");
-+		MEMBER_OFFSET_INIT(radix_tree_node_slots,
-+			"radix_tree_node","slots");
-+		MEMBER_OFFSET_INIT(radix_tree_node_height,
-+			"radix_tree_node","height");
-+		MEMBER_OFFSET_INIT(radix_tree_node_shift,
-+			"radix_tree_node","shift");
-+	}
-+
- 	if (symbol_exists("pidhash") && symbol_exists("pid_hash") &&
- 	    !symbol_exists("pidhash_shift"))
- 		error(FATAL, 
-         "pidhash and pid_hash both exist -- cannot distinquish between them\n");
- 
--	if (symbol_exists("pid_hash") && symbol_exists("pidhash_shift")) {
-+	if (VALID_MEMBER(pid_namespace_idr)) {
-+		STRUCT_SIZE_INIT(pid, "pid");
-+		tt->refresh_task_table = refresh_radix_tree_task_table;
-+		tt->pid_radix_tree = symbol_value("init_pid_ns") +
-+			OFFSET(pid_namespace_idr) + OFFSET(idr_idr_rt);
-+		tt->flags |= PID_RADIX_TREE;
-+
-+	} else if (symbol_exists("pid_hash") && symbol_exists("pidhash_shift")) {
- 		int pidhash_shift;
- 
- 	   	if (get_symbol_type("PIDTYPE_PID", NULL, &req) != 
-@@ -2271,6 +2316,233 @@ chain_next:
- 	tt->retries = MAX(tt->retries, retries);
- }
- 
-+/*
-+ *  Linux 4.15: pid_hash[] replaced by IDR/radix_tree
-+ */
-+static int
-+radix_tree_task_callback(ulong task)
-+{
-+	ulong *tlp;
-+
-+	if (tt->callbacks < tt->max_tasks) {
-+		tlp = (ulong *)tt->task_local;
-+		tlp += tt->callbacks++;
-+		*tlp = task;
-+	}
-+
-+	return TRUE;
-+}
-+
-+static void
-+refresh_radix_tree_task_table(void)
-+{
-+	int i, cnt;
-+	ulong count, retries, next, curtask, curpid, upid_ns, pid_tasks_0, task;
-+	ulong *tlp;
-+	char *tp;
-+	struct radix_tree_pair rtp;
-+	struct task_context *tc;
-+	char *pidbuf;
-+
-+	if (DUMPFILE() && (tt->flags & TASK_INIT_DONE))   /* impossible */
-+		return;
-+
-+	if (DUMPFILE()) {                                 /* impossible */
-+		please_wait("gathering task table data");
-+		if (!symbol_exists("panic_threads"))
-+			tt->flags |= POPULATE_PANIC;
-+	}
-+
-+	if (ACTIVE() && !(tt->flags & TASK_REFRESH))
-+		return;
-+
-+	curpid = NO_PID;
-+	curtask = NO_TASK;
-+
-+	/*
-+	 *  The current task's task_context entry may change,
-+	 *  or the task may not even exist anymore.
-+	 */
-+	if (ACTIVE() && (tt->flags & TASK_INIT_DONE)) {
-+		curtask = CURRENT_TASK();
-+		curpid = CURRENT_PID();
-+	}
-+
-+	count = do_radix_tree(tt->pid_radix_tree, RADIX_TREE_COUNT, NULL);
-+	if (CRASHDEBUG(1))
-+		console("do_radix_tree: count: %ld\n", count);
-+
-+	retries = 0;
-+	pidbuf = GETBUF(SIZE(pid));
-+
-+retry_radix_tree:
-+	if (retries && DUMPFILE())
-+		error(FATAL,
-+			"\ncannot gather a stable task list via radix tree\n");
-+
-+	if ((retries == MAX_UNLIMITED_TASK_RETRIES) &&
-+	    !(tt->flags & TASK_INIT_DONE))
-+		error(FATAL,
-+		    "\ncannot gather a stable task list via radix tree (%d retries)\n",
-+			retries);
-+
-+	if (count > tt->max_tasks) {
-+		tt->max_tasks = count + TASK_SLUSH;
-+		allocate_task_space(tt->max_tasks);
-+	}
-+
-+	BZERO(tt->task_local, tt->max_tasks * sizeof(void *));
-+	tt->callbacks = 0;
-+	rtp.index = 0;
-+	rtp.value = (void *)&radix_tree_task_callback;
-+	count = do_radix_tree(tt->pid_radix_tree, RADIX_TREE_DUMP_CB, &rtp);
-+	if (CRASHDEBUG(1))
-+		console("do_radix_tree: count: %ld  tt->callbacks: %d\n", count, tt->callbacks);
-+
-+	if (count > tt->max_tasks) {
-+		retries++;
-+		goto retry_radix_tree;
-+	}
-+
-+	if (!hq_open()) {
-+		error(INFO, "cannot hash task_struct entries\n");
-+		if (!(tt->flags & TASK_INIT_DONE))
-+			clean_exit(1);
-+		error(INFO, "using stale task_structs\n");
-+		return;
-+       }
-+
-+	/*
-+	 *  Get the idle threads first.
-+	 */
-+	cnt = 0;
-+	for (i = 0; i < kt->cpus; i++) {
-+		if (!tt->idle_threads[i])
-+			continue;
-+		if (hq_enter(tt->idle_threads[i]))
-+			cnt++;
-+		else
-+			error(WARNING, "%sduplicate idle tasks?\n",
-+				DUMPFILE() ? "\n" : "");
-+	}
-+
-+	for (i = 0; i < tt->max_tasks; i++) {
-+		tlp = (ulong *)tt->task_local;
-+		tlp += i;
-+		if ((next = *tlp) == 0)
-+			break;
-+
-+		/*
-+		 *  Translate radix tree contents to PIDTYPE_PID task.
-+		 *  - the radix tree contents are struct pid pointers
-+		 *  - upid is contained in pid.numbers[0]
-+		 *  - upid.ns should point to init->init_pid_ns
-+		 *  - pid->tasks[0] is first hlist_node in task->pids[3]
-+		 *  - get task from address of task->pids[0]
-+		 */
-+		if (!readmem(next, KVADDR, pidbuf,
-+		    SIZE(pid), "pid", RETURN_ON_ERROR|QUIET)) {
-+			error(INFO, "\ncannot read pid struct from radix tree\n");
-+			if (DUMPFILE())
-+				continue;
-+			hq_close();
-+			retries++;
-+			goto retry_radix_tree;
-+		}
-+
-+		upid_ns = ULONG(pidbuf + OFFSET(pid_numbers) + OFFSET(upid_ns));
-+		if (upid_ns != tt->init_pid_ns)
-+			continue;
-+		pid_tasks_0 = ULONG(pidbuf + OFFSET(pid_tasks));
-+		if (!pid_tasks_0)
-+			continue;
-+		task = pid_tasks_0 - OFFSET(task_struct_pids);
-+
-+		if (CRASHDEBUG(1))
-+			console("pid: %lx  ns: %lx  tasks[0]: %lx task: %lx\n",
-+				next, upid_ns, pid_tasks_0, task);
-+
-+		if (is_idle_thread(task))
-+			continue;
-+
-+		if (!IS_TASK_ADDR(task)) {
-+			error(INFO, "%s: IDR radix tree: invalid task address: %lx\n",
-+				DUMPFILE() ? "\n" : "", task);
-+			if (DUMPFILE())
-+				break;
-+			hq_close();
-+			retries++;
-+			goto retry_radix_tree;
-+		}
-+
-+		if (!hq_enter(task)) {
-+			error(INFO, "%s: IDR radix tree: duplicate task: %lx\n",
-+				DUMPFILE() ? "\n" : "", task);
-+			if (DUMPFILE())
-+				break;
-+			hq_close();
-+			retries++;
-+			goto retry_radix_tree;
-+		}
-+
-+		cnt++;
-+	}
-+
-+	BZERO(tt->task_local, tt->max_tasks * sizeof(void *));
-+	cnt = retrieve_list((ulong *)tt->task_local, cnt);
-+	hq_close();
-+
-+	clear_task_cache();
-+
-+        for (i = 0, tlp = (ulong *)tt->task_local,
-+             tt->running_tasks = 0, tc = tt->context_array;
-+             i < tt->max_tasks; i++, tlp++) {
-+		if (!(*tlp))
-+			continue;
-+
-+		if (!IS_TASK_ADDR(*tlp)) {
-+			error(WARNING,
-+		            "%sinvalid task address found in task list: %lx\n",
-+				DUMPFILE() ? "\n" : "", *tlp);
-+			if (DUMPFILE())
-+				continue;
-+			retries++;
-+			goto retry_radix_tree;
-+		}
-+
-+		if (task_exists(*tlp)) {
-+			error(WARNING,
-+		           "%sduplicate task address found in task list: %lx\n",
-+				DUMPFILE() ? "\n" : "", *tlp);
-+			if (DUMPFILE())
-+				continue;
-+			retries++;
-+			goto retry_radix_tree;
-+		}
-+
-+		if (!(tp = fill_task_struct(*tlp))) {
-+			if (DUMPFILE())
-+				continue;
-+			retries++;
-+			goto retry_radix_tree;
-+		}
-+
-+		if (store_context(tc, *tlp, tp)) {
-+			tc++;
-+			tt->running_tasks++;
-+		}
-+	}
-+
-+	FREEBUF(pidbuf);
-+
-+	please_wait_done();
-+
-+	if (ACTIVE() && (tt->flags & TASK_INIT_DONE))
-+		refresh_context(curtask, curpid);
-+
-+	tt->retries = MAX(tt->retries, retries);
-+}
-+
- static void
- refresh_active_task_table(void)
- {
-@@ -7054,6 +7326,8 @@ dump_task_table(int verbose)
-                 fprintf(fp, "refresh_hlist_task_table_v3()\n");
-         else if (tt->refresh_task_table == refresh_active_task_table)
-                 fprintf(fp, "refresh_active_task_table()\n");
-+        else if (tt->refresh_task_table == refresh_radix_tree_task_table)
-+                fprintf(fp, "refresh_radix_tree_task_table()\n");
- 	else
- 		fprintf(fp, "%lx\n", (ulong)tt->refresh_task_table);
- 
-@@ -7090,6 +7364,9 @@ dump_task_table(int verbose)
-         if (tt->flags & PID_HASH)
-                 sprintf(&buf[strlen(buf)], 
- 			"%sPID_HASH", others++ ? "|" : "");
-+	if (tt->flags & PID_RADIX_TREE)
-+		sprintf(&buf[strlen(buf)],
-+			"%sPID_RADIX_TREE", others++ ? "|" : "");
-         if (tt->flags & THREAD_INFO)
-                 sprintf(&buf[strlen(buf)], 
- 			"%sTHREAD_INFO", others++ ? "|" : "");
-@@ -7122,6 +7399,8 @@ dump_task_table(int verbose)
- 	fprintf(fp, "          task_end: %lx\n",  tt->task_end);
- 	fprintf(fp, "        task_local: %lx\n",  (ulong)tt->task_local);
- 	fprintf(fp, "         max_tasks: %d\n", tt->max_tasks);
-+	fprintf(fp, "    pid_radix_tree: %lx\n", tt->pid_radix_tree);
-+	fprintf(fp, "         callbacks: %d\n", tt->callbacks);
- 	fprintf(fp, "        nr_threads: %d\n", tt->nr_threads);
- 	fprintf(fp, "     running_tasks: %ld\n", tt->running_tasks);
- 	fprintf(fp, "           retries: %ld\n", tt->retries);
-
-commit a94b86e9eb3faa963a7c20517574d230837a4292
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Tue Nov 28 12:12:50 2017 -0500
-
-    Fix for the "net" command when the network device listing has an
-    unusually large number of IP addresses.  In that case, without the
-    patch, the command may generate a segmentation violation.
-    (k-hagio@ab.jp.nec.com)
-
-diff --git a/net.c b/net.c
-index bb86963..4199091 100644
---- a/net.c
-+++ b/net.c
-@@ -70,7 +70,7 @@ static void show_net_devices_v3(ulong);
- static void print_neighbour_q(ulong, int);
- static void get_netdev_info(ulong, struct devinfo *);
- static void get_device_name(ulong, char *);
--static void get_device_address(ulong, char *);
-+static long get_device_address(ulong, char **, long);
- static void get_sock_info(ulong, char *);
- static void dump_arp(void);
- static void arp_state_to_flags(unsigned char);
-@@ -441,7 +441,8 @@ show_net_devices(ulong task)
- {
- 	ulong next;
- 	long flen;
--	char buf[BUFSIZE];
-+	char *buf;
-+	long buflen = BUFSIZE;
- 
- 	if (symbol_exists("dev_base_head")) {
- 		show_net_devices_v2(task);
-@@ -459,6 +460,7 @@ show_net_devices(ulong task)
- 	if (!net->netdevice || !next)
- 		return;
- 
-+	buf = GETBUF(buflen);
- 	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
- 
- 	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
-@@ -472,12 +474,14 @@ show_net_devices(ulong task)
- 		get_device_name(next, buf);
- 		fprintf(fp, "%-6s ", buf);
- 
--		get_device_address(next, buf);
-+		buflen = get_device_address(next, &buf, buflen);
- 		fprintf(fp, "%s\n", buf);
- 
-         	readmem(next+net->dev_next, KVADDR, &next, 
- 			sizeof(void *), "(net_)device.next", FAULT_ON_ERROR);
- 	} while (next);
-+
-+	FREEBUF(buf);
- }
- 
- static void
-@@ -485,13 +489,15 @@ show_net_devices_v2(ulong task)
- {
- 	struct list_data list_data, *ld;
- 	char *net_device_buf;
--	char buf[BUFSIZE];
-+	char *buf;
-+	long buflen = BUFSIZE;
- 	int ndevcnt, i;
- 	long flen;
- 
- 	if (!net->netdevice) /* initialized in net_init() */
- 		return;
- 
-+	buf = GETBUF(buflen);
- 	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
- 
- 	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
-@@ -521,12 +527,13 @@ show_net_devices_v2(ulong task)
- 		get_device_name(ld->list_ptr[i], buf);
- 		fprintf(fp, "%-6s ", buf);
- 
--		get_device_address(ld->list_ptr[i], buf);
-+		buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
- 		fprintf(fp, "%s\n", buf);
- 	}
- 	
- 	FREEBUF(ld->list_ptr);
- 	FREEBUF(net_device_buf);
-+	FREEBUF(buf);
- }
- 
- static void
-@@ -535,13 +542,15 @@ show_net_devices_v3(ulong task)
- 	ulong nsproxy_p, net_ns_p;
- 	struct list_data list_data, *ld;
- 	char *net_device_buf;
--	char buf[BUFSIZE];
-+	char *buf;
-+	long buflen = BUFSIZE;
- 	int ndevcnt, i;
- 	long flen;
- 
- 	if (!net->netdevice) /* initialized in net_init() */
- 		return;
- 
-+	buf = GETBUF(buflen);
- 	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
- 
- 	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
-@@ -581,12 +590,13 @@ show_net_devices_v3(ulong task)
- 		get_device_name(ld->list_ptr[i], buf);
- 		fprintf(fp, "%-6s ", buf);
- 
--		get_device_address(ld->list_ptr[i], buf);
-+		buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
- 		fprintf(fp, "%s\n", buf);
- 	}
- 	
- 	FREEBUF(ld->list_ptr);
- 	FREEBUF(net_device_buf);
-+	FREEBUF(buf);
- }
- 
- /*
-@@ -869,19 +879,24 @@ get_device_name(ulong devaddr, char *buf)
-  *  in_ifaddr->ifa_next points to the next in_ifaddr in the list (if any).
-  * 
-  */
--static void
--get_device_address(ulong devaddr, char *buf)
-+static long
-+get_device_address(ulong devaddr, char **bufp, long buflen)
- {
- 	ulong ip_ptr, ifa_list;
- 	struct in_addr ifa_address;
-+	char *buf;
-+	char buf2[BUFSIZE];
-+	long pos = 0;
- 
--	BZERO(buf, BUFSIZE);
-+	buf = *bufp;
-+	BZERO(buf, buflen);
-+	BZERO(buf2, BUFSIZE);
- 
-         readmem(devaddr + net->dev_ip_ptr, KVADDR,
-         	&ip_ptr, sizeof(ulong), "ip_ptr", FAULT_ON_ERROR);
- 
- 	if (!ip_ptr)
--		return;
-+		return buflen;
- 
-         readmem(ip_ptr + OFFSET(in_device_ifa_list), KVADDR,
-         	&ifa_list, sizeof(ulong), "ifa_list", FAULT_ON_ERROR);
-@@ -891,13 +906,20 @@ get_device_address(ulong devaddr, char *buf)
-         		&ifa_address, sizeof(struct in_addr), "ifa_address", 
- 			FAULT_ON_ERROR);
- 
--		sprintf(&buf[strlen(buf)], "%s%s", 
--			strlen(buf) ? ", " : "",
--			inet_ntoa(ifa_address));
-+		sprintf(buf2, "%s%s", pos ? ", " : "", inet_ntoa(ifa_address));
-+		if (pos + strlen(buf2) >= buflen) {
-+			RESIZEBUF(*bufp, buflen, buflen * 2);
-+			buf = *bufp;
-+			BZERO(buf + buflen, buflen);
-+			buflen *= 2;
-+		}
-+		BCOPY(buf2, &buf[pos], strlen(buf2));
-+		pos += strlen(buf2);
- 
-         	readmem(ifa_list + OFFSET(in_ifaddr_ifa_next), KVADDR,
-         		&ifa_list, sizeof(ulong), "ifa_next", FAULT_ON_ERROR);
- 	}
-+	return buflen;
- }
- 
- /*
-
-commit 264f22dafe9f37780c4113fd08e8d5b2138edbce
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Wed Nov 29 15:28:41 2017 -0500
-
-    Fix for Linux 4.15 and later kernels that are configured with
-    CONFIG_SPARSEMEM_EXTREME, and that contain kernel commit
-    83e3c48729d9ebb7af5a31a504f3fd6aff0348c4, titled "mm/sparsemem:
-    Allocate mem_section at runtime for CONFIG_SPARSEMEM_EXTREME=y".
-    Without the patch, kernels configured with SPARSEMEM_EXTREME
-    have changed the data type of "mem_section" from an array to
-    a pointer, leading to errors in commands such as "kmem -p",
-    "kmem -n", "kmem -s", and any other command that translates a
-    physical address to its page struct address.
-    (anderson@redhat.com)
-
-diff --git a/memory.c b/memory.c
-index 7537c43..0df8ecc 100644
---- a/memory.c
-+++ b/memory.c
-@@ -16928,7 +16928,7 @@ sparse_mem_init(void)
- {
- 	ulong addr;
- 	ulong mem_section_size;
--	int len, dimension;
-+	int len, dimension, mem_section_is_ptr;
- 
- 	if (!IS_SPARSEMEM())
- 		return;
-@@ -16940,8 +16940,19 @@ sparse_mem_init(void)
- 		error(FATAL, 
- 		    "CONFIG_SPARSEMEM kernels not supported for this architecture\n");
- 
-+	/*
-+	 *  The kernel's mem_section changed from array to pointer in this commit:
-+	 *
-+	 *   commit 83e3c48729d9ebb7af5a31a504f3fd6aff0348c4
-+	 *   mm/sparsemem: Allocate mem_section at runtime for CONFIG_SPARSEMEM_EXTREME=y
-+	 */
-+	mem_section_is_ptr = 
-+		get_symbol_type("mem_section", NULL, NULL) == TYPE_CODE_PTR ? 
-+			TRUE : FALSE;
-+
- 	if (((len = get_array_length("mem_section", &dimension, 0)) ==
--	    (NR_MEM_SECTIONS() / _SECTIONS_PER_ROOT_EXTREME())) || !dimension)
-+	    (NR_MEM_SECTIONS() / _SECTIONS_PER_ROOT_EXTREME())) || 
-+	    mem_section_is_ptr || !dimension)
- 		vt->flags |= SPARSEMEM_EX;
- 
- 	if (IS_SPARSEMEM_EX()) {
-@@ -16960,7 +16971,7 @@ sparse_mem_init(void)
- 		fprintf(fp, "SECTIONS_PER_ROOT = %ld\n", SECTIONS_PER_ROOT() );
- 		fprintf(fp, "SECTION_ROOT_MASK = 0x%lx\n", SECTION_ROOT_MASK());
- 		fprintf(fp, "PAGES_PER_SECTION = %ld\n", PAGES_PER_SECTION());
--		if (IS_SPARSEMEM_EX() && !len)
-+		if (!mem_section_is_ptr && IS_SPARSEMEM_EX() && !len)
- 			error(WARNING, "SPARSEMEM_EX: questionable section values\n");
- 	}
- 
-@@ -16969,8 +16980,12 @@ sparse_mem_init(void)
- 	if (!(vt->mem_section = (char *)malloc(SIZE(mem_section))))
- 		error(FATAL, "cannot malloc mem_section cache\n");
- 
--	addr = symbol_value("mem_section");
--	readmem(addr, KVADDR,vt->mem_sec ,mem_section_size,
-+	if (mem_section_is_ptr)
-+		get_symbol_data("mem_section", sizeof(void *), &addr);
-+	else
-+		addr = symbol_value("mem_section");
-+
-+	readmem(addr, KVADDR, vt->mem_sec, mem_section_size,
- 		"memory section root table", FAULT_ON_ERROR);
- }
- 
-
-commit ed2abb47be9846be7a47d769c420ee3992cc0196
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Wed Dec 13 11:18:05 2017 -0500
-
-    With the latest PPC64 NMI IPI changes, crash_ipi_callback is found
-    multiple times on the stack of active non-panic tasks.  Ensure that
-    the symbol reference relates to an actual backtrace stack frame.
-    (hbathini@linux.vnet.ibm.com)
-
-diff --git a/ppc64.c b/ppc64.c
-index 672ee60..0b04187 100644
---- a/ppc64.c
-+++ b/ppc64.c
-@@ -2337,6 +2337,14 @@ retry:
-                         *nip = *up;
-                         *ksp = bt->stackbase + 
- 				((char *)(up) - 16 - bt->stackbuf);
-+			/*
-+			 * Check whether this symbol relates to a
-+			 * backtrace or not
-+			 */
-+			ur_ksp =  *(ulong *)&bt->stackbuf[(*ksp) - bt->stackbase];
-+			if (!INSTACK(ur_ksp, bt))
-+				continue;
-+
-                         return TRUE;
-                 }
- 	}
-
-commit b6c0fc74fa58d48a0b6801de790e86db1130d22f
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Tue Jan 2 10:07:18 2018 -0500
-
-    Update the starting virtual address of vmalloc space for kernels
-    configured with CONFIG_X86_5LEVEL.
-    (douly.fnst@cn.fujitsu.com)
-
-diff --git a/defs.h b/defs.h
-index ba9abad..4cd07b8 100644
---- a/defs.h
-+++ b/defs.h
-@@ -3316,7 +3316,7 @@ struct arm64_stackframe {
- 
- #define USERSPACE_TOP_5LEVEL       0x0100000000000000
- #define PAGE_OFFSET_5LEVEL         0xff10000000000000
--#define VMALLOC_START_ADDR_5LEVEL  0xff92000000000000
-+#define VMALLOC_START_ADDR_5LEVEL  0xffa0000000000000
- #define VMALLOC_END_5LEVEL         0xffd1ffffffffffff
- #define MODULES_VADDR_5LEVEL       0xffffffffa0000000
- #define MODULES_END_5LEVEL         0xffffffffff5fffff
-
-commit cff3f2076ab52b9d6bae2b516fe3de32cccdb830
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Tue Jan 2 10:29:54 2018 -0500
-
-    Update the X86_64 VSYSCALL_END address to reflect that it only
-    contains 1 page.
-    (douly.fnst@cn.fujitsu.com)
-
-diff --git a/defs.h b/defs.h
-index 4cd07b8..97738a6 100644
---- a/defs.h
-+++ b/defs.h
-@@ -3324,7 +3324,7 @@ struct arm64_stackframe {
- #define VMEMMAP_END_5LEVEL         0xffd5ffffffffffff
- 
- #define VSYSCALL_START             0xffffffffff600000
--#define VSYSCALL_END               0xffffffffffe00000
-+#define VSYSCALL_END               0xffffffffff601000
- 
- #define PTOV(X)               ((unsigned long)(X)+(machdep->kvbase))
- #define VTOP(X)               x86_64_VTOP((ulong)(X))
-
-commit 3fe2663be5c6a5b160025a5a65b655a570e7e79e
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Thu Jan 4 12:54:19 2018 -0500
-
-    Prevent the X86_64 FILL_PML() macro from updating the internal
-    machdep->machspec->last_pml4_read address every time a vmalloc'd
-    kernel virtual address is translated.
-    (douly.fnst@cn.fujitsu.com)
-
-diff --git a/defs.h b/defs.h
-index 97738a6..9a33b41 100644
---- a/defs.h
-+++ b/defs.h
-@@ -3344,7 +3344,7 @@ struct arm64_stackframe {
- #define PTRS_PER_P4D         512
- 
- #define __PGDIR_SHIFT  (machdep->machspec->pgdir_shift)
-- 
-+
- #define pml4_index(address) (((address) >> PML4_SHIFT) & (PTRS_PER_PML4-1))
- #define p4d_index(address)  (((address) >> P4D_SHIFT) & (PTRS_PER_P4D - 1))
- #define pgd_index(address)  (((address) >> __PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-@@ -3353,26 +3353,24 @@ struct arm64_stackframe {
- 
- #define IS_LAST_PML4_READ(pml4) ((ulong)(pml4) == machdep->machspec->last_pml4_read)
- 
--#define FILL_PML4() { \
--	if (!(pc->flags & RUNTIME) || ACTIVE()) { \
--		if (!IS_LAST_PML4_READ(vt->kernel_pgd[0])) \
--                    readmem(vt->kernel_pgd[0], KVADDR, machdep->machspec->pml4, \
--                        PAGESIZE(), "init_level4_pgt", FAULT_ON_ERROR); \
--                machdep->machspec->last_pml4_read = (ulong)(vt->kernel_pgd[0]); \
--	} \
--}
-+#define FILL_PML4() 									\
-+	if (!(pc->flags & RUNTIME) || ACTIVE()) { 					\
-+		if (!IS_LAST_PML4_READ(vt->kernel_pgd[0])) { 				\
-+			readmem(vt->kernel_pgd[0], KVADDR, machdep->machspec->pml4, 	\
-+					PAGESIZE(), "init_level4_pgt", FAULT_ON_ERROR); \
-+			machdep->machspec->last_pml4_read = (ulong)(vt->kernel_pgd[0]); \
-+		} 									\
-+	}
- 
--#define FILL_PML4_HYPER() { \
--	if (!machdep->machspec->last_pml4_read) { \
--		unsigned long idle_pg_table = \
--		    symbol_exists("idle_pg_table_4") ? symbol_value("idle_pg_table_4") : \
--			symbol_value("idle_pg_table"); \
--		readmem(idle_pg_table, KVADDR, \
--			machdep->machspec->pml4, PAGESIZE(), "idle_pg_table", \
--			FAULT_ON_ERROR); \
--		machdep->machspec->last_pml4_read = idle_pg_table; \
--	}\
--}
-+#define FILL_PML4_HYPER() 								\
-+	if (!machdep->machspec->last_pml4_read) { 					\
-+		unsigned long idle_pg_table = symbol_exists("idle_pg_table_4") ? 	\
-+						symbol_value("idle_pg_table_4") : 	\
-+						symbol_value("idle_pg_table"); 	\
-+		readmem(idle_pg_table, KVADDR, machdep->machspec->pml4, PAGESIZE(), 	\
-+				"idle_pg_table", FAULT_ON_ERROR); 			\
-+		machdep->machspec->last_pml4_read = idle_pg_table; 			\
-+	}
- 
- #define IS_LAST_UPML_READ(pml) ((ulong)(pml) == machdep->machspec->last_upml_read)
- 
-
-commit 63419fb9a535732082ae7b542ebb2399e6a3ccc9
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Wed Jan 10 14:11:27 2018 -0500
-
-    Fix for the "bt" command in x86_64 kernels that contain, or have
-    backports of, kernel commit 4950d6d48a0c43cc61d0bbb76fb10e0214b79c66,
-    titled "x86/dumpstack: Remove 64-byte gap at end of irq stack".
-    Without the patch, backtraces fail to transition from the IRQ stack
-    back to the process stack, showing an error message such as
-    "bt: cannot transition exception stack to IRQ stack to current
-    process stack".
-    (anderson@redhat.com)
-
-diff --git a/crash.8 b/crash.8
-index 4b53f44..33af024 100644
---- a/crash.8
-+++ b/crash.8
-@@ -258,6 +258,7 @@ required in very rare circumstances:
- X86_64:
-   phys_base=<physical-address>
-   irq_eframe_link=<value>
-+  irq_stack_gap=<value>
-   max_physmem_bits=<value>
-   kernel_image_size=<value>
-   vm=orig       (pre-2.6.11 virtual memory address ranges)
-diff --git a/defs.h b/defs.h
-index 9a33b41..dcd6c26 100644
---- a/defs.h
-+++ b/defs.h
-@@ -1,8 +1,8 @@
- /* defs.h - core analysis suite
-  *
-  * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
-- * Copyright (C) 2002-2017 David Anderson
-- * Copyright (C) 2002-2017 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2002-2018 David Anderson
-+ * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
-  * Copyright (C) 2002 Silicon Graphics, Inc.
-  *
-  * This program is free software; you can redistribute it and/or modify
-@@ -5768,6 +5768,7 @@ struct machine_specific {
-         char *p4d;
- 	ulong last_p4d_read;
- 	struct ORC_data orc;
-+	ulong irq_stack_gap;
- };
- 
- #define KSYMS_START    (0x1)
-diff --git a/help.c b/help.c
-index e017b03..5b04b09 100644
---- a/help.c
-+++ b/help.c
-@@ -1,8 +1,8 @@
- /* help.c - core analysis suite
-  *
-  * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
-- * Copyright (C) 2002-2017 David Anderson
-- * Copyright (C) 2002-2017 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2002-2018 David Anderson
-+ * Copyright (C) 2002-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
-@@ -159,6 +159,7 @@ char *program_usage_info[] = {
-     "    X86_64:",
-     "      phys_base=<physical-address>",
-     "      irq_eframe_link=<value>",
-+    "      irq_stack_gap=<value>",
-     "      max_physmem_bits=<value>",
-     "      kernel_image_size=<value>",
-     "      vm=orig       (pre-2.6.11 virtual memory address ranges)",
-diff --git a/x86_64.c b/x86_64.c
-index 7d01140..d8fade4 100644
---- a/x86_64.c
-+++ b/x86_64.c
-@@ -1,7 +1,7 @@
- /* x86_64.c -- core analysis suite
-  *
-- * Copyright (C) 2004-2017 David Anderson
-- * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2004-2018 David Anderson
-+ * Copyright (C) 2004-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
-@@ -83,6 +83,7 @@ static void x86_64_init_kernel_pgd(void);
- static void x86_64_cpu_pda_init(void);
- static void x86_64_per_cpu_init(void);
- static void x86_64_ist_init(void);
-+static void x86_64_irq_stack_gap_init(void);
- static void x86_64_post_init(void);
- static void parse_cmdline_args(void);
- static void x86_64_clear_machdep_cache(void);
-@@ -181,6 +182,7 @@ x86_64_init(int when)
- 		machdep->flags |= MACHDEP_BT_TEXT;
- 		machdep->flags |= FRAMESIZE_DEBUG;
- 		machdep->machspec->irq_eframe_link = UNINITIALIZED;
-+		machdep->machspec->irq_stack_gap = UNINITIALIZED;
- 		machdep->get_kvaddr_ranges = x86_64_get_kvaddr_ranges;
-                 if (machdep->cmdline_args[0])
-                         parse_cmdline_args();
-@@ -638,6 +640,7 @@ x86_64_init(int when)
- 				MEMBER_OFFSET("cpu_user_regs", "cs") - sizeof(ulong);
-                 }
- 		x86_64_irq_eframe_link_init();
-+		x86_64_irq_stack_gap_init();
- 		x86_64_framepointer_init();
- 		x86_64_ORC_init();
- 		x86_64_thread_return_init();
-@@ -857,8 +860,6 @@ x86_64_dump_machdep_table(ulong arg)
- 		fprintf(fp, "            last_p4d_read: (unused)\n");
- 	}
- 
--	fprintf(fp, "                 irqstack: %lx\n", (ulong)ms->irqstack);
--	fprintf(fp, "          irq_eframe_link: %ld\n", ms->irq_eframe_link);
- 	fprintf(fp, "                 ORC_data: %s", machdep->flags & ORC ? "\n" : "(unused)\n");
- 	if (machdep->flags & ORC) {
- 		fprintf(fp, "                    module_ORC: %s\n", ms->orc.module_ORC ? "TRUE" : "FALSE");
-@@ -931,6 +932,9 @@ x86_64_dump_machdep_table(ulong arg)
- 	fprintf(fp, "            thread_return: %lx\n", ms->thread_return); 
- 	fprintf(fp, "            page_protnone: %lx\n", ms->page_protnone); 
- 
-+	fprintf(fp, "                 irqstack: %lx\n", (ulong)ms->irqstack);
-+	fprintf(fp, "          irq_eframe_link: %ld\n", ms->irq_eframe_link);
-+	fprintf(fp, "            irq_stack_gap: %ld\n", ms->irq_stack_gap);
- 	fprintf(fp, "                  stkinfo: isize: %d\n", 
- 		ms->stkinfo.isize);
- 	fprintf(fp, "                           esize[%d]: %d,%d,%d,%d,%d,%d,%d%s\n", 
-@@ -1338,6 +1342,71 @@ x86_64_ist_init(void)
- 	}
- }
- 
-+/*
-+ *  Determine whether the unused gap at the top of the IRQ stack exists,
-+ *  and store its size (either 0 or 64 bytes).
-+ */
-+static void 
-+x86_64_irq_stack_gap_init(void)
-+{
-+	int c, cpus;
-+	struct syment *sp;
-+	ulong irq_stack_ptr;
-+	struct machine_specific *ms = machdep->machspec;
-+	
-+	if (ms->irq_stack_gap != UNINITIALIZED)
-+		return;
-+
-+	if (THIS_KERNEL_VERSION >= LINUX(4,9,0)) {
-+		ms->irq_stack_gap = 0;
-+		return;
-+	}
-+
-+	ms->irq_stack_gap = 64;
-+
-+	/*
-+	 *  Check for backports of this commit:
-+	 *
-+	 *    commit 4950d6d48a0c43cc61d0bbb76fb10e0214b79c66
-+	 *    Author: Josh Poimboeuf <jpoimboe@redhat.com>
-+	 *    Date:   Thu Aug 18 10:59:08 2016 -0500
-+	 *
-+	 *        x86/dumpstack: Remove 64-byte gap at end of irq stack
-+	 */
-+
-+	if (!(sp = per_cpu_symbol_search("per_cpu__irq_stack_ptr")))
-+		return;
-+
-+	/*
-+	 *  CONFIG_SMP=n
-+	 */
-+	if (!(kt->flags & PER_CPU_OFF)) {
-+		get_symbol_data(sp->name, sizeof(ulong), &irq_stack_ptr);
-+		if ((irq_stack_ptr & 0xfff) == 0)
-+			ms->irq_stack_gap = 0;
-+		return;
-+	}
-+
-+	/*
-+	 *  Check the per-cpu irq_stack_ptr of the first possible cpu.
-+	 */
-+	if (!cpu_map_addr("possible"))
-+		return;
-+
-+	cpus = kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS;
-+	for (c = 0; c < cpus; c++) {
-+		if (!in_cpu_map(POSSIBLE, c))
-+			continue;
-+		if (readmem(sp->value + kt->__per_cpu_offset[c],
-+		    KVADDR, &irq_stack_ptr, sizeof(void *), "irq_stack_ptr",
-+		    QUIET|RETURN_ON_ERROR)) {
-+			if ((irq_stack_ptr & 0xfff) == 0)
-+				ms->irq_stack_gap = 0;
-+			break;
-+		}
-+	}
-+}
-+
- static void 
- x86_64_post_init(void)
- { 
-@@ -3352,7 +3421,7 @@ in_exception_stack:
-                     	error(FATAL, "read of IRQ stack at %lx failed\n",
- 				bt->stackbase);
- 
--		stacktop = bt->stacktop - 64; /* from kernel code */
-+		stacktop = bt->stacktop - ms->irq_stack_gap; 
- 
- 		bt->flags &= ~BT_FRAMESIZE_DISABLE;
- 
-@@ -3829,7 +3898,7 @@ in_exception_stack:
-                     	error(FATAL, "read of IRQ stack at %lx failed\n",
- 				bt->stackbase);
- 
--		stacktop = bt->stacktop - 64; /* from kernel code */
-+		stacktop = bt->stacktop - ms->irq_stack_gap;
- 
- 		if (!done) {
- 			level = dwarf_backtrace(bt, level, stacktop);
-@@ -5575,6 +5644,10 @@ x86_64_compiler_warning_stub(void)
-  *
-  *   --machdep irq_eframe_link=<offset>
-  *
-+ *  Force the IRQ stack gap size via:
-+ *
-+ *   --machdep irq_stack_gap=<size>
-+ *
-  *  Force max_physmem_bits via:
-  *
-  *   --machdep max_physmem_bits=<count>
-@@ -5704,6 +5777,15 @@ parse_cmdline_args(void)
- 						continue;
- 					}
- 				}
-+	                } else if (STRNEQ(arglist[i], "irq_stack_gap=")) {
-+	                        p = arglist[i] + strlen("irq_stack_gap=");
-+				if (strlen(p)) {
-+					value = stol(p, RETURN_ON_ERROR|QUIET, &errflag);
-+					if (!errflag) {
-+						machdep->machspec->irq_stack_gap = value;
-+						continue;
-+					}
-+				}
- 			} else if (STRNEQ(arglist[i], "max_physmem_bits=")) {
- 	                        p = arglist[i] + strlen("max_physmem_bits=");
- 				if (strlen(p)) {
diff --git a/SOURCES/github_5fe78861_ppc64_invalid_NIP.patch b/SOURCES/github_5fe78861_ppc64_invalid_NIP.patch
new file mode 100644
index 0000000..1b6a41e
--- /dev/null
+++ b/SOURCES/github_5fe78861_ppc64_invalid_NIP.patch
@@ -0,0 +1,207 @@
+commit 5fe78861ea1589084f6a2956a6ff63677c9269e1
+Author: Dave Anderson <anderson@redhat.com>
+Date:   Fri Sep 7 16:05:52 2018 -0400
+
+    Commit 3db3d3992d781c1e42587d2d2bf81e785408e0c2 in crash-7.1.8 was
+    aimed at making the PPC64 "bt" command work for dumpfiles saved
+    with the FADUMP facility, but it introduced a bit of unwarranted
+    complexity in "bt" command processing.  Reworked the "bt" command
+    processing for PPC64 arch to make it a little less compilated and
+    also to print symbols for NIP and LR registers in exception frames.
+    Without the patch, "bt" on non-panic active tasks may fail with
+    the message "bt: invalid kernel virtual address: <address>
+    type: Regs NIP value".
+    (hbathini@linux.ibm.com)
+
+diff --git a/ppc64.c b/ppc64.c
+index f5d0dac..03fecd3 100644
+--- a/ppc64.c
++++ b/ppc64.c
+@@ -2093,15 +2093,10 @@ ppc64_print_stack_entry(int frame,
+ 					lr);
+ 				return;
+ 			}
+-			if (req->pc != lr) {
+-				fprintf(fp, "\n%s[Link Register] ", 
+-					frame < 10 ? " " : "");
+-				fprintf(fp, "[%lx] %s at %lx",
+-					req->sp, lrname, lr);
+-			}
+ 			req->ra = lr;
+ 		}
+-		if (!req->name || STREQ(req->name,lrname)) 
++		if (!req->name || STREQ(req->name, lrname) ||
++		    !is_kernel_text(req->pc))
+ 			fprintf(fp, "  (unreliable)");
+ 		
+ 		fprintf(fp, "\n"); 
+@@ -2219,6 +2214,22 @@ ppc64_print_regs(struct ppc64_pt_regs *regs)
+         fprintf(fp, "    Syscall Result: %016lx\n", regs->result);
+ }
+ 
++static void ppc64_print_nip_lr(struct ppc64_pt_regs *regs, int print_lr)
++{
++	char buf[BUFSIZE];
++	char *sym_buf;
++
++	sym_buf = value_to_symstr(regs->nip, buf, 0);
++	if (sym_buf[0] != NULLCHAR)
++		fprintf(fp, " [NIP  : %s]\n", sym_buf);
++
++	if (print_lr) {
++		sym_buf = value_to_symstr(regs->link, buf, 0);
++		if (sym_buf[0] != NULLCHAR)
++			fprintf(fp, " [LR   : %s]\n", sym_buf);
++	}
++}
++
+ /*
+  * Print the exception frame information
+  */
+@@ -2231,6 +2242,59 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs *regs,
+ 
+ 	fprintf(fp, " %s [%lx] exception frame:\n", efrm_str, regs->trap);
+ 	ppc64_print_regs(regs);
++	ppc64_print_nip_lr(regs, 1);
++}
++
++/*
++ * For vmcore typically saved with KDump or FADump, get SP and IP values
++ * from the saved ptregs.
++ */
++static int
++ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
++{
++	struct ppc64_pt_regs *pt_regs;
++	unsigned long unip;
++
++	pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
++	if (!pt_regs || !pt_regs->gpr[1]) {
++		/*
++		 * Not collected regs. May be the corresponding CPU not
++		 * responded to an IPI in case of KDump OR f/w has not
++		 * not provided the register info in case of FADump.
++		 */
++		fprintf(fp, "%0lx: GPR1 register value (SP) was not saved\n",
++			bt_in->task);
++		return FALSE;
++	}
++	*ksp = pt_regs->gpr[1];
++	if (IS_KVADDR(*ksp)) {
++		readmem(*ksp+16, KVADDR, &unip, sizeof(ulong), "Regs NIP value",
++			FAULT_ON_ERROR);
++		*nip = unip;
++	} else {
++		if (IN_TASK_VMA(bt_in->task, *ksp))
++			fprintf(fp, "%0lx: Task is running in user space\n",
++				bt_in->task);
++		else
++			fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
++				bt_in->task, *ksp);
++		*nip = pt_regs->nip;
++	}
++
++	if (bt_in->flags &&
++	((BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_PRINT|BT_TEXT_SYMBOLS_NOPRINT)))
++		return TRUE;
++
++	/*
++	 * Print the collected regs for the active task
++	 */
++	ppc64_print_regs(pt_regs);
++	if (!IS_KVADDR(*ksp))
++		return FALSE;
++
++	ppc64_print_nip_lr(pt_regs, (unip != pt_regs->link) ? 1 : 0);
++
++	return TRUE;
+ }
+ 
+ /*
+@@ -2239,7 +2303,7 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs *regs,
+ static int
+ ppc64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
+ {
+-	int i;
++	int i, ret, panic_task;
+ 	char *sym;
+ 	ulong *up;
+ 	struct bt_info bt_local, *bt;
+@@ -2251,11 +2315,29 @@ ppc64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
+ 	struct ppc64_pt_regs *pt_regs;
+ 	struct syment *sp;
+ 
+-        bt = &bt_local;
+-        BCOPY(bt_in, bt, sizeof(struct bt_info));
+-        ms = machdep->machspec;
++	bt = &bt_local;
++	BCOPY(bt_in, bt, sizeof(struct bt_info));
++	ms = machdep->machspec;
++	ur_nip = ur_ksp = 0;
++
++	panic_task = tt->panic_task == bt->task ? TRUE : FALSE;
+ 
+ 	check_hardirq = check_softirq = tt->flags & IRQSTACKS ? TRUE : FALSE;
++	if (panic_task && bt->machdep) {
++		pt_regs = (struct ppc64_pt_regs *)bt->machdep;
++		ur_nip = pt_regs->nip;
++		ur_ksp = pt_regs->gpr[1];
++	} else if ((pc->flags & KDUMP) ||
++		   ((pc->flags & DISKDUMP) &&
++		    (*diskdump_flags & KDUMP_CMPRS_LOCAL))) {
++		/*
++		 * For the KDump or FADump vmcore, use SP and IP values
++		 * that are saved in ptregs.
++		 */
++		ret = ppc64_vmcore_stack_frame(bt_in, nip, ksp);
++		if (ret)
++			return TRUE;
++	}
+ 
+ 	if (bt->task != tt->panic_task) {
+ 		char cpu_frozen = FALSE;
+@@ -2385,38 +2467,14 @@ retry:
+ 		check_intrstack = FALSE;
+ 		goto retry;
+ 	}
+-
+ 	/*
+-	 * We didn't find what we were looking for, so try to use
+-	 * the SP and IP values saved in ptregs.
++	 *  We didn't find what we were looking for, so just use what was
++	 *  passed in the ELF header.
+ 	 */
+-	pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
+-	if (!pt_regs || !pt_regs->gpr[1]) {
+-		/*
+-		 * Not collected regs. May be the corresponding CPU did not
+-		 * respond to an IPI.
+-		 */
+-		if (CRASHDEBUG(1))
+-			fprintf(fp, "%0lx: GPR1(SP) register value not saved\n",
+-				bt_in->task);
+-	} else {
+-		*ksp = pt_regs->gpr[1];
+-		if (IS_KVADDR(*ksp)) {
+-			readmem(*ksp+16, KVADDR, nip, sizeof(ulong),
+-				"Regs NIP value", FAULT_ON_ERROR);
+-			ppc64_print_regs(pt_regs);
+-			return TRUE;
+-		} else {
+-			if (IN_TASK_VMA(bt_in->task, *ksp))
+-				fprintf(fp, "%0lx: Task is running in user space\n",
+-					bt_in->task);
+-			else
+-				fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
+-					bt_in->task, *ksp);
+-			*nip = pt_regs->nip;
+-			ppc64_print_regs(pt_regs);
+-			return FALSE;
+-		}
++	if (ur_nip && ur_ksp) {
++		*nip = ur_nip;
++		*ksp = ur_ksp;
++		return TRUE;
+ 	}
+ 
+         console("ppc64_get_dumpfile_stack_frame: cannot find SP for panic task\n");
diff --git a/SOURCES/github_7e393689_ppc64_bt_user_space.patch b/SOURCES/github_7e393689_ppc64_bt_user_space.patch
new file mode 100644
index 0000000..dfe886b
--- /dev/null
+++ b/SOURCES/github_7e393689_ppc64_bt_user_space.patch
@@ -0,0 +1,49 @@
+commit 7e3936895386ea6e85a6dc01bc5027f8133d12bb
+Author: Dave Anderson <anderson@redhat.com>
+Date:   Mon Sep 17 14:33:08 2018 -0400
+
+    An addendum to crash commit 5fe78861ea1589084f6a2956a6ff63677c9269e1,
+    this patch for the PPC64 "bt" command prevents an invalid error
+    message from being displayed when an active non-panic task is
+    interrupted while running in user space.  Without the patch, the
+    command correctly indicates "Task is running in user space", dumps
+    the user-space exception frame, but then prints the invalid error
+    message "bt: invalid kernel virtual address: ffffffffffffff90 type:
+    Regs NIP value".
+    (anderson@redhat.com)
+
+diff --git a/ppc64.c b/ppc64.c
+index 03fecd3..8badcde 100644
+--- a/ppc64.c
++++ b/ppc64.c
+@@ -2254,6 +2254,7 @@ ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
+ {
+ 	struct ppc64_pt_regs *pt_regs;
+ 	unsigned long unip;
++	int in_user_space = FALSE;
+ 
+ 	pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
+ 	if (!pt_regs || !pt_regs->gpr[1]) {
+@@ -2272,10 +2273,11 @@ ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
+ 			FAULT_ON_ERROR);
+ 		*nip = unip;
+ 	} else {
+-		if (IN_TASK_VMA(bt_in->task, *ksp))
++		if (IN_TASK_VMA(bt_in->task, *ksp)) {
+ 			fprintf(fp, "%0lx: Task is running in user space\n",
+ 				bt_in->task);
+-		else
++			in_user_space = TRUE;
++		} else
+ 			fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
+ 				bt_in->task, *ksp);
+ 		*nip = pt_regs->nip;
+@@ -2289,6 +2291,8 @@ ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
+ 	 * Print the collected regs for the active task
+ 	 */
+ 	ppc64_print_regs(pt_regs);
++	if (in_user_space)
++		return TRUE;
+ 	if (!IS_KVADDR(*ksp))
+ 		return FALSE;
+ 
diff --git a/SOURCES/github_9446958f_95daa11b_bpf_covscan.patch b/SOURCES/github_9446958f_95daa11b_bpf_covscan.patch
new file mode 100644
index 0000000..fb07782
--- /dev/null
+++ b/SOURCES/github_9446958f_95daa11b_bpf_covscan.patch
@@ -0,0 +1,45 @@
+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");
+
+commit 95daa11b82dfa6aa3e68ffc92e1282abc1b2b62a
+Author: Dave Anderson <anderson@redhat.com>
+Date:   Fri Jun 1 15:28:55 2018 -0400
+
+    Fix for the "bpf -t" option.  Although highly unlikely, without the
+    patch, the target function name of a BPF bytecode call instruction
+    may fail to be resolved correctly.
+    (anderson@redhat.com)
+
+diff --git a/bpf.c b/bpf.c
+index ee1986f..427263d 100644
+--- a/bpf.c
++++ b/bpf.c
+@@ -1060,8 +1060,7 @@ static char *__func_get_name(const struct bpf_insn *insn,
+ 		return buff;
+ 
+ 	if (insn->src_reg != BPF_PSEUDO_CALL &&
+-	    insn->imm >= 0 && insn->imm < __BPF_FUNC_MAX_ID &&
+-	    func_id_str[insn->imm]) {
++	    insn->imm >= 0 && insn->imm < __BPF_FUNC_MAX_ID) {
+ //              return func_id_str[insn->imm];
+ 		if (!readmem(symbol_value("func_id_str") + (insn->imm * sizeof(void *)), 
+ 		    KVADDR, &func_id_ptr, sizeof(void *), "func_id_str pointer", 
diff --git a/SOURCES/github_a38e3ec4_machine_kexec.patch b/SOURCES/github_a38e3ec4_machine_kexec.patch
deleted file mode 100644
index 1662ca4..0000000
--- a/SOURCES/github_a38e3ec4_machine_kexec.patch
+++ /dev/null
@@ -1,170 +0,0 @@
-commit a38e3ec4cb2692205d3af7483192077b1acfb199
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Fri Feb 9 14:58:34 2018 -0500
-
-    Fix for the ARM64 "bt" command running against Linux 4.14 and
-    later kernels.  Without the patch, the backtraces of the active
-    tasks in a kdump-generated dumpfile are truncated.  Without the
-    patch, the panic task will just show the "crash_kexec" frame
-    and the kernel-entry user-space exception frame; the non-panic
-    tasks will show their backtraces starting from the stackframe
-    addresses captured in the per-cpu NT_PRSTATUS notes, and will
-    not display the exception frame generated by the NMI callback,
-    nor any stackframes on the IRQ stack.
-    (anderson@redhat.com)
-
-
---- crash-7.2.0/defs.h.orig
-+++ crash-7.2.0/defs.h
-@@ -3137,6 +3137,8 @@ struct machine_specific {
- 	ulong user_eframe_offset;
- 	/* for v4.14 or later */
- 	ulong kern_eframe_offset;
-+	ulong machine_kexec_start;
-+	ulong machine_kexec_end;
- };
- 
- struct arm64_stackframe {
---- crash-7.2.0/arm64.c.orig
-+++ crash-7.2.0/arm64.c
-@@ -1,8 +1,8 @@
- /*
-  * arm64.c - core analysis suite
-  *
-- * Copyright (C) 2012-2017 David Anderson
-- * Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved.
-+ * Copyright (C) 2012-2018 David Anderson
-+ * Copyright (C) 2012-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
-@@ -633,6 +633,8 @@ arm64_dump_machdep_table(ulong arg)
-         	fprintf(fp, "%lx\n", ms->__SWP_OFFSET_MASK);
- 	else
- 		fprintf(fp, "(unused)\n");
-+	fprintf(fp, "   machine_kexec_start: %lx\n", ms->machine_kexec_start);
-+	fprintf(fp, "     machine_kexec_end: %lx\n", ms->machine_kexec_end);
- 	fprintf(fp, "     crash_kexec_start: %lx\n", ms->crash_kexec_start);
- 	fprintf(fp, "       crash_kexec_end: %lx\n", ms->crash_kexec_end);
- 	fprintf(fp, "  crash_save_cpu_start: %lx\n", ms->crash_save_cpu_start);
-@@ -1336,7 +1338,7 @@ arm64_irq_stack_init(void)
- 	struct syment *sp;
- 	struct gnu_request request, *req;
- 	struct machine_specific *ms = machdep->machspec;
--	ulong p;
-+	ulong p, sz;
- 	req = &request;
- 
- 	if (symbol_exists("irq_stack") &&
-@@ -1384,7 +1386,26 @@ arm64_irq_stack_init(void)
- 
- 		if (!(ms->irq_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
- 			error(FATAL, "cannot malloc irq_stack addresses\n");
--		ms->irq_stack_size = ARM64_IRQ_STACK_SIZE;
-+
-+		/*
-+		 *  Determining the IRQ_STACK_SIZE is tricky, but for now
-+		 *  4.14 kernel has:
-+		 *
-+		 *    #define IRQ_STACK_SIZE          THREAD_SIZE
-+		 *
-+		 *  and finding a solid usage of THREAD_SIZE is hard, but:   
-+		 *
-+		 *    union thread_union {
-+		 *            ... 
-+	         *            unsigned long stack[THREAD_SIZE/sizeof(long)];
-+		 *    };
-+		 */
-+		if (MEMBER_EXISTS("thread_union", "stack")) { 
-+			if ((sz = MEMBER_SIZE("thread_union", "stack")) > 0)
-+				ms->irq_stack_size = sz;
-+		} else
-+			ms->irq_stack_size = ARM64_IRQ_STACK_SIZE;
-+
- 		machdep->flags |= IRQ_STACKS;
- 
- 		for (i = 0; i < kt->cpus; i++) {
-@@ -1404,7 +1425,7 @@ arm64_stackframe_init(void)
- 	long task_struct_thread;
- 	long thread_struct_cpu_context;
- 	long context_sp, context_pc, context_fp;
--	struct syment *sp1, *sp1n, *sp2, *sp2n;
-+	struct syment *sp1, *sp1n, *sp2, *sp2n, *sp3, *sp3n;
- 
- 	STRUCT_SIZE_INIT(note_buf, "note_buf_t");
- 	STRUCT_SIZE_INIT(elf_prstatus, "elf_prstatus");
-@@ -1441,11 +1462,15 @@ arm64_stackframe_init(void)
- 	if ((sp1 = kernel_symbol_search("crash_kexec")) &&
- 	    (sp1n = next_symbol(NULL, sp1)) && 
- 	    (sp2 = kernel_symbol_search("crash_save_cpu")) &&
--	    (sp2n = next_symbol(NULL, sp2))) {
-+	    (sp2n = next_symbol(NULL, sp2)) &&
-+	    (sp3 = kernel_symbol_search("machine_kexec")) &&
-+	    (sp3n = next_symbol(NULL, sp3))) {
- 		machdep->machspec->crash_kexec_start = sp1->value;
- 		machdep->machspec->crash_kexec_end = sp1n->value;
- 		machdep->machspec->crash_save_cpu_start = sp2->value;
- 		machdep->machspec->crash_save_cpu_end = sp2n->value;
-+		machdep->machspec->machine_kexec_start = sp3->value;
-+		machdep->machspec->machine_kexec_end = sp3n->value;
- 		machdep->flags |= KDUMP_ENABLED;
- 	}
- 
-@@ -2592,6 +2617,7 @@ arm64_in_kdump_text(struct bt_info *bt,
- {
- 	ulong *ptr, *start, *base;
- 	struct machine_specific *ms;
-+	ulong crash_kexec_frame;
- 
- 	if (!(machdep->flags & KDUMP_ENABLED))
- 		return FALSE;
-@@ -2606,6 +2632,7 @@ arm64_in_kdump_text(struct bt_info *bt,
- 			start = (ulong *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(bt->stacktop))];
- 	}
- 
-+	crash_kexec_frame = 0;
- 	ms = machdep->machspec;
- 	for (ptr = start - 8; ptr >= base; ptr--) {
- 		if (bt->flags & BT_OPT_BACK_TRACE) {
-@@ -2628,13 +2655,27 @@ arm64_in_kdump_text(struct bt_info *bt,
- 				return TRUE;
- 			}
- 		} else {
--			if ((*ptr >= ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) {
-+			if ((*ptr >= ms->machine_kexec_start) && (*ptr < ms->machine_kexec_end)) {
- 				bt->bptr = ((ulong)ptr - (ulong)base)
- 					   + task_to_stackbase(bt->tc->task);
- 				if (CRASHDEBUG(1))
--					fprintf(fp, "%lx: %lx (crash_kexec)\n", bt->bptr, *ptr);
-+					fprintf(fp, "%lx: %lx (machine_kexec)\n", bt->bptr, *ptr);
- 				return TRUE;
- 			}
-+			if ((*ptr >= ms->crash_kexec_start) && (*ptr < ms->crash_kexec_end)) {
-+				/*
-+				 *  Stash the first crash_kexec frame in case the machine_kexec
-+				 *  frame is not found.
-+				 */
-+				if (!crash_kexec_frame) {
-+					crash_kexec_frame = ((ulong)ptr - (ulong)base)
-+						+ task_to_stackbase(bt->tc->task);
-+					if (CRASHDEBUG(1))
-+						fprintf(fp, "%lx: %lx (crash_kexec)\n", 
-+							bt->bptr, *ptr);
-+				}
-+				continue;
-+			}
- 			if ((*ptr >= ms->crash_save_cpu_start) && (*ptr < ms->crash_save_cpu_end)) {
- 				bt->bptr = ((ulong)ptr - (ulong)base)
- 					   + task_to_stackbase(bt->tc->task);
-@@ -2645,6 +2686,11 @@ arm64_in_kdump_text(struct bt_info *bt,
- 		}
- 	} 
- 
-+	if (crash_kexec_frame) {
-+		bt->bptr = crash_kexec_frame;
-+		return TRUE;
-+	}
-+
- 	return FALSE;
- }
- 
diff --git a/SOURCES/github_a6cd8408_mach-m.patch b/SOURCES/github_a6cd8408_mach-m.patch
new file mode 100644
index 0000000..a1aaa77
--- /dev/null
+++ b/SOURCES/github_a6cd8408_mach-m.patch
@@ -0,0 +1,223 @@
+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]);
+         }
+ }
diff --git a/SOURCES/github_b9d76838_c79a11fa_proc_kcore.patch b/SOURCES/github_b9d76838_c79a11fa_proc_kcore.patch
new file mode 100644
index 0000000..0d84189
--- /dev/null
+++ b/SOURCES/github_b9d76838_c79a11fa_proc_kcore.patch
@@ -0,0 +1,149 @@
+commit b9d76838372d1b4087bb506ce6da425afad68876
+Author: Dave Anderson <anderson@redhat.com>
+Date:   Thu Jun 7 13:20:16 2018 -0400
+
+    If /proc/kcore gets selected for the live memory source because
+    /dev/mem was configured with CONFIG_STRICT_DEVMEM, its ELF header
+    contents are not displayed by "help -[dD]", and are not displayed
+    when the crash session is invoked with -d<number>".  Without the
+    patch, the ELF contents are only displayed in those two situations
+    if "/proc/kcore" is explicitly entered on the crash command line.
+    (anderson@redhat.com)
+
+diff --git a/netdump.c b/netdump.c
+index 25683eb..1f3e26c 100644
+--- a/netdump.c
++++ b/netdump.c
+@@ -4334,11 +4334,8 @@ kcore_memory_dump(FILE *ofp)
+ 	Elf32_Phdr *lp32;
+ 	Elf64_Phdr *lp64;
+ 
+-	if (!(pkd->flags & KCORE_LOCAL))
+-		return FALSE;
+-
+ 	fprintf(ofp, "proc_kcore_data:\n");
+-	fprintf(ofp, "       flags: %lx (", nd->flags);
++	fprintf(ofp, "       flags: %x (", pkd->flags);
+ 	others = 0;
+ 	if (pkd->flags & KCORE_LOCAL)
+ 		fprintf(ofp, "%sKCORE_LOCAL", others++ ? "|" : "");
+commit c79a11fa10da94b71ddf341ec996c522fbd75237
+Author: Dave Anderson <anderson@redhat.com>
+Date:   Fri Jun 8 14:31:08 2018 -0400
+
+    If the default live memory source /dev/mem is determined to be
+    unusable because the kernel was configured with CONFIG_STRICT_DEVMEM,
+    the first memory read during session initialization will fail.  The
+    current behavior results in a readmem() error message, followed by two
+    notification messages that indicate that /dev/mem is restricted and
+    a switch to using /proc/kcore will be attempted; the readmem is
+    reattempted from /proc/kcore, and if successful, the session will
+    continue initialization.  With this patch, the behavior will change
+    such that if the switch to /proc/kcore and the reattempted readmem()
+    are successful, no messages will be displayed unless the crash
+    session is invoked with "crash -d&lt;number>".
+    (anderson@redhat.com)
+
+diff --git a/kernel.c b/kernel.c
+index 138a47f..3cd5bf1 100644
+--- a/kernel.c
++++ b/kernel.c
+@@ -882,7 +882,7 @@ cpu_maps_init(void)
+ {
+         int i, c, m, cpu, len;
+         char *buf;
+-        ulong *maskptr, addr;
++        ulong *maskptr, addr, error_handle;
+ 	struct mapinfo {
+ 		ulong cpu_flag;
+ 		char *name;
+@@ -902,8 +902,9 @@ cpu_maps_init(void)
+ 		if (!(addr = cpu_map_addr(mapinfo[m].name)))
+ 			continue;
+ 
++		error_handle = pc->flags & DEVMEM ? RETURN_ON_ERROR|QUIET : RETURN_ON_ERROR;
+ 		if (!readmem(addr, KVADDR, buf, len,
+-		    mapinfo[m].name, RETURN_ON_ERROR)) {
++		    mapinfo[m].name, error_handle)) {
+ 			error(WARNING, "cannot read cpu_%s_map\n",
+ 			      mapinfo[m].name);
+ 			continue;
+diff --git a/memory.c b/memory.c
+index 82f9cbf..2f568d5 100644
+--- a/memory.c
++++ b/memory.c
+@@ -2243,9 +2243,11 @@ readmem(ulonglong addr, int memtype, void *buffer, long size,
+ 				error(INFO, READ_ERRMSG, memtype_string(memtype, 0), addr, type);
+ 			if ((pc->flags & DEVMEM) && (kt->flags & PRE_KERNEL_INIT) &&
+ 			    !(error_handle & NO_DEVMEM_SWITCH) && devmem_is_restricted() && 
+-			    switch_to_proc_kcore())
++			    switch_to_proc_kcore()) {
++				error_handle &= ~QUIET;
+ 				return(readmem(addr, memtype, bufptr, size,
+ 					type, error_handle));
++			}
+ 			goto readmem_error;
+ 
+ 		case PAGE_EXCLUDED:
+@@ -2457,7 +2459,7 @@ devmem_is_restricted(void)
+ 		    QUIET|RETURN_ON_ERROR|NO_DEVMEM_SWITCH))
+ 			restricted = TRUE;
+ 
+-		if (restricted)
++		if (restricted && CRASHDEBUG(1))
+ 			error(INFO, 
+  	    		    "this kernel may be configured with CONFIG_STRICT_DEVMEM,"
+ 			    " which\n       renders /dev/mem unusable as a live memory "
+@@ -2472,9 +2474,10 @@ switch_to_proc_kcore(void)
+ {
+ 	close(pc->mfd);
+ 
+-	if (file_exists("/proc/kcore", NULL))
+-		error(INFO, "trying /proc/kcore as an alternative to /dev/mem\n\n");
+-	else
++	if (file_exists("/proc/kcore", NULL)) {
++		if (CRASHDEBUG(1))
++			error(INFO, "trying /proc/kcore as an alternative to /dev/mem\n\n");
++	} else
+ 		return FALSE;
+ 
+ 	if ((pc->mfd = open("/proc/kcore", O_RDONLY)) < 0) {
+diff --git a/ppc64.c b/ppc64.c
+index 0b04187..0dd8a2a 100644
+--- a/ppc64.c
++++ b/ppc64.c
+@@ -1,7 +1,7 @@
+ /* ppc64.c -- core analysis suite
+  *
+- * Copyright (C) 2004-2015,2017 David Anderson
+- * Copyright (C) 2004-2015,2017 Red Hat, Inc. All rights reserved.
++ * Copyright (C) 2004-2015,2018 David Anderson
++ * Copyright (C) 2004-2015,2018 Red Hat, Inc. All rights reserved.
+  * Copyright (C) 2004, 2006 Haren Myneni, IBM Corporation
+  *
+  * This program is free software; you can redistribute it and/or modify
+@@ -343,8 +343,9 @@ ppc64_init(int when)
+ 
+ 		if (symbol_exists("vmemmap_populate")) {
+ 			if (symbol_exists("vmemmap")) {
+-				get_symbol_data("vmemmap", sizeof(void *),
+-					&machdep->machspec->vmemmap_base);
++				readmem(symbol_value("vmemmap"), KVADDR,
++					&machdep->machspec->vmemmap_base,
++					sizeof(void *), "vmemmap", QUIET|FAULT_ON_ERROR);
+ 			} else
+ 				machdep->machspec->vmemmap_base =
+ 					VMEMMAP_REGION_ID << REGION_SHIFT;
+diff --git a/x86_64.c b/x86_64.c
+index 54b6539..e01082b 100644
+--- a/x86_64.c
++++ b/x86_64.c
+@@ -356,7 +356,7 @@ x86_64_init(int when)
+ 			machdep->flags |= RANDOMIZED;
+ 			readmem(symbol_value("page_offset_base"), KVADDR,
+ 				&machdep->machspec->page_offset, sizeof(ulong),
+-				"page_offset_base", FAULT_ON_ERROR);
++				"page_offset_base", QUIET|FAULT_ON_ERROR);
+ 			machdep->kvbase = machdep->machspec->page_offset;
+ 			machdep->identity_map_base = machdep->machspec->page_offset;
+ 		}
diff --git a/SOURCES/github_d833432f_kpti_trampoline.patch b/SOURCES/github_d833432f_kpti_trampoline.patch
deleted file mode 100644
index 6d15641..0000000
--- a/SOURCES/github_d833432f_kpti_trampoline.patch
+++ /dev/null
@@ -1,216 +0,0 @@
-commit d833432f1ed2d7f507c05d3b6c3e6aa732c49e56
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Fri Jan 19 14:17:53 2018 -0500
-
-    Initial pass for support of kernel page table isolation.  The x86_64
-    "bt" command may indicate "bt: cannot transition from exception stack
-    to current process stack" if the crash callback NMI occurred while an
-    active task was running on the new entry trampoline stack.  This has
-    only been tested on the RHEL7 backport of the upstream patch because
-    as of this commit, crash does not run on 4.15-rc kernels.  Further
-    changes may be required for upstream kernels, and distributions that
-    implement the kernel changes differently than upstream.
-    (anderson@redhat.com)
-
-diff --git a/defs.h b/defs.h
-index dcd6c26..4d2fb2f 100644
---- a/defs.h
-+++ b/defs.h
-@@ -5769,6 +5769,8 @@ struct machine_specific {
- 	ulong last_p4d_read;
- 	struct ORC_data orc;
- 	ulong irq_stack_gap;
-+	ulong kpti_entry_stack;
-+	ulong kpti_entry_stack_size;
- };
- 
- #define KSYMS_START    (0x1)
-@@ -5786,6 +5788,7 @@ struct machine_specific {
- #define RANDOMIZED  (0x1000)
- #define VM_5LEVEL   (0x2000)
- #define ORC         (0x4000)
-+#define KPTI        (0x8000)
- 
- #define VM_FLAGS (VM_ORIG|VM_2_6_11|VM_XEN|VM_XEN_RHEL4|VM_5LEVEL)
- 
-diff --git a/x86_64.c b/x86_64.c
-index d8fade4..e924ca9 100644
---- a/x86_64.c
-+++ b/x86_64.c
-@@ -48,6 +48,7 @@ static void x86_64_back_trace_cmd(struct bt_info *);
- static ulong x86_64_in_exception_stack(struct bt_info *, int *);
- static ulong x86_64_in_irqstack(struct bt_info *);
- static int x86_64_in_alternate_stack(int, ulong);
-+static ulong x86_64_in_kpti_entry_stack(int, ulong);
- static ulong __schedule_frame_adjust(ulong, struct bt_info *);
- static void x86_64_low_budget_back_trace_cmd(struct bt_info *);
- static void x86_64_dwarf_back_trace_cmd(struct bt_info *);
-@@ -84,6 +85,7 @@ static void x86_64_cpu_pda_init(void);
- static void x86_64_per_cpu_init(void);
- static void x86_64_ist_init(void);
- static void x86_64_irq_stack_gap_init(void);
-+static void x86_64_entry_trampoline_init(void);
- static void x86_64_post_init(void);
- static void parse_cmdline_args(void);
- static void x86_64_clear_machdep_cache(void);
-@@ -641,6 +643,7 @@ x86_64_init(int when)
-                 }
- 		x86_64_irq_eframe_link_init();
- 		x86_64_irq_stack_gap_init();
-+		x86_64_entry_trampoline_init();
- 		x86_64_framepointer_init();
- 		x86_64_ORC_init();
- 		x86_64_thread_return_init();
-@@ -722,6 +725,8 @@ x86_64_dump_machdep_table(ulong arg)
- 		fprintf(fp, "%sNESTED_NMI", others++ ? "|" : "");
- 	if (machdep->flags & RANDOMIZED)
- 		fprintf(fp, "%sRANDOMIZED", others++ ? "|" : "");
-+	if (machdep->flags & KPTI)
-+		fprintf(fp, "%sKPTI", others++ ? "|" : "");
-         fprintf(fp, ")\n");
- 
- 	fprintf(fp, "             kvbase: %lx\n", machdep->kvbase);
-@@ -973,7 +978,18 @@ x86_64_dump_machdep_table(ulong arg)
- 			fprintf(fp, "\n   ");
- 		fprintf(fp, "%016lx ", ms->stkinfo.ibase[c]);
- 	}
--	fprintf(fp, "\n");
-+	fprintf(fp, "\n                 kpti_entry_stack_size: %ld", ms->kpti_entry_stack_size);
-+	fprintf(fp, "\n                      kpti_entry_stack: ");
-+	if (machdep->flags & KPTI) {
-+		fprintf(fp, "%lx\n   ", ms->kpti_entry_stack);
-+		for (c = 0; c < cpus; c++) {
-+			if (c && !(c%4))
-+				fprintf(fp, "\n   ");
-+			fprintf(fp, "%016lx ", ms->kpti_entry_stack + kt->__per_cpu_offset[c]);
-+		}
-+		fprintf(fp, "\n");
-+	} else
-+		fprintf(fp, "(unused)\n");
- }
- 
- /*
-@@ -3147,7 +3163,7 @@ x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in)
- 	struct syment *sp, *spt;
- 	FILE *ofp;
- 	ulong estack, irqstack;
--	ulong irq_eframe;
-+	ulong irq_eframe, kpti_eframe;
- 	struct bt_info bt_local, *bt;
- 	struct machine_specific *ms;
- 	ulong last_process_stack_eframe;
-@@ -3493,6 +3509,16 @@ in_exception_stack:
- 		bt->stacktop = GET_STACKTOP(bt->tc->task);
- 
- 		if (!INSTACK(rsp, bt)) {
-+			/*
-+			 *  If the exception occurred while on the KPTI entry trampoline stack,
-+			 *  just print the entry exception frame and bail out.
-+			 */
-+			if ((kpti_eframe = x86_64_in_kpti_entry_stack(bt->tc->processor, rsp))) {
-+				x86_64_exception_frame(EFRAME_PRINT, kpti_eframe, 0, bt, ofp);
-+				fprintf(fp, "--- <entry trampoline stack> ---\n");
-+				return;
-+			}
-+
- 			switch (bt->flags & (BT_EXCEPTION_STACK|BT_IRQSTACK))
- 			{
- 			case (BT_EXCEPTION_STACK|BT_IRQSTACK):
-@@ -3720,7 +3746,7 @@ x86_64_dwarf_back_trace_cmd(struct bt_info *bt_in)
- 	struct syment *sp;
- 	FILE *ofp;
- 	ulong estack, irqstack;
--	ulong irq_eframe;
-+	ulong irq_eframe, kpti_eframe;
- 	struct bt_info bt_local, *bt;
- 	struct machine_specific *ms;
- 	ulong last_process_stack_eframe;
-@@ -3940,6 +3966,16 @@ in_exception_stack:
- 		bt->stacktop = GET_STACKTOP(bt->tc->task);
- 
- 		if (!INSTACK(rsp, bt)) {
-+			/*
-+			 *  If the exception occurred while on the KPTI entry trampoline stack,
-+			 *  just print the entry exception frame and bail out.
-+			 */
-+			if ((kpti_eframe = x86_64_in_kpti_entry_stack(bt->tc->processor, rsp))) {
-+				x86_64_exception_frame(EFRAME_PRINT, kpti_eframe, 0, bt, ofp);
-+				fprintf(fp, "--- <ENTRY TRAMPOLINE stack> ---\n");
-+				return;
-+			}
-+
- 			switch (bt->flags & (BT_EXCEPTION_STACK|BT_IRQSTACK))
- 			{
- 			case (BT_EXCEPTION_STACK|BT_IRQSTACK):
-@@ -8661,4 +8697,71 @@ next_in_func:
- 			goto next_in_func;
- }
- 
-+/*
-+ *  KPTI entry stack initialization.  May vary signficantly
-+ *  between upstream and distribution backports.
-+ */
-+static void 
-+x86_64_entry_trampoline_init(void)
-+{
-+	struct machine_specific *ms;
-+	struct syment *sp;
-+
-+	ms = machdep->machspec;
-+
-+	if (!kernel_symbol_exists("pti_init") &&
-+	    !kernel_symbol_exists("kaiser_init"))
-+		return;
-+
-+	/*
-+	 *  4.15
-+	 */
-+	if (MEMBER_EXISTS("entry_stack", "words") && 
-+	    MEMBER_EXISTS("entry_stack_page", "stack") &&
-+	    (sp = per_cpu_symbol_search("per_cpu__entry_stack_storage"))) {
-+		ms->kpti_entry_stack = sp->value + MEMBER_OFFSET("entry_stack_page", "stack");
-+		ms->kpti_entry_stack_size = MEMBER_SIZE("entry_stack", "words");
-+		machdep->flags |= KPTI;
-+		return;
-+	}
-+
-+	/* 
-+	 *  RHEL
-+	 */
-+	if (MEMBER_EXISTS("tss_struct", "stack")) {
-+		if (!(sp = per_cpu_symbol_search("per_cpu__init_tss")))
-+			sp = per_cpu_symbol_search("per_cpu__cpu_tss");
-+		ms->kpti_entry_stack = sp->value + MEMBER_OFFSET("tss_struct", "stack");
-+		ms->kpti_entry_stack_size = MEMBER_SIZE("tss_struct", "stack");
-+		machdep->flags |= KPTI;
-+		return;
-+	}
-+}
-+
-+static ulong
-+x86_64_in_kpti_entry_stack(int cpu, ulong rsp)
-+{
-+	ulong stack_base, stack_end;
-+	struct machine_specific *ms;
-+
-+	if (!(machdep->flags & KPTI))
-+		return 0;
-+
-+	ms = machdep->machspec;
-+
-+	if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) {
-+		if (kt->__per_cpu_offset[cpu] == 0)
-+			return 0;
-+		stack_base = ms->kpti_entry_stack + kt->__per_cpu_offset[cpu];
-+	} else
-+		stack_base = ms->kpti_entry_stack; 
-+
-+	stack_end = stack_base + 
-+		(ms->kpti_entry_stack_size > 0 ? ms->kpti_entry_stack_size : 512);
-+
-+	if ((rsp >= stack_base) && (rsp < stack_end))
-+		return(stack_end - SIZE(pt_regs));
-+
-+	return 0;
-+}
- #endif  /* X86_64 */ 
diff --git a/SOURCES/github_da49e201_cpu_entry_area.patch b/SOURCES/github_da49e201_cpu_entry_area.patch
new file mode 100644
index 0000000..8829afb
--- /dev/null
+++ b/SOURCES/github_da49e201_cpu_entry_area.patch
@@ -0,0 +1,133 @@
+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 
diff --git a/SOURCES/github_da9bd35a_to_e2efacdd.patch b/SOURCES/github_da9bd35a_to_e2efacdd.patch
deleted file mode 100644
index 0c8bb82..0000000
--- a/SOURCES/github_da9bd35a_to_e2efacdd.patch
+++ /dev/null
@@ -1,2334 +0,0 @@
-commit da9bd35afc2269529b029dd22815e04362e89e5b
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Wed Oct 11 11:17:30 2017 -0400
-
-    Fix for the "runq" command on Linux 4.14 and later kernels that
-    contain commit cd9e61ed1eebbcd5dfad59475d41ec58d9b64b6a, titled
-    "rbtree: cache leftmost node internally".  Without the patch,
-    the command fails with the error message "runq: invalid structure
-    member offset: cfs_rq_rb_leftmost".
-    (anderson@redhat.com)
-
-diff --git a/task.c b/task.c
-index 88706bf..2b12af0 100644
---- a/task.c
-+++ b/task.c
-@@ -8765,10 +8765,15 @@ cfs_rq_offset_init(void)
- 		MEMBER_OFFSET_INIT(sched_rt_entity_my_q, "sched_rt_entity",
- 			"my_q");
- 		MEMBER_OFFSET_INIT(sched_entity_on_rq, "sched_entity", "on_rq");
--		MEMBER_OFFSET_INIT(cfs_rq_rb_leftmost, "cfs_rq", "rb_leftmost");
--		MEMBER_OFFSET_INIT(cfs_rq_nr_running, "cfs_rq", "nr_running");
- 		MEMBER_OFFSET_INIT(cfs_rq_tasks_timeline, "cfs_rq", 
- 			"tasks_timeline");
-+		MEMBER_OFFSET_INIT(cfs_rq_rb_leftmost, "cfs_rq", "rb_leftmost");
-+		if (INVALID_MEMBER(cfs_rq_rb_leftmost) && 
-+		    VALID_MEMBER(cfs_rq_tasks_timeline) &&
-+		    MEMBER_EXISTS("rb_root_cached", "rb_leftmost"))
-+			ASSIGN_OFFSET(cfs_rq_rb_leftmost) = OFFSET(cfs_rq_tasks_timeline) + 
-+				MEMBER_OFFSET("rb_root_cached", "rb_leftmost");
-+		MEMBER_OFFSET_INIT(cfs_rq_nr_running, "cfs_rq", "nr_running");
- 		MEMBER_OFFSET_INIT(cfs_rq_curr, "cfs_rq", "curr");
- 		MEMBER_OFFSET_INIT(rt_rq_active, "rt_rq", "active");
-                 MEMBER_OFFSET_INIT(task_struct_run_list, "task_struct",
-
-commit 9e5255af26233e7ef051ebdd8bdccbd15d0d9256
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Wed Oct 11 16:11:34 2017 -0400
-
-    Fix to prevent a useless message during session inialization.
-    Without the patch, if the highest possible node bit in the
-    node_states[N_ONLINE] multi-word bitmask is set, then a message
-    such as "crash: next_online_node: 256 is too large!" will be
-    displayed.
-    (anderson@redhat.com)
-
-diff --git a/memory.c b/memory.c
-index 8efe0b2..9c9a40d 100644
---- a/memory.c
-+++ b/memory.c
-@@ -17200,10 +17200,8 @@ next_online_node(int first)
- 	int i, j, node;
- 	ulong mask, *maskptr;
- 
--	if ((first/BITS_PER_LONG) >= vt->node_online_map_len) {
--		error(INFO, "next_online_node: %d is too large!\n", first);
-+	if ((first/BITS_PER_LONG) >= vt->node_online_map_len)
- 		return -1;
--	}
- 
- 	maskptr = (ulong *)vt->node_online_map;
- 	for (i = node = 0; i <  vt->node_online_map_len; i++, maskptr++) {
-
-commit 2b93c036edf2a5cc21a06a14f377cd9b365f858a
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Tue Oct 17 15:40:17 2017 -0400
-
-    Additional fixes for the ARM64 "bt" command for Linux 4.14 kernels.
-    The patch corrects the contents of in-kernel exception frame register
-    dumps, and properly transitions the backtrace from the IRQ stack
-    to the process stack.
-    (takahiro.akashi@linaro.org)
-
-diff --git a/arm64.c b/arm64.c
-index 20c5d34..c75669b 100644
---- a/arm64.c
-+++ b/arm64.c
-@@ -72,6 +72,7 @@ static void arm64_cmd_mach(void);
- static void arm64_display_machine_stats(void);
- static int arm64_get_smp_cpus(void);
- static void arm64_clear_machdep_cache(void);
-+static int arm64_on_process_stack(struct bt_info *, ulong);
- static int arm64_in_alternate_stack(int, ulong);
- static int arm64_on_irq_stack(int, ulong);
- static void arm64_set_irq_stack(struct bt_info *);
-@@ -1333,34 +1334,64 @@ arm64_irq_stack_init(void)
- 	int i;
- 	struct syment *sp;
- 	struct gnu_request request, *req;
--	req = &request;
- 	struct machine_specific *ms = machdep->machspec;
-+	ulong p;
-+	req = &request;
- 
--	if (!symbol_exists("irq_stack") ||
--	    !(sp = per_cpu_symbol_search("irq_stack")) ||
--	    !get_symbol_type("irq_stack", NULL, req) ||
--	    (req->typecode != TYPE_CODE_ARRAY) ||
--	    (req->target_typecode != TYPE_CODE_INT))
--		return;
--
--	if (CRASHDEBUG(1)) {
--		fprintf(fp, "irq_stack: \n");
--		fprintf(fp, "  type: %s\n", 
--			(req->typecode == TYPE_CODE_ARRAY) ? "TYPE_CODE_ARRAY" : "other");
--		fprintf(fp, "  target_typecode: %s\n", 
--			req->target_typecode == TYPE_CODE_INT ? "TYPE_CODE_INT" : "other");
--		fprintf(fp, "  target_length: %ld\n", req->target_length);
--		fprintf(fp, "  length: %ld\n", req->length);
--	}
--
--	ms->irq_stack_size = req->length;
--	if (!(ms->irq_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
--		error(FATAL, "cannot malloc irq_stack addresses\n");
-+	if (symbol_exists("irq_stack") &&
-+	    (sp = per_cpu_symbol_search("irq_stack")) &&
-+	    get_symbol_type("irq_stack", NULL, req)) {
-+		/* before v4.14 or CONFIG_VMAP_STACK disabled */
-+		if (CRASHDEBUG(1)) {
-+			fprintf(fp, "irq_stack: \n");
-+			fprintf(fp, "  type: %s\n",
-+				(req->typecode == TYPE_CODE_ARRAY) ?
-+						"TYPE_CODE_ARRAY" : "other");
-+			fprintf(fp, "  target_typecode: %s\n",
-+				req->target_typecode == TYPE_CODE_INT ?
-+						"TYPE_CODE_INT" : "other");
-+			fprintf(fp, "  target_length: %ld\n",
-+						req->target_length);
-+			fprintf(fp, "  length: %ld\n", req->length);
-+		}
-+
-+		if (!(ms->irq_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
-+			error(FATAL, "cannot malloc irq_stack addresses\n");
-+		ms->irq_stack_size = req->length;
-+		machdep->flags |= IRQ_STACKS;
- 
--	for (i = 0; i < kt->cpus; i++)
--		ms->irq_stacks[i] = kt->__per_cpu_offset[i] + sp->value;
-+		for (i = 0; i < kt->cpus; i++)
-+			ms->irq_stacks[i] = kt->__per_cpu_offset[i] + sp->value;
-+	} else if (symbol_exists("irq_stack_ptr") &&
-+	    (sp = per_cpu_symbol_search("irq_stack_ptr")) &&
-+	    get_symbol_type("irq_stack_ptr", NULL, req)) {
-+		/* v4.14 and later with CONFIG_VMAP_STACK enabled */
-+		if (CRASHDEBUG(1)) {
-+			fprintf(fp, "irq_stack_ptr: \n");
-+			fprintf(fp, "  type: %x, %s\n",
-+				(int)req->typecode,
-+				(req->typecode == TYPE_CODE_PTR) ?
-+						"TYPE_CODE_PTR" : "other");
-+			fprintf(fp, "  target_typecode: %x, %s\n",
-+				(int)req->target_typecode,
-+				req->target_typecode == TYPE_CODE_INT ?
-+						"TYPE_CODE_INT" : "other");
-+			fprintf(fp, "  target_length: %ld\n",
-+						req->target_length);
-+			fprintf(fp, "  length: %ld\n", req->length);
-+		}
-+
-+		if (!(ms->irq_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
-+			error(FATAL, "cannot malloc irq_stack addresses\n");
-+		ms->irq_stack_size = 16384;
-+		machdep->flags |= IRQ_STACKS;
- 
--	machdep->flags |= IRQ_STACKS;
-+		for (i = 0; i < kt->cpus; i++) {
-+			p = kt->__per_cpu_offset[i] + sp->value;
-+			readmem(p, KVADDR, &(ms->irq_stacks[i]), sizeof(ulong),
-+			    "IRQ stack pointer", RETURN_ON_ERROR);
-+		}
-+	} 
- }
- 
- /*
-@@ -1750,11 +1781,20 @@ arm64_display_full_frame(struct bt_info *bt, ulong sp)
- 	if (bt->frameptr == sp)
- 		return;
- 
--	if (!INSTACK(sp, bt) || !INSTACK(bt->frameptr, bt)) {
--		if (sp == 0)
--			sp = bt->stacktop - USER_EFRAME_OFFSET;
--		else
--			return;
-+	if (INSTACK(bt->frameptr, bt)) {
-+		if (INSTACK(sp, bt)) {
-+			; /* normal case */
-+		} else {
-+			if (sp == 0)
-+				/* interrupt in user mode */
-+				sp = bt->stacktop - USER_EFRAME_OFFSET;
-+			else
-+				/* interrupt in kernel mode */
-+				sp = bt->stacktop;
-+		}
-+	} else { 
-+		/* IRQ exception frame */
-+		return;
- 	}
- 
- 	words = (sp - bt->frameptr) / sizeof(ulong);
-@@ -1860,6 +1900,9 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
- 	if ((frame->fp == 0) && (frame->pc == 0))
- 		return FALSE;
- 
-+	if (!(machdep->flags & IRQ_STACKS))
-+		return TRUE;
-+
- 	/*
- 	 * The kernel's manner of determining the end of the IRQ stack:
- 	 *
-@@ -1872,7 +1915,25 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
- 	 *  irq_stack_ptr = IRQ_STACK_PTR(raw_smp_processor_id());
- 	 *  orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr);   (pt_regs pointer on process stack)
- 	 */
--	if (machdep->flags & IRQ_STACKS) {
-+	if (machdep->flags & UNW_4_14) {
-+		if ((bt->flags & BT_IRQSTACK) &&
-+		    !arm64_on_irq_stack(bt->tc->processor, frame->fp)) {
-+			if (arm64_on_process_stack(bt, frame->fp)) {
-+				arm64_set_process_stack(bt);
-+
-+				frame->sp = frame->fp - SIZE(pt_regs) + 16;
-+				/* for switch_stack */
-+				/* fp still points to irq stack */
-+				bt->bptr = fp;
-+				/* for display_full_frame */
-+				/* sp points to process stack */
-+				bt->frameptr = frame->sp;
-+			} else {
-+				/* irq -> user */
-+				return FALSE;
-+			}
-+		}
-+	} else { /* !UNW_4_14 */
- 		ms = machdep->machspec;
- 		irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size - 16;
- 
-@@ -1896,7 +1957,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
- 				return FALSE;
- 			}
- 		}
--	}
-+	} /* UNW_4_14 */
- 
- 	return TRUE;
- }
-@@ -2086,10 +2147,17 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
- 			 * We are on process stack. Just add a faked frame
- 			 */
- 
--			if (!arm64_on_irq_stack(bt->tc->processor, ext_frame.fp))
--				frame->sp = ext_frame.fp
--					    - sizeof(struct arm64_pt_regs);
--			else {
-+			if (!arm64_on_irq_stack(bt->tc->processor, ext_frame.fp)) {
-+				if (MEMBER_EXISTS("pt_regs", "stackframe")) {
-+					frame->sp = ext_frame.fp
-+						    - sizeof(struct arm64_pt_regs) - 16;
-+					frame->fp = ext_frame.fp;
-+				} else {
-+					frame->sp = ext_frame.fp
-+						    - sizeof(struct arm64_pt_regs);
-+					frame->fp = frame->sp;
-+				}
-+			} else {
- 				/*
- 				 * FIXME: very exceptional case
- 				 * We are already back on process stack, but
-@@ -2109,10 +2177,10 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
- 				 * Really ugly
- 				 */
- 				frame->sp = frame->fp + 0x20;
-+				frame->fp = frame->sp;
- 				fprintf(ofp, " (Next exception frame might be wrong)\n");
- 			}
- 
--			frame->fp = frame->sp;
- 		} else {
- 			/* We are on IRQ stack */
- 
-@@ -2122,9 +2190,15 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
- 			if (ext_frame.fp != irq_stack_ptr) {
- 				/* (2) Just add a faked frame */
- 
--				frame->sp = ext_frame.fp
--					    - sizeof(struct arm64_pt_regs);
--				frame->fp = frame->sp;
-+				if (MEMBER_EXISTS("pt_regs", "stackframe")) {
-+					frame->sp = ext_frame.fp
-+						    - sizeof(struct arm64_pt_regs);
-+					frame->fp = ext_frame.fp;
-+				} else {
-+					frame->sp = ext_frame.fp
-+						    - sizeof(struct arm64_pt_regs) - 16;
-+					frame->fp = frame->sp;
-+				}
- 			} else {
- 				/*
- 				 * (3)
-@@ -2303,12 +2377,17 @@ arm64_back_trace_cmd(struct bt_info *bt)
- 
- 		if (arm64_in_exception_text(bt->instptr) && INSTACK(stackframe.fp, bt)) {
- 			if (!(bt->flags & BT_IRQSTACK) ||
--			    (((stackframe.sp + SIZE(pt_regs)) < bt->stacktop)))
--				exception_frame = stackframe.fp - SIZE(pt_regs);
-+			    (((stackframe.sp + SIZE(pt_regs)) < bt->stacktop))) {
-+				if (MEMBER_EXISTS("pt_regs", "stackframe"))
-+					/* v4.14 or later */
-+					exception_frame = stackframe.fp - SIZE(pt_regs) + 16;
-+				else
-+					exception_frame = stackframe.fp - SIZE(pt_regs);
-+			}
- 		}
- 
- 		if ((bt->flags & BT_IRQSTACK) &&
--		    !arm64_on_irq_stack(bt->tc->processor, stackframe.sp)) {
-+		    !arm64_on_irq_stack(bt->tc->processor, stackframe.fp)) {
- 			bt->flags &= ~BT_IRQSTACK;
- 			if (arm64_switch_stack(bt, &stackframe, ofp) == USER_MODE)
- 				break;
-@@ -2424,6 +2503,8 @@ user_space:
- 		 * otherwise show an exception frame.
- 		 * Since exception entry code doesn't have a real
- 		 * stackframe, we fake a dummy frame here.
-+		 * Note: Since we have a real stack frame in pt_regs,
-+		 * We no longer need a dummy frame on v4.14 or later.
- 		 */
- 		if (!arm64_in_exp_entry(stackframe.pc))
- 			continue;
-@@ -2669,7 +2750,9 @@ arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp
- 	if (frame->fp == 0)
- 		return USER_MODE;
- 
--	arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
-+	if (!(machdep->flags & UNW_4_14))
-+		arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
-+
- 	return KERNEL_MODE;
- }
- 
-@@ -3363,6 +3446,20 @@ arm64_clear_machdep_cache(void) {
- }
- 
- static int
-+arm64_on_process_stack(struct bt_info *bt, ulong stkptr)
-+{
-+	ulong stackbase, stacktop;
-+
-+	stackbase = GET_STACKBASE(bt->task);
-+	stacktop = GET_STACKTOP(bt->task);
-+
-+	if ((stkptr >= stackbase) && (stkptr < stacktop))
-+		return TRUE;
-+
-+	return FALSE;
-+}
-+
-+static int
- arm64_on_irq_stack(int cpu, ulong stkptr)
- {
- 	return arm64_in_alternate_stack(cpu, stkptr);
-
-commit 30950ba8885fb39a1ed7b071cdb225e3ec38e7b3
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Tue Oct 17 16:20:19 2017 -0400
-
-    Implemented a new "search -T" option, which is identical to the
-    "search -t" option, except that the search is restricted to the
-    kernel stacks of active tasks.
-    (atomlin@redhat.com)
-
-diff --git a/help.c b/help.c
-index 2d80202..a9aab37 100644
---- a/help.c
-+++ b/help.c
-@@ -2862,7 +2862,7 @@ NULL
- char *help_search[] = {
- "search",
- "search memory",
--"[-s start] [ -[kKV] | -u | -p | -t ] [-e end | -l length] [-m mask]\n"
-+"[-s start] [ -[kKV] | -u | -p | -t | -T ] [-e end | -l length] [-m mask]\n"
- "         [-x count] -[cwh] [value | (expression) | symbol | string] ...",
- "  This command searches for a given value within a range of user virtual, kernel",
- "  virtual, or physical memory space.  If no end nor length value is entered, ",
-@@ -2893,6 +2893,7 @@ char *help_search[] = {
- "          -t  Search only the kernel stack pages of every task.  If one or more",
- "              matches are found in a task's kernel stack, precede the output",
- "              with a task-identifying header.",
-+"          -T  Same as -t, except only the active task(s) are considered.",
- "      -e end  Stop the search at this hexadecimal user or kernel virtual",
- "              address, kernel symbol, or physical address.  The end address",
- "              must be appropriate for the memory type specified.",
-diff --git a/memory.c b/memory.c
-index 9c9a40d..fb534e8 100644
---- a/memory.c
-+++ b/memory.c
-@@ -13882,7 +13882,7 @@ cmd_search(void)
- 	ulong value, mask, len;
- 	ulong uvaddr_start, uvaddr_end;
- 	ulong kvaddr_start, kvaddr_end, range_end;
--	int sflag, Kflag, Vflag, pflag, tflag;
-+	int sflag, Kflag, Vflag, pflag, Tflag, tflag;
- 	struct searchinfo searchinfo;
- 	struct syment *sp;
- 	struct node_table *nt;
-@@ -13896,7 +13896,7 @@ cmd_search(void)
- 
- 	context = max = 0;
- 	start = end = 0;
--	value = mask = sflag = pflag = Kflag = Vflag = memtype = len = tflag = 0;
-+	value = mask = sflag = pflag = Kflag = Vflag = memtype = len = Tflag = tflag = 0;
- 	kvaddr_start = kvaddr_end = 0;
- 	uvaddr_start = UNINITIALIZED;
- 	uvaddr_end = COMMON_VADDR_SPACE() ? (ulong)(-1) : machdep->kvbase;
-@@ -13933,7 +13933,7 @@ cmd_search(void)
- 
- 	searchinfo.mode = SEARCH_ULONG;	/* default search */
- 
--        while ((c = getopt(argcnt, args, "tl:ukKVps:e:v:m:hwcx:")) != EOF) {
-+        while ((c = getopt(argcnt, args, "Ttl:ukKVps:e:v:m:hwcx:")) != EOF) {
-                 switch(c)
-                 {
- 		case 'u':
-@@ -14038,12 +14038,19 @@ cmd_search(void)
- 			context = dtoi(optarg, FAULT_ON_ERROR, NULL);
- 			break;
- 
-+		case 'T':
- 		case 't':
- 			if (XEN_HYPER_MODE())
- 				error(FATAL, 
-- 			 	    "-t option is not applicable to the "
--				    "Xen hypervisor\n");
--			tflag++;
-+ 			 	    "-%c option is not applicable to the "
-+				    "Xen hypervisor\n", c);
-+			if (c == 'T')
-+				Tflag++;
-+			else if (c == 't')
-+				tflag++;
-+			if (tflag && Tflag)
-+				error(FATAL, 
-+				    "-t and -T options are mutually exclusive\n");
- 			break;
- 
-                 default:
-@@ -14052,10 +14059,11 @@ cmd_search(void)
-                 }
-         }
- 
--	if (tflag && (memtype || start || end || len)) 
-+	if ((tflag || Tflag) && (memtype || start || end || len)) 
- 		error(FATAL, 
--		    "-t option cannot be used with other "
--		    "memory-selection options\n");
-+		    "-%c option cannot be used with other "
-+		    "memory-selection options\n",
-+		    tflag ? 't' : 'T');
- 
- 	if (XEN_HYPER_MODE()) {
- 		memtype = KVADDR;
-@@ -14328,10 +14336,12 @@ cmd_search(void)
- 			break;
- 		}
- 
--		if (tflag) {
-+		if (tflag || Tflag) {
- 			searchinfo.tasks_found = 0;
- 			tc = FIRST_CONTEXT();
- 			for (i = 0; i < RUNNING_TASKS(); i++, tc++) {
-+				if (Tflag && !is_task_active(tc->task))
-+					continue;
- 				searchinfo.vaddr_start = GET_STACKBASE(tc->task); 
- 				searchinfo.vaddr_end = GET_STACKTOP(tc->task);
- 				searchinfo.task_context = tc;
-
-commit 090bf28907782549ba980c588979372061764aa7
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Fri Oct 20 14:23:36 2017 -0400
-
-    Removal of the ARM64 "bt -o" option for Linux 4.14 and later kernels,
-    along with several cleanups/readability improvements.
-    (takahiro.akashi@linaro.org)
-
-diff --git a/arm64.c b/arm64.c
-index c75669b..7904f65 100644
---- a/arm64.c
-+++ b/arm64.c
-@@ -612,6 +612,7 @@ arm64_dump_machdep_table(ulong arg)
- 	fprintf(fp, "        exp_entry2_end: %lx\n", ms->exp_entry2_end);
- 	fprintf(fp, "       panic_task_regs: %lx\n", (ulong)ms->panic_task_regs);
- 	fprintf(fp, "    user_eframe_offset: %ld\n", ms->user_eframe_offset);
-+	fprintf(fp, "    kern_eframe_offset: %ld\n", ms->kern_eframe_offset);
- 	fprintf(fp, "         PTE_PROT_NONE: %lx\n", ms->PTE_PROT_NONE);
- 	fprintf(fp, "              PTE_FILE: ");
- 	if (ms->PTE_FILE)
-@@ -1383,7 +1384,7 @@ arm64_irq_stack_init(void)
- 
- 		if (!(ms->irq_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
- 			error(FATAL, "cannot malloc irq_stack addresses\n");
--		ms->irq_stack_size = 16384;
-+		ms->irq_stack_size = ARM64_IRQ_STACK_SIZE;
- 		machdep->flags |= IRQ_STACKS;
- 
- 		for (i = 0; i < kt->cpus; i++) {
-@@ -1410,10 +1411,13 @@ arm64_stackframe_init(void)
- 	MEMBER_OFFSET_INIT(elf_prstatus_pr_pid, "elf_prstatus", "pr_pid");
- 	MEMBER_OFFSET_INIT(elf_prstatus_pr_reg, "elf_prstatus", "pr_reg");
- 
--	if (MEMBER_EXISTS("pt_regs", "stackframe")) 
-+	if (MEMBER_EXISTS("pt_regs", "stackframe")) {
- 		machdep->machspec->user_eframe_offset = SIZE(pt_regs);
--	else
-+		machdep->machspec->kern_eframe_offset = SIZE(pt_regs) - 16;
-+	} else {
- 		machdep->machspec->user_eframe_offset = SIZE(pt_regs) + 16;
-+		machdep->machspec->kern_eframe_offset = SIZE(pt_regs);
-+	}
- 
- 	machdep->machspec->__exception_text_start = 
- 		symbol_value("__exception_text_start");
-@@ -1503,6 +1507,7 @@ arm64_stackframe_init(void)
- #define USER_MODE   (2)
- 
- #define USER_EFRAME_OFFSET (machdep->machspec->user_eframe_offset)
-+#define KERN_EFRAME_OFFSET (machdep->machspec->kern_eframe_offset)
- 
- /*
-  * PSR bits
-@@ -1793,7 +1798,7 @@ arm64_display_full_frame(struct bt_info *bt, ulong sp)
- 				sp = bt->stacktop;
- 		}
- 	} else { 
--		/* IRQ exception frame */
-+		/* This is a transition case from irq to process stack. */
- 		return;
- 	}
- 
-@@ -1903,61 +1908,73 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
- 	if (!(machdep->flags & IRQ_STACKS))
- 		return TRUE;
- 
--	/*
--	 * The kernel's manner of determining the end of the IRQ stack:
--	 *
--	 *  #define THREAD_SIZE        16384
--	 *  #define THREAD_START_SP    (THREAD_SIZE - 16)
--	 *  #define IRQ_STACK_START_SP THREAD_START_SP
--	 *  #define IRQ_STACK_PTR(cpu) ((unsigned long)per_cpu(irq_stack, cpu) + IRQ_STACK_START_SP)
--	 *  #define IRQ_STACK_TO_TASK_STACK(ptr) (*((unsigned long *)((ptr) - 0x08)))
--	 *
--	 *  irq_stack_ptr = IRQ_STACK_PTR(raw_smp_processor_id());
--	 *  orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr);   (pt_regs pointer on process stack)
--	 */
-+	if (!(machdep->flags & IRQ_STACKS))
-+		return TRUE;
-+
- 	if (machdep->flags & UNW_4_14) {
- 		if ((bt->flags & BT_IRQSTACK) &&
- 		    !arm64_on_irq_stack(bt->tc->processor, frame->fp)) {
- 			if (arm64_on_process_stack(bt, frame->fp)) {
- 				arm64_set_process_stack(bt);
- 
--				frame->sp = frame->fp - SIZE(pt_regs) + 16;
--				/* for switch_stack */
--				/* fp still points to irq stack */
-+				frame->sp = frame->fp - KERN_EFRAME_OFFSET;
-+				/*
-+				 * for switch_stack
-+				 * fp still points to irq stack
-+				 */
- 				bt->bptr = fp;
--				/* for display_full_frame */
--				/* sp points to process stack */
--				bt->frameptr = frame->sp;
-+				/*
-+				 * for display_full_frame
-+				 * sp points to process stack
-+				 *
-+				 * If we want to see pt_regs,
-+				 * comment out the below.
-+				 * bt->frameptr = frame->sp;
-+				 */
- 			} else {
- 				/* irq -> user */
- 				return FALSE;
- 			}
- 		}
--	} else { /* !UNW_4_14 */
--		ms = machdep->machspec;
--		irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size - 16;
--
--		if (frame->sp == irq_stack_ptr) {
--			orig_sp = GET_STACK_ULONG(irq_stack_ptr - 8);
--			arm64_set_process_stack(bt);
--			if (INSTACK(orig_sp, bt) && (INSTACK(frame->fp, bt) || (frame->fp == 0))) {
--				ptregs = (struct arm64_pt_regs *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(orig_sp))];
--				frame->sp = orig_sp;
--				frame->pc = ptregs->pc;
--				bt->bptr = fp;
--				if (CRASHDEBUG(1))
--					error(INFO, 
--					    "arm64_unwind_frame: switch stacks: fp: %lx sp: %lx  pc: %lx\n",
--						frame->fp, frame->sp, frame->pc);
--			} else {
--				error(WARNING, 
--				    "arm64_unwind_frame: on IRQ stack: oriq_sp: %lx%s fp: %lx%s\n",
--					orig_sp, INSTACK(orig_sp, bt) ? "" : " (?)",
--					frame->fp, INSTACK(frame->fp, bt) ? "" : " (?)");
--				return FALSE;
--			}
-+
-+		return TRUE;
-+	}
-+
-+	/*
-+	 * The kernel's manner of determining the end of the IRQ stack:
-+	 *
-+	 *  #define THREAD_SIZE        16384
-+	 *  #define THREAD_START_SP    (THREAD_SIZE - 16)
-+	 *  #define IRQ_STACK_START_SP THREAD_START_SP
-+	 *  #define IRQ_STACK_PTR(cpu) ((unsigned long)per_cpu(irq_stack, cpu) + IRQ_STACK_START_SP)
-+	 *  #define IRQ_STACK_TO_TASK_STACK(ptr) (*((unsigned long *)((ptr) - 0x08)))
-+	 *
-+	 *  irq_stack_ptr = IRQ_STACK_PTR(raw_smp_processor_id());
-+	 *  orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr);   (pt_regs pointer on process stack)
-+	 */
-+	ms = machdep->machspec;
-+	irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size - 16;
-+
-+	if (frame->sp == irq_stack_ptr) {
-+		orig_sp = GET_STACK_ULONG(irq_stack_ptr - 8);
-+		arm64_set_process_stack(bt);
-+		if (INSTACK(orig_sp, bt) && (INSTACK(frame->fp, bt) || (frame->fp == 0))) {
-+			ptregs = (struct arm64_pt_regs *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(orig_sp))];
-+			frame->sp = orig_sp;
-+			frame->pc = ptregs->pc;
-+			bt->bptr = fp;
-+			if (CRASHDEBUG(1))
-+				error(INFO,
-+				    "arm64_unwind_frame: switch stacks: fp: %lx sp: %lx  pc: %lx\n",
-+					frame->fp, frame->sp, frame->pc);
-+		} else {
-+			error(WARNING,
-+			    "arm64_unwind_frame: on IRQ stack: oriq_sp: %lx%s fp: %lx%s\n",
-+				orig_sp, INSTACK(orig_sp, bt) ? "" : " (?)",
-+				frame->fp, INSTACK(frame->fp, bt) ? "" : " (?)");
-+			return FALSE;
- 		}
--	} /* UNW_4_14 */
-+	}
- 
- 	return TRUE;
- }
-@@ -2147,17 +2164,10 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
- 			 * We are on process stack. Just add a faked frame
- 			 */
- 
--			if (!arm64_on_irq_stack(bt->tc->processor, ext_frame.fp)) {
--				if (MEMBER_EXISTS("pt_regs", "stackframe")) {
--					frame->sp = ext_frame.fp
--						    - sizeof(struct arm64_pt_regs) - 16;
--					frame->fp = ext_frame.fp;
--				} else {
--					frame->sp = ext_frame.fp
--						    - sizeof(struct arm64_pt_regs);
--					frame->fp = frame->sp;
--				}
--			} else {
-+			if (!arm64_on_irq_stack(bt->tc->processor, ext_frame.fp))
-+				frame->sp = ext_frame.fp
-+					    - sizeof(struct arm64_pt_regs);
-+			else {
- 				/*
- 				 * FIXME: very exceptional case
- 				 * We are already back on process stack, but
-@@ -2177,10 +2187,10 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
- 				 * Really ugly
- 				 */
- 				frame->sp = frame->fp + 0x20;
--				frame->fp = frame->sp;
- 				fprintf(ofp, " (Next exception frame might be wrong)\n");
- 			}
- 
-+			frame->fp = frame->sp;
- 		} else {
- 			/* We are on IRQ stack */
- 
-@@ -2190,15 +2200,9 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
- 			if (ext_frame.fp != irq_stack_ptr) {
- 				/* (2) Just add a faked frame */
- 
--				if (MEMBER_EXISTS("pt_regs", "stackframe")) {
--					frame->sp = ext_frame.fp
--						    - sizeof(struct arm64_pt_regs);
--					frame->fp = ext_frame.fp;
--				} else {
--					frame->sp = ext_frame.fp
--						    - sizeof(struct arm64_pt_regs) - 16;
--					frame->fp = frame->sp;
--				}
-+				frame->sp = ext_frame.fp
-+					    - sizeof(struct arm64_pt_regs);
-+				frame->fp = frame->sp;
- 			} else {
- 				/*
- 				 * (3)
-@@ -2285,6 +2289,11 @@ arm64_back_trace_cmd(struct bt_info *bt)
- 	FILE *ofp;
- 
- 	if (bt->flags & BT_OPT_BACK_TRACE) {
-+		if (machdep->flags & UNW_4_14) {
-+			option_not_supported('o');
-+			return;
-+		}
-+
- 		arm64_back_trace_cmd_v2(bt);
- 		return;
- 	}
-@@ -2346,7 +2355,7 @@ arm64_back_trace_cmd(struct bt_info *bt)
- 			goto complete_user;
- 
- 		if (DUMPFILE() && is_task_active(bt->task)) {
--			exception_frame = stackframe.fp - SIZE(pt_regs);
-+			exception_frame = stackframe.fp - KERN_EFRAME_OFFSET;
- 			if (arm64_is_kernel_exception_frame(bt, exception_frame))
- 				arm64_print_exception_frame(bt, exception_frame, 
- 					KERNEL_MODE, ofp);
-@@ -2377,13 +2386,8 @@ arm64_back_trace_cmd(struct bt_info *bt)
- 
- 		if (arm64_in_exception_text(bt->instptr) && INSTACK(stackframe.fp, bt)) {
- 			if (!(bt->flags & BT_IRQSTACK) ||
--			    (((stackframe.sp + SIZE(pt_regs)) < bt->stacktop))) {
--				if (MEMBER_EXISTS("pt_regs", "stackframe"))
--					/* v4.14 or later */
--					exception_frame = stackframe.fp - SIZE(pt_regs) + 16;
--				else
--					exception_frame = stackframe.fp - SIZE(pt_regs);
--			}
-+			    (((stackframe.sp + SIZE(pt_regs)) < bt->stacktop)))
-+				exception_frame = stackframe.fp - KERN_EFRAME_OFFSET;
- 		}
- 
- 		if ((bt->flags & BT_IRQSTACK) &&
-@@ -2503,8 +2507,6 @@ user_space:
- 		 * otherwise show an exception frame.
- 		 * Since exception entry code doesn't have a real
- 		 * stackframe, we fake a dummy frame here.
--		 * Note: Since we have a real stack frame in pt_regs,
--		 * We no longer need a dummy frame on v4.14 or later.
- 		 */
- 		if (!arm64_in_exp_entry(stackframe.pc))
- 			continue;
-diff --git a/defs.h b/defs.h
-index 7768895..a694a66 100644
---- a/defs.h
-+++ b/defs.h
-@@ -3038,6 +3038,7 @@ typedef signed int s32;
- #define ARM64_VMEMMAP_END    (ARM64_VMEMMAP_VADDR + GIGABYTES(8UL) - 1)
- 
- #define ARM64_STACK_SIZE   (16384)
-+#define ARM64_IRQ_STACK_SIZE   ARM64_STACK_SIZE
- 
- #define _SECTION_SIZE_BITS      30
- #define _MAX_PHYSMEM_BITS       40
-@@ -3117,6 +3118,8 @@ struct machine_specific {
- 	ulong kimage_text;
- 	ulong kimage_end;
- 	ulong user_eframe_offset;
-+	/* for v4.14 or later */
-+	ulong kern_eframe_offset;
- };
- 
- struct arm64_stackframe {
-diff --git a/help.c b/help.c
-index a9aab37..f9c5792 100644
---- a/help.c
-+++ b/help.c
-@@ -1799,7 +1799,8 @@ char *help_bt[] = {
- "           It does so by verifying the thread_info.task pointer, ensuring that",
- "           the thread_info.cpu is a valid cpu number, and checking the end of ",
- "           the stack for the STACK_END_MAGIC value.",
--"       -o  arm64: use optional backtrace method.",
-+"       -o  arm64: use optional backtrace method; not supported on Linux 4.14 or",
-+"           later kernels.",
- "           x86: use old backtrace method, permissible only on kernels that were",
- "           compiled without the -fomit-frame_pointer.",
- "           x86_64: use old backtrace method, which dumps potentially stale",
-diff --git a/task.c b/task.c
-index 2b12af0..362822c 100644
---- a/task.c
-+++ b/task.c
-@@ -6750,6 +6750,8 @@ panic_search(void)
- 	fd->keyword_array[0] = FOREACH_BT; 
- 	if (machine_type("S390X"))
- 		fd->flags |= FOREACH_o_FLAG;
-+	else if (machine_type("ARM64"))
-+		fd->flags |= FOREACH_t_FLAG;
- 	else
- 		fd->flags |= (FOREACH_t_FLAG|FOREACH_o_FLAG);
- 
-
-commit 45b74b89530d611b3fa95a1041e158fbb865fa84
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Mon Oct 23 11:15:39 2017 -0400
-
-    Fix for support of KASLR enabled kernels captured by the SADUMP
-    dumpfile facility. SADUMP dumpfile headers do not contain phys_base
-    or VMCOREINFO notes, so without this patch, the crash session fails
-    during initialization with the message "crash: seek error: kernel
-    virtual address: <address>  type: "page_offset_base".  This patch
-    calculates the phys_base value and the KASLR offset using the IDTR
-    and CR3 registers from the dumpfile header.
-    (indou.takao@jp.fujitsu.com)
-
-diff --git a/defs.h b/defs.h
-index a694a66..76e5512 100644
---- a/defs.h
-+++ b/defs.h
-@@ -2591,6 +2591,9 @@ struct symbol_table_data {
- 	ulong last_section_end;
- 	ulong _stext_vmlinux;
- 	struct downsized downsized;
-+	ulong divide_error_vmlinux;
-+	ulong idt_table_vmlinux;
-+	ulong saved_command_line_vmlinux;
- };
- 
- /* flags for st */
-@@ -6312,6 +6315,7 @@ void sadump_set_zero_excluded(void);
- void sadump_unset_zero_excluded(void);
- struct sadump_data;
- struct sadump_data *get_sadump_data(void);
-+int sadump_calc_kaslr_offset(ulong *);
- 
- /*
-  * qemu.c
-diff --git a/sadump.c b/sadump.c
-index a96ba9c..2ccfa82 100644
---- a/sadump.c
-+++ b/sadump.c
-@@ -1558,12 +1558,17 @@ sadump_display_regs(int cpu, FILE *ofp)
-  */
- int sadump_phys_base(ulong *phys_base)
- {
--	if (SADUMP_VALID()) {
-+	if (SADUMP_VALID() && !sd->phys_base) {
- 		if (CRASHDEBUG(1))
- 			error(NOTE, "sadump: does not save phys_base.\n");
- 		return FALSE;
- 	}
- 
-+	if (sd->phys_base) {
-+		*phys_base = sd->phys_base;
-+		return TRUE;
-+	}
-+
- 	return FALSE;
- }
- 
-@@ -1649,3 +1654,461 @@ get_sadump_data(void)
- {
- 	return sd;
- }
-+
-+#ifdef X86_64
-+static int
-+get_sadump_smram_cpu_state_any(struct sadump_smram_cpu_state *smram)
-+{
-+	ulong offset;
-+	struct sadump_header *sh = sd->dump_header;
-+	int apicid;
-+	struct sadump_smram_cpu_state scs, zero;
-+
-+	offset = sd->sub_hdr_offset + sizeof(uint32_t) +
-+		 sd->dump_header->nr_cpus * sizeof(struct sadump_apic_state);
-+
-+	memset(&zero, 0, sizeof(zero));
-+
-+	for (apicid = 0; apicid < sh->nr_cpus; ++apicid) {
-+		if (!read_device(&scs, sizeof(scs), &offset)) {
-+			error(INFO, "sadump: cannot read sub header "
-+			      "cpu_state\n");
-+			return FALSE;
-+		}
-+		if (memcmp(&scs, &zero, sizeof(scs)) != 0) {
-+			*smram = scs;
-+			return TRUE;
-+		}
-+	}
-+
-+	return FALSE;
-+}
-+
-+/*
-+ * Get address of vector0 interrupt handler (Devide Error) from Interrupt
-+ * Descriptor Table.
-+ */
-+static ulong
-+get_vec0_addr(ulong idtr)
-+{
-+	struct gate_struct64 {
-+		uint16_t offset_low;
-+		uint16_t segment;
-+		uint32_t ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
-+		uint16_t offset_middle;
-+		uint32_t offset_high;
-+		uint32_t zero1;
-+	} __attribute__((packed)) gate;
-+
-+	readmem(idtr, PHYSADDR, &gate, sizeof(gate), "idt_table", FAULT_ON_ERROR);
-+
-+	return ((ulong)gate.offset_high << 32)
-+		+ ((ulong)gate.offset_middle << 16)
-+		+ gate.offset_low;
-+}
-+
-+/*
-+ * Parse a string of [size[KMG] ]offset[KMG]
-+ * Import from Linux kernel(lib/cmdline.c)
-+ */
-+static ulong memparse(char *ptr, char **retptr)
-+{
-+	char *endptr;
-+
-+	unsigned long long ret = strtoull(ptr, &endptr, 0);
-+
-+	switch (*endptr) {
-+	case 'E':
-+	case 'e':
-+		ret <<= 10;
-+	case 'P':
-+	case 'p':
-+		ret <<= 10;
-+	case 'T':
-+	case 't':
-+		ret <<= 10;
-+	case 'G':
-+	case 'g':
-+		ret <<= 10;
-+	case 'M':
-+	case 'm':
-+		ret <<= 10;
-+	case 'K':
-+	case 'k':
-+		ret <<= 10;
-+		endptr++;
-+	default:
-+		break;
-+	}
-+
-+	if (retptr)
-+		*retptr = endptr;
-+
-+	return ret;
-+}
-+
-+/*
-+ * Find "elfcorehdr=" in the boot parameter of kernel and return the address
-+ * of elfcorehdr.
-+ */
-+static ulong
-+get_elfcorehdr(ulong cr3, ulong kaslr_offset)
-+{
-+	char cmdline[BUFSIZE], *ptr;
-+	ulong cmdline_vaddr;
-+	ulong cmdline_paddr;
-+	ulong buf_vaddr, buf_paddr;
-+	char *end;
-+	ulong elfcorehdr_addr = 0, elfcorehdr_size = 0;
-+	int verbose = CRASHDEBUG(1)? 1: 0;
-+
-+	cmdline_vaddr = st->saved_command_line_vmlinux + kaslr_offset;
-+	if (!kvtop(NULL, cmdline_vaddr, &cmdline_paddr, verbose))
-+		return 0;
-+
-+	if (CRASHDEBUG(1)) {
-+		fprintf(fp, "cmdline vaddr=%lx\n", cmdline_vaddr);
-+		fprintf(fp, "cmdline paddr=%lx\n", cmdline_paddr);
-+	}
-+
-+	if (!readmem(cmdline_paddr, PHYSADDR, &buf_vaddr, sizeof(ulong),
-+		     "saved_command_line", RETURN_ON_ERROR))
-+		return 0;
-+
-+	if (!kvtop(NULL, buf_vaddr, &buf_paddr, verbose))
-+		return 0;
-+
-+	if (CRASHDEBUG(1)) {
-+		fprintf(fp, "cmdline buffer vaddr=%lx\n", buf_vaddr);
-+		fprintf(fp, "cmdline buffer paddr=%lx\n", buf_paddr);
-+	}
-+
-+	memset(cmdline, 0, BUFSIZE);
-+	if (!readmem(buf_paddr, PHYSADDR, cmdline, BUFSIZE,
-+		     "saved_command_line", RETURN_ON_ERROR))
-+		return 0;
-+
-+	ptr = strstr(cmdline, "elfcorehdr=");
-+	if (!ptr)
-+		return 0;
-+
-+	if (CRASHDEBUG(1))
-+		fprintf(fp, "2nd kernel detected\n");
-+
-+	ptr += strlen("elfcorehdr=");
-+	elfcorehdr_addr = memparse(ptr, &end);
-+	if (*end == '@') {
-+		elfcorehdr_size = elfcorehdr_addr;
-+		elfcorehdr_addr = memparse(end + 1, &end);
-+	}
-+
-+	if (CRASHDEBUG(1)) {
-+		fprintf(fp, "elfcorehdr_addr=%lx\n", elfcorehdr_addr);
-+		fprintf(fp, "elfcorehdr_size=%lx\n", elfcorehdr_size);
-+	}
-+
-+	return elfcorehdr_addr;
-+}
-+
-+ /*
-+  * Get vmcoreinfo from elfcorehdr.
-+  * Some codes are imported from Linux kernel(fs/proc/vmcore.c)
-+  */
-+static int
-+get_vmcoreinfo(ulong elfcorehdr, ulong *addr, int *len)
-+{
-+	unsigned char e_ident[EI_NIDENT];
-+	Elf64_Ehdr ehdr;
-+	Elf64_Phdr phdr;
-+	Elf64_Nhdr nhdr;
-+	ulong ptr;
-+	ulong nhdr_offset = 0;
-+	int i;
-+
-+	if (!readmem(elfcorehdr, PHYSADDR, e_ident, EI_NIDENT,
-+		     "EI_NIDENT", RETURN_ON_ERROR))
-+		return FALSE;
-+
-+	if (e_ident[EI_CLASS] != ELFCLASS64) {
-+		error(INFO, "Only ELFCLASS64 is supportd\n");
-+		return FALSE;
-+	}
-+
-+	if (!readmem(elfcorehdr, PHYSADDR, &ehdr, sizeof(ehdr),
-+			"Elf64_Ehdr", RETURN_ON_ERROR))
-+		return FALSE;
-+
-+	/* Sanity Check */
-+	if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
-+		(ehdr.e_type != ET_CORE) ||
-+		ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
-+		ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
-+		ehdr.e_version != EV_CURRENT ||
-+		ehdr.e_ehsize != sizeof(Elf64_Ehdr) ||
-+		ehdr.e_phentsize != sizeof(Elf64_Phdr) ||
-+		ehdr.e_phnum == 0) {
-+		error(INFO, "Invalid elf header\n");
-+		return FALSE;
-+	}
-+
-+	ptr = elfcorehdr + ehdr.e_phoff;
-+	for (i = 0; i < ehdr.e_phnum; i++) {
-+		ulong offset;
-+		char name[16];
-+
-+		if (!readmem(ptr, PHYSADDR, &phdr, sizeof(phdr),
-+				"Elf64_Phdr", RETURN_ON_ERROR))
-+			return FALSE;
-+
-+		ptr += sizeof(phdr);
-+		if (phdr.p_type != PT_NOTE)
-+			continue;
-+
-+		offset = phdr.p_offset;
-+		if (!readmem(offset, PHYSADDR, &nhdr, sizeof(nhdr),
-+				"Elf64_Nhdr", RETURN_ON_ERROR))
-+			return FALSE;
-+
-+		offset += DIV_ROUND_UP(sizeof(Elf64_Nhdr), sizeof(Elf64_Word))*
-+			  sizeof(Elf64_Word);
-+		memset(name, 0, sizeof(name));
-+		if (!readmem(offset, PHYSADDR, name, sizeof(name),
-+				"Elf64_Nhdr name", RETURN_ON_ERROR))
-+			return FALSE;
-+
-+		if(!strcmp(name, "VMCOREINFO")) {
-+			nhdr_offset = offset;
-+			break;
-+		}
-+	}
-+
-+	if (!nhdr_offset)
-+		return FALSE;
-+
-+	*addr = nhdr_offset +
-+		DIV_ROUND_UP(nhdr.n_namesz, sizeof(Elf64_Word))*
-+		sizeof(Elf64_Word);
-+	*len = nhdr.n_descsz;
-+
-+	if (CRASHDEBUG(1)) {
-+		fprintf(fp, "vmcoreinfo addr=%lx\n", *addr);
-+		fprintf(fp, "vmcoreinfo len=%d\n", *len);
-+	}
-+
-+	return TRUE;
-+}
-+
-+/*
-+ * Check if current kaslr_offset/phys_base is for 1st kernel or 2nd kernel.
-+ * If we are in 2nd kernel, get kaslr_offset/phys_base from vmcoreinfo.
-+ *
-+ * 1. Get command line and try to retrieve "elfcorehdr=" boot parameter
-+ * 2. If "elfcorehdr=" is not found in command line, we are in 1st kernel.
-+ *    There is nothing to do.
-+ * 3. If "elfcorehdr=" is found, we are in 2nd kernel. Find vmcoreinfo
-+ *    using "elfcorehdr=" and retrieve kaslr_offset/phys_base from vmcoreinfo.
-+ */
-+static int
-+get_kaslr_offset_from_vmcoreinfo(ulong cr3, ulong orig_kaslr_offset,
-+		                 ulong *kaslr_offset, ulong *phys_base)
-+{
-+	ulong elfcorehdr_addr = 0;
-+	ulong vmcoreinfo_addr;
-+	int vmcoreinfo_len;
-+	char *buf, *pos;
-+	int ret = FALSE;
-+
-+	/* Find "elfcorehdr=" in the kernel boot parameter */
-+	elfcorehdr_addr = get_elfcorehdr(cr3, orig_kaslr_offset);
-+	if (!elfcorehdr_addr)
-+		return FALSE;
-+
-+	/* Get vmcoreinfo from the address of "elfcorehdr=" */
-+	if (!get_vmcoreinfo(elfcorehdr_addr, &vmcoreinfo_addr, &vmcoreinfo_len))
-+		return FALSE;
-+
-+	if (!vmcoreinfo_len)
-+		return FALSE;
-+
-+	if (CRASHDEBUG(1))
-+		fprintf(fp, "Find vmcoreinfo in kdump memory\n");
-+
-+	buf = GETBUF(vmcoreinfo_len);
-+	if (!readmem(vmcoreinfo_addr, PHYSADDR, buf, vmcoreinfo_len,
-+			"vmcoreinfo", RETURN_ON_ERROR))
-+		goto quit;
-+
-+	/* Get phys_base form vmcoreinfo */
-+	pos = strstr(buf, "NUMBER(phys_base)=");
-+	if (!pos)
-+		goto quit;
-+	*phys_base  = strtoull(pos + strlen("NUMBER(phys_base)="), NULL, 0);
-+
-+	/* Get kaslr_offset form vmcoreinfo */
-+	pos = strstr(buf, "KERNELOFFSET=");
-+	if (!pos)
-+		goto quit;
-+	*kaslr_offset = strtoull(pos + strlen("KERNELOFFSET="), NULL, 16);
-+
-+	ret = TRUE;
-+
-+quit:
-+	FREEBUF(buf);
-+	return ret;
-+}
-+
-+/*
-+ * Calculate kaslr_offset and phys_base
-+ *
-+ * kaslr_offset:
-+ *   The difference between original address in System.map or vmlinux and
-+ *   actual address placed randomly by kaslr feature. To be more accurate,
-+ *   kaslr_offset = actual address  - original address
-+ *
-+ * phys_base:
-+ *   Physical address where the kerenel is placed. In other words, it's a
-+ *   physical address of __START_KERNEL_map. This is also decided randomly by
-+ *   kaslr.
-+ *
-+ * kaslr offset and phys_base are calculated as follows:
-+ *
-+ * kaslr_offset:
-+ * 1) Get IDTR and CR3 value from the dump header.
-+ * 2) Get a virtual address of IDT from IDTR value
-+ *    --- (A)
-+ * 3) Translate (A) to physical address using CR3, which points a top of
-+ *    page table.
-+ *    --- (B)
-+ * 4) Get an address of vector0 (Devide Error) interrupt handler from
-+ *    IDT, which are pointed by (B).
-+ *    --- (C)
-+ * 5) Get an address of symbol "divide_error" form vmlinux
-+ *    --- (D)
-+ *
-+ * Now we have two addresses:
-+ * (C)-> Actual address of "divide_error"
-+ * (D)-> Original address of "divide_error" in the vmlinux
-+ *
-+ * kaslr_offset can be calculated by the difference between these two
-+ * value.
-+ *
-+ * phys_base;
-+ * 1) Get IDT virtual address from vmlinux
-+ *    --- (E)
-+ *
-+ * So phys_base can be calculated using relationship of directly mapped
-+ * address.
-+ *
-+ * phys_base =
-+ *   Physical address(B) -
-+ *   (Virtual address(E) + kaslr_offset - __START_KERNEL_map)
-+ *
-+ * Note that the address (A) cannot be used instead of (E) because (A) is
-+ * not direct map address, it's a fixed map address.
-+ *
-+ * This solution works in most every case, but does not work in the
-+ * following case.
-+ *
-+ * 1) If the dump is captured on early stage of kernel boot, IDTR points
-+ *    early IDT table(early_idts) instead of normal IDT(idt_table).
-+ * 2) If the dump is captured whle kdump is working, IDTR points
-+ *    IDT table of 2nd kernel, not 1st kernel.
-+ *
-+ * Current implementation does not support the case 1), need
-+ * enhancement in the future. For the case 2), get kaslr_offset and
-+ * phys_base as follows.
-+ *
-+ * 1) Get kaslr_offset and phys_base using the above solution.
-+ * 2) Get kernel boot parameter from "saved_command_line"
-+ * 3) If "elfcorehdr=" is not included in boot parameter, we are in the
-+ *    first kernel, nothing to do any more.
-+ * 4) If "elfcorehdr=" is included in boot parameter, we are in the 2nd
-+ *    kernel. Retrieve vmcoreinfo from address of "elfcorehdr=" and
-+ *    get kaslr_offset and phys_base from vmcoreinfo.
-+ */
-+int
-+sadump_calc_kaslr_offset(ulong *kaslr_offset)
-+{
-+	ulong phys_base = 0;
-+	struct sadump_smram_cpu_state scs;
-+	uint64_t idtr = 0, cr3 = 0, idtr_paddr;
-+	ulong divide_error_vmcore;
-+	ulong kaslr_offset_kdump, phys_base_kdump;
-+	int ret = FALSE;
-+	int verbose = CRASHDEBUG(1)? 1: 0;
-+
-+	if (!machine_type("X86_64"))
-+		return FALSE;
-+
-+	memset(&scs, 0, sizeof(scs));
-+	get_sadump_smram_cpu_state_any(&scs);
-+	cr3 = scs.Cr3;
-+	idtr = ((uint64_t)scs.IdtUpper)<<32 | (uint64_t)scs.IdtLower;
-+
-+	/*
-+	 * Set up for kvtop.
-+	 *
-+	 * calc_kaslr_offset() is called before machdep_init(PRE_GDB), so some
-+	 * variables are not initialized yet. Set up them here to call kvtop().
-+	 *
-+	 * TODO: XEN and 5-level is not supported
-+	 */
-+	vt->kernel_pgd[0] = cr3;
-+	machdep->machspec->last_pml4_read = vt->kernel_pgd[0];
-+	machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_2_6;
-+	machdep->machspec->pgdir_shift = PGDIR_SHIFT;
-+	if (!readmem(cr3, PHYSADDR, machdep->machspec->pml4, PAGESIZE(),
-+			"cr3", RETURN_ON_ERROR))
-+		goto quit;
-+
-+	/* Convert virtual address of IDT table to physical address */
-+	if (!kvtop(NULL, idtr, &idtr_paddr, verbose))
-+		goto quit;
-+
-+	/* Now we can calculate kaslr_offset and phys_base */
-+	divide_error_vmcore = get_vec0_addr(idtr_paddr);
-+	*kaslr_offset = divide_error_vmcore - st->divide_error_vmlinux;
-+	phys_base = idtr_paddr -
-+		(st->idt_table_vmlinux + *kaslr_offset - __START_KERNEL_map);
-+
-+	if (CRASHDEBUG(1)) {
-+		fprintf(fp, "calc_kaslr_offset: idtr=%lx\n", idtr);
-+		fprintf(fp, "calc_kaslr_offset: cr3=%lx\n", cr3);
-+		fprintf(fp, "calc_kaslr_offset: idtr(phys)=%lx\n", idtr_paddr);
-+		fprintf(fp, "calc_kaslr_offset: divide_error(vmlinux): %lx\n",
-+			st->divide_error_vmlinux);
-+		fprintf(fp, "calc_kaslr_offset: divide_error(vmcore): %lx\n",
-+			divide_error_vmcore);
-+	}
-+
-+	/*
-+	 * Check if current kaslr_offset/phys_base is for 1st kernel or 2nd
-+	 * kernel. If we are in 2nd kernel, get kaslr_offset/phys_base
-+	 * from vmcoreinfo
-+	 */
-+	if (get_kaslr_offset_from_vmcoreinfo(
-+		cr3, *kaslr_offset, &kaslr_offset_kdump, &phys_base_kdump)) {
-+		*kaslr_offset =  kaslr_offset_kdump;
-+		phys_base =  phys_base_kdump;
-+	}
-+
-+	if (CRASHDEBUG(1)) {
-+		fprintf(fp, "calc_kaslr_offset: kaslr_offset=%lx\n",
-+			*kaslr_offset);
-+		fprintf(fp, "calc_kaslr_offset: phys_base=%lx\n", phys_base);
-+	}
-+
-+	sd->phys_base = phys_base;
-+	ret = TRUE;
-+quit:
-+	vt->kernel_pgd[0] = 0;
-+	machdep->machspec->last_pml4_read = 0;
-+	return ret;
-+}
-+#else
-+int
-+sadump_calc_kaslr_offset(ulong *kaslr_offset)
-+{
-+	return FALSE;
-+}
-+#endif /* X86_64 */
-diff --git a/sadump.h b/sadump.h
-index 7f8e384..681f5e4 100644
---- a/sadump.h
-+++ b/sadump.h
-@@ -219,6 +219,7 @@ struct sadump_data {
- 	ulonglong backup_offset;
- 
- 	uint64_t max_mapnr;
-+	ulong phys_base;
- };
- 
- struct sadump_data *sadump_get_sadump_data(void);
-diff --git a/symbols.c b/symbols.c
-index 02cb34e..b2f2796 100644
---- a/symbols.c
-+++ b/symbols.c
-@@ -624,6 +624,9 @@ kaslr_init(void)
- 			st->_stext_vmlinux = UNINITIALIZED;
- 		}
- 	}
-+
-+	if (SADUMP_DUMPFILE())
-+		kt->flags2 |= KASLR_CHECK;
- }
- 
- /*
-@@ -637,6 +640,19 @@ derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte *start, bfd_byte *end,
- 	unsigned long relocate;
- 	ulong _stext_relocated;
- 
-+	if (SADUMP_DUMPFILE()) {
-+		ulong kaslr_offset = 0;
-+
-+		sadump_calc_kaslr_offset(&kaslr_offset);
-+
-+		if (kaslr_offset) {
-+			kt->relocate = kaslr_offset * -1;
-+			kt->flags |= RELOC_SET;
-+		}
-+
-+		return;
-+	}
-+
- 	if (ACTIVE()) {
- 		_stext_relocated = symbol_value_from_proc_kallsyms("_stext");
- 		if (_stext_relocated == BADVAL)
-@@ -3052,6 +3068,16 @@ dump_symbol_table(void)
- 	else
- 		fprintf(fp, "\n");
- 
-+	if (SADUMP_DUMPFILE()) {
-+		fprintf(fp, "divide_error_vmlinux: %lx\n", st->divide_error_vmlinux);
-+		fprintf(fp, "   idt_table_vmlinux: %lx\n", st->idt_table_vmlinux);
-+		fprintf(fp, "saved_command_line_vmlinux: %lx\n", st->saved_command_line_vmlinux);
-+	} else {
-+		fprintf(fp, "divide_error_vmlinux: (unused)\n");
-+		fprintf(fp, "   idt_table_vmlinux: (unused)\n");
-+		fprintf(fp, "saved_command_line_vmlinux: (unused)\n");
-+	}
-+
-         fprintf(fp, "    symval_hash[%d]: %lx\n", SYMVAL_HASH,
-                 (ulong)&st->symval_hash[0]);
- 
-@@ -12246,6 +12272,24 @@ numeric_forward(const void *P_x, const void *P_y)
- 		}
- 	}
- 
-+	if (SADUMP_DUMPFILE()) {
-+		/* Need for kaslr_offset and phys_base */
-+		if (STREQ(x->name, "divide_error"))
-+			st->divide_error_vmlinux = valueof(x);
-+		else if (STREQ(y->name, "divide_error"))
-+			st->divide_error_vmlinux = valueof(y);
-+
-+		if (STREQ(x->name, "idt_table"))
-+			st->idt_table_vmlinux = valueof(x);
-+		else if (STREQ(y->name, "idt_table"))
-+			st->idt_table_vmlinux = valueof(y);
-+
-+		if (STREQ(x->name, "saved_command_line"))
-+			st->saved_command_line_vmlinux = valueof(x);
-+		else if (STREQ(y->name, "saved_command_line"))
-+			st->saved_command_line_vmlinux = valueof(y);
-+	}
-+
-   	xs = bfd_get_section(x);
-   	ys = bfd_get_section(y);
- 
-diff --git a/x86_64.c b/x86_64.c
-index 6e60dda..2f9e6db 100644
---- a/x86_64.c
-+++ b/x86_64.c
-@@ -194,6 +194,9 @@ x86_64_init(int when)
- 			machdep->machspec->kernel_image_size = dtol(string, QUIET, NULL);
- 			free(string);
- 		}
-+		if (SADUMP_DUMPFILE())
-+			/* Need for calculation of kaslr_offset and phys_base */
-+			machdep->kvtop = x86_64_kvtop;
- 		break;
- 
- 	case PRE_GDB:
-@@ -2019,6 +2022,22 @@ x86_64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbo
- 	ulong pte;
- 	physaddr_t physpage;
- 
-+	if (SADUMP_DUMPFILE() && !(machdep->flags & KSYMS_START)) {
-+		/*
-+		 * In the case of sadump, to calculate kaslr_offset and
-+		 * phys_base, kvtop is called during symtab_init(). In this
-+		 * stage phys_base is not initialized yet and x86_64_VTOP()
-+		 * does not work. Jump to the code of pagetable translation.
-+		 */
-+		FILL_PML4();
-+		pml4 = ((ulong *)machdep->machspec->pml4) + pml4_index(kvaddr);
-+		if (verbose) {
-+			fprintf(fp, "PML4 DIRECTORY: %lx\n", vt->kernel_pgd[0]);
-+			fprintf(fp, "PAGE DIRECTORY: %lx\n", *pml4);
-+		}
-+		goto start_vtop_with_pagetable;
-+	}
-+
-         if (!IS_KVADDR(kvaddr))
-                 return FALSE;
- 
-@@ -2065,6 +2084,8 @@ x86_64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbo
-                		fprintf(fp, "PAGE DIRECTORY: %lx\n", *pml4);
- 		}
- 	}
-+
-+start_vtop_with_pagetable:
- 	if (!(*pml4) & _PAGE_PRESENT)
- 		goto no_kpage;
- 	pgd_paddr = (*pml4) & PHYSICAL_PAGE_MASK;
-
-commit 4550bf32a5ec1d9b7b6d5099aaee6e8e363a7827
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Wed Oct 25 11:04:53 2017 -0400
-
-    Implemented a new "ps -y policy" option to filter the task display
-    by scheduling policy.  Applicable to both standalone ps invocation
-    as well as via foreach.
-    (oleksandr@redhat.com)
-
-diff --git a/defs.h b/defs.h
-index 76e5512..4b4e331 100644
---- a/defs.h
-+++ b/defs.h
-@@ -1139,6 +1139,7 @@ extern struct machdep_table *machdep;
- #define FOREACH_a_FLAG   (0x4000000)
- #define FOREACH_G_FLAG   (0x8000000)
- #define FOREACH_F_FLAG2 (0x10000000)
-+#define FOREACH_y_FLAG  (0x20000000)
- 
- #define FOREACH_PS_EXCLUSIVE \
-   (FOREACH_g_FLAG|FOREACH_a_FLAG|FOREACH_t_FLAG|FOREACH_c_FLAG|FOREACH_p_FLAG|FOREACH_l_FLAG|FOREACH_r_FLAG|FOREACH_m_FLAG)
-@@ -1162,6 +1163,7 @@ struct foreach_data {
- 	int comms;
- 	int args;
- 	int regexs;
-+	int policy;
- };
- 
- struct reference {       
-@@ -1992,6 +1994,7 @@ struct offset_table {                    /* stash of commonly-used offsets */
- 	long mod_arch_specific_num_orcs;
- 	long mod_arch_specific_orc_unwind_ip;
- 	long mod_arch_specific_orc_unwind;
-+	long task_struct_policy;
- };
- 
- struct size_table {         /* stash of commonly-used sizes */
-@@ -2141,6 +2144,7 @@ struct size_table {         /* stash of commonly-used sizes */
- 	long sk_buff_head_qlen;
- 	long sk_buff_len;
- 	long orc_entry;
-+	long task_struct_policy;
- };
- 
- struct array_table {
-@@ -4576,6 +4580,13 @@ enum type_code {
-  */
- #define PF_EXITING 0x00000004  /* getting shut down */
- #define PF_KTHREAD 0x00200000  /* I am a kernel thread */
-+#define SCHED_NORMAL	0
-+#define SCHED_FIFO	1
-+#define SCHED_RR	2
-+#define SCHED_BATCH	3
-+#define SCHED_ISO	4
-+#define SCHED_IDLE	5
-+#define SCHED_DEADLINE	6
- 
- extern long _ZOMBIE_;
- #define IS_ZOMBIE(task)   (task_state(task) & _ZOMBIE_)
-@@ -4603,6 +4614,7 @@ extern long _ZOMBIE_;
- #define PS_NO_HEADER  (0x10000)
- #define PS_MSECS      (0x20000)
- #define PS_SUMMARY    (0x40000)
-+#define PS_POLICY     (0x80000)
- 
- #define PS_EXCLUSIVE (PS_TGID_LIST|PS_ARGV_ENVP|PS_TIMES|PS_CHILD_LIST|PS_PPID_LIST|PS_LAST_RUN|PS_RLIMIT|PS_MSECS|PS_SUMMARY)
- 
-@@ -4620,6 +4632,7 @@ struct psinfo {
- 	} regex_data[MAX_PS_ARGS];
- 	int regexs;
- 	ulong *cpus;
-+	int policy;
- };
- 
- #define IS_A_NUMBER(X)      (decimal(X, 0) || hexadecimal(X, 0))
-@@ -4823,7 +4836,7 @@ char *strip_ending_char(char *, char);
- char *strip_beginning_char(char *, char);
- char *strip_comma(char *);
- char *strip_hex(char *);
--char *upper_case(char *, char *);
-+char *upper_case(const char *, char *);
- char *first_nonspace(char *);
- char *first_space(char *);
- char *replace_string(char *, char *, char);
-diff --git a/help.c b/help.c
-index f9c5792..efa55e0 100644
---- a/help.c
-+++ b/help.c
-@@ -844,7 +844,7 @@ char *help_foreach[] = {
- "             net  run the \"net\" command  (optional flags: -s -S -R -d -x)",
- "             set  run the \"set\" command",
- "              ps  run the \"ps\" command  (optional flags: -G -s -p -c -t -l -a",
--"                  -g -r)",
-+"                  -g -r -y)",
- "             sig  run the \"sig\" command (optional flag: -g)",
- "            vtop  run the \"vtop\" command  (optional flags: -c -u -k)\n",
- "     flag  Pass this optional flag to the command selected.",
-@@ -1250,7 +1250,7 @@ NULL
- char *help_ps[] = {
- "ps",
- "display process status information",
--"[-k|-u|-G] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S]\n     [pid | task | command] ...",
-+"[-k|-u|-G|-y policy] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S]\n     [pid | task | command] ...",
- "  This command displays process status for selected, or all, processes" ,
- "  in the system.  If no arguments are entered, the process data is",
- "  is displayed for all processes.  Specific processes may be selected",
-@@ -1267,6 +1267,16 @@ char *help_ps[] = {
- "        -k  restrict the output to only kernel threads.",
- "        -u  restrict the output to only user tasks.",
- "        -G  display only the thread group leader in a thread group.",
-+" -y policy  restrict the output to tasks having a specified scheduling policy",
-+"            expressed by its integer value or by its (case-insensitive) name;",
-+"            multiple policies may be entered in a comma-separated list:",
-+"              0 or NORMAL",
-+"              1 or FIFO",
-+"              2 or RR",
-+"              3 or BATCH",
-+"              4 or ISO",
-+"              5 or IDLE",
-+"              6 or DEADLINE",
- " ",
- "  The process identifier types may be mixed.  For each task, the following",
- "  items are displayed:",
-diff --git a/symbols.c b/symbols.c
-index b2f2796..f7599e8 100644
---- a/symbols.c
-+++ b/symbols.c
-@@ -8584,6 +8584,8 @@ dump_offset_table(char *spec, ulong makestruct)
-                 OFFSET(task_struct_prio));
-         fprintf(fp, "             task_struct_on_rq: %ld\n",
-                 OFFSET(task_struct_on_rq));
-+        fprintf(fp, "            task_struct_policy: %ld\n",
-+                OFFSET(task_struct_policy));
- 
- 	fprintf(fp, "              thread_info_task: %ld\n",
-                 OFFSET(thread_info_task));
-@@ -10211,6 +10213,7 @@ dump_offset_table(char *spec, ulong makestruct)
-         fprintf(fp, "                       pt_regs: %ld\n", SIZE(pt_regs));
-         fprintf(fp, "                   task_struct: %ld\n", SIZE(task_struct));
-         fprintf(fp, "             task_struct_flags: %ld\n", SIZE(task_struct_flags));
-+        fprintf(fp, "            task_struct_policy: %ld\n", SIZE(task_struct_policy));
-         fprintf(fp, "                   thread_info: %ld\n", SIZE(thread_info));
-         fprintf(fp, "                 softirq_state: %ld\n", 
- 		SIZE(softirq_state));
-diff --git a/task.c b/task.c
-index 362822c..5754159 100644
---- a/task.c
-+++ b/task.c
-@@ -109,6 +109,24 @@ static void show_ps_summary(ulong);
- static void irqstacks_init(void);
- static void parse_task_thread(int argcnt, char *arglist[], struct task_context *);
- static void stack_overflow_check_init(void);
-+static int has_sched_policy(ulong, ulong);
-+static ulong task_policy(ulong);
-+static ulong sched_policy_bit_from_str(const char *);
-+static ulong make_sched_policy(const char *);
-+
-+static struct sched_policy_info {
-+	ulong value;
-+	char *name;
-+} sched_policy_info[] = {
-+	{ SCHED_NORMAL,		"NORMAL" },
-+	{ SCHED_FIFO,		"FIFO" },
-+	{ SCHED_RR,		"RR" },
-+	{ SCHED_BATCH,		"BATCH" },
-+	{ SCHED_ISO,		"ISO" },
-+	{ SCHED_IDLE,		"IDLE" },
-+	{ SCHED_DEADLINE,	"DEADLINE" },
-+	{ ULONG_MAX,		NULL }
-+};
- 
- /*
-  *  Figure out how much space will be required to hold the task context
-@@ -273,6 +291,8 @@ task_init(void)
- 	MEMBER_OFFSET_INIT(task_struct_next_run, "task_struct", "next_run");
- 	MEMBER_OFFSET_INIT(task_struct_flags, "task_struct", "flags");
- 	MEMBER_SIZE_INIT(task_struct_flags, "task_struct", "flags");
-+	MEMBER_OFFSET_INIT(task_struct_policy, "task_struct", "policy");
-+	MEMBER_SIZE_INIT(task_struct_policy, "task_struct", "policy");
-         MEMBER_OFFSET_INIT(task_struct_pidhash_next,
-                 "task_struct", "pidhash_next");
- 	MEMBER_OFFSET_INIT(task_struct_pgrp, "task_struct", "pgrp");
-@@ -2974,7 +2994,7 @@ cmd_ps(void)
- 	cpuspec = NULL;
- 	flag = 0;
- 
--        while ((c = getopt(argcnt, args, "SgstcpkuGlmarC:")) != EOF) {
-+        while ((c = getopt(argcnt, args, "SgstcpkuGlmarC:y:")) != EOF) {
-                 switch(c)
- 		{
- 		case 'k':
-@@ -3075,6 +3095,11 @@ cmd_ps(void)
- 			make_cpumask(cpuspec, psinfo.cpus, FAULT_ON_ERROR, NULL);
- 			break;
- 
-+		case 'y':
-+			flag |= PS_POLICY;
-+			psinfo.policy = make_sched_policy(optarg);
-+			break;
-+
- 		default:
- 			argerrs++;
- 			break;
-@@ -3218,6 +3243,8 @@ show_ps_data(ulong flag, struct task_context *tc, struct psinfo *psi)
- 		return;
- 	if ((flag & PS_KERNEL) && !is_kernel_thread(tc->task))
- 		return;
-+	if ((flag & PS_POLICY) && !has_sched_policy(tc->task, psi->policy))
-+		return;
- 	if (flag & PS_GROUP) {
- 		if (flag & (PS_LAST_RUN|PS_MSECS))
- 			error(FATAL, "-G not supported with -%c option\n",
-@@ -3336,7 +3363,7 @@ show_ps(ulong flag, struct psinfo *psi)
- 
- 		tc = FIRST_CONTEXT();
- 		for (i = 0; i < RUNNING_TASKS(); i++, tc++)
--			show_ps_data(flag, tc, NULL);
-+			show_ps_data(flag, tc, psi);
- 		
- 		return;
- 	}
-@@ -3391,7 +3418,7 @@ show_ps(ulong flag, struct psinfo *psi)
- 				if (flag & PS_TIMES) 
- 					show_task_times(tc, flag);
- 				else
--					show_ps_data(flag, tc, NULL);
-+					show_ps_data(flag, tc, psi);
- 			}
- 		}
- 	}
-@@ -3546,7 +3573,7 @@ show_milliseconds(struct task_context *tc, struct psinfo *psi)
- 	sprintf(format, "[%c%dll%c] ", '%', c, 
- 		pc->output_radix == 10 ? 'u' : 'x');
- 
--	if (psi) {
-+	if (psi && psi->cpus) {
- 		for (c = others = 0; c < kt->cpus; c++) {
- 			if (!NUM_IN_BITMAP(psi->cpus, c))
- 				continue;
-@@ -5366,6 +5393,27 @@ task_flags(ulong task)
- }
- 
- /*
-+ * Return task's policy as bitmask bit.
-+ */
-+static ulong
-+task_policy(ulong task)
-+{
-+	ulong policy = 0;
-+
-+	fill_task_struct(task);
-+
-+	if (!tt->last_task_read)
-+		return policy;
-+
-+	if (SIZE(task_struct_policy) == sizeof(unsigned int))
-+		policy = 1 << UINT(tt->task_struct + OFFSET(task_struct_policy));
-+	else
-+		policy = 1 << ULONG(tt->task_struct + OFFSET(task_struct_policy));
-+
-+	return policy;
-+}
-+
-+/*
-  *  Return a task's tgid.
-  */
- ulong
-@@ -5797,7 +5845,7 @@ cmd_foreach(void)
- 	BZERO(&foreach_data, sizeof(struct foreach_data));
- 	fd = &foreach_data;
- 
--        while ((c = getopt(argcnt, args, "R:vomlgersStTpukcfFxhdaG")) != EOF) {
-+        while ((c = getopt(argcnt, args, "R:vomlgersStTpukcfFxhdaGy:")) != EOF) {
-                 switch(c)
- 		{
- 		case 'R':
-@@ -5892,6 +5940,11 @@ cmd_foreach(void)
- 			fd->flags |= FOREACH_G_FLAG;
- 			break;
- 
-+		case 'y':
-+			fd->flags |= FOREACH_y_FLAG;
-+			fd->policy = make_sched_policy(optarg);
-+			break;
-+
- 		default:
- 			argerrs++;
- 			break;
-@@ -6554,6 +6607,10 @@ foreach(struct foreach_data *fd)
- 					cmdflags |= PS_GROUP;
- 				if (fd->flags & FOREACH_s_FLAG)
- 					cmdflags |= PS_KSTACKP;
-+				if (fd->flags & FOREACH_y_FLAG) {
-+					cmdflags |= PS_POLICY;
-+					psinfo.policy = fd->policy;
-+				}
- 				/*
- 				 * mutually exclusive flags
- 				 */ 
-@@ -7389,6 +7446,82 @@ is_kernel_thread(ulong task)
- }
- 
- /*
-+ * Checks if task policy corresponds to given mask.
-+ */
-+static int
-+has_sched_policy(ulong task, ulong policy)
-+{
-+	return !!(task_policy(task) & policy);
-+}
-+
-+/*
-+ * Converts sched policy name into mask bit.
-+ */
-+static ulong
-+sched_policy_bit_from_str(const char *policy_str)
-+{
-+	struct sched_policy_info *info = NULL;
-+	ulong policy = 0;
-+	int found = 0;
-+	char *upper = NULL;
-+	/*
-+	 * Once kernel gets more than 10 scheduling policies,
-+	 * sizes of these arrays should be adjusted
-+	 */
-+	char digit[2] = { 0, 0 };
-+	char hex[4] = { 0, 0, 0, 0 };
-+
-+	upper = GETBUF(strlen(policy_str) + 1);
-+	upper_case(policy_str, upper);
-+
-+	for (info = sched_policy_info; info->name; info++) {
-+		snprintf(digit, sizeof digit, "%lu", info->value);
-+		/*
-+		 * Not using %#lX format here since "0X" prefix
-+		 * is not prepended if 0 value is given
-+		 */
-+		snprintf(hex, sizeof hex, "0X%lX", info->value);
-+		if (strncmp(upper, info->name, strlen(info->name)) == 0 ||
-+			strncmp(upper, digit, sizeof digit) == 0 ||
-+			strncmp(upper, hex, sizeof hex) == 0) {
-+			policy = 1 << info->value;
-+			found = 1;
-+			break;
-+		}
-+	}
-+
-+	FREEBUF(upper);
-+
-+	if (!found)
-+		error(FATAL,
-+			"%s: invalid scheduling policy\n", policy_str);
-+
-+	return policy;
-+}
-+
-+/*
-+ * Converts sched policy string set into bitmask.
-+ */
-+static ulong
-+make_sched_policy(const char *policy_str)
-+{
-+	ulong policy = 0;
-+	char *iter = NULL;
-+	char *orig = NULL;
-+	char *cur = NULL;
-+
-+	iter = STRDUPBUF(policy_str);
-+	orig = iter;
-+
-+	while ((cur = strsep(&iter, ",")))
-+		policy |= sched_policy_bit_from_str(cur);
-+
-+	FREEBUF(orig);
-+
-+	return policy;
-+}
-+
-+/*
-  *  Gather an arry of pointers to the per-cpu idle tasks.  The tasklist
-  *  argument must be at least the size of ulong[NR_CPUS].  There may be
-  *  junk in everything after the first entry on a single CPU box, so the
-diff --git a/tools.c b/tools.c
-index 886d7fb..186b703 100644
---- a/tools.c
-+++ b/tools.c
-@@ -423,9 +423,10 @@ strip_hex(char *line)
-  *  Turn a string into upper-case.
-  */
- char *
--upper_case(char *s, char *buf)
-+upper_case(const char *s, char *buf)
- {
--	char *p1, *p2;
-+	const char *p1;
-+	char *p2;
- 
- 	p1 = s;
- 	p2 = buf;
-
-commit d3909692e9f64e4a1ac440afa81e9efd6e9ea0b4
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Thu Oct 26 16:54:28 2017 -0400
-
-    Fix for the "kmem -[sS]" options on Linux 4.14 and later kernels that
-    contain commit 2482ddec670fb83717d129012bc558777cb159f7, titled
-    "mm: add SLUB free list pointer obfuscation".  Without the patch,
-    there will numerous error messages of the type "kmem: <cache name>
-    slab: <address> invalid freepointer: <obfuscated address>".
-    (anderson@redhat.com)
-
-diff --git a/defs.h b/defs.h
-index 4b4e331..967fce0 100644
---- a/defs.h
-+++ b/defs.h
-@@ -1995,6 +1995,7 @@ struct offset_table {                    /* stash of commonly-used offsets */
- 	long mod_arch_specific_orc_unwind_ip;
- 	long mod_arch_specific_orc_unwind;
- 	long task_struct_policy;
-+	long kmem_cache_random;
- };
- 
- struct size_table {         /* stash of commonly-used sizes */
-diff --git a/memory.c b/memory.c
-index fb534e8..9926199 100644
---- a/memory.c
-+++ b/memory.c
-@@ -75,7 +75,7 @@ struct meminfo {           /* general purpose memory information structure */
- 	ulong container;
- 	int *freelist;
- 	int freelist_index_size;
--
-+	ulong random;
- };
- 
- /*
-@@ -293,6 +293,7 @@ static void dump_per_cpu_offsets(void);
- static void dump_page_flags(ulonglong);
- static ulong kmem_cache_nodelists(ulong);
- static void dump_hstates(void);
-+static ulong freelist_ptr(struct meminfo *, ulong, ulong);
- 
- /*
-  *  Memory display modes specific to this file.
-@@ -726,6 +727,7 @@ vm_init(void)
- 		MEMBER_OFFSET_INIT(kmem_cache_red_left_pad, "kmem_cache", "red_left_pad");
- 		MEMBER_OFFSET_INIT(kmem_cache_name, "kmem_cache", "name");
- 		MEMBER_OFFSET_INIT(kmem_cache_flags, "kmem_cache", "flags");
-+		MEMBER_OFFSET_INIT(kmem_cache_random, "kmem_cache", "random");
- 		MEMBER_OFFSET_INIT(kmem_cache_cpu_freelist, "kmem_cache_cpu", "freelist");
- 		MEMBER_OFFSET_INIT(kmem_cache_cpu_page, "kmem_cache_cpu", "page");
- 		MEMBER_OFFSET_INIT(kmem_cache_cpu_node, "kmem_cache_cpu", "node");
-@@ -18000,6 +18002,9 @@ dump_kmem_cache_slub(struct meminfo *si)
- 		si->slabsize = (PAGESIZE() << order);
- 		si->inuse = si->num_slabs = 0;
- 		si->slab_offset = offset;
-+		si->random = VALID_MEMBER(kmem_cache_random) ?
-+			ULONG(si->cache_buf + OFFSET(kmem_cache_random)) : 0;
-+
- 		if (!get_kmem_cache_slub_data(GET_SLUB_SLABS, si) ||
- 		    !get_kmem_cache_slub_data(GET_SLUB_OBJECTS, si))
- 			si->flags |= SLAB_GATHER_FAILURE;
-@@ -18587,6 +18592,15 @@ count_free_objects(struct meminfo *si, ulong freelist)
- 	return c;
- }
- 
-+static ulong
-+freelist_ptr(struct meminfo *si, ulong ptr, ulong ptr_addr)
-+{
-+	if (si->random)
-+		/* CONFIG_SLAB_FREELIST_HARDENED */
-+		return (ptr ^ si->random ^ ptr_addr);
-+	else
-+		return ptr;
-+}
- 
- static ulong
- get_freepointer(struct meminfo *si, void *object)
-@@ -18601,7 +18615,7 @@ get_freepointer(struct meminfo *si, void *object)
- 		return BADADDR;
- 	}
- 
--	return nextfree;
-+	return (freelist_ptr(si, nextfree, vaddr));
- }
- 
- static void
-diff --git a/symbols.c b/symbols.c
-index f7599e8..8a4c878 100644
---- a/symbols.c
-+++ b/symbols.c
-@@ -9378,6 +9378,8 @@ dump_offset_table(char *spec, ulong makestruct)
-                 OFFSET(kmem_cache_cpu_cache));
-         fprintf(fp, "                 kmem_cache_oo: %ld\n",
-                 OFFSET(kmem_cache_oo));
-+        fprintf(fp, "             kmem_cache_random: %ld\n",
-+                OFFSET(kmem_cache_random));
- 
-         fprintf(fp, "    kmem_cache_node_nr_partial: %ld\n",
-                 OFFSET(kmem_cache_node_nr_partial));
-
-commit e81db08bc69fb1a7a7e48f892c2038d992a71f6d
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Fri Oct 27 14:10:43 2017 -0400
-
-    Fix for the validation of the bits located in the least signficant
-    bits of mem_section.section_mem_map pointers.  Without the patch,
-    the validation functions always returned valid, due to a coding
-    error found by clang.  However, it was never really a problem
-    because it is extremely unlikely that an existing mem_section would
-    ever be invalid.
-    (oleksandr@redhat.com, anderson@redhat.com)
-
-diff --git a/memory.c b/memory.c
-index 9926199..60594a4 100644
---- a/memory.c
-+++ b/memory.c
-@@ -17003,8 +17003,8 @@ valid_section(ulong addr)
- 
- 	if ((mem_section = read_mem_section(addr)))
-         	return (ULONG(mem_section + 
--			OFFSET(mem_section_section_mem_map)) && 
--			SECTION_MARKED_PRESENT);
-+			OFFSET(mem_section_section_mem_map))
-+			& SECTION_MARKED_PRESENT);
- 	return 0;
- }
- 
-@@ -17012,11 +17012,17 @@ int
- section_has_mem_map(ulong addr)
- {
- 	char *mem_section;
-+	ulong kernel_version_bit;
-+
-+	if (THIS_KERNEL_VERSION >= LINUX(2,6,24))
-+		kernel_version_bit = SECTION_HAS_MEM_MAP;
-+	else
-+		kernel_version_bit = SECTION_MARKED_PRESENT;
- 
- 	if ((mem_section = read_mem_section(addr)))
- 		return (ULONG(mem_section + 
- 			OFFSET(mem_section_section_mem_map))
--			&& SECTION_HAS_MEM_MAP);
-+			& kernel_version_bit);
- 	return 0;
- }
- 
-
-commit 0f40db8fbac538ea448bbb2beb44912e4c43a54a
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Mon Oct 30 14:20:41 2017 -0400
-
-    Fix for the x86_64 kernel virtual address to physical address
-    translation mechanism.  Without the patch, when verifying that the
-    PAGE_PRESENT bit is set in the top-level page table, it would always
-    test positively, and the translation would continue parsing the
-    remainder of the page tables.  This would virtually never be a
-    problem in practice because if the top-level page table entry
-    existed, its PAGE_PRESENT bit would be set.
-    (oleksandr@redhat.com, anderson@redhat.com)
-
-diff --git a/x86_64.c b/x86_64.c
-index 2f9e6db..7d01140 100644
---- a/x86_64.c
-+++ b/x86_64.c
-@@ -2086,7 +2086,7 @@ x86_64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbo
- 	}
- 
- start_vtop_with_pagetable:
--	if (!(*pml4) & _PAGE_PRESENT)
-+	if (!(*pml4 & _PAGE_PRESENT))
- 		goto no_kpage;
- 	pgd_paddr = (*pml4) & PHYSICAL_PAGE_MASK;
- 	FILL_PGD(pgd_paddr, PHYSADDR, PAGESIZE());
-@@ -2187,7 +2187,7 @@ x86_64_kvtop_xen_wpt(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, i
- 		fprintf(fp, "PML4 DIRECTORY: %lx\n", vt->kernel_pgd[0]);
-                 fprintf(fp, "PAGE DIRECTORY: %lx [machine]\n", *pml4);
- 	}
--	if (!(*pml4) & _PAGE_PRESENT)
-+	if (!(*pml4 & _PAGE_PRESENT))
- 		goto no_kpage;
- 	pgd_paddr = (*pml4) & PHYSICAL_PAGE_MASK;
- 	pgd_paddr = xen_m2p(pgd_paddr);
-
-commit 9339874f3764fe99a408aec1a814b19c77f5dfe1
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Mon Oct 30 14:33:15 2017 -0400
-
-    Removed a check for a negative block_size value which is always a
-    non-negative unsigned value in the SADUMP header parsing function.
-    (oleksandr@redhat.com)
-
-diff --git a/sadump.c b/sadump.c
-index 2ccfa82..6b912d4 100644
---- a/sadump.c
-+++ b/sadump.c
-@@ -157,9 +157,6 @@ read_dump_header(char *file)
- 	}
- 
- restart:
--	if (block_size < 0)
--		return FALSE;
--
- 	if (!read_device(sph, block_size, &offset)) {
- 		error(INFO, "sadump: cannot read partition header\n");
- 		goto err;
-
-commit b2d1bba766118fddf43235f0bed483dff32ac6e0
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Mon Oct 30 14:46:32 2017 -0400
-
-    Removed a check for an impossible negative value when calculating
-    the beginning address when applying the context value specified by
-    the "search -x <count>" option.
-    (oleksandr@redhat.com)
-
-diff --git a/memory.c b/memory.c
-index 60594a4..ebd671a 100644
---- a/memory.c
-+++ b/memory.c
-@@ -14467,7 +14467,7 @@ display_with_pre_and_post(void *bufptr, ulonglong addr, struct searchinfo *si)
- 	}
- 
- 	amount = ctx * t;
--	addr_d = addr - amount < 0 ? 0 : addr - amount;
-+	addr_d = addr - amount;
- 
- 	display_memory(addr_d, ctx, flag, memtype, NULL);
- 
-
-commit e2efacdd9b7b229747a78c743b2acc6d15280a8a
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Mon Oct 30 16:49:48 2017 -0400
-
-    Implemented a new "timer -C <cpu-specifier>" option that restricts
-    the timer or hrtimer output to the timer queue data associated with
-    one or more cpus.  For multiple cpus, the cpu-specifier uses the
-    standard comma or dash separated list format.
-    (oleksandr@redhat.com)
-
-diff --git a/help.c b/help.c
-index efa55e0..f7f61a1 100644
---- a/help.c
-+++ b/help.c
-@@ -2387,7 +2387,7 @@ NULL
- char *help_timer[] = {
- "timer",
- "timer queue data",
--"[-r]",
-+"[-r][-C cpu]",
- "  This command displays the timer queue entries, both old- and new-style,",
- "  in chronological order.  In the case of the old-style timers, the",
- "  timer_table array index is shown; in the case of the new-style timers, ",
-@@ -2397,6 +2397,8 @@ char *help_timer[] = {
- "        chronological order.  In the case of the old-style hrtimers, the",
- "        expiration time is a single value; in the new-style hrtimers, the",
- "        expiration time is a range.",
-+" -C cpu Restrict the output to one or more CPUs, where multiple cpu[s] can", 
-+"        be specified, for example, as \"1,3,5\", \"1-3\", or \"1,3,5-7,10\".",
- "\nEXAMPLES",
- "    %s> timer",
- "    JIFFIES",
-diff --git a/kernel.c b/kernel.c
-index 8e95573..4638495 100644
---- a/kernel.c
-+++ b/kernel.c
-@@ -38,18 +38,18 @@ static void display_bh_1(void);
- static void display_bh_2(void);
- static void display_bh_3(void);
- static void display_bh_4(void);
--static void dump_hrtimer_data(void);
-+static void dump_hrtimer_data(const ulong *cpus);
- static void dump_hrtimer_clock_base(const void *, const int);
- static void dump_hrtimer_base(const void *, const int);
- static void dump_active_timers(const void *, ulonglong);
- static int get_expires_len(const int, const ulong *, const int);
- static void print_timer(const void *);
- static ulonglong ktime_to_ns(const void *);
--static void dump_timer_data(void);
--static void dump_timer_data_tvec_bases_v1(void);
--static void dump_timer_data_tvec_bases_v2(void);
--static void dump_timer_data_tvec_bases_v3(void);
--static void dump_timer_data_timer_bases(void);
-+static void dump_timer_data(const ulong *cpus);
-+static void dump_timer_data_tvec_bases_v1(const ulong *cpus);
-+static void dump_timer_data_tvec_bases_v2(const ulong *cpus);
-+static void dump_timer_data_tvec_bases_v3(const ulong *cpus);
-+static void dump_timer_data_timer_bases(const ulong *cpus);
- struct tv_range;
- static void init_tv_ranges(struct tv_range *, int, int, int);
- static int do_timer_list(ulong,int, ulong *, void *,ulong *,struct tv_range *);
-@@ -7353,16 +7353,24 @@ cmd_timer(void)
- {
-         int c;
- 	int rflag;
-+	char *cpuspec;
-+	ulong *cpus = NULL;
- 
- 	rflag = 0;
- 
--        while ((c = getopt(argcnt, args, "r")) != EOF) {
-+        while ((c = getopt(argcnt, args, "rC:")) != EOF) {
-                 switch(c)
-                 {
- 		case 'r':
- 			rflag = 1;
- 			break;
- 
-+		case 'C':
-+			cpuspec = optarg;
-+			cpus = get_cpumask_buf();
-+			make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL);
-+			break;
-+
-                 default:
-                         argerrs++;
-                         break;
-@@ -7373,15 +7381,18 @@ cmd_timer(void)
-                 cmd_usage(pc->curcmd, SYNOPSIS);
- 
- 	if (rflag)
--		dump_hrtimer_data();
-+		dump_hrtimer_data(cpus);
- 	else
--		dump_timer_data();
-+		dump_timer_data(cpus);
-+
-+	if (cpus)
-+		FREEBUF(cpus);
- }
- 
- static void
--dump_hrtimer_data(void)
-+dump_hrtimer_data(const ulong *cpus)
- {
--	int i, j;
-+	int i, j, k = 0;
- 	int hrtimer_max_clock_bases, max_hrtimer_bases;
- 	struct syment * hrtimer_bases;
- 
-@@ -7405,7 +7416,10 @@ dump_hrtimer_data(void)
- 	hrtimer_bases = per_cpu_symbol_search("hrtimer_bases");
- 
- 	for (i = 0; i < kt->cpus; i++) {
--		if (i)
-+		if (cpus && !NUM_IN_BITMAP(cpus, i))
-+			continue;
-+
-+		if (k++)
- 			fprintf(fp, "\n");
- 
- 		if (hide_offline_cpu(i)) {
-@@ -7752,7 +7766,7 @@ struct tv_range {
- #define TVN (6)
- 
- static void
--dump_timer_data(void)
-+dump_timer_data(const ulong *cpus)
- {
- 	int i;
- 	ulong timer_active;
-@@ -7773,16 +7787,16 @@ dump_timer_data(void)
-         struct tv_range tv[TVN];
- 
- 	if (kt->flags2 & TIMER_BASES) {
--		dump_timer_data_timer_bases();
-+		dump_timer_data_timer_bases(cpus);
- 		return;
- 	} else if (kt->flags2 & TVEC_BASES_V3) {
--		dump_timer_data_tvec_bases_v3();
-+		dump_timer_data_tvec_bases_v3(cpus);
- 		return;
- 	} else if (kt->flags & TVEC_BASES_V2) {
--		dump_timer_data_tvec_bases_v2();
-+		dump_timer_data_tvec_bases_v2(cpus);
- 		return;
- 	} else if (kt->flags & TVEC_BASES_V1) {
--		dump_timer_data_tvec_bases_v1();
-+		dump_timer_data_tvec_bases_v1(cpus);
- 		return;
- 	}
- 		
-@@ -7924,7 +7938,7 @@ dump_timer_data(void)
-  */
- 
- static void
--dump_timer_data_tvec_bases_v1(void)
-+dump_timer_data_tvec_bases_v1(const ulong *cpus)
- {
- 	int i, cpu, tdx, flen;
-         struct timer_data *td;
-@@ -7947,6 +7961,11 @@ dump_timer_data_tvec_bases_v1(void)
- 	cpu = 0;
- 
- next_cpu:
-+	if (cpus && !NUM_IN_BITMAP(cpus, cpu)) {
-+		if (++cpu < kt->cpus)
-+			goto next_cpu;
-+		return;
-+	}
- 
-         count = 0;
-         td = (struct timer_data *)NULL;
-@@ -8039,7 +8058,7 @@ next_cpu:
-  */
- 
- static void
--dump_timer_data_tvec_bases_v2(void)
-+dump_timer_data_tvec_bases_v2(const ulong *cpus)
- {
- 	int i, cpu, tdx, flen;
-         struct timer_data *td;
-@@ -8073,6 +8092,11 @@ dump_timer_data_tvec_bases_v2(void)
- 	cpu = 0;
- 
- next_cpu:
-+	if (cpus && !NUM_IN_BITMAP(cpus, cpu)) {
-+		if (++cpu < kt->cpus)
-+			goto next_cpu;
-+		return;
-+	}
- 	/*
- 	 * hide data of offline cpu and goto next cpu
- 	 */
-@@ -8185,7 +8209,7 @@ next_cpu:
-  *  Linux 4.2 timers use new tvec_root, tvec and timer_list structures
-  */
- static void
--dump_timer_data_tvec_bases_v3(void)
-+dump_timer_data_tvec_bases_v3(const ulong *cpus)
- {
- 	int i, cpu, tdx, flen;
- 	struct timer_data *td;
-@@ -8216,6 +8240,11 @@ dump_timer_data_tvec_bases_v3(void)
- 	cpu = 0;
- 
- next_cpu:
-+	if (cpus && !NUM_IN_BITMAP(cpus, cpu)) {
-+		if (++cpu < kt->cpus)
-+			goto next_cpu;
-+		return;
-+	}
- 	/*
- 	 * hide data of offline cpu and goto next cpu
- 	 */
-@@ -8758,9 +8787,9 @@ do_timer_list_v4(struct timer_bases_data *data)
-  *  Linux 4.8 timers use new timer_bases[][]
-  */
- static void
--dump_timer_data_timer_bases(void)
-+dump_timer_data_timer_bases(const ulong *cpus)
- {
--	int i, cpu, flen, base, nr_bases, found, display;
-+	int i, cpu, flen, base, nr_bases, found, display, j = 0;
- 	struct syment *sp;
- 	ulong timer_base, jiffies, function;
- 	struct timer_bases_data data;
-@@ -8785,6 +8814,11 @@ dump_timer_data_timer_bases(void)
- 		RJUST|LONG_DEC,MKSTR(jiffies)));
- 
- next_cpu:
-+	if (cpus && !NUM_IN_BITMAP(cpus, cpu)) {
-+		if (++cpu < kt->cpus)
-+			goto next_cpu;
-+		goto done;
-+	}
- 	/*
- 	 * hide data of offline cpu and goto next cpu
- 	 */
-@@ -8803,7 +8837,7 @@ next_cpu:
- 	else
- 		timer_base = sp->value;
- 
--	if (cpu)
-+	if (j++)
- 		fprintf(fp, "\n");
- next_base:
- 
diff --git a/SOURCES/github_ddace972_exception_frame.patch b/SOURCES/github_ddace972_exception_frame.patch
deleted file mode 100644
index 116d86b..0000000
--- a/SOURCES/github_ddace972_exception_frame.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-commit ddace9720fe7582cd2c92000f75f1f261daa53fd
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Fri Feb 9 16:26:27 2018 -0500
-
-    Fix for the ARM64 "bt" command in kernels that contain commit
-    30d88c0e3ace625a92eead9ca0ad94093a8f59fe, titled "arm64: entry:
-    Apply BP hardening for suspicious interrupts from EL0".  Without
-    the patch, there may be invalid kernel kernel exception frames
-    displayed on an active task's kernel stack, often below a stackframe
-    of the "do_el0_ia_bp_hardening" function; the address translation
-    of the PC and LR values in the the bogus exception frame will
-    display "[unknown or invalid address]".
-    (anderson@redhat.com)
-
-
---- crash-7.2.0/arm64.c.orig
-+++ crash-7.2.0/arm64.c
-@@ -2411,8 +2411,10 @@ arm64_back_trace_cmd(struct bt_info *bt)
- 
- 		if (arm64_in_exception_text(bt->instptr) && INSTACK(stackframe.fp, bt)) {
- 			if (!(bt->flags & BT_IRQSTACK) ||
--			    (((stackframe.sp + SIZE(pt_regs)) < bt->stacktop)))
--				exception_frame = stackframe.fp - KERN_EFRAME_OFFSET;
-+			    ((stackframe.sp + SIZE(pt_regs)) < bt->stacktop)) {
-+				if (arm64_is_kernel_exception_frame(bt, stackframe.fp - KERN_EFRAME_OFFSET))
-+					exception_frame = stackframe.fp - KERN_EFRAME_OFFSET;
-+			}
- 		}
- 
- 		if ((bt->flags & BT_IRQSTACK) &&
diff --git a/SOURCES/github_f294197b_bpf_idr.patch b/SOURCES/github_f294197b_bpf_idr.patch
new file mode 100644
index 0000000..b0d601a
--- /dev/null
+++ b/SOURCES/github_f294197b_bpf_idr.patch
@@ -0,0 +1,250 @@
+commit f294197b5511537e6b14d5e1db324f4fc4fdd3f8
+Author: Dave Anderson <anderson@redhat.com>
+Date:   Fri Jul 6 10:57:50 2018 -0400
+
+    Support for the "bpf" command on RHEL 3.10.0-913.el7 and later
+    3.10-based RHEL7 kernels, which contain a backport of the upstream
+    eBPF code, but still use the older, pre-4.11, IDR facility that does
+    not use radix trees for linking the active bpf_prog and bpf_map
+    structures.  Without the patch, the command indicates "bpf: command
+    not supported or applicable on this architecture or kernel".
+    (anderson@redhat.com)
+
+diff --git a/bpf.c b/bpf.c
+index 427263d..8871b76 100644
+--- a/bpf.c
++++ b/bpf.c
+@@ -45,6 +45,10 @@ static void bpf_prog_gpl_compatible(char *, ulong);
+ static void dump_xlated_plain(void *, unsigned int, int);
+ static void print_boot_time(unsigned long long, char *, unsigned int);
+ 
++static int do_old_idr(int, ulong, struct radix_tree_pair *);
++#define OLD_IDR_INIT   (1)
++#define OLD_IDR_COUNT  (2)
++#define OLD_IDR_GATHER (3)
+ 
+ #define PROG_ID        (0x1)
+ #define MAP_ID         (0x2)
+@@ -167,7 +171,6 @@ bpf_init(struct bpf_info *bpf)
+ 		    !VALID_STRUCT(bpf_map) ||
+ 		    !VALID_STRUCT(bpf_insn) ||
+ 		    INVALID_MEMBER(bpf_prog_aux) ||
+-		    INVALID_MEMBER(idr_idr_rt) ||
+ 		    INVALID_MEMBER(bpf_prog_type) ||
+ 		    INVALID_MEMBER(bpf_prog_tag) ||
+ 		    INVALID_MEMBER(bpf_prog_jited_len) ||
+@@ -210,6 +213,9 @@ bpf_init(struct bpf_info *bpf)
+ 			mkstring(buf2, VADDR_PRLEN, CENTER|LJUST, "BPF_MAP"),
+ 			mkstring(buf3, bpf->bpf_map_map_type_size, CENTER|LJUST, "BPF_MAP_TYPE"));
+ 
++		if (INVALID_MEMBER(idr_idr_rt))
++			do_old_idr(OLD_IDR_INIT, 0, NULL);
++
+ 		bpf->status = TRUE;
+ 		break;
+ 
+@@ -220,24 +226,38 @@ bpf_init(struct bpf_info *bpf)
+ 		command_not_supported();
+ 	}
+ 
+-	bpf->progs = do_radix_tree(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
+-		RADIX_TREE_COUNT, NULL);
++	if (VALID_MEMBER(idr_idr_rt))
++		bpf->progs = do_radix_tree(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
++			RADIX_TREE_COUNT, NULL);
++	else 
++		bpf->progs = do_old_idr(OLD_IDR_COUNT, symbol_value("prog_idr"), NULL);
++
+ 	if (bpf->progs) {
+ 		len = sizeof(struct radix_tree_pair) * (bpf->progs+1);
+ 		bpf->proglist = (struct radix_tree_pair *)GETBUF(len);
+ 		bpf->proglist[0].index = bpf->progs;
+-		bpf->progs = do_radix_tree(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
+-			RADIX_TREE_GATHER, bpf->proglist);
++		if (VALID_MEMBER(idr_idr_rt))
++			bpf->progs = do_radix_tree(symbol_value("prog_idr") + OFFSET(idr_idr_rt),
++				RADIX_TREE_GATHER, bpf->proglist);
++		else
++			bpf->progs = do_old_idr(OLD_IDR_GATHER, symbol_value("prog_idr"), bpf->proglist);
+ 	}
+ 
+-	bpf->maps = do_radix_tree(symbol_value("map_idr") + OFFSET(idr_idr_rt), 
+-		RADIX_TREE_COUNT, NULL);
++	if (VALID_MEMBER(idr_idr_rt))
++		bpf->maps = do_radix_tree(symbol_value("map_idr") + OFFSET(idr_idr_rt), 
++			RADIX_TREE_COUNT, NULL);
++	else
++		bpf->maps = do_old_idr(OLD_IDR_COUNT, symbol_value("map_idr"), NULL);
++
+ 	if (bpf->maps) {
+ 		len = sizeof(struct radix_tree_pair) * (bpf->maps+1);
+ 		bpf->maplist = (struct radix_tree_pair *)GETBUF(len);
+ 		bpf->maplist[0].index = bpf->maps;
+-		bpf->maps = do_radix_tree(symbol_value("map_idr") + OFFSET(idr_idr_rt),
+-			RADIX_TREE_GATHER, bpf->maplist);
++		if (VALID_MEMBER(idr_idr_rt))
++			bpf->maps = do_radix_tree(symbol_value("map_idr") + OFFSET(idr_idr_rt),
++				RADIX_TREE_GATHER, bpf->maplist);
++		else
++			bpf->maps = do_old_idr(OLD_IDR_GATHER, symbol_value("map_idr"), bpf->maplist);
+ 	}
+ 
+ 	bpf->bpf_prog_buf = GETBUF(SIZE(bpf_prog));
+@@ -538,8 +558,10 @@ do_map_only:
+ 	}
+ 
+ bailout:
+-	FREEBUF(bpf->proglist);
+-	FREEBUF(bpf->maplist);
++	if (bpf->proglist)
++		FREEBUF(bpf->proglist);
++	if (bpf->maplist)
++		FREEBUF(bpf->maplist);
+ 	FREEBUF(bpf->bpf_prog_buf);
+ 	FREEBUF(bpf->bpf_prog_aux_buf);
+ 	FREEBUF(bpf->bpf_map_buf);
+@@ -1255,3 +1277,50 @@ print_boot_time(unsigned long long nsecs, char *buf, unsigned int size)
+ 	sprintf(buf, "(unknown)");
+ #endif
+ }
++
++/*
++ *  Borrow the old (pre-radix_tree) IDR facility code used by
++ *  the ipcs command.
++ */
++static int
++do_old_idr(int cmd, ulong idr, struct radix_tree_pair *rtp)
++{
++	int i, max, cur, next_id, total = 0;
++	ulong entry;
++
++	switch (cmd)
++	{
++	case OLD_IDR_INIT:
++		ipcs_init();
++		break;
++
++	case OLD_IDR_COUNT:
++		readmem(idr + OFFSET(idr_cur), KVADDR, &cur, 
++			sizeof(int), "idr.cur", FAULT_ON_ERROR);
++		for (total = next_id = 0; next_id < cur; next_id++) {
++			entry = idr_find(idr, next_id);
++			if (entry == 0)
++				continue;
++			total++;
++		}
++		break;
++
++	case OLD_IDR_GATHER:
++		max = rtp[0].index;
++		readmem(idr + OFFSET(idr_cur), KVADDR, &cur, 
++			sizeof(int), "idr.cur", FAULT_ON_ERROR);
++		for (i = total = next_id = 0; next_id < cur; next_id++) {
++			entry = idr_find(idr, next_id);
++			if (entry == 0)
++				continue;
++			total++;
++			rtp[i].index = next_id;
++			rtp[i].value = (void *)entry;
++			if (++i == max)
++				break;
++		}
++		break;
++	}
++
++	return total;
++}
+diff --git a/defs.h b/defs.h
+index e6e3850..b05aecc 100644
+--- a/defs.h
++++ b/defs.h
+@@ -2031,6 +2031,7 @@ struct offset_table {                    /* stash of commonly-used offsets */
+ 	long bpf_prog_aux_load_time;
+ 	long bpf_prog_aux_user;
+ 	long user_struct_uid;
++	long idr_cur;
+ };
+ 
+ struct size_table {         /* stash of commonly-used sizes */
+@@ -5590,6 +5591,12 @@ enum {
+ void dev_init(void);
+ void dump_dev_table(void);
+ 
++/*
++ *  ipcs.c
++ */
++void ipcs_init(void);
++ulong idr_find(ulong, int);
++
+ #ifdef ARM
+ void arm_init(int);
+ void arm_dump_machdep_table(ulong);
+diff --git a/ipcs.c b/ipcs.c
+index ef51fdd..80f78e4 100644
+--- a/ipcs.c
++++ b/ipcs.c
+@@ -79,13 +79,11 @@ struct ipcs_table {
+  * function declaration
+  */
+ 
+-static void ipcs_init(void);
+ static int dump_shared_memory(int, ulong, int, ulong);
+ static int dump_semaphore_arrays(int, ulong, int, ulong);
+ static int dump_message_queues(int, ulong, int, ulong);
+ static int ipc_search_idr(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int);
+ static int ipc_search_array(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int);
+-static ulong idr_find(ulong, int);
+ static int dump_shm_info(ulong, int, ulong, int, int);
+ static int dump_sem_info(ulong, int, ulong, int, int);
+ static int dump_msg_info(ulong, int, ulong, int, int);
+@@ -101,7 +99,7 @@ static void gather_radix_tree_entries(ulong);
+  */
+ static struct ipcs_table ipcs_table = { 0 };
+ 
+-static void
++void
+ ipcs_init(void)
+ {
+ 	if (ipcs_table.init_flags & IPCS_INIT) {
+@@ -119,6 +117,7 @@ ipcs_init(void)
+ 	MEMBER_OFFSET_INIT(idr_layer_layer, "idr_layer", "layer");
+ 	MEMBER_OFFSET_INIT(idr_layer_ary, "idr_layer", "ary");
+ 	MEMBER_OFFSET_INIT(idr_top, "idr", "top");
++	MEMBER_OFFSET_INIT(idr_cur, "idr", "cur");
+ 	MEMBER_OFFSET_INIT(ipc_id_ary_p, "ipc_id_ary", "p");
+ 	MEMBER_OFFSET_INIT(ipc_ids_entries, "ipc_ids", "entries");
+ 	MEMBER_OFFSET_INIT(ipc_ids_max_id, "ipc_ids", "max_id");
+@@ -188,7 +187,10 @@ ipcs_init(void)
+ 		ipcs_table.shm_f_op_huge_addr = -1;
+ 	}
+ 
+-	if (BITS32())
++	if (VALID_MEMBER(idr_layer_ary) && 
++	    get_array_length("idr_layer.ary", NULL, 0) > 64)
++		ipcs_table.idr_bits = 8;
++	else if (BITS32())
+ 		ipcs_table.idr_bits = 5;
+ 	else if (BITS64())
+ 		ipcs_table.idr_bits = 6;
+@@ -635,7 +637,7 @@ ipc_search_idr(ulong ipc_ids_p, int specified, ulong specified_value, int (*fn)(
+ /*
+  * search every idr_layer
+  */
+-static ulong
++ulong
+ idr_find(ulong idp, int id)
+ {
+ 	ulong idr_layer_p;
+diff --git a/symbols.c b/symbols.c
+index bf55319..8ff1430 100644
+--- a/symbols.c
++++ b/symbols.c
+@@ -10041,6 +10041,8 @@ dump_offset_table(char *spec, ulong makestruct)
+ 		OFFSET(idr_layers));
+ 	fprintf(fp, "                       idr_top: %ld\n",
+ 		OFFSET(idr_top));
++	fprintf(fp, "                       idr_cur: %ld\n",
++		OFFSET(idr_cur));
+ 	fprintf(fp, "                  ipc_id_ary_p: %ld\n",
+ 		OFFSET(ipc_id_ary_p));
+ 	fprintf(fp, "               ipc_ids_entries: %ld\n",
diff --git a/SOURCES/github_f852f5ce_to_03a3e57b.patch b/SOURCES/github_f852f5ce_to_03a3e57b.patch
deleted file mode 100644
index 36fde99..0000000
--- a/SOURCES/github_f852f5ce_to_03a3e57b.patch
+++ /dev/null
@@ -1,785 +0,0 @@
-commit f852f5ce4d28f88308f0e555c067e63e3edd7f37
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Fri Nov 3 09:21:22 2017 -0400
-
-    Fix for a "ps -l" regression introduced by the new "ps -y" option
-    introduced above.  Without the patch, the -l option generates a
-    segmentation violation if not accompanied by a -C cpu specifier
-    option.
-    (vinayakm.list@gmail.com)
-
-diff --git a/task.c b/task.c
-index 5754159..f2628b7 100644
---- a/task.c
-+++ b/task.c
-@@ -3485,7 +3485,7 @@ show_last_run(struct task_context *tc, struct psinfo *psi)
- 	sprintf(format, "[%c%dll%c] ", '%', c, 
- 		pc->output_radix == 10 ? 'u' : 'x');
- 
--	if (psi) {
-+	if (psi && psi->cpus) {
- 		for (c = others = 0; c < kt->cpus; c++) {
- 			if (!NUM_IN_BITMAP(psi->cpus, c))
- 				continue;
-
-commit 7ac1368cdca0fc2013bb3963456fcd2574c7cdd7
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Mon Nov 6 10:48:40 2017 -0500
-
-    Fix for the "kmem -i" and "kmem -V" options in Linux 4.8 and later
-    kernels containing commit 75ef7184053989118d3814c558a9af62e7376a58,
-    titled "mm, vmstat: add infrastructure for per-node vmstats".
-    Without the patch, the CACHED line of "kmem -i" shows 0, and the
-    VM_STAT section of "kmem -V" is missing entirely.
-    (vinayakm.list@gmail.com)
-
-diff --git a/memory.c b/memory.c
-index ebd671a..3097558 100644
---- a/memory.c
-+++ b/memory.c
-@@ -17340,30 +17340,43 @@ vm_stat_init(void)
- 	int c ATTRIBUTE_UNUSED;
-         struct gnu_request *req;
- 	char *start;
--	long enum_value;
-+	long enum_value, zc = -1;
-+	int split_vmstat = 0, ni = 0;
- 
- 	if (vt->flags & VM_STAT)
- 		return TRUE;
- 
--	if ((vt->nr_vm_stat_items == -1) || !symbol_exists("vm_stat"))
-+	if ((vt->nr_vm_stat_items == -1) ||
-+		(!symbol_exists("vm_stat") && !symbol_exists("vm_zone_stat")))
- 		goto bailout;
- 
-         /*
-          *  look for type: type = atomic_long_t []
-          */
- 	if (LKCD_KERNTYPES()) {
--        	if (!symbol_exists("vm_stat"))
-+		if ((!symbol_exists("vm_stat") &&
-+				!symbol_exists("vm_zone_stat")))
- 			goto bailout;
- 		/* 
- 		 *  Just assume that vm_stat is an array; there is
- 		 *  no symbol info in a kerntypes file. 
- 		 */
- 	} else {
--		if (!symbol_exists("vm_stat") ||
--		    get_symbol_type("vm_stat", NULL, NULL) != TYPE_CODE_ARRAY)
-+		if (symbol_exists("vm_stat") &&
-+		    get_symbol_type("vm_stat", NULL, NULL) == TYPE_CODE_ARRAY) {
-+			vt->nr_vm_stat_items =
-+				get_array_length("vm_stat", NULL, 0);
-+		} else if (symbol_exists("vm_zone_stat") &&
-+			get_symbol_type("vm_zone_stat",
-+			NULL, NULL) == TYPE_CODE_ARRAY) {
-+			vt->nr_vm_stat_items =
-+				get_array_length("vm_zone_stat", NULL, 0)
-+				+ get_array_length("vm_node_stat", NULL, 0);
-+			split_vmstat = 1;
-+			enumerator_value("NR_VM_ZONE_STAT_ITEMS", &zc);
-+		} else {
- 			goto bailout;
--
--		vt->nr_vm_stat_items = get_array_length("vm_stat", NULL, 0);
-+		}
- 	}
- 
-         open_tmpfile();
-@@ -17372,6 +17385,14 @@ vm_stat_init(void)
-         req->name = "zone_stat_item";
-         req->flags = GNU_PRINT_ENUMERATORS;
-         gdb_interface(req);
-+
-+	if (split_vmstat) {
-+		req->command = GNU_GET_DATATYPE;
-+		req->name = "node_stat_item";
-+		req->flags = GNU_PRINT_ENUMERATORS;
-+		gdb_interface(req);
-+	}
-+
-         FREEBUF(req);
- 
- 	stringlen = 1;
-@@ -17383,11 +17404,17 @@ vm_stat_init(void)
- 			continue;
- 		clean_line(buf);
- 		c = parse_line(buf, arglist);
--		if (STREQ(arglist[0], "NR_VM_ZONE_STAT_ITEMS")) {
-+		if ((!split_vmstat &&
-+			STREQ(arglist[0], "NR_VM_ZONE_STAT_ITEMS")) ||
-+			(split_vmstat &&
-+			STREQ(arglist[0], "NR_VM_NODE_STAT_ITEMS"))) {
- 			if (LKCD_KERNTYPES())
- 				vt->nr_vm_stat_items = 
- 					MAX(atoi(arglist[2]), count);
- 			break;
-+		} else if (split_vmstat &&
-+			STREQ(arglist[0], "NR_VM_ZONE_STAT_ITEMS")) {
-+			continue;
- 		} else {
- 			stringlen += strlen(arglist[0]);
- 			count++;
-@@ -17409,18 +17436,24 @@ vm_stat_init(void)
-                 if (strstr(buf, "{") || strstr(buf, "}"))
-                         continue;
- 		c = parse_line(buf, arglist);
--		if (enumerator_value(arglist[0], &enum_value))
--			i = enum_value;
--		else {
-+		if (!enumerator_value(arglist[0], &enum_value)) {
- 			close_tmpfile();
- 			goto bailout;
- 		}
-+
-+		i = ni + enum_value;
-+		if (!ni && (enum_value == zc)) {
-+			ni = zc;
-+			continue;
-+		}
-+
- 		if (i < vt->nr_vm_stat_items) {
- 			vt->vm_stat_items[i] = start;
- 			strcpy(start, arglist[0]);
- 			start += strlen(arglist[0]) + 1;
- 		}
-         }
-+
- 	close_tmpfile();
- 
- 	vt->flags |= VM_STAT;
-@@ -17443,39 +17476,61 @@ dump_vm_stat(char *item, long *retval, ulong zone)
- 	ulong *vp;
- 	ulong location;
- 	int i, maxlen, len;
-+	long tc, zc = 0, nc = 0;
-+	int split_vmstat = 0;
- 
- 	if (!vm_stat_init()) {
- 		if (!item)
- 			if (CRASHDEBUG(1))
--				error(INFO, 
-+				error(INFO,
- 			    	    "vm_stat not available in this kernel\n");
- 		return FALSE;
- 	}
- 
- 	buf = GETBUF(sizeof(ulong) * vt->nr_vm_stat_items);
- 
--	location = zone ? zone : symbol_value("vm_stat");
--
--	readmem(location, KVADDR, buf, 
--	    sizeof(ulong) * vt->nr_vm_stat_items, 
--	    "vm_stat", FAULT_ON_ERROR);
-+	if (symbol_exists("vm_node_stat") && symbol_exists("vm_zone_stat"))
-+		split_vmstat = 1;
-+	else
-+		location = zone ? zone : symbol_value("vm_stat");
-+
-+	if (split_vmstat) {
-+		enumerator_value("NR_VM_ZONE_STAT_ITEMS", &zc);
-+		location = zone ? zone : symbol_value("vm_zone_stat");
-+		readmem(location, KVADDR, buf,
-+			sizeof(ulong) * zc,
-+			"vm_zone_stat", FAULT_ON_ERROR);
-+		if (!zone) {
-+			location = symbol_value("vm_node_stat");
-+			enumerator_value("NR_VM_NODE_STAT_ITEMS", &nc);
-+			readmem(location, KVADDR, buf + (sizeof(ulong) * zc),
-+				sizeof(ulong) * nc,
-+				"vm_node_stat", FAULT_ON_ERROR);
-+		}
-+		tc = zc + nc;
-+	} else {
-+		readmem(location, KVADDR, buf,
-+			sizeof(ulong) * vt->nr_vm_stat_items,
-+			"vm_stat", FAULT_ON_ERROR);
-+		tc = vt->nr_vm_stat_items;
-+	}
- 
- 	if (!item) {
- 		if (!zone)
- 			fprintf(fp, "  VM_STAT:\n");
--		for (i = maxlen = 0; i < vt->nr_vm_stat_items; i++)
-+		for (i = maxlen = 0; i < tc; i++)
- 			if ((len = strlen(vt->vm_stat_items[i])) > maxlen)
- 				maxlen = len;
- 		vp = (ulong *)buf;
--		for (i = 0; i < vt->nr_vm_stat_items; i++)
--			fprintf(fp, "%s%s: %ld\n", 
-+		for (i = 0; i < tc; i++)
-+			fprintf(fp, "%s%s: %ld\n",
- 				space(maxlen - strlen(vt->vm_stat_items[i])),
- 				 vt->vm_stat_items[i], vp[i]);
- 		return TRUE;
- 	}
- 
- 	vp = (ulong *)buf;
--	for (i = 0; i < vt->nr_vm_stat_items; i++) {
-+	for (i = 0; i < tc; i++) {
- 		if (STREQ(vt->vm_stat_items[i], item)) {
- 			*retval = vp[i];
- 			return TRUE;
-
-commit 333df037bc72aa81faf0904aaea29d43be2c724d
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Mon Nov 6 11:01:45 2017 -0500
-
-    Fix for Linux 4.11 and later kernels that contain kernel commit
-    4b3ef9daa4fc0bba742a79faecb17fdaaead083b, titled "mm/swap: split
-    swap cache into 64MB trunks".  Without the patch, the CACHED line
-    of "kmem -i" may show nonsensical data.
-    (vinayakm.list@gmail.com)
-
-diff --git a/memory.c b/memory.c
-index 3097558..7537c43 100644
---- a/memory.c
-+++ b/memory.c
-@@ -8236,7 +8236,44 @@ dump_kmeminfo(void)
- 		char *swapper_space = GETBUF(SIZE(address_space));
- 
- 		swapper_space_nrpages = 0;
--		if (symbol_exists("swapper_spaces") && 
-+		if (symbol_exists("nr_swapper_spaces") &&
-+			(len = get_array_length("nr_swapper_spaces",
-+				NULL, 0))) {
-+			char *nr_swapper_space =
-+				GETBUF(len * sizeof(unsigned int));
-+			readmem(symbol_value("nr_swapper_spaces"), KVADDR,
-+				nr_swapper_space,  len * sizeof(unsigned int),
-+				"nr_swapper_space", RETURN_ON_ERROR);
-+			for (i = 0; i < len; i++) {
-+				int j;
-+				unsigned long sa;
-+				unsigned int banks = UINT(nr_swapper_space +
-+					(i * sizeof(unsigned int)));
-+
-+				if (!banks)
-+					continue;
-+
-+				readmem(symbol_value("swapper_spaces") +
-+					(i * sizeof(void *)),KVADDR,
-+					&sa, sizeof(void *),
-+					"swapper_space", RETURN_ON_ERROR);
-+
-+				if (!sa)
-+					continue;
-+
-+				for (j = 0; j < banks; j++) {
-+					readmem(sa + j * SIZE(address_space),
-+						KVADDR, swapper_space,
-+						SIZE(address_space),
-+						"swapper_space",
-+						RETURN_ON_ERROR);
-+					swapper_space_nrpages +=
-+						ULONG(swapper_space +
-+						OFFSET(address_space_nrpages));
-+				}
-+			}
-+			FREEBUF(nr_swapper_space);
-+		} else if (symbol_exists("swapper_spaces") &&
- 		    (len = get_array_length("swapper_spaces", NULL, 0))) {
- 			for (i = 0; i < len; i++) {
- 		    		if (!readmem(symbol_value("swapper_spaces") + 
-@@ -8253,7 +8290,7 @@ dump_kmeminfo(void)
- 		    RETURN_ON_ERROR))
- 			swapper_space_nrpages = ULONG(swapper_space + 
- 				OFFSET(address_space_nrpages));
--			
-+
- 		page_cache_size = nr_file_pages - swapper_space_nrpages -
- 			buffer_pages;
- 		FREEBUF(swapper_space);
-
-commit 613e5c7d6998c61880498537b4f288ef095cbe14
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Mon Nov 6 15:12:59 2017 -0500
-
-    Implemented a new "dev -D" option that is the same as "dev -d", but
-    filters out the display of disks that have no I/O in progress.
-    (oleksandr@redhat.com)
-
-diff --git a/dev.c b/dev.c
-index e46081e..3db898a 100644
---- a/dev.c
-+++ b/dev.c
-@@ -31,7 +31,7 @@ static const char *pci_strclass (uint, char *);
- static const char *pci_strvendor(uint, char *); 
- static const char *pci_strdev(uint, uint, char *); 
- 
--static void diskio_option(void);
-+static void diskio_option(ulong flags);
-  
- static struct dev_table {
-         ulong flags;
-@@ -42,6 +42,9 @@ struct dev_table *dt = &dev_table;
- #define DEV_INIT    0x1
- #define DISKIO_INIT 0x2
- 
-+#define DIOF_ALL	1 << 0
-+#define DIOF_NONZERO	1 << 1
-+
- void
- dev_init(void)
- {
-@@ -93,11 +96,15 @@ cmd_dev(void)
- 
- 	flags = 0;
- 
--        while ((c = getopt(argcnt, args, "dpi")) != EOF) {
-+        while ((c = getopt(argcnt, args, "dDpi")) != EOF) {
-                 switch(c)
-                 {
- 		case 'd':
--			diskio_option();
-+			diskio_option(DIOF_ALL);
-+			return;
-+
-+		case 'D':
-+			diskio_option(DIOF_NONZERO);
- 			return;
- 
- 		case 'i':
-@@ -4002,7 +4009,7 @@ init_iter(struct iter *i)
- }
- 
- static void 
--display_one_diskio(struct iter *i, unsigned long gendisk)
-+display_one_diskio(struct iter *i, unsigned long gendisk, ulong flags)
- {
- 	char disk_name[BUFSIZE + 1];
- 	char buf0[BUFSIZE];
-@@ -4028,6 +4035,10 @@ display_one_diskio(struct iter *i, unsigned long gendisk)
- 		"gen_disk.major", FAULT_ON_ERROR);
- 	i->get_diskio(queue_addr, &io);
- 
-+	if ((flags & DIOF_NONZERO)
-+		&& (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),
-@@ -4055,7 +4066,7 @@ display_one_diskio(struct iter *i, unsigned long gendisk)
- }
- 
- static void 
--display_all_diskio(void)
-+display_all_diskio(ulong flags)
- {
- 	struct iter i;
- 	unsigned long gendisk;
-@@ -4089,7 +4100,7 @@ display_all_diskio(void)
- 		mkstring(buf5, 5, RJUST, "DRV"));
- 
- 	while ((gendisk = i.next_disk(&i)) != 0)
--		display_one_diskio(&i, gendisk);
-+		display_one_diskio(&i, gendisk, flags);
- }
- 
- static 
-@@ -4149,8 +4160,8 @@ void diskio_init(void)
- }
- 
- static void 
--diskio_option(void)
-+diskio_option(ulong flags)
- {
- 	diskio_init();
--	display_all_diskio();
-+	display_all_diskio(flags);
- }
-diff --git a/help.c b/help.c
-index f7f61a1..fa01bfb 100644
---- a/help.c
-+++ b/help.c
-@@ -2722,7 +2722,7 @@ NULL
- char *help_dev[] = {
- "dev",
- "device data",
--"[-i | -p | -d]",
-+"[-i | -p | -d | -D]",
- "  If no argument is entered, this command dumps character and block",
- "  device data.\n",
- "    -i  display I/O port usage; on 2.4 kernels, also display I/O memory usage.",
-@@ -2736,6 +2736,7 @@ char *help_dev[] = {
- "           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).",
-+"    -D  same as -d, but filter out disks with no in-progress I/O requests.",
- "\nEXAMPLES",
- "  Display character and block device data:\n",
- "    %s> dev",
-
-commit 57eaba59bff54ab3158d3a909e9f64551e27accf
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Wed Nov 8 14:22:16 2017 -0500
-
-    If a line number request for a module text address initially fails,
-    force the embedded gdb module to complete its two-stage strategy
-    used for reading debuginfo symbol tables from module object files,
-    and then retry the line number extraction.  This automatically does
-    what the "mod -r" or "crash --readnow" options accomplish.
-    (anderson@redhat.com)
-
-diff --git a/defs.h b/defs.h
-index 967fce0..18f36b3 100644
---- a/defs.h
-+++ b/defs.h
-@@ -2688,6 +2688,7 @@ struct load_module {
- 	struct syment *mod_init_symend;
- 	ulong mod_percpu;
- 	ulong mod_percpu_size;
-+	struct objfile *loaded_objfile;
- };
- 
- #define IN_MODULE(A,L) \
-@@ -4479,6 +4480,7 @@ struct gnu_request {
-     		struct symbol *sym;
-     		struct objfile *obj;
-   	} global_iterator;
-+	struct load_module *lm;
- };
- 
- /*
-diff --git a/gdb-7.6.patch b/gdb-7.6.patch
-index 094f01a..6aeffda 100644
---- a/gdb-7.6.patch
-+++ b/gdb-7.6.patch
-@@ -2323,3 +2323,72 @@ diff -up gdb-7.6/opcodes/configure.orig gdb-7.6/opcodes/configure
-      NO_WERROR="-Wno-error"
-  fi
-  
-+--- gdb-7.6/gdb/symtab.c.orig
-++++ gdb-7.6/gdb/symtab.c
-+@@ -5266,6 +5266,7 @@ gdb_get_line_number(struct gnu_request *
-+ {
-+         struct symtab_and_line sal;
-+ 	struct symbol *sym;
-++	struct objfile *objfile;
-+         CORE_ADDR pc;
-+ 
-+ #define LASTCHAR(s)      (s[strlen(s)-1])
-+@@ -5281,8 +5282,22 @@ gdb_get_line_number(struct gnu_request *
-+         sal = find_pc_line(pc, 0);
-+ 
-+ 	if (!sal.symtab) {
-+-		req->buf[0] = '\0';
-+-		return;
-++		/*
-++		 *  If a module address line number can't be found, it's typically
-++		 *  due to its addrmap still containing offset values because its 
-++		 *  objfile doesn't have full symbols loaded.
-++		 */
-++		if (req->lm) {
-++			objfile = req->lm->loaded_objfile;
-++			if (!objfile_has_full_symbols(objfile) && objfile->sf) { 
-++				objfile->sf->qf->expand_all_symtabs(objfile);
-++				sal = find_pc_line(pc, 0);
-++			}
-++		}
-++		if (!sal.symtab) {
-++			req->buf[0] = '\0';
-++			return;
-++		}
-+ 	}
-+ 
-+         if (sal.symtab->filename && sal.symtab->dirname) {
-+@@ -5557,7 +5572,6 @@ struct load_module *gdb_current_load_mod
-+ static void 
-+ gdb_add_symbol_file(struct gnu_request *req)
-+ {
-+-	register struct objfile *loaded_objfile = NULL;
-+ 	register struct objfile *objfile;
-+ 	register struct minimal_symbol *m;
-+ 	struct load_module *lm;
-+@@ -5576,6 +5590,7 @@ gdb_add_symbol_file(struct gnu_request *
-+ 
-+ 	req->name = lm->mod_namelist;
-+ 	gdb_delete_symbol_file(req);
-++	lm->loaded_objfile = NULL;
-+ 
-+ 	if ((lm->mod_flags & MOD_NOPATCH) == 0) {
-+ 	        for (i = 0 ; i < lm->mod_sections; i++) {
-+@@ -5623,12 +5638,15 @@ gdb_add_symbol_file(struct gnu_request *
-+ 
-+         ALL_OBJFILES(objfile) {
-+ 		if (same_file(objfile->name, lm->mod_namelist)) {
-+-                        loaded_objfile = objfile;
-++			if (objfile->separate_debug_objfile)
-++				lm->loaded_objfile = objfile->separate_debug_objfile;
-++			else
-++				lm->loaded_objfile = objfile;
-+ 			break;
-+ 		}
-+         }
-+ 
-+-	if (!loaded_objfile)
-++	if (!lm->loaded_objfile)
-+                 req->flags |= GNU_COMMAND_FAILED;
-+ }
-+ 
-diff --git a/symbols.c b/symbols.c
-index 8a4c878..0d85ff7 100644
---- a/symbols.c
-+++ b/symbols.c
-@@ -3284,6 +3284,8 @@ dump_symbol_table(void)
- 				lm->mod_section_data[s].size);
- 		}
- 
-+		fprintf(fp, "        loaded_objfile: %lx\n", (ulong)lm->loaded_objfile);
-+
- 		if (CRASHDEBUG(1)) {
-         		for (sp = lm->mod_load_symtable; 
- 			     sp < lm->mod_load_symend; sp++) {
-@@ -4100,6 +4102,7 @@ get_line_number(ulong addr, char *buf, int reserved)
- 	struct load_module *lm;
- 
- 	buf[0] = NULLCHAR;
-+	lm = NULL;
- 
- 	if (NO_LINE_NUMBERS() || !is_kernel_text(addr))
- 		return(buf);
-@@ -4129,6 +4132,8 @@ get_line_number(ulong addr, char *buf, int reserved)
- 		req->command = GNU_GET_LINE_NUMBER;
- 		req->addr = addr;
- 		req->buf = buf;
-+		if (lm && lm->loaded_objfile)
-+			req->lm = lm;
- 		if ((sp = value_search(addr, NULL)))
- 			req->name = sp->name;
- 		gdb_interface(req);
-@@ -12025,6 +12030,7 @@ delete_load_module(ulong base_addr)
- 			if (lm->mod_section_data)
- 				free(lm->mod_section_data);
- 			lm->mod_section_data = (struct mod_section_data *)0;
-+			lm->loaded_objfile = NULL;
- 		}
- 		st->flags &= ~LOAD_MODULE_SYMS;
- 		return;
-@@ -12061,6 +12067,7 @@ delete_load_module(ulong base_addr)
- 			if (lm->mod_section_data)
- 				free(lm->mod_section_data);
- 			lm->mod_section_data = (struct mod_section_data *)0;
-+			lm->loaded_objfile = NULL;
-                 } else if (lm->mod_flags & MOD_LOAD_SYMS)
- 			st->flags |= LOAD_MODULE_SYMS;
-         }
-
-commit c8178eca9c74f81a7f803a58d339635cc152e8d9
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Thu Nov 9 11:39:05 2017 -0500
-
-    Update for support of Linux 4.14 and later PPC64 kernels where the
-    hash page table geometry accomodates a larger virtual address range.
-    Without the patch, the virtual-to-physical translation of user space
-    virtual addresses by "vm -p", "vtop", and "rd -u" may generate an
-    invalid translation or otherwise fail.
-    (hbathini@linux.vnet.ibm.com)
-
-diff --git a/defs.h b/defs.h
-index 18f36b3..9132075 100644
---- a/defs.h
-+++ b/defs.h
-@@ -3915,6 +3915,9 @@ struct efi_memory_desc_t {
- #define PGD_INDEX_SIZE_L4_64K_3_10  12
- #define PMD_INDEX_SIZE_L4_64K_4_6  5
- #define PUD_INDEX_SIZE_L4_64K_4_6  5
-+#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 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 84cec09..672ee60 100644
---- a/ppc64.c
-+++ b/ppc64.c
-@@ -447,10 +447,16 @@ ppc64_init(int when)
- 				} else if (!(machdep->flags & BOOK3E) &&
- 				    (THIS_KERNEL_VERSION >= LINUX(4,6,0))) {
- 					m->l1_index_size = PTE_INDEX_SIZE_L4_64K_3_10;
--					m->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_6;
--					m->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_6;
--					m->l4_index_size = PGD_INDEX_SIZE_L4_64K_3_10;
- 
-+					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;
-+						m->l4_index_size = PGD_INDEX_SIZE_L4_64K_4_12;
-+					} else {
-+						m->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_6;
-+						m->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_6;
-+						m->l4_index_size = PGD_INDEX_SIZE_L4_64K_3_10;
-+					}
- 				} else if (THIS_KERNEL_VERSION >= LINUX(3,10,0)) {
- 					m->l1_index_size = PTE_INDEX_SIZE_L4_64K_3_10;
- 					m->l2_index_size = PMD_INDEX_SIZE_L4_64K_3_10;
-
-commit 03a3e57b9ad849314e262cac37787604a9fe8362
-Author: Dave Anderson <anderson@redhat.com>
-Date:   Thu Nov 9 14:04:08 2017 -0500
-
-    Implemented a new "runq -T" option that displays the time lag of each
-    CPU relative to the most recent runqueue timestamp.
-    (oleksandr@redhat.com)
-
-diff --git a/help.c b/help.c
-index fa01bfb..e017b03 100644
---- a/help.c
-+++ b/help.c
-@@ -2532,7 +2532,7 @@ NULL
- char *help_runq[] = {
- "runq",
- "run queue",
--"[-t] [-m] [-g] [-c cpu(s)]",
-+"[-t] [-T] [-m] [-g] [-c cpu(s)]",
- "  With no argument, this command displays the tasks on the run queues",
- "  of each cpu.",
- " ",
-@@ -2541,6 +2541,8 @@ char *help_runq[] = {
- "         whichever applies; following each cpu timestamp is the last_run or ",
- "         timestamp value of the active task on that cpu, whichever applies, ",
- "         along with the task identification.",
-+"     -T  Display the time lag of each CPU relative to the most recent runqueue",
-+"         timestamp.",
- "     -m  Display the amount of time that the active task on each cpu has been",
- "         running, expressed in a format consisting of days, hours, minutes, ",
- "         seconds and milliseconds.",
-diff --git a/task.c b/task.c
-index f2628b7..724532d 100644
---- a/task.c
-+++ b/task.c
-@@ -55,6 +55,7 @@ static long rq_idx(int);
- static long cpu_idx(int);
- static void dump_runq(void);
- static void dump_on_rq_timestamp(void);
-+static void dump_on_rq_lag(void);
- static void dump_on_rq_milliseconds(void);
- static void dump_runqueues(void);
- static void dump_prio_array(int, ulong, char *);
-@@ -8045,10 +8046,11 @@ cmd_runq(void)
- 	ulong *cpus = NULL;
- 	int sched_debug = 0;
- 	int dump_timestamp_flag = 0;
-+	int dump_lag_flag = 0;
- 	int dump_task_group_flag = 0;
- 	int dump_milliseconds_flag = 0;
- 
--        while ((c = getopt(argcnt, args, "dtgmc:")) != EOF) {
-+        while ((c = getopt(argcnt, args, "dtTgmc:")) != EOF) {
-                 switch(c)
-                 {
- 		case 'd':
-@@ -8057,6 +8059,9 @@ cmd_runq(void)
- 		case 't':
- 			dump_timestamp_flag = 1;
- 			break;
-+		case 'T':
-+			dump_lag_flag = 1;
-+			break;
- 		case 'm':
- 			dump_milliseconds_flag = 1;
- 			break;
-@@ -8092,6 +8097,8 @@ cmd_runq(void)
- 
- 	if (dump_timestamp_flag)
-                 dump_on_rq_timestamp();
-+	else if (dump_lag_flag)
-+		dump_on_rq_lag();
- 	else if (dump_milliseconds_flag)
-                 dump_on_rq_milliseconds();
- 	else if (sched_debug)
-@@ -8177,6 +8184,90 @@ dump_on_rq_timestamp(void)
- }
- 
- /*
-+ * Runqueue timestamp struct for dump_on_rq_lag().
-+ */
-+struct runq_ts_info {
-+	int cpu;
-+	ulonglong ts;
-+};
-+
-+/*
-+ * Comparison function for dump_on_rq_lag().
-+ * Sorts runqueue timestamps in a descending order.
-+ */
-+static int
-+compare_runq_ts(const void *p1, const void *p2)
-+{
-+	const struct runq_ts_info *ts1 = p1;
-+	const struct runq_ts_info *ts2 = p2;
-+
-+	if (ts1->ts > ts2->ts)
-+		return -1;
-+
-+	if (ts1->ts < ts2->ts)
-+		return 1;
-+
-+	return 0;
-+}
-+
-+/*
-+ * Calculates integer log10
-+ */
-+static ulong
-+__log10ul(ulong x)
-+{
-+	ulong ret = 1;
-+
-+	while (x > 9) {
-+		ret++;
-+		x /= 10;
-+	}
-+
-+	return ret;
-+}
-+
-+/*
-+ * Displays relative CPU lag.
-+ */
-+static void
-+dump_on_rq_lag(void)
-+{
-+	struct syment *rq_sp;
-+	int cpu;
-+	ulong runq;
-+	ulonglong timestamp;
-+	struct runq_ts_info runq_ts[kt->cpus];
-+
-+	if (!(rq_sp = per_cpu_symbol_search("per_cpu__runqueues")))
-+		error(FATAL, "per-cpu runqueues do not exist\n");
-+	if (INVALID_MEMBER(rq_timestamp))
-+		option_not_supported('T');
-+
-+	for (cpu = 0; cpu < kt->cpus; cpu++) {
-+		if ((kt->flags & SMP) && (kt->flags &PER_CPU_OFF))
-+			runq = rq_sp->value + kt->__per_cpu_offset[cpu];
-+		else
-+			runq = rq_sp->value;
-+
-+		readmem(runq + OFFSET(rq_timestamp), KVADDR, &timestamp,
-+				sizeof(ulonglong), "per-cpu rq timestamp",
-+				FAULT_ON_ERROR);
-+
-+		runq_ts[cpu].cpu = cpu;
-+		runq_ts[cpu].ts = timestamp;
-+	}
-+
-+	qsort(runq_ts, (size_t)kt->cpus, sizeof(struct runq_ts_info), compare_runq_ts);
-+
-+	for (cpu = 0; cpu < kt->cpus; cpu++) {
-+		fprintf(fp, "%sCPU %d: %.2lf secs\n",
-+			space(2 + __log10ul(kt->cpus) - __log10ul(runq_ts[cpu].cpu)),
-+			runq_ts[cpu].cpu,
-+			((double)runq_ts[0].ts - (double)runq_ts[cpu].ts) / 1000000000.0);
-+	}
-+}
-+
-+/*
-  *  Displays the runqueue and active task timestamps of each cpu.
-  */
- static void
diff --git a/SOURCES/rhel7.6-s390-nat.patch b/SOURCES/rhel7.6-s390-nat.patch
new file mode 100644
index 0000000..e79dac2
--- /dev/null
+++ b/SOURCES/rhel7.6-s390-nat.patch
@@ -0,0 +1,21 @@
+--- crash-7.2.3/gdb-7.6.patch.orig
++++ crash-7.2.3/gdb-7.6.patch
+@@ -2392,3 +2392,18 @@ diff -up gdb-7.6/opcodes/configure.orig
+                  req->flags |= GNU_COMMAND_FAILED;
+  }
+  
++--- gdb-7.6/gdb/s390-nat.c.orig
+++++ gdb-7.6/gdb/s390-nat.c
++@@ -31,6 +31,12 @@
++ #include "elf/common.h"
++ 
++ #include <asm/ptrace.h>
+++#undef PTRACE_PEEKUSR_AREA
+++#undef PTRACE_POKEUSR_AREA
+++#undef PTRACE_GET_LAST_BREAK
+++#undef PTRACE_ENABLE_TE
+++#undef PTRACE_DISABLE_TE
+++#undef PTRACE_TE_ABORT_RAND
++ #include <sys/ptrace.h>
++ #include <asm/types.h>
++ #include <sys/procfs.h>
diff --git a/SPECS/crash.spec b/SPECS/crash.spec
index 8c5171f..ae5803b 100644
--- a/SPECS/crash.spec
+++ b/SPECS/crash.spec
@@ -3,8 +3,8 @@
 #
 Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles
 Name: crash
-Version: 7.2.0
-Release: 6%{?dist}
+Version: 7.2.3
+Release: 8%{?dist}
 License: GPLv3
 Group: Development/Debuggers
 Source: http://people.redhat.com/anderson/crash-%{version}.tar.gz
@@ -15,13 +15,17 @@ Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n)
 BuildRequires: ncurses-devel zlib-devel lzo-devel bison snappy-devel
 Requires: binutils
 Patch0: lzo_snappy.patch
-Patch1: github_da9bd35a_to_e2efacdd.patch
-Patch2: github_f852f5ce_to_03a3e57b.patch
-Patch3: github_494a796e_to_63419fb9.patch
-Patch4: github_d833432f_kpti_trampoline.patch
-Patch5: github_1e488cfe_to_1160ba19.patch
-Patch6: github_a38e3ec4_machine_kexec.patch
-Patch7: github_ddace972_exception_frame.patch
+Patch1: rhel7.6-s390-nat.patch
+Patch2: github_46d21219.patch
+Patch3: github_a6cd8408_mach-m.patch
+Patch4: github_da49e201_cpu_entry_area.patch
+Patch5: github_9446958f_95daa11b_bpf_covscan.patch
+Patch6: github_b9d76838_c79a11fa_proc_kcore.patch
+Patch7: github_1926150e_ppc64_stacksize.patch
+Patch8: github_f294197b_bpf_idr.patch
+Patch9: github_28fa7bd0_ppc64_increase_VA_range.patch
+Patch10: github_5fe78861_ppc64_invalid_NIP.patch
+Patch11: github_7e393689_ppc64_bt_user_space.patch
 
 %description
 The core analysis suite is a self-contained tool that can be used to
@@ -43,13 +47,17 @@ offered by Mission Critical Linux, or the LKCD kernel patch.
 %prep
 %setup -n %{name}-%{version} -q
 %patch0 -p1 -b lzo_snappy.patch
-%patch1 -p1 -b github_87179026_to_ad3b8476.patch
-%patch2 -p1 -b github_f852f5ce_to_03a3e57b.patch
-%patch3 -p1 -b github_494a796e_to_63419fb9.patch
-%patch4 -p1 -b github_d833432f_kpti_trampoline.patch
-%patch5 -p1 -b github_1e488cfe_to_1160ba19.patch
-%patch6 -p1 -b github_a38e3ec4_machine_kexec.patch
-%patch7 -p1 -b github_ddace972_exception_frame.patch
+%patch1 -p1 -b rhel7.6-s390-nat.patch
+%patch2 -p1 -b github_46d21219.patch
+%patch3 -p1 -b github_a6cd8408_mach-m.patch
+%patch4 -p1 -b github_da49e201_cpu_entry_area.patch
+%patch5 -p1 -b github_9446958f_95daa11b_bpf_covscan.patch
+%patch6 -p1 -b github_b9d76838_c79a11fa_proc_kcore.patch
+%patch7 -p1 -b github_1926150e_ppc64_stacksize.patch
+%patch8 -p1 -b github_f294197b_bpf_idr.patch
+%patch9 -p1 -b github_28fa7bd0_ppc64_increase_VA_range.patch
+%patch10 -p1 -b github_5fe78861_ppc64_invalid_NIP.patch
+%patch11 -p1 -b github_7e393689_ppc64_bt_user_space.patch
 
 %build
 make RPMPKG="%{version}-%{release}" CFLAGS="%{optflags}"
@@ -78,6 +86,44 @@ rm -rf %{buildroot}
 %{_includedir}/*
 
 %changelog
+* Mon Sep 17 2018 Dave Anderson <anderson@redhat.com> - 7.2.3-8
+- Fix ppc64 "bt" command failure reporting invalid NIP value for a user-space task. 
+  Resolves: rhbz#1617936
+
+* Thu Sep 13 2018 Dave Anderson <anderson@redhat.com> - 7.2.3-7
+- Support ppc64 increased VA range
+- Fix ppc64 "bt" command failure reporting invalid NIP value
+  Resolves: rhbz#1617936
+
+* Fri Jul  6 2018 Dave Anderson <anderson@redhat.com> - 7.2.3-6
+- Fix for RHEL7 kernel's eBPF support that uses old IDR facility
+  Resolves: rhbz#1559758
+
+* Mon Jun 11 2018 Dave Anderson <anderson@redhat.com> - 7.2.3-5
+- Rebase to github commits b9d76838 to c79a11fa
+  Resolves: rhbz#1559460
+- Fix ppc64/ppc6le stacksize calculation
+  Resolves: rhbz#1589685
+
+* Fri Jun  1 2018 Dave Anderson <anderson@redhat.com> - 7.2.3-4
+- Fix bpf.c covscan issues
+  Resolves: rhbz#1559758
+
+* Fri Jun  1 2018 Dave Anderson <anderson@redhat.com> - 7.2.3-3
+- Rebase to github commits a6cd8408 to da49e201 
+  Resolves: rhbz#1559460
+
+* Tue May 29 2018 Dave Anderson <anderson@redhat.com> - 7.2.3-2
+- Work around rhel-7.6 s390/s390x ptrace.h incompatiblity FTBFS issue
+- Rebase to github commit 46d21219
+  Resolves: rhbz#1559460
+
+* Fri May 18 2018 Dave Anderson <anderson@redhat.com> - 7.2.3-1
+- Rebase to upstream version 7.2.3
+  Resolves: rhbz#1559460
+- eBPF support with new bpf command
+  Resolves: rhbz#1559758
+
 * Mon Feb 12 2018 Dave Anderson <anderson@redhat.com> - 7.2.0-6
 - Fix arm64 backtrace issues seen in Linux 4.14
   Resolves: rhbz#1542312