Hello community, here is the log from the commit of package makedumpfile for openSUSE:Factory checked in at 2018-01-30 15:39:26 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/makedumpfile (Old) and /work/SRC/openSUSE:Factory/.makedumpfile.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "makedumpfile" Tue Jan 30 15:39:26 2018 rev:65 rq:570629 version:1.6.3 Changes: -------- --- /work/SRC/openSUSE:Factory/makedumpfile/makedumpfile.changes 2018-01-16 09:32:17.369996555 +0100 +++ /work/SRC/openSUSE:Factory/.makedumpfile.new/makedumpfile.changes 2018-01-30 15:39:27.364463901 +0100 @@ -1,0 +2,28 @@ +Mon Jan 29 14:01:03 UTC 2018 - ptesa...@suse.com + +- makedumpfile-always-use-bigger-SECTION_MAP_MASK.patch: Always use + bigger SECTION_MAP_MASK (bsc#1066811, bsc#1067703). + +------------------------------------------------------------------- +Mon Jan 29 13:49:43 UTC 2018 - ptesa...@suse.com + +- Update to 1.6.3 + * Support kernels up to 4.14.8 (bsc#1068864). + * 86_64: handle renamed init_level4_pgt -> init_top_pgt + * Fix SECTION_MAP_MASK for kernel >= v.13 + * book3s/ppc64: Lower the max real address to 53 bits for + kernels >= v4.11 + * Support symbol __cpu_online_mask + * ppc64: update hash page table geometry +- Drop upstreamed patches: + * makedumpfile-Fix-SECTION_MAP_MASK-for-kernel-v.13.patch + * makedumpfile-handle-renamed-init_level4_pgt-init_top_pgt.patch + * makedumpfile-ppc64-update-hash-page-table-geometry.patch + * makedumpfile-book3s-ppc64-Lower-the-max-real-address-to-53-bits.patch + * makedumpfile-__cpu_online_mask-symbol.patch + * makedumpfile-vtop4_x86_64_pagetable.patch + * makedumpfile-fix-KASLR-for-sadump.patch + * makedumpfile-fix-KASLR-for-sadump-while-kdump.patch + * makedumpfile-support-4.12.patch + +------------------------------------------------------------------- Old: ---- makedumpfile-1.6.2.tar.gz makedumpfile-Fix-SECTION_MAP_MASK-for-kernel-v.13.patch makedumpfile-__cpu_online_mask-symbol.patch makedumpfile-book3s-ppc64-Lower-the-max-real-address-to-53-bits.patch makedumpfile-fix-KASLR-for-sadump-while-kdump.patch makedumpfile-fix-KASLR-for-sadump.patch makedumpfile-handle-renamed-init_level4_pgt-init_top_pgt.patch makedumpfile-ppc64-update-hash-page-table-geometry.patch makedumpfile-vtop4_x86_64_pagetable.patch New: ---- makedumpfile-1.6.3.tar.gz makedumpfile-always-use-bigger-SECTION_MAP_MASK.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ makedumpfile.spec ++++++ --- /var/tmp/diff_new_pack.UvDSG1/_old 2018-01-30 15:39:27.940437011 +0100 +++ /var/tmp/diff_new_pack.UvDSG1/_new 2018-01-30 15:39:27.944436824 +0100 @@ -29,7 +29,7 @@ %endif Name: makedumpfile -Version: 1.6.2 +Version: 1.6.3 Release: 0 Summary: Partial kernel dump License: GPL-2.0 @@ -38,15 +38,8 @@ Source: https://sourceforge.net/projects/makedumpfile/files/makedumpfile/%{version}/%{name}-%{version}.tar.gz Source99: %{name}-rpmlintrc Patch0: %{name}-coptflags.diff -Patch1: %{name}-Fix-SECTION_MAP_MASK-for-kernel-v.13.patch -Patch2: %{name}-override-libtinfo.patch -Patch3: %{name}-handle-renamed-init_level4_pgt-init_top_pgt.patch -Patch4: %{name}-ppc64-update-hash-page-table-geometry.patch -Patch5: %{name}-book3s-ppc64-Lower-the-max-real-address-to-53-bits.patch -Patch6: %{name}-__cpu_online_mask-symbol.patch -Patch7: %{name}-vtop4_x86_64_pagetable.patch -Patch8: %{name}-fix-KASLR-for-sadump.patch -Patch9: %{name}-fix-KASLR-for-sadump-while-kdump.patch +Patch1: %{name}-override-libtinfo.patch +Patch2: %{name}-always-use-bigger-SECTION_MAP_MASK.patch BuildRequires: libdw-devel BuildRequires: libebl-devel BuildRequires: libelf-devel @@ -77,13 +70,6 @@ %patch0 -p1 %patch1 -p1 %patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 %build %if %{have_snappy} ++++++ makedumpfile-1.6.2.tar.gz -> makedumpfile-1.6.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/Makefile new/makedumpfile-1.6.3/Makefile --- old/makedumpfile-1.6.2/Makefile 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/Makefile 2018-01-26 02:30:25.000000000 +0100 @@ -1,7 +1,7 @@ # makedumpfile -VERSION=1.6.2 -DATE=27 Jul 2017 +VERSION=1.6.3 +DATE=29 Jun 2018 # Honour the environment variable CC ifeq ($(strip $CC),) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/README new/makedumpfile-1.6.3/README --- old/makedumpfile-1.6.2/README 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/README 2018-01-26 02:30:25.000000000 +0100 @@ -119,6 +119,9 @@ 4.9 | OK | ** | | | | ** | | -- | OK | OK | | | 4.10 | OK | ** | | | | ** | | -- | OK | OK | | | 4.11 | OK | ** | | | | ** | | -- | OK | OK | | | + 4.12 | OK | ** | | | | ** | | -- | OK | OK | | | + 4.13 | OK | ** | | | | ** | | -- | OK | OK | | | + 4.14 | OK | ** | | | | ** | | -- | OK | OK | | | OK : Support. -- : Not support. @@ -192,8 +195,7 @@ * BUG REPORT If finding some bugs, please send the information to the following: Masaki Tachibana <mas-tachib...@vf.jp.nec.com> - Minoru Usui <min-u...@ti.jp.nec.com> + Takuya Nakayama <tak-nakay...@tg.jp.nec.com> Daisuke Nishimura <dai-nishim...@rc.jp.nec.com> - Atsushi Kumagai <ats-kuma...@wm.jp.nec.com> kexec-ml <ke...@lists.infradead.org> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/arch/arm64.c new/makedumpfile-1.6.3/arch/arm64.c --- old/makedumpfile-1.6.2/arch/arm64.c 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/arch/arm64.c 2018-01-26 02:30:25.000000000 +0100 @@ -57,6 +57,8 @@ #define PGDIR_SHIFT ((PAGESHIFT() - 3) * pgtable_level + 3) #define PTRS_PER_PGD (1 << (va_bits - PGDIR_SHIFT)) #define PUD_SHIFT get_pud_shift_arm64() +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE - 1)) #define PTRS_PER_PTE (1 << (PAGESHIFT() - 3)) #define PTRS_PER_PUD PTRS_PER_PTE #define PMD_SHIFT ((PAGESHIFT() - 3) * 2 + 3) @@ -79,6 +81,10 @@ #define PMD_TYPE_SECT 1 #define PMD_TYPE_TABLE 3 +#define PUD_TYPE_MASK 3 +#define PUD_TYPE_SECT 1 +#define PUD_TYPE_TABLE 3 + #define pgd_index(vaddr) (((vaddr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) #define pgd_offset(pgdir, vaddr) ((pgd_t *)(pgdir) + pgd_index(vaddr)) @@ -253,6 +259,13 @@ return NOT_PADDR; } + if ((pud_val(pudv) & PUD_TYPE_MASK) == PUD_TYPE_SECT) { + /* 1GB section for Page Table level = 4 and Page Size = 4KB */ + paddr = (pud_val(pudv) & (PUD_MASK & PMD_SECTION_MASK)) + + (vaddr & (PUD_SIZE - 1)); + return paddr; + } + pmda = pmd_offset(puda, &pudv, vaddr); if (!readmem(PADDR, (unsigned long long)pmda, &pmdv, sizeof(pmdv))) { ERRMSG("Can't read pmd\n"); @@ -278,7 +291,7 @@ } break; case PMD_TYPE_SECT: - /* 1GB section */ + /* 512MB section for Page Table level = 3 and Page Size = 64KB*/ paddr = (pmd_val(pmdv) & (PMD_MASK & PMD_SECTION_MASK)) + (vaddr & (PMD_SIZE - 1)); break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/arch/ppc64.c new/makedumpfile-1.6.3/arch/ppc64.c --- old/makedumpfile-1.6.2/arch/ppc64.c 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/arch/ppc64.c 2018-01-26 02:30:25.000000000 +0100 @@ -245,10 +245,16 @@ } else if (info->kernel_version >= KERNEL_VERSION(4, 6, 0)) { info->l1_index_size = PTE_INDEX_SIZE_L4_64K_3_10; - info->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_6; - info->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_6; - info->l4_index_size = PGD_INDEX_SIZE_L4_64K_3_10; + if (info->kernel_version >= KERNEL_VERSION(4, 12, 0)) { + info->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_12; + info->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_12; + info->l4_index_size = PGD_INDEX_SIZE_L4_64K_4_12; + } else { + info->l2_index_size = PMD_INDEX_SIZE_L4_64K_4_6; + info->l3_index_size = PUD_INDEX_SIZE_L4_64K_4_6; + info->l4_index_size = PGD_INDEX_SIZE_L4_64K_3_10; + } } else if (info->kernel_version >= KERNEL_VERSION(3, 10, 0)) { info->l1_index_size = PTE_INDEX_SIZE_L4_64K_3_10; info->l2_index_size = PMD_INDEX_SIZE_L4_64K_3_10; @@ -307,11 +313,17 @@ } info->pte_rpn_mask = PTE_RPN_MASK_DEFAULT; - if (info->kernel_version >= KERNEL_VERSION(4, 6, 0)) { + if ((info->kernel_version >= KERNEL_VERSION(4, 6, 0)) && + (info->kernel_version < KERNEL_VERSION(4, 11, 0))) { info->pte_rpn_mask = PTE_RPN_MASK_L4_4_6; info->pte_rpn_shift = PTE_RPN_SHIFT_L4_4_6; } + if (info->kernel_version >= KERNEL_VERSION(4, 11, 0)) { + info->pte_rpn_mask = PTE_RPN_MASK_L4_4_11; + info->pte_rpn_shift = PTE_RPN_SHIFT_L4_4_11; + } + /* * Compute ptrs per each level */ @@ -576,6 +588,7 @@ ERRMSG("Can't initialize for vmalloc translation\n"); return FALSE; } + info->page_offset = __PAGE_OFFSET; return TRUE; } @@ -616,4 +629,40 @@ return ppc64_vtop_level4(vaddr); } +int arch_crashkernel_mem_size_ppc64() +{ + const char f_crashsize[] = "/proc/device-tree/chosen/linux,crashkernel-size"; + const char f_crashbase[] = "/proc/device-tree/chosen/linux,crashkernel-base"; + unsigned long crashk_sz_be, crashk_sz; + unsigned long crashk_base_be, crashk_base; + uint swap; + FILE *fp, *fpb; + + fp = fopen(f_crashsize, "r"); + if (!fp) { + ERRMSG("Cannot open %s\n", f_crashsize); + return FALSE; + } + fpb = fopen(f_crashbase, "r"); + if (!fp) { + ERRMSG("Cannot open %s\n", f_crashbase); + fclose(fp); + return FALSE; + } + + fread(&crashk_sz_be, sizeof(crashk_sz_be), 1, fp); + fread(&crashk_base_be, sizeof(crashk_base_be), 1, fpb); + fclose(fp); + fclose(fpb); + /* dev tree is always big endian */ + swap = !is_bigendian(); + crashk_sz = swap64(crashk_sz_be, swap); + crashk_base = swap64(crashk_base_be, swap); + crash_reserved_mem_nr = 1; + crash_reserved_mem[0].start = crashk_base; + crash_reserved_mem[0].end = crashk_base + crashk_sz - 1; + + return TRUE; +} + #endif /* powerpc64 */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/arch/x86_64.c new/makedumpfile-1.6.3/arch/x86_64.c --- old/makedumpfile-1.6.2/arch/x86_64.c 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/arch/x86_64.c 2018-01-26 02:30:25.000000000 +0100 @@ -255,20 +255,15 @@ * Translate a virtual address to a physical address by using 4 levels paging. */ unsigned long long -vtop4_x86_64(unsigned long vaddr) +__vtop4_x86_64(unsigned long vaddr, unsigned long pagetable) { unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte; unsigned long pte_paddr, pte; - if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) { - ERRMSG("Can't get the symbol of init_level4_pgt.\n"); - return NOT_PADDR; - } - /* * Get PGD. */ - page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + info->phys_base; + page_dir = pagetable; if (is_xen_memory()) { page_dir = ptom_xen(page_dir); if (page_dir == NOT_PADDR) @@ -346,6 +341,37 @@ return (pte & ENTRY_MASK) + PAGEOFFSET(vaddr); } +unsigned long long +vtop4_x86_64(unsigned long vaddr) +{ + unsigned long pagetable; + unsigned long init_level4_pgt; + + if (SYMBOL(init_level4_pgt) != NOT_FOUND_SYMBOL) + init_level4_pgt = SYMBOL(init_level4_pgt); + else if (SYMBOL(init_top_pgt) != NOT_FOUND_SYMBOL) + init_level4_pgt = SYMBOL(init_top_pgt); + else { + ERRMSG("Can't get the symbol of init_level4_pgt.\n"); + return NOT_PADDR; + } + + if (SYMBOL(level4_kernel_pgt) != NOT_FOUND_SYMBOL) { + ERRMSG("Kernel is built with 5-level page tables\n"); + return NOT_PADDR; + } + + pagetable = init_level4_pgt - __START_KERNEL_map + info->phys_base; + + return __vtop4_x86_64(vaddr, pagetable); +} + +unsigned long long +vtop4_x86_64_pagetable(unsigned long vaddr, unsigned long pagetable) +{ + return __vtop4_x86_64(vaddr, pagetable); +} + /* * for Xen extraction */ @@ -549,8 +575,16 @@ struct vmap_pfns *vmapp, *vmaphead = NULL, *cur, *tail; init_level4_pgt = SYMBOL(init_level4_pgt); + if (init_level4_pgt == NOT_FOUND_SYMBOL) + init_level4_pgt = SYMBOL(init_top_pgt); + if (init_level4_pgt == NOT_FOUND_SYMBOL) { - ERRMSG("init_level4_pgt not found\n"); + ERRMSG("init_level4_pgt/init_top_pgt not found\n"); + return FAILED; + } + + if (SYMBOL(level4_kernel_pgt) != NOT_FOUND_SYMBOL) { + ERRMSG("kernel is configured for 5-level page tables\n"); return FAILED; } pagestructsize = size_table.page; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/elf_info.c new/makedumpfile-1.6.3/elf_info.c --- old/makedumpfile-1.6.2/elf_info.c 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/elf_info.c 2018-01-26 02:30:25.000000000 +0100 @@ -810,8 +810,8 @@ int i, j, tidx = -1; unsigned long long vstart, vend, kvstart, kvend; struct pt_load_segment temp_seg = {0}; - kvstart = (ulong)start | PAGE_OFFSET; - kvend = (ulong)end | PAGE_OFFSET; + kvstart = (ulong)start + PAGE_OFFSET; + kvend = (ulong)end + PAGE_OFFSET; unsigned long size; for (i = 0; i < (*num_pt_loads); i++) { @@ -820,26 +820,26 @@ if (kvstart < vend && kvend > vstart) { if (kvstart != vstart && kvend != vend) { /* Split load segment */ - temp_seg.phys_start = end + 1; + temp_seg.phys_start = end; temp_seg.phys_end = (*pt_loads)[i].phys_end; - temp_seg.virt_start = kvend + 1; + temp_seg.virt_start = kvend; temp_seg.virt_end = vend; temp_seg.file_offset = (*pt_loads)[i].file_offset + temp_seg.virt_start - (*pt_loads)[i].virt_start; temp_seg.file_size = temp_seg.phys_end - temp_seg.phys_start; - (*pt_loads)[i].virt_end = kvstart - 1; - (*pt_loads)[i].phys_end = start - 1; + (*pt_loads)[i].virt_end = kvstart; + (*pt_loads)[i].phys_end = start; (*pt_loads)[i].file_size -= temp_seg.file_size; tidx = i+1; } else if (kvstart != vstart) { - (*pt_loads)[i].phys_end = start - 1; - (*pt_loads)[i].virt_end = kvstart - 1; + (*pt_loads)[i].phys_end = start; + (*pt_loads)[i].virt_end = kvstart; } else { - (*pt_loads)[i].phys_start = end + 1; - (*pt_loads)[i].virt_start = kvend + 1; + (*pt_loads)[i].phys_start = end; + (*pt_loads)[i].virt_start = kvend; } (*pt_loads)[i].file_size -= (end -start); } @@ -917,7 +917,7 @@ for (i = 0; i < crash_reserved_mem_nr; i++) { exclude_segment(&pt_loads, &num_pt_loads, - crash_reserved_mem[i].start, crash_reserved_mem[i].end); + crash_reserved_mem[i].start, crash_reserved_mem[i].end + 1); } max_file_offset = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/makedumpfile.8 new/makedumpfile-1.6.3/makedumpfile.8 --- old/makedumpfile-1.6.2/makedumpfile.8 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/makedumpfile.8 2018-01-26 02:30:25.000000000 +0100 @@ -1,4 +1,4 @@ -.TH MAKEDUMPFILE 8 "27 Jul 2017" "makedumpfile v1.6.2" "Linux System Administrator's Manual" +.TH MAKEDUMPFILE 8 "29 Jun 2018" "makedumpfile v1.6.3" "Linux System Administrator's Manual" .SH NAME makedumpfile \- make a small dumpfile of kdump .SH SYNOPSIS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/makedumpfile.c new/makedumpfile-1.6.3/makedumpfile.c --- old/makedumpfile-1.6.2/makedumpfile.c 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/makedumpfile.c 2018-01-26 02:30:25.000000000 +0100 @@ -1089,6 +1089,21 @@ return TRUE; } +static int populate_kernel_version(void) +{ + struct utsname utsname; + + if (uname(&utsname)) { + ERRMSG("Cannot get name and information about current kernel : %s\n", + strerror(errno)); + return FALSE; + } + + info->kernel_version = get_kernel_version(utsname.release); + + return TRUE; +} + int check_release(void) { @@ -1486,6 +1501,8 @@ SYMBOL_INIT(_stext, "_stext"); SYMBOL_INIT(swapper_pg_dir, "swapper_pg_dir"); SYMBOL_INIT(init_level4_pgt, "init_level4_pgt"); + SYMBOL_INIT(level4_kernel_pgt, "level4_kernel_pgt"); + SYMBOL_INIT(init_top_pgt, "init_top_pgt"); SYMBOL_INIT(vmlist, "vmlist"); SYMBOL_INIT(vmap_area_list, "vmap_area_list"); SYMBOL_INIT(node_online_map, "node_online_map"); @@ -1517,8 +1534,13 @@ SYMBOL_INIT(__per_cpu_load, "__per_cpu_load"); SYMBOL_INIT(__per_cpu_offset, "__per_cpu_offset"); SYMBOL_INIT(cpu_online_mask, "cpu_online_mask"); - if (SYMBOL(cpu_online_mask) == NOT_FOUND_SYMBOL) - SYMBOL_INIT(cpu_online_mask, "cpu_online_map"); + SYMBOL_INIT(__cpu_online_mask, "__cpu_online_mask"); + if (SYMBOL(cpu_online_mask) == NOT_FOUND_SYMBOL) { + if (SYMBOL(__cpu_online_mask) == NOT_FOUND_SYMBOL) + SYMBOL_INIT(cpu_online_mask, "cpu_online_map"); + else + SYMBOL_INIT(cpu_online_mask, "__cpu_online_mask"); + } SYMBOL_INIT(kexec_crash_image, "kexec_crash_image"); SYMBOL_INIT(node_remap_start_vaddr, "node_remap_start_vaddr"); SYMBOL_INIT(node_remap_end_vaddr, "node_remap_end_vaddr"); @@ -1547,6 +1569,10 @@ SYMBOL_INIT(demote_segment_4k, "demote_segment_4k"); SYMBOL_INIT(cur_cpu_spec, "cur_cpu_spec"); + SYMBOL_INIT(divide_error, "divide_error"); + SYMBOL_INIT(idt_table, "idt_table"); + SYMBOL_INIT(saved_command_line, "saved_command_line"); + return TRUE; } @@ -2105,6 +2131,8 @@ WRITE_SYMBOL("_stext", _stext); WRITE_SYMBOL("swapper_pg_dir", swapper_pg_dir); WRITE_SYMBOL("init_level4_pgt", init_level4_pgt); + WRITE_SYMBOL("level4_kernel_pgt", level4_kernel_pgt); + WRITE_SYMBOL("init_top_pgt", init_top_pgt); WRITE_SYMBOL("vmlist", vmlist); WRITE_SYMBOL("vmap_area_list", vmap_area_list); WRITE_SYMBOL("node_online_map", node_online_map); @@ -2242,6 +2270,13 @@ WRITE_NUMBER_UNSIGNED("kimage_voffset", kimage_voffset); #endif + if (info->phys_base) + fprintf(info->file_vmcoreinfo, "%s%lu\n", STR_NUMBER("phys_base"), + info->phys_base); + if (info->kaslr_offset) + fprintf(info->file_vmcoreinfo, "%s%lx\n", STR_KERNELOFFSET, + info->kaslr_offset); + /* * write the source file of 1st kernel */ @@ -2500,6 +2535,8 @@ READ_SYMBOL("_stext", _stext); READ_SYMBOL("swapper_pg_dir", swapper_pg_dir); READ_SYMBOL("init_level4_pgt", init_level4_pgt); + READ_SYMBOL("level4_kernel_pgt", level4_kernel_pgt); + READ_SYMBOL("init_top_pgt", init_top_pgt); READ_SYMBOL("vmlist", vmlist); READ_SYMBOL("vmap_area_list", vmap_area_list); READ_SYMBOL("node_online_map", node_online_map); @@ -3300,7 +3337,10 @@ return NOT_KV_ADDR; } map = ULONG(mem_section + OFFSET(mem_section.section_mem_map)); - map &= SECTION_MAP_MASK; + if (info->kernel_version < KERNEL_VERSION(4, 13, 0)) + map &= SECTION_MAP_MASK_4_12; + else + map &= SECTION_MAP_MASK; free(mem_section); return map; @@ -4203,7 +4243,7 @@ int byte, bit; static int warning = 0; - if (pfn < cycle->start_pfn || cycle->end_pfn <= pfn) { + if (!is_cyclic_region(pfn, cycle)) { if (warning == 0) { MSG("WARNING: PFN out of cycle range. (pfn:%llx, ", pfn); MSG("cycle:[%llx-%llx])\n", cycle->start_pfn, cycle->end_pfn); @@ -9401,15 +9441,15 @@ int initial_xen(void) { - int xen_info_required = TRUE; - off_t offset; - unsigned long size; - #if defined(__powerpc64__) || defined(__powerpc32__) MSG("\n"); MSG("Xen is not supported on powerpc.\n"); return FALSE; #else + int xen_info_required = TRUE; + off_t offset; + unsigned long size; + #ifndef __x86_64__ if (DL_EXCLUDE_ZERO < info->max_dump_level) { MSG("Dump_level is invalid. It should be 0 or 1.\n"); @@ -10925,6 +10965,9 @@ { int ret; + if (arch_crashkernel_mem_size()) + return TRUE; + ret = iomem_for_each_line("Crash kernel\n", crashkernel_mem_callback, NULL); crash_reserved_mem_nr = ret; @@ -10934,20 +10977,14 @@ static int get_page_offset(void) { - struct utsname utsname; - if (uname(&utsname)) { - ERRMSG("Cannot get name and information about current kernel : %s", - strerror(errno)); + if (!populate_kernel_version()) return FALSE; - } - info->kernel_version = get_kernel_version(utsname.release); get_versiondep_info(); return TRUE; } - /* Returns the physical address of start of crash notes buffer for a kernel. */ static int get_sys_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len) { @@ -11324,6 +11361,9 @@ MSG("Try `makedumpfile --help' for more information.\n"); goto out; } + if (!populate_kernel_version()) + goto out; + if (info->kernel_version < KERNEL_VERSION(4, 11, 0) && !info->flag_force) { MSG("mem-usage not supported for this kernel.\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/makedumpfile.conf.5 new/makedumpfile-1.6.3/makedumpfile.conf.5 --- old/makedumpfile-1.6.2/makedumpfile.conf.5 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/makedumpfile.conf.5 2018-01-26 02:30:25.000000000 +0100 @@ -1,4 +1,4 @@ -.TH MAKEDUMPFILE.CONF 5 "27 Jul 2017" "makedumpfile v1.6.2" "Linux System Administrator's Manual" +.TH MAKEDUMPFILE.CONF 5 "29 Jun 2018" "makedumpfile v1.6.3" "Linux System Administrator's Manual" .SH NAME makedumpfile.conf \- The filter configuration file for makedumpfile(8). .SH DESCRIPTION diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/makedumpfile.h new/makedumpfile-1.6.3/makedumpfile.h --- old/makedumpfile-1.6.2/makedumpfile.h 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/makedumpfile.h 2018-01-26 02:30:25.000000000 +0100 @@ -45,6 +45,7 @@ #include "sadump_mod.h" #include <pthread.h> #include <semaphore.h> +#include <inttypes.h> #define VMEMMAPSTART 0xffffea0000000000UL #define BITS_PER_WORD 64 @@ -183,7 +184,9 @@ #define SECTIONS_PER_ROOT() (info->sections_per_root) #define SECTION_ROOT_MASK() (SECTIONS_PER_ROOT() - 1) #define SECTION_NR_TO_ROOT(sec) ((sec) / SECTIONS_PER_ROOT()) -#define SECTION_MAP_LAST_BIT (1UL<<2) +#define SECTION_IS_ONLINE (1UL<<2) +#define SECTION_MAP_LAST_BIT (1UL<<3) +#define SECTION_MAP_MASK_4_12 (~(SECTION_IS_ONLINE-1)) #define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1)) #define NR_SECTION_ROOTS() divideup(num_section, SECTIONS_PER_ROOT()) #define SECTION_NR_TO_PFN(sec) ((sec) << PFN_SECTION_SHIFT()) @@ -475,7 +478,7 @@ #define KVER_MIN_SHIFT 16 #define KERNEL_VERSION(x,y,z) (((x) << KVER_MAJ_SHIFT) | ((y) << KVER_MIN_SHIFT) | (z)) #define OLDEST_VERSION KERNEL_VERSION(2, 6, 15)/* linux-2.6.15 */ -#define LATEST_VERSION KERNEL_VERSION(4, 11, 7)/* linux-4.11.7 */ +#define LATEST_VERSION KERNEL_VERSION(4, 14, 8)/* linux-4.14.8 */ /* * vmcoreinfo in /proc/vmcore @@ -666,6 +669,9 @@ #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 @@ -689,6 +695,11 @@ #define PUD_MASKED_BITS_4_7 0xc0000000000000ffUL #define PMD_MASKED_BITS_4_7 0xc0000000000000ffUL +#define PTE_RPN_SIZE_L4_4_11 53 +#define PTE_RPN_MASK_L4_4_11 \ + (((1UL << PTE_RPN_SIZE_L4_4_11) - 1) & ~((1UL << info->page_shift) - 1)) +#define PTE_RPN_SHIFT_L4_4_11 info->page_shift + /* * Supported MMU types */ @@ -933,6 +944,7 @@ #define get_xen_basic_info_arch(X) get_xen_basic_info_arm64(X) #define get_xen_info_arch(X) get_xen_info_arm64(X) #define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() #endif /* aarch64 */ #ifdef __arm__ @@ -946,6 +958,7 @@ #define get_kaslr_offset(X) stub_false() #define vaddr_to_paddr(X) vaddr_to_paddr_arm(X) #define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() #endif /* arm */ #ifdef __x86__ @@ -959,6 +972,7 @@ #define get_kaslr_offset(X) stub_false() #define vaddr_to_paddr(X) vaddr_to_paddr_x86(X) #define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() #endif /* x86 */ #ifdef __x86_64__ @@ -967,6 +981,7 @@ int get_machdep_info_x86_64(void); int get_versiondep_info_x86_64(void); unsigned long long vtop4_x86_64(unsigned long vaddr); +unsigned long long vtop4_x86_64_pagetable(unsigned long vaddr, unsigned long pagetable); #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() @@ -974,12 +989,14 @@ #define get_kaslr_offset(X) get_kaslr_offset_x86_64(X) #define vaddr_to_paddr(X) vtop4_x86_64(X) #define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() #endif /* x86_64 */ #ifdef __powerpc64__ /* powerpc64 */ int get_machdep_info_ppc64(void); int get_versiondep_info_ppc64(void); unsigned long long vaddr_to_paddr_ppc64(unsigned long vaddr); +int arch_crashkernel_mem_size_ppc64(void); #define find_vmemmap() stub_false() #define get_phys_base() stub_true() #define get_machdep_info() get_machdep_info_ppc64() @@ -987,6 +1004,7 @@ #define get_kaslr_offset(X) stub_false() #define vaddr_to_paddr(X) vaddr_to_paddr_ppc64(X) #define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() arch_crashkernel_mem_size_ppc64() #endif /* powerpc64 */ #ifdef __powerpc32__ /* powerpc32 */ @@ -999,6 +1017,7 @@ #define get_kaslr_offset(X) stub_false() #define vaddr_to_paddr(X) vaddr_to_paddr_ppc(X) #define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() #endif /* powerpc32 */ #ifdef __s390x__ /* s390x */ @@ -1012,6 +1031,7 @@ #define get_kaslr_offset(X) stub_false() #define vaddr_to_paddr(X) vaddr_to_paddr_s390x(X) #define is_phys_addr(X) is_iomem_phys_addr_s390x(X) +#define arch_crashkernel_mem_size() stub_false() #endif /* s390x */ #ifdef __ia64__ /* ia64 */ @@ -1026,6 +1046,7 @@ #define vaddr_to_paddr(X) vaddr_to_paddr_ia64(X) #define VADDR_REGION(X) (((unsigned long)(X)) >> REGION_SHIFT) #define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() #endif /* ia64 */ #ifdef __sparc64__ /* sparc64 */ @@ -1038,6 +1059,7 @@ #define get_versiondep_info() get_versiondep_info_sparc64() #define vaddr_to_paddr(X) vaddr_to_paddr_sparc64(X) #define is_phys_addr(X) stub_true_ul(X) +#define arch_crashkernel_mem_size() stub_false() #endif /* sparc64 */ typedef unsigned long long mdf_pfn_t; @@ -1517,6 +1539,8 @@ unsigned long long _stext; unsigned long long swapper_pg_dir; unsigned long long init_level4_pgt; + unsigned long long level4_kernel_pgt; + unsigned long long init_top_pgt; unsigned long long vmlist; unsigned long long vmap_area_list; unsigned long long phys_base; @@ -1578,7 +1602,11 @@ unsigned long long __per_cpu_offset; unsigned long long __per_cpu_load; unsigned long long cpu_online_mask; + unsigned long long __cpu_online_mask; unsigned long long kexec_crash_image; + unsigned long long divide_error; + unsigned long long idt_table; + unsigned long long saved_command_line; /* * symbols on ppc64 arch @@ -1939,7 +1967,8 @@ unsigned long base, unsigned long length), void *data); - +int is_bigendian(void); +int get_symbol_info(void); /* * for Xen extraction @@ -2096,11 +2125,20 @@ } static inline int -is_dumpable_buffer(struct dump_bitmap *bitmap, mdf_pfn_t pfn, struct cycle *cycle) +is_cyclic_region(mdf_pfn_t pfn, struct cycle *cycle) { if (pfn < cycle->start_pfn || cycle->end_pfn <= pfn) return FALSE; else + return TRUE; +} + +static inline int +is_dumpable_buffer(struct dump_bitmap *bitmap, mdf_pfn_t pfn, struct cycle *cycle) +{ + if (!is_cyclic_region(pfn, cycle)) + return FALSE; + else return is_on(bitmap->buf, pfn - cycle->start_pfn); } @@ -2140,15 +2178,6 @@ } static inline int -is_cyclic_region(mdf_pfn_t pfn, struct cycle *cycle) -{ - if (pfn < cycle->start_pfn || cycle->end_pfn <= pfn) - return FALSE; - else - return TRUE; -} - -static inline int is_zero_page(unsigned char *buf, long page_size) { size_t i; @@ -2244,7 +2273,7 @@ #define OPT_DEBUG 'D' #define OPT_DUMP_LEVEL 'd' #define OPT_ELF_DUMPFILE 'E' -#define OPT_EXCLUDE_UNUSED_VM 'e' +#define OPT_EXCLUDE_UNUSED_VM 'e' #define OPT_FLATTEN 'F' #define OPT_FORCE 'f' #define OPT_GENERATE_VMCOREINFO 'g' @@ -2271,10 +2300,10 @@ #define OPT_EPPIC OPT_START+11 #define OPT_NON_MMAP OPT_START+12 #define OPT_MEM_USAGE OPT_START+13 -#define OPT_SPLITBLOCK_SIZE OPT_START+14 +#define OPT_SPLITBLOCK_SIZE OPT_START+14 #define OPT_WORKING_DIR OPT_START+15 -#define OPT_NUM_THREADS OPT_START+16 -#define OPT_PARTIAL_DMESG OPT_START+17 +#define OPT_NUM_THREADS OPT_START+16 +#define OPT_PARTIAL_DMESG OPT_START+17 /* * Function Prototype. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/makedumpfile.spec new/makedumpfile-1.6.3/makedumpfile.spec --- old/makedumpfile-1.6.2/makedumpfile.spec 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/makedumpfile.spec 2018-01-26 02:30:25.000000000 +0100 @@ -1,6 +1,6 @@ Name: makedumpfile Summary: makedumpfile package -Version: 1.6.2 +Version: 1.6.3 Release: 1 Group: Applications/Text License: GPL diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.2/sadump_info.c new/makedumpfile-1.6.3/sadump_info.c --- old/makedumpfile-1.6.2/sadump_info.c 2017-07-26 09:49:08.000000000 +0200 +++ new/makedumpfile-1.6.3/sadump_info.c 2018-01-26 02:30:25.000000000 +0100 @@ -953,7 +953,8 @@ return FALSE; } - if (SIZE(cpumask) == NOT_FOUND_STRUCTURE) + if ((SIZE(cpumask) == NOT_FOUND_STRUCTURE) || + (SYMBOL(__cpu_online_mask) != NOT_FOUND_SYMBOL)) cpu_online_mask_addr = SYMBOL(cpu_online_mask); else { @@ -1034,6 +1035,409 @@ #ifdef __x86_64__ +/* + * Get address of vector0 interrupt handler (Devide Error) form Interrupt + * Descriptor Table. + */ +static unsigned long +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(PADDR, idtr, &gate, sizeof(gate)); + + 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) +{ + char cmdline[BUFSIZE], *ptr; + ulong cmdline_vaddr; + ulong cmdline_paddr; + ulong buf_vaddr, buf_paddr; + char *end; + ulong elfcorehdr_addr = 0, elfcorehdr_size = 0; + + if (SYMBOL(saved_command_line) == NOT_FOUND_SYMBOL) { + ERRMSG("Can't get the symbol of saved_command_line.\n"); + return 0; + } + cmdline_vaddr = SYMBOL(saved_command_line); + if ((cmdline_paddr = vtop4_x86_64_pagetable(cmdline_vaddr, cr3)) == NOT_PADDR) + return 0; + + DEBUG_MSG("sadump: cmdline vaddr: %lx\n", cmdline_vaddr); + DEBUG_MSG("sadump: cmdline paddr: %lx\n", cmdline_paddr); + + if (!readmem(PADDR, cmdline_paddr, &buf_vaddr, sizeof(ulong))) + return 0; + + if ((buf_paddr = vtop4_x86_64_pagetable(buf_vaddr, cr3)) == NOT_PADDR) + return 0; + + DEBUG_MSG("sadump: cmdline buf vaddr: %lx\n", buf_vaddr); + DEBUG_MSG("sadump: cmdline buf paddr: %lx\n", buf_paddr); + + memset(cmdline, 0, BUFSIZE); + if (!readmem(PADDR, buf_paddr, cmdline, BUFSIZE)) + return 0; + + ptr = strstr(cmdline, "elfcorehdr="); + if (!ptr) + return 0; + + DEBUG_MSG("sadump: 2nd kernel detected.\n"); + + ptr += strlen("elfcorehdr="); + elfcorehdr_addr = memparse(ptr, &end); + if (*end == '@') { + elfcorehdr_size = elfcorehdr_addr; + elfcorehdr_addr = memparse(end + 1, &end); + } + + DEBUG_MSG("sadump: elfcorehdr_addr: %lx\n", elfcorehdr_addr); + DEBUG_MSG("sadump: 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_in_kdump_kernel(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(PADDR, elfcorehdr, e_ident, EI_NIDENT)) + return FALSE; + + if (e_ident[EI_CLASS] != ELFCLASS64) { + ERRMSG("Only ELFCLASS64 is supportd\n"); + return FALSE; + } + + if (!readmem(PADDR, elfcorehdr, &ehdr, sizeof(ehdr))) + 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) { + ERRMSG("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(PADDR, ptr, &phdr, sizeof(phdr))) + return FALSE; + + ptr += sizeof(phdr); + if (phdr.p_type != PT_NOTE) + continue; + + offset = phdr.p_offset; + if (!readmem(PADDR, offset, &nhdr, sizeof(nhdr))) + return FALSE; + + offset += divideup(sizeof(Elf64_Nhdr), sizeof(Elf64_Word))* + sizeof(Elf64_Word); + memset(name, 0, sizeof(name)); + if (!readmem(PADDR, offset, name, sizeof(name))) + return FALSE; + + if(!strcmp(name, "VMCOREINFO")) { + nhdr_offset = offset; + break; + } + } + + if (!nhdr_offset) + return FALSE; + + *addr = nhdr_offset + + divideup(nhdr.n_namesz, sizeof(Elf64_Word))* + sizeof(Elf64_Word); + *len = nhdr.n_descsz; + + DEBUG_MSG("sadump: vmcoreinfo addr: %lx\n", *addr); + DEBUG_MSG("sadump: 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. + */ +int +get_kaslr_offset_from_vmcoreinfo(ulong cr3, ulong *kaslr_offset, + ulong *phys_base) +{ + ulong elfcorehdr_addr = 0; + ulong vmcoreinfo_addr; + int vmcoreinfo_len; + char *buf, *pos; + int ret = FALSE; + + elfcorehdr_addr = get_elfcorehdr(cr3); + if (!elfcorehdr_addr) + return FALSE; + + if (!get_vmcoreinfo_in_kdump_kernel(elfcorehdr_addr, &vmcoreinfo_addr, + &vmcoreinfo_len)) + return FALSE; + + if (!vmcoreinfo_len) + return FALSE; + + DEBUG_MSG("sadump: Find vmcoreinfo in kdump memory\n"); + + if (!(buf = malloc(vmcoreinfo_len))) { + ERRMSG("Can't allocate vmcoreinfo buffer.\n"); + return FALSE; + } + + if (!readmem(PADDR, vmcoreinfo_addr, buf, vmcoreinfo_len)) + goto finish; + + pos = strstr(buf, STR_NUMBER("phys_base")); + if (!pos) + goto finish; + *phys_base = strtoull(pos + strlen(STR_NUMBER("phys_base")), NULL, 0); + + pos = strstr(buf, STR_KERNELOFFSET); + if (!pos) + goto finish; + *kaslr_offset = strtoull(pos + strlen(STR_KERNELOFFSET), NULL, 16); + ret = TRUE; + +finish: + free(buf); + return ret; +} + +/* + * Calculate kaslr_offset and phys_base + * + * kaslr_offset: + * The difference between original address in 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 +calc_kaslr_offset(void) +{ + struct sadump_header *sh = si->sh_memory; + uint64_t idtr = 0, cr3 = 0, idtr_paddr; + struct sadump_smram_cpu_state smram, zero; + int apicid; + unsigned long divide_error_vmcore, divide_error_vmlinux; + unsigned long kaslr_offset, phys_base; + unsigned long kaslr_offset_kdump, phys_base_kdump; + + memset(&zero, 0, sizeof(zero)); + for (apicid = 0; apicid < sh->nr_cpus; ++apicid) { + if (!get_smram_cpu_state(apicid, &smram)) { + ERRMSG("get_smram_cpu_state error\n"); + return FALSE; + } + + if (memcmp(&smram, &zero, sizeof(smram)) != 0) + break; + } + if (apicid >= sh->nr_cpus) { + ERRMSG("Can't get smram state\n"); + return FALSE; + } + + idtr = ((uint64_t)smram.IdtUpper)<<32 | (uint64_t)smram.IdtLower; + cr3 = smram.Cr3; + + /* Convert virtual address of IDT table to physical address */ + if ((idtr_paddr = vtop4_x86_64_pagetable(idtr, cr3)) == NOT_PADDR) + return FALSE; + + /* Now we can calculate kaslr_offset and phys_base */ + divide_error_vmlinux = SYMBOL(divide_error); + divide_error_vmcore = get_vec0_addr(idtr_paddr); + kaslr_offset = divide_error_vmcore - divide_error_vmlinux; + phys_base = idtr_paddr - + (SYMBOL(idt_table) + kaslr_offset - __START_KERNEL_map); + + info->kaslr_offset = kaslr_offset; + info->phys_base = phys_base; + + DEBUG_MSG("sadump: idtr=%" PRIx64 "\n", idtr); + DEBUG_MSG("sadump: cr3=%" PRIx64 "\n", cr3); + DEBUG_MSG("sadump: idtr(phys)=%" PRIx64 "\n", idtr_paddr); + DEBUG_MSG("sadump: devide_error(vmlinux)=%lx\n", + divide_error_vmlinux); + DEBUG_MSG("sadump: devide_error(vmcore)=%lx\n", + divide_error_vmcore); + + /* Reload symbol */ + if (!get_symbol_info()) + return FALSE; + + /* + * 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_kdump, + &phys_base_kdump)) { + info->kaslr_offset = kaslr_offset_kdump; + info->phys_base = phys_base_kdump; + + /* Reload symbol */ + if (!get_symbol_info()) + return FALSE; + } + + DEBUG_MSG("sadump: kaslr_offset=%lx\n", info->kaslr_offset); + DEBUG_MSG("sadump: phys_base=%lx\n", info->phys_base); + + return TRUE; +} + int sadump_virt_phys_base(void) { @@ -1064,6 +1468,9 @@ } failed: + if (calc_kaslr_offset()) + return TRUE; + info->phys_base = 0; DEBUG_MSG("sadump: failed to calculate phys_base; default to 0\n"); @@ -1517,10 +1924,14 @@ if (!readmem(VADDR, SYMBOL(x86_bios_cpu_apicid_early_ptr), &early_ptr, sizeof(early_ptr))) return FALSE; - + /* + * Note: SYMBOL(name) value is adjusted by info->kaslr_offset, + * but per_cpu symbol does not need to be adjusted becasue it + * is not affected by kaslr. + */ apicid_addr = early_ptr ? SYMBOL(x86_bios_cpu_apicid_early_map)+cpu*sizeof(uint16_t) - : per_cpu_ptr(SYMBOL(x86_bios_cpu_apicid), cpu); + : per_cpu_ptr(SYMBOL(x86_bios_cpu_apicid) - info->kaslr_offset, cpu); if (!readmem(VADDR, apicid_addr, &apicid_u16, sizeof(uint16_t))) return FALSE; ++++++ makedumpfile-always-use-bigger-SECTION_MAP_MASK.patch ++++++ From: Petr Tesarik <ptesa...@suse.com> Date: Mon, 29 Jan 2018 14:59:28 +0200 Subject: Always use bigger SECTION_MAP_MASK References: bsc#1066811, bsc#1067703 Upstream: not yet Since kernel commit 2d070eab2e82 merely reused a previously unused bit, it is safe to mask it off for all kernel versions, because it had always been zero (even in kernels < 4.13). Signed-off-by: Petr Tesarik <ptesa...@suse.com> --- makedumpfile.c | 5 +---- makedumpfile.h | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) --- a/makedumpfile.c +++ b/makedumpfile.c @@ -3337,10 +3337,7 @@ section_mem_map_addr(unsigned long addr) return NOT_KV_ADDR; } map = ULONG(mem_section + OFFSET(mem_section.section_mem_map)); - if (info->kernel_version < KERNEL_VERSION(4, 13, 0)) - map &= SECTION_MAP_MASK_4_12; - else - map &= SECTION_MAP_MASK; + map &= SECTION_MAP_MASK; free(mem_section); return map; --- a/makedumpfile.h +++ b/makedumpfile.h @@ -186,7 +186,6 @@ isAnon(unsigned long mapping) #define SECTION_NR_TO_ROOT(sec) ((sec) / SECTIONS_PER_ROOT()) #define SECTION_IS_ONLINE (1UL<<2) #define SECTION_MAP_LAST_BIT (1UL<<3) -#define SECTION_MAP_MASK_4_12 (~(SECTION_IS_ONLINE-1)) #define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1)) #define NR_SECTION_ROOTS() divideup(num_section, SECTIONS_PER_ROOT()) #define SECTION_NR_TO_PFN(sec) ((sec) << PFN_SECTION_SHIFT())