From 658db699409981426b2a22160c103c99bbc0cab2 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Wed, 26 Oct 2016 10:54:50 +0800 Subject: [PATCH] Support kdump for kaslr enabled Fedora kernel Since in Fedora 25 kernel kaslr is enabled (x86) but makedumpfile can not save a correct vmcore, so it means kdump default setup will not work. Pratyush posted a patch series to upstream which can fix the issue. Let's merge them in F25, will get the normal fixes after it being merged in upstream, we hopefully can rebase soon in rawhide. This is an urgent fix for F25 since F25 freeze is this week. Signed-off-by: Dave Young Acked-by: Pratyush Anand Acked-by: Baoquan He --- ...4-calculate-page-offset-from-pt-load.patch | 69 ++++++++ ...e-x86-64-kill-is-vmalloc-addr-x86-64.patch | 89 +++++++++++ ...6-64-kill-some-unused-initialization.patch | 58 +++++++ ...all-VA-to-PA-using-page-table-values.patch | 148 ++++++++++++++++++ kexec-tools.spec | 9 ++ 5 files changed, 373 insertions(+) create mode 100644 kexec-tools-2.0.13-makedumpfile-x86-64-calculate-page-offset-from-pt-load.patch create mode 100644 kexec-tools-2.0.13-makedumpfile-x86-64-kill-is-vmalloc-addr-x86-64.patch create mode 100644 kexec-tools-2.0.13-makedumpfile-x86-64-kill-some-unused-initialization.patch create mode 100644 kexec-tools-2.0.13-makedumpfile-x86-64-translate-all-VA-to-PA-using-page-table-values.patch diff --git a/kexec-tools-2.0.13-makedumpfile-x86-64-calculate-page-offset-from-pt-load.patch b/kexec-tools-2.0.13-makedumpfile-x86-64-calculate-page-offset-from-pt-load.patch new file mode 100644 index 0000000..50e7717 --- /dev/null +++ b/kexec-tools-2.0.13-makedumpfile-x86-64-calculate-page-offset-from-pt-load.patch @@ -0,0 +1,69 @@ +From: Pratyush Anand +To: ats-kumagai@wm.jp.nec.com +Subject: [PATCH Makedumpfile 1/4] x86_64: Calculate page_offset from pt_load +Date: Mon, 24 Oct 2016 22:18:43 +0530 +Cc: Pratyush Anand , dyoung@redhat.com, + kexec@lists.infradead.org, bhe@redhat.com +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +Content-Type: text/plain; charset=utf-8 + +page_offset can always be calculated as 'virtual - physical' for a direct +mapping area on x86. Therefore, remove the version dependent calculation +and use this method. + +Signed-off-by: Pratyush Anand +--- + arch/x86_64.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +diff --git a/arch/x86_64.c b/arch/x86_64.c +index ddf7be6bc57b..a96fd8ae00a1 100644 +--- a/makedumpfile-1.6.0/arch/x86_64.c ++++ b/makedumpfile-1.6.0/arch/x86_64.c +@@ -44,6 +44,24 @@ get_xen_p2m_mfn(void) + return NOT_FOUND_LONG_VALUE; + } + ++static int ++get_page_offset_x86_64(void) ++{ ++ int i; ++ unsigned long long phys_start; ++ unsigned long long virt_start; ++ ++ for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) { ++ if (virt_start >= __START_KERNEL_map) { ++ info->page_offset = virt_start - phys_start; ++ return TRUE; ++ } ++ } ++ ++ ERRMSG("Can't get any pt_load to calculate page offset.\n"); ++ return FALSE; ++} ++ + int + get_phys_base_x86_64(void) + { +@@ -159,10 +177,8 @@ get_versiondep_info_x86_64(void) + else + info->max_physmem_bits = _MAX_PHYSMEM_BITS_2_6_31; + +- if (info->kernel_version < KERNEL_VERSION(2, 6, 27)) +- info->page_offset = __PAGE_OFFSET_ORIG; +- else +- info->page_offset = __PAGE_OFFSET_2_6_27; ++ if (!get_page_offset_x86_64()) ++ return FALSE; + + if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) { + info->vmalloc_start = VMALLOC_START_ORIG; +-- +2.7.4 + + +_______________________________________________ +kexec mailing list +kexec@lists.infradead.org +http://lists.infradead.org/mailman/listinfo/kexec diff --git a/kexec-tools-2.0.13-makedumpfile-x86-64-kill-is-vmalloc-addr-x86-64.patch b/kexec-tools-2.0.13-makedumpfile-x86-64-kill-is-vmalloc-addr-x86-64.patch new file mode 100644 index 0000000..be12ee6 --- /dev/null +++ b/kexec-tools-2.0.13-makedumpfile-x86-64-kill-is-vmalloc-addr-x86-64.patch @@ -0,0 +1,89 @@ +From: Pratyush Anand +To: ats-kumagai@wm.jp.nec.com +Subject: [PATCH Makedumpfile 3/4] x86_64: kill is_vmalloc_addr_x86_64() +Date: Mon, 24 Oct 2016 22:18:45 +0530 +Cc: Pratyush Anand , dyoung@redhat.com, + kexec@lists.infradead.org, bhe@redhat.com +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +Content-Type: text/plain; charset=utf-8 + +From kernel documentation: +ffffffff80000000 - ffffffff9fffffff (=512 MB) kernel text mapping, from phys 0 +ffffffffa0000000 - ffffffffff5fffff (=1526 MB) module mapping space + +So, it is only the module area which is lying above __START_KERNEL_map. +However, kexec-tools only creates PT_LOAD segments for kernel text region +and crash memory region. So, we can safely remove the check for +!is_vmalloc_addr_x86_64() from get_phys_base_x86_64(). + +Since, this was the last usage of is_vmalloc_addr_x86_64(), so kill it as +well. + +Signed-off-by: Pratyush Anand +--- + arch/x86_64.c | 14 +------------- + makedumpfile.h | 3 +-- + 2 files changed, 2 insertions(+), 15 deletions(-) + +diff --git a/arch/x86_64.c b/arch/x86_64.c +index fe2764a8bec2..597cdac36dfc 100644 +--- a/makedumpfile-1.6.0/arch/x86_64.c ++++ b/makedumpfile-1.6.0/arch/x86_64.c +@@ -21,17 +21,6 @@ + extern struct vmap_pfns *gvmem_pfns; + extern int nr_gvmem_pfns; + +-int +-is_vmalloc_addr_x86_64(ulong vaddr) +-{ +- /* +- * vmalloc, virtual memmap, and module space as VMALLOC space. +- */ +- return ((vaddr >= VMALLOC_START && vaddr <= VMALLOC_END) +- || (vaddr >= VMEMMAP_START && vaddr <= VMEMMAP_END) +- || (vaddr >= MODULES_VADDR && vaddr <= MODULES_END)); +-} +- + static unsigned long + get_xen_p2m_mfn(void) + { +@@ -75,8 +64,7 @@ get_phys_base_x86_64(void) + info->phys_base = 0; /* default/traditional */ + + for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) { +- if ((virt_start >= __START_KERNEL_map) && +- !(is_vmalloc_addr_x86_64(virt_start))) { ++ if (virt_start >= __START_KERNEL_map) { + + info->phys_base = phys_start - + (virt_start & ~(__START_KERNEL_map)); +diff --git a/makedumpfile.h b/makedumpfile.h +index 13559651feb6..8a96da1f61bd 100644 +--- a/makedumpfile-1.6.0/makedumpfile.h ++++ b/makedumpfile-1.6.0/makedumpfile.h +@@ -859,7 +859,6 @@ unsigned long long vaddr_to_paddr_x86(unsigned long vaddr); + #endif /* x86 */ + + #ifdef __x86_64__ +-int is_vmalloc_addr_x86_64(ulong vaddr); + int get_phys_base_x86_64(void); + int get_machdep_info_x86_64(void); + int get_versiondep_info_x86_64(void); +@@ -869,7 +868,7 @@ unsigned long long vtop4_x86_64(unsigned long vaddr); + #define get_machdep_info() get_machdep_info_x86_64() + #define get_versiondep_info() get_versiondep_info_x86_64() + #define vaddr_to_paddr(X) vtop4_x86_64(X) +-#define is_phys_addr(X) (!is_vmalloc_addr_x86_64(X)) ++#define is_phys_addr(X) stub_true_ul(X) + #endif /* x86_64 */ + + #ifdef __powerpc64__ /* powerpc64 */ +-- +2.7.4 + + +_______________________________________________ +kexec mailing list +kexec@lists.infradead.org +http://lists.infradead.org/mailman/listinfo/kexec diff --git a/kexec-tools-2.0.13-makedumpfile-x86-64-kill-some-unused-initialization.patch b/kexec-tools-2.0.13-makedumpfile-x86-64-kill-some-unused-initialization.patch new file mode 100644 index 0000000..750f279 --- /dev/null +++ b/kexec-tools-2.0.13-makedumpfile-x86-64-kill-some-unused-initialization.patch @@ -0,0 +1,58 @@ +From: Pratyush Anand +To: ats-kumagai@wm.jp.nec.com +Subject: [PATCH Makedumpfile 4/4] x86_64: kill some unused initialization +Date: Mon, 24 Oct 2016 22:18:46 +0530 +Cc: Pratyush Anand , dyoung@redhat.com, + kexec@lists.infradead.org, bhe@redhat.com +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +Content-Type: text/plain; charset=utf-8 + +VMALLOC_START, VMALLOC_END, MODULES_VADDR and MODULES_END are mo more +needed for x86_64 now. So, kill their initialization. + +Signed-off-by: Pratyush Anand +--- + arch/x86_64.c | 4 ---- + makedumpfile.h | 2 -- + 2 files changed, 6 deletions(-) + +diff --git a/arch/x86_64.c b/arch/x86_64.c +index 597cdac36dfc..13990cef839b 100644 +--- a/makedumpfile-1.6.0/arch/x86_64.c ++++ b/makedumpfile-1.6.0/arch/x86_64.c +@@ -169,13 +169,9 @@ get_versiondep_info_x86_64(void) + return FALSE; + + if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) { +- info->vmalloc_start = VMALLOC_START_ORIG; +- info->vmalloc_end = VMALLOC_END_ORIG; + info->vmemmap_start = VMEMMAP_START_ORIG; + info->vmemmap_end = VMEMMAP_END_ORIG; + } else { +- info->vmalloc_start = VMALLOC_START_2_6_31; +- info->vmalloc_end = VMALLOC_END_2_6_31; + info->vmemmap_start = VMEMMAP_START_2_6_31; + info->vmemmap_end = VMEMMAP_END_2_6_31; + } +diff --git a/makedumpfile.h b/makedumpfile.h +index 8a96da1f61bd..338c651388f0 100644 +--- a/makedumpfile-1.6.0/makedumpfile.h ++++ b/makedumpfile-1.6.0/makedumpfile.h +@@ -575,8 +575,6 @@ int get_va_bits_arm64(void); + #define __START_KERNEL_map (0xffffffff80000000) + #define KERNEL_IMAGE_SIZE_ORIG (0x0000000008000000) /* 2.6.25, or former */ + #define KERNEL_IMAGE_SIZE_2_6_26 (0x0000000020000000) /* 2.6.26, or later */ +-#define MODULES_VADDR (__START_KERNEL_map + NUMBER(KERNEL_IMAGE_SIZE)) +-#define MODULES_END (0xfffffffffff00000) + #define KVBASE PAGE_OFFSET + #define _SECTION_SIZE_BITS (27) + #define _MAX_PHYSMEM_BITS_ORIG (40) +-- +2.7.4 + + +_______________________________________________ +kexec mailing list +kexec@lists.infradead.org +http://lists.infradead.org/mailman/listinfo/kexec diff --git a/kexec-tools-2.0.13-makedumpfile-x86-64-translate-all-VA-to-PA-using-page-table-values.patch b/kexec-tools-2.0.13-makedumpfile-x86-64-translate-all-VA-to-PA-using-page-table-values.patch new file mode 100644 index 0000000..4920c87 --- /dev/null +++ b/kexec-tools-2.0.13-makedumpfile-x86-64-translate-all-VA-to-PA-using-page-table-values.patch @@ -0,0 +1,148 @@ +From: Pratyush Anand +To: ats-kumagai@wm.jp.nec.com +Subject: [PATCH Makedumpfile 2/4] x86_64: translate all VA to PA using page + table values +Date: Mon, 24 Oct 2016 22:18:44 +0530 +Cc: Pratyush Anand , dyoung@redhat.com, + kexec@lists.infradead.org, bhe@redhat.com +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +Content-Type: text/plain; charset=utf-8 + +Currently we translate some of the VA areas using linear mapping while some +other(which can not be linearly mapped) using page table. + +However, we will have entry of a page in the page table irrespective of its +virtual region. So, we can always look into page table for any VA to PA +translation. This approach will solve lot of complexity in makedumpfile. It +will in turn remove dependency over variables like VMALLOC_START, +MODULES_VADDR etc whose definition keeps changing in newer kernel version. + +Moreover, I do not see any side effect of this approach in terms of +execution timing. I tested with IBM x3950 X6 machine having 4136359 MB of +memory. These are the results of makedumpfile execution time: + +Without this patch: +=================== +With -d 31: +Trial 1: 237.59526248 S +Trial 2: 235.236914962 S +Trail 3: 237.678712045 S + +With -d 1: +Trial 1: 2548.905296877 S +Trial 2: 2549.759881756 S + +With this patch: +=================== +With -d 31: +Trial 1: 232.713841516 S +Trial 2: 228.45697177 S +Trail 3: 232.942262441 S + +With -d 1: +Trial 1: 2768.424565806 S +Trial 2: 2749.622115455 S +Trail 3: 2537.770359073 S + +Signed-off-by: Pratyush Anand +--- + arch/x86_64.c | 42 ++++++++---------------------------------- + makedumpfile.h | 4 ++-- + 2 files changed, 10 insertions(+), 36 deletions(-) + +diff --git a/arch/x86_64.c b/arch/x86_64.c +index a96fd8ae00a1..fe2764a8bec2 100644 +--- a/makedumpfile-1.6.0/arch/x86_64.c ++++ b/makedumpfile-1.6.0/arch/x86_64.c +@@ -203,6 +203,12 @@ 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"); +@@ -212,9 +218,9 @@ vtop4_x86_64(unsigned long vaddr) + /* + * Get PGD. + */ +- page_dir = SYMBOL(init_level4_pgt); ++ page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base; + page_dir += pml4_index(vaddr) * sizeof(unsigned long); +- if (!readmem(VADDR, page_dir, &pml4, sizeof pml4)) { ++ if (!readmem(PADDR, page_dir, &pml4, sizeof pml4)) { + ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir); + return NOT_PADDR; + } +@@ -285,38 +291,6 @@ vtop4_x86_64(unsigned long vaddr) + return (pte & ENTRY_MASK) + PAGEOFFSET(vaddr); + } + +-unsigned long long +-vaddr_to_paddr_x86_64(unsigned long vaddr) +-{ +- unsigned long phys_base; +- unsigned long long paddr; +- +- /* +- * Check the relocatable kernel. +- */ +- if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL) +- phys_base = info->phys_base; +- else +- phys_base = 0; +- +- if (is_vmalloc_addr_x86_64(vaddr)) { +- if ((paddr = vtop4_x86_64(vaddr)) == NOT_PADDR) { +- ERRMSG("Can't convert a virtual address(%lx) to " \ +- "physical address.\n", vaddr); +- return NOT_PADDR; +- } +- } else if (vaddr >= __START_KERNEL_map) { +- paddr = vaddr - __START_KERNEL_map + phys_base; +- +- } else { +- if (is_xen_memory()) +- paddr = vaddr - PAGE_OFFSET_XEN_DOM0; +- else +- paddr = vaddr - PAGE_OFFSET; +- } +- return paddr; +-} +- + /* + * for Xen extraction + */ +diff --git a/makedumpfile.h b/makedumpfile.h +index a5955ff750e5..13559651feb6 100644 +--- a/makedumpfile-1.6.0/makedumpfile.h ++++ b/makedumpfile-1.6.0/makedumpfile.h +@@ -863,12 +863,12 @@ int is_vmalloc_addr_x86_64(ulong vaddr); + int get_phys_base_x86_64(void); + int get_machdep_info_x86_64(void); + int get_versiondep_info_x86_64(void); +-unsigned long long vaddr_to_paddr_x86_64(unsigned long vaddr); ++unsigned long long vtop4_x86_64(unsigned long vaddr); + #define find_vmemmap() find_vmemmap_x86_64() + #define get_phys_base() get_phys_base_x86_64() + #define get_machdep_info() get_machdep_info_x86_64() + #define get_versiondep_info() get_versiondep_info_x86_64() +-#define vaddr_to_paddr(X) vaddr_to_paddr_x86_64(X) ++#define vaddr_to_paddr(X) vtop4_x86_64(X) + #define is_phys_addr(X) (!is_vmalloc_addr_x86_64(X)) + #endif /* x86_64 */ + +-- +2.7.4 + + +_______________________________________________ +kexec mailing list +kexec@lists.infradead.org +http://lists.infradead.org/mailman/listinfo/kexec diff --git a/kexec-tools.spec b/kexec-tools.spec index 8063078..5ef6180 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -87,6 +87,11 @@ Patch601: kexec-tools-2.0.3-disable-kexec-test.patch Patch602: kexec-tools-2.0.12-makedumpfile-Support-_count-_refcount-rename-in-struct-p.patch Patch603: kexec-tools-2.0.13-fix-armv7-build-failure.patch +Patch604: kexec-tools-2.0.13-makedumpfile-x86-64-calculate-page-offset-from-pt-load.patch +Patch605: kexec-tools-2.0.13-makedumpfile-x86-64-translate-all-VA-to-PA-using-page-table-values.patch +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 + %description kexec-tools provides /sbin/kexec binary that facilitates a new kernel to boot using the kernel's kexec feature either on a @@ -112,6 +117,10 @@ tar -z -x -v -f %{SOURCE23} %patch601 -p1 %patch602 -p1 %patch603 -p1 +%patch604 -p1 +%patch605 -p1 +%patch606 -p1 +%patch607 -p1 %ifarch ppc %define archdef ARCH=ppc