Resolves: bz1440587
https://bugzilla.redhat.com/show_bug.cgi?id=1440587
Current fc25 kernel version is v4.10.
4.9+ kernel has phys_base virtual address in vmcoreinfo rather it's
symbol address. Therefore, backport makedumpfile patch "Adapt code to
get value of phys_base"
While doing that, also backport "kexec-tools/x86:
get_kernel_vaddr_and_size off-by-one fix" to fix following with kexec
-p:
"Can't find kernel text map area from kcore"
v4.11 kernel will have another fix for kcore ( 464920104bf7 /proc/kcore:
update physical address for kcore ram and text)which allows only valid
physical address to pass in PT_LOAD.With that fix in kernel, kexec-tools
may not work always until we backport "build_mem_phdrs(): check if
p_paddr is invalid" from kexec-tools. Since there does not seem any side
effect of taking that kexec-tools commit even for v4.10 because
"phdr->p_paddr != (unsigned long long)-1" will always be TRUE for them,
therefore we take that kexec-tools patch as well.
Signed-off-by: Pratyush Anand <panand(a)redhat.com>
---
Build info:
https://koji.fedoraproject.org/koji/taskinfo?taskID=18908776
FC25 crash does not like the vmcore, however crash/master worked fine.
Probably, FC25 crash will need to backport atleast following commit:
commit 24a696228c56fd4354d29abe05b206373e0c8bfb
Fix for Linux 4.10 commit 7fd8329ba502ef76dd91db561c7aed696b2c7720
"taint/module: Clean up global and module taint flags handling".
v1 -> v2:
v1 missed to apply Patchc611 in spec file. Since that patch does
not affect kernel < v4.11, so it had worked. However, v2 fixes that as we
talk about it in commit log.
...ild_mem_phdrs-check-if-p_paddr-is-invalid.patch | 43 +++++++
...-x86-get_kernel_vaddr_and_size-off-by-one.patch | 43 +++++++
...file-Adapt-code-to-get-value-of-phys_base.patch | 126 +++++++++++++++++++++
kexec-tools.spec | 6 +
4 files changed, 218 insertions(+)
create mode 100644 kexec-tools-2.0.13-build_mem_phdrs-check-if-p_paddr-is-invalid.patch
create mode 100644
kexec-tools-2.0.13-kexec-tools-x86-get_kernel_vaddr_and_size-off-by-one.patch
create mode 100644
kexec-tools-2.0.13-makedumpfile-Adapt-code-to-get-value-of-phys_base.patch
diff --git a/kexec-tools-2.0.13-build_mem_phdrs-check-if-p_paddr-is-invalid.patch
b/kexec-tools-2.0.13-build_mem_phdrs-check-if-p_paddr-is-invalid.patch
new file mode 100644
index 000000000000..4d4f34361b45
--- /dev/null
+++ b/kexec-tools-2.0.13-build_mem_phdrs-check-if-p_paddr-is-invalid.patch
@@ -0,0 +1,43 @@
+From ed15ba1b9977e506637ff1697821d97127b2c919 Mon Sep 17 00:00:00 2001
+Message-Id:
<ed15ba1b9977e506637ff1697821d97127b2c919.1491794671.git.panand(a)redhat.com>
+From: Pratyush Anand <panand(a)redhat.com>
+Date: Wed, 1 Mar 2017 11:19:42 +0530
+Subject: [PATCH] build_mem_phdrs(): check if p_paddr is invalid
+
+Currently, all the p_paddr of PT_LOAD headers are assigned to 0, which
+is not correct and could be misleading, since 0 is a valid physical
+address.
+
+Upstream kernel commit "464920104bf7 /proc/kcore: update physical
+address for kcore ram and text" fixed it and now invalid PT_LOAD is
+assigned as -1.
+
+kexec/arch/i386/crashdump-x86.c:get_kernel_vaddr_and_size() uses kcore
+interface and so calls build_mem_phdrs() for kcore PT_LOAD headers.
+
+This patch fixes build_mem_phdrs() to check if p_paddr is invalid.
+
+Signed-off-by: Pratyush Anand <panand(a)redhat.com>
+Acked-by: Dave Young <dyoung(a)redhat.com>
+Signed-off-by: Simon Horman <horms(a)verge.net.au>
+---
+ kexec/kexec-elf.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/kexec/kexec-elf.c b/kexec/kexec-elf.c
+index 1d6320a2f0e6..be60bbd48486 100644
+--- a/kexec/kexec-elf.c
++++ b/kexec/kexec-elf.c
+@@ -432,7 +432,8 @@ static int build_mem_phdrs(const char *buf, off_t len, struct
mem_ehdr *ehdr,
+ }
+ return -1;
+ }
+- if ((phdr->p_paddr + phdr->p_memsz) < phdr->p_paddr) {
++ if (phdr->p_paddr != (unsigned long long)-1 &&
++ (phdr->p_paddr + phdr->p_memsz) < phdr->p_paddr) {
+ /* The memory address wraps */
+ if (probe_debug) {
+ fprintf(stderr, "ELF address wrap around\n");
+--
+2.9.3
+
diff --git a/kexec-tools-2.0.13-kexec-tools-x86-get_kernel_vaddr_and_size-off-by-one.patch
b/kexec-tools-2.0.13-kexec-tools-x86-get_kernel_vaddr_and_size-off-by-one.patch
new file mode 100644
index 000000000000..c707c8ec0e07
--- /dev/null
+++ b/kexec-tools-2.0.13-kexec-tools-x86-get_kernel_vaddr_and_size-off-by-one.patch
@@ -0,0 +1,43 @@
+From dbb99d938810b60035122a1bcc68c4d585a0e57f Mon Sep 17 00:00:00 2001
+Message-Id:
<dbb99d938810b60035122a1bcc68c4d585a0e57f.1491799333.git.panand(a)redhat.com>
+From: Dave Young <dyoung(a)redhat.com>
+Date: Thu, 8 Dec 2016 10:52:22 +0800
+Subject: [PATCH] kexec-tools/x86: get_kernel_vaddr_and_size off-by-one fix
+
+I got below error while tesing kexec -p:
+"Can't find kernel text map area from kcore"
+
+The case is the pt_load start addr was same as stext_sym. The checking
+code should really be saddr <= stext_sym so that the right pt_load area
+includes stext_sym can be matched.
+
+This was not reported by people previously because it will fail over to
+use hardcode X86_64__START_KERNEL_map to match the pt_load areas again
+in later code and it sometimes succeeds because of kernel address
+randomization.
+
+With this change according to my test stext_sym checking can garantee
+falling into right pt_load area if we get correct stext_sym.
+
+Signed-off-by: Dave Young <dyoung(a)redhat.com>
+Signed-off-by: Simon Horman <horms(a)verge.net.au>
+---
+ kexec/arch/i386/crashdump-x86.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
+index ab833d416320..88aeee33572b 100644
+--- a/kexec/arch/i386/crashdump-x86.c
++++ b/kexec/arch/i386/crashdump-x86.c
+@@ -205,7 +205,7 @@ static int get_kernel_vaddr_and_size(struct kexec_info
*UNUSED(info),
+ unsigned long long size;
+
+ /* Look for kernel text mapping header. */
+- if (saddr < stext_sym && eaddr > stext_sym) {
++ if (saddr <= stext_sym && eaddr > stext_sym) {
+ saddr = _ALIGN_DOWN(saddr, X86_64_KERN_VADDR_ALIGN);
+ elf_info->kern_vaddr_start = saddr;
+ size = eaddr - saddr;
+--
+2.9.3
+
diff --git a/kexec-tools-2.0.13-makedumpfile-Adapt-code-to-get-value-of-phys_base.patch
b/kexec-tools-2.0.13-makedumpfile-Adapt-code-to-get-value-of-phys_base.patch
new file mode 100644
index 000000000000..c0b16655dc4d
--- /dev/null
+++ b/kexec-tools-2.0.13-makedumpfile-Adapt-code-to-get-value-of-phys_base.patch
@@ -0,0 +1,126 @@
+From acdbb1d6aee9207ccdea697326574e8d6142cd73 Mon Sep 17 00:00:00 2001
+Message-Id:
<acdbb1d6aee9207ccdea697326574e8d6142cd73.1491806706.git.panand(a)redhat.com>
+From: Baoquan He <bhe(a)redhat.com>
+Date: Thu, 10 Nov 2016 15:30:57 +0900
+Subject: [PATCH] [PATCH v2 1/2] Adapt code to get value of phys_base
+
+* Required for kernel 4.9
+
+Kernel code only exports virtual address of phys_base now and it's helpless
+for Crash and Makedumpfile. Below patch which changes code to export value
+of phys_base has been posted to upstream. So adapt code to get it.
+
+kexec: Change to export the value of phys_base instead of symbol address
+marc.info/?l=linux-kernel&m=147856863629624&w=2
+
+Signed-off-by: Baoquan He <bhe(a)redhat.com>
+---
+ arch/x86_64.c | 12 +++++-------
+ makedumpfile.c | 5 ++---
+ makedumpfile.h | 2 +-
+ 3 files changed, 8 insertions(+), 11 deletions(-)
+
+diff --git a/makedumpfile-1.6.0/arch/x86_64.c b/makedumpfile-1.6.0/arch/x86_64.c
+index 3ef33ae4ef2d..010ea10e6fa8 100644
+--- a/makedumpfile-1.6.0/arch/x86_64.c
++++ b/makedumpfile-1.6.0/arch/x86_64.c
+@@ -62,6 +62,10 @@ get_phys_base_x86_64(void)
+ * Get the relocatable offset
+ */
+ info->phys_base = 0; /* default/traditional */
++ if (NUMBER(phys_base) != NOT_FOUND_NUMBER) {
++ info->phys_base = NUMBER(phys_base);
++ return TRUE;
++ }
+
+ for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
+ if (virt_start >= __START_KERNEL_map) {
+@@ -187,12 +191,6 @@ vtop4_x86_64(unsigned long vaddr)
+ {
+ unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
+ unsigned long pte_paddr, pte;
+- unsigned long phys_base;
+-
+- if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
+- phys_base = info->phys_base;
+- else
+- phys_base = 0;
+
+ if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
+ ERRMSG("Can't get the symbol of init_level4_pgt.\n");
+@@ -202,7 +200,7 @@ vtop4_x86_64(unsigned long vaddr)
+ /*
+ * Get PGD.
+ */
+- page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base;
++ page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + info->phys_base;
+ page_dir += pml4_index(vaddr) * sizeof(unsigned long);
+ if (!readmem(PADDR, page_dir, &pml4, sizeof pml4)) {
+ ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir);
+diff --git a/makedumpfile-1.6.0/makedumpfile.c b/makedumpfile-1.6.0/makedumpfile.c
+index b916dfb8b189..a3f711e3e9bf 100644
+--- a/makedumpfile-1.6.0/makedumpfile.c
++++ b/makedumpfile-1.6.0/makedumpfile.c
+@@ -1507,7 +1507,6 @@ get_symbol_info(void)
+ SYMBOL_INIT(init_level4_pgt, "init_level4_pgt");
+ SYMBOL_INIT(vmlist, "vmlist");
+ SYMBOL_INIT(vmap_area_list, "vmap_area_list");
+- SYMBOL_INIT(phys_base, "phys_base");
+ SYMBOL_INIT(node_online_map, "node_online_map");
+ SYMBOL_INIT(node_states, "node_states");
+ SYMBOL_INIT(node_memblk, "node_memblk");
+@@ -2134,7 +2133,6 @@ write_vmcoreinfo_data(void)
+ WRITE_SYMBOL("init_level4_pgt", init_level4_pgt);
+ WRITE_SYMBOL("vmlist", vmlist);
+ WRITE_SYMBOL("vmap_area_list", vmap_area_list);
+- WRITE_SYMBOL("phys_base", phys_base);
+ WRITE_SYMBOL("node_online_map", node_online_map);
+ WRITE_SYMBOL("node_states", node_states);
+ WRITE_SYMBOL("node_data", node_data);
+@@ -2261,6 +2259,7 @@ write_vmcoreinfo_data(void)
+
+ WRITE_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
+ WRITE_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
++ WRITE_NUMBER("phys_base", phys_base);
+
+ WRITE_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
+
+@@ -2488,7 +2487,6 @@ read_vmcoreinfo(void)
+ READ_SYMBOL("init_level4_pgt", init_level4_pgt);
+ READ_SYMBOL("vmlist", vmlist);
+ READ_SYMBOL("vmap_area_list", vmap_area_list);
+- READ_SYMBOL("phys_base", phys_base);
+ READ_SYMBOL("node_online_map", node_online_map);
+ READ_SYMBOL("node_states", node_states);
+ READ_SYMBOL("node_data", node_data);
+@@ -2609,6 +2607,7 @@ read_vmcoreinfo(void)
+
+ READ_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
+ READ_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
++ READ_NUMBER("phys_base", phys_base);
+
+ READ_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
+
+diff --git a/makedumpfile-1.6.0/makedumpfile.h b/makedumpfile-1.6.0/makedumpfile.h
+index 338c651388f0..422b6bed102b 100644
+--- a/makedumpfile-1.6.0/makedumpfile.h
++++ b/makedumpfile-1.6.0/makedumpfile.h
+@@ -1394,7 +1394,6 @@ struct symbol_table {
+ unsigned long long init_level4_pgt;
+ unsigned long long vmlist;
+ unsigned long long vmap_area_list;
+- unsigned long long phys_base;
+ unsigned long long node_online_map;
+ unsigned long long node_states;
+ unsigned long long node_memblk;
+@@ -1718,6 +1717,7 @@ struct number_table {
+ long SECTION_SIZE_BITS;
+ long MAX_PHYSMEM_BITS;
+ long HUGETLB_PAGE_DTOR;
++ long phys_base;
+ };
+
+ struct srcfile_table {
+--
+2.9.3
+
diff --git a/kexec-tools.spec b/kexec-tools.spec
index 3f9f9ae668fb..71c2979563c7 100644
--- a/kexec-tools.spec
+++ b/kexec-tools.spec
@@ -97,6 +97,9 @@ Patch605:
kexec-tools-2.0.13-makedumpfile-x86-64-translate-all-VA-to-PA-using-pa
Patch606: kexec-tools-2.0.13-makedumpfile-x86-64-kill-is-vmalloc-addr-x86-64.patch
Patch607: kexec-tools-2.0.13-makedumpfile-x86-64-kill-some-unused-initialization.patch
Patch608: kexec-tools-2.0.13-makedumpfile-x86_64-fix-page_offset-calculation.patch
+Patch609: kexec-tools-2.0.13-makedumpfile-Adapt-code-to-get-value-of-phys_base.patch
+Patch610: kexec-tools-2.0.13-kexec-tools-x86-get_kernel_vaddr_and_size-off-by-one.patch
+Patch611: kexec-tools-2.0.13-build_mem_phdrs-check-if-p_paddr-is-invalid.patch
%description
kexec-tools provides /sbin/kexec binary that facilitates a new
@@ -134,6 +137,9 @@ tar -z -x -v -f %{SOURCE23}
%patch606 -p1
%patch607 -p1
%patch608 -p1
+%patch609 -p1
+%patch610 -p1
+%patch611 -p1
%ifarch ppc
%define archdef ARCH=ppc
--
2.9.3