Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package makedumpfile for openSUSE:Factory checked in at 2021-04-08 21:03:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/makedumpfile (Old) and /work/SRC/openSUSE:Factory/.makedumpfile.new.2401 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "makedumpfile" Thu Apr 8 21:03:19 2021 rev:79 rq:883570 version:1.6.8 Changes: -------- --- /work/SRC/openSUSE:Factory/makedumpfile/makedumpfile.changes 2020-06-08 23:51:34.922761854 +0200 +++ /work/SRC/openSUSE:Factory/.makedumpfile.new.2401/makedumpfile.changes 2021-04-08 21:03:29.149986199 +0200 @@ -1,0 +2,30 @@ +Wed Apr 7 09:52:16 UTC 2021 - Petr Tesa????k <[email protected]> + +- Support kernel 5.11: + * makedumpfile-use-uts_namespace.name-offset-VMCOREINFO.patch: + make use of 'uts_namespace.name' offset in VMCOREINFO. + +------------------------------------------------------------------- +Sun Apr 4 13:13:31 UTC 2021 - Petr Tesa????k <[email protected]> + +- Update upstream project location (URL and Source). + +------------------------------------------------------------------- +Wed Mar 24 16:05:04 UTC 2021 - Petr Mladek <[email protected]> + +- Update to version 1.6.8: + * Support newer kernels up to v5.9 + * arm64: Add support for ARMv8.2-LPA (52-bit PA support) + * Retrieve MAX_PHYSMEM_BITS from vmcoreinfo + * sadump, kaslr: fix failure of calculating kaslr_offset + * Introduce --check-params option + * cope with not-present mem section +- Drop upstreamed patches: + * makedumpfile-Fix-cd_header-offset-overflow-with-large-pfn.patch + * makedumpfile-arm64-Align-PMD_SECTION_MASK-with-PHYS_MASK.patch + * makedumpfile-sadump-Fix-failure-of-reading.patch +- Allow to read kernel log from the lockless ringbuffer (bsc#1183965): + * makedumpfile-printk-add-support-for-lockless-ringbuffer.patch + * makedumpfile-printk-use-committed-finalized-state-value.patch + +------------------------------------------------------------------- Old: ---- makedumpfile-1.6.7.tar.gz makedumpfile-Fix-cd_header-offset-overflow-with-large-pfn.patch makedumpfile-arm64-Align-PMD_SECTION_MASK-with-PHYS_MASK.patch makedumpfile-sadump-Fix-failure-of-reading.patch New: ---- makedumpfile-1.6.8.tar.gz makedumpfile-printk-add-support-for-lockless-ringbuffer.patch makedumpfile-printk-use-committed-finalized-state-value.patch makedumpfile-use-uts_namespace.name-offset-VMCOREINFO.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ makedumpfile.spec ++++++ --- /var/tmp/diff_new_pack.Fw0YXX/_old 2021-04-08 21:03:29.825986929 +0200 +++ /var/tmp/diff_new_pack.Fw0YXX/_new 2021-04-08 21:03:29.825986929 +0200 @@ -1,7 +1,7 @@ # # spec file for package makedumpfile # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -32,20 +32,20 @@ # End of compatibility cruft Name: makedumpfile -Version: 1.6.7 +Version: 1.6.8 Release: 0 Summary: Partial kernel dump License: GPL-2.0-only Group: System/Kernel -URL: https://sourceforge.net/projects/makedumpfile/ -Source: https://sourceforge.net/projects/makedumpfile/files/makedumpfile/%{version}/%{name}-%{version}.tar.gz +URL: https://github.com/makedumpfile/makedumpfile +Source: https://github.com/makedumpfile/makedumpfile/releases/download/%{version}/%{name}-%{version}.tar.gz Source99: %{name}-rpmlintrc Patch1: %{name}-override-libtinfo.patch Patch2: %{name}-ppc64-VA-range-SUSE.patch Patch3: %{name}-PN_XNUM.patch -Patch4: %{name}-arm64-Align-PMD_SECTION_MASK-with-PHYS_MASK.patch -Patch5: %{name}-Fix-cd_header-offset-overflow-with-large-pfn.patch -Patch6: %{name}-sadump-Fix-failure-of-reading.patch +Patch4: %{name}-printk-add-support-for-lockless-ringbuffer.patch +Patch5: %{name}-printk-use-committed-finalized-state-value.patch +Patch6: %{name}-use-uts_namespace.name-offset-VMCOREINFO.patch BuildRequires: libdw-devel BuildRequires: libelf-devel BuildRequires: libeppic-devel ++++++ makedumpfile-1.6.7.tar.gz -> makedumpfile-1.6.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/Makefile new/makedumpfile-1.6.8/Makefile --- old/makedumpfile-1.6.7/Makefile 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/Makefile 2020-11-16 01:29:37.000000000 +0100 @@ -1,7 +1,7 @@ # makedumpfile -VERSION=1.6.7 -DATE=16 Jan 2020 +VERSION=1.6.8 +DATE=16 Nov 2020 # Honour the environment variable CC ifeq ($(strip $CC),) @@ -52,7 +52,7 @@ LIBS = -ldw -lbz2 -ldl -lelf -lz ifneq ($(LINKTYPE), dynamic) -LIBS := -static $(LIBS) +LIBS := -static $(LIBS) -llzma endif ifeq ($(USELZO), on) @@ -62,6 +62,9 @@ ifeq ($(USESNAPPY), on) LIBS := -lsnappy $(LIBS) +ifneq ($(LINKTYPE), dynamic) +LIBS := $(LIBS) -lstdc++ +endif CFLAGS += -DUSESNAPPY endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/README new/makedumpfile-1.6.8/README --- old/makedumpfile-1.6.7/README 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/README 2020-11-16 01:29:37.000000000 +0100 @@ -18,6 +18,7 @@ # # mkdir /usr/local/include/elfutils/ # cp ./libdw/libdw.h /usr/local/include/elfutils/libdw.h + # cp ./libdwfl/libdwfl.h /usr/local/include/elfutils/libdwfl.h # cp ./libdw/dwarf.h /usr/local/include/dwarf.h # cp ./libelf/libelf.h /usr/local/include/libelf.h # cp ./libelf/gelf.h /usr/local/include/gelf.h @@ -30,7 +31,7 @@ * BUILD & INSTALL 1.Get the latest makedumpfile from the following site: - https://sourceforge.net/projects/makedumpfile/ + https://github.com/makedumpfile/makedumpfile 2.Uncompress the tar file: # tar -zxvf makedumpfile-x.y.z.tar.gz 3.Enter the makedumpfile subdirectory: @@ -133,6 +134,11 @@ 5.2 | | ** | | | | ** | | -- | | OK | | | 5.3 | | ** | | | | ** | | -- | | OK | | | 5.4 | OK | ** | | | | ** | | -- | OK | OK | | | + 5.5 | | ** | | | | ** | | -- | | OK | | | + 5.6 | | ** | | | | ** | | -- | | OK | | | + 5.7 | | ** | | | | ** | | -- | | OK | | | + 5.8 | | ** | | | | ** | | -- | | OK | | | + 5.9 | | ** | | | | ** | | -- | | OK | | | OK : Support. -- : Not support. @@ -199,12 +205,19 @@ * REFERENCES - https://sourceforge.net/projects/makedumpfile/ - http://lists.infradead.org/pipermail/kexec/ - https://lists.linux-foundation.org/pipermail/fastboot/ + - The makedumpfile project page + https://github.com/makedumpfile/makedumpfile + + - The kexec mailing list archives + http://lists.infradead.org/pipermail/kexec/ + - The fastboot mailing list archives + https://lists.linux-foundation.org/pipermail/fastboot/ * BUG REPORT If finding some bugs, please send the information to the following: Kazuhito Hagio <[email protected]> kexec-ml <[email protected]> + Please refer to the project page's wiki: + https://github.com/makedumpfile/makedumpfile/wiki + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/arch/arm.c new/makedumpfile-1.6.8/arch/arm.c --- old/makedumpfile-1.6.7/arch/arm.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/arch/arm.c 2020-11-16 01:29:37.000000000 +0100 @@ -81,7 +81,13 @@ get_machdep_info_arm(void) { info->page_offset = SYMBOL(_stext) & 0xffff0000UL; - info->max_physmem_bits = _MAX_PHYSMEM_BITS; + + /* Check if we can get MAX_PHYSMEM_BITS from vmcoreinfo */ + if (NUMBER(MAX_PHYSMEM_BITS) != NOT_FOUND_NUMBER) + info->max_physmem_bits = NUMBER(MAX_PHYSMEM_BITS); + else + info->max_physmem_bits = _MAX_PHYSMEM_BITS; + info->kernel_start = SYMBOL(_stext); info->section_size_bits = _SECTION_SIZE_BITS; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/arch/arm64.c new/makedumpfile-1.6.8/arch/arm64.c --- old/makedumpfile-1.6.7/arch/arm64.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/arch/arm64.c 2020-11-16 01:29:37.000000000 +0100 @@ -39,72 +39,184 @@ unsigned long pte; } pte_t; +#define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) +#define __pud(x) ((pud_t) { (x) } ) +#define __pgd(x) ((pgd_t) { (x) } ) + +static int lpa_52_bit_support_available; static int pgtable_level; static int va_bits; static unsigned long kimage_voffset; -#define SZ_4K (4 * 1024) -#define SZ_16K (16 * 1024) -#define SZ_64K (64 * 1024) -#define SZ_128M (128 * 1024 * 1024) - -#define PAGE_OFFSET_36 ((0xffffffffffffffffUL) << 36) -#define PAGE_OFFSET_39 ((0xffffffffffffffffUL) << 39) -#define PAGE_OFFSET_42 ((0xffffffffffffffffUL) << 42) -#define PAGE_OFFSET_47 ((0xffffffffffffffffUL) << 47) -#define PAGE_OFFSET_48 ((0xffffffffffffffffUL) << 48) +#define SZ_4K 4096 +#define SZ_16K 16384 +#define SZ_64K 65536 + +#define PAGE_OFFSET_36 ((0xffffffffffffffffUL) << 36) +#define PAGE_OFFSET_39 ((0xffffffffffffffffUL) << 39) +#define PAGE_OFFSET_42 ((0xffffffffffffffffUL) << 42) +#define PAGE_OFFSET_47 ((0xffffffffffffffffUL) << 47) +#define PAGE_OFFSET_48 ((0xffffffffffffffffUL) << 48) +#define PAGE_OFFSET_52 ((0xffffffffffffffffUL) << 52) #define pgd_val(x) ((x).pgd) #define pud_val(x) (pgd_val((x).pgd)) #define pmd_val(x) (pud_val((x).pud)) #define pte_val(x) ((x).pte) -#define PAGE_MASK (~(PAGESIZE() - 1)) -#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) -#define PMD_SIZE (1UL << PMD_SHIFT) -#define PMD_MASK (~(PMD_SIZE - 1)) +/* See 'include/uapi/linux/const.h' for definitions below */ +#define __AC(X,Y) (X##Y) +#define _AC(X,Y) __AC(X,Y) +#define _AT(T,X) ((T)(X)) + +/* See 'include/asm/pgtable-types.h' for definitions below */ +typedef unsigned long pteval_t; +typedef unsigned long pmdval_t; +typedef unsigned long pudval_t; +typedef unsigned long pgdval_t; + +#define PAGE_SHIFT PAGESHIFT() + +/* See 'arch/arm64/include/asm/pgtable-hwdef.h' for definitions below */ + +#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n) ((PAGE_SHIFT - 3) * (4 - (n)) + 3) + +#define PTRS_PER_PTE (1 << (PAGE_SHIFT - 3)) + +/* + * PMD_SHIFT determines the size a level 2 page table entry can map. + */ +#define PMD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(2) +#define PMD_SIZE (_AC(1, UL) << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) #define PTRS_PER_PMD PTRS_PER_PTE -#define PAGE_PRESENT (1 << 0) +/* + * PUD_SHIFT determines the size a level 1 page table entry can map. + */ +#define PUD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(1) +#define PUD_SIZE (_AC(1, UL) << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE-1)) +#define PTRS_PER_PUD PTRS_PER_PTE + +/* + * PGDIR_SHIFT determines the size a top-level page table entry can map + * (depending on the configuration, this level can be 0, 1 or 2). + */ +#define PGDIR_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - (pgtable_level)) +#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) +#define PTRS_PER_PGD (1 << ((va_bits) - PGDIR_SHIFT)) + +/* + * Section address mask and size definitions. + */ #define SECTIONS_SIZE_BITS 30 -/* Highest possible physical address supported */ -#define PHYS_MASK_SHIFT 48 -#define PHYS_MASK ((1UL << PHYS_MASK_SHIFT) - 1) + /* - * Remove the highest order bits that are not a part of the - * physical address in a section + * Hardware page table definitions. + * + * Level 1 descriptor (PUD). */ -#define PMD_SECTION_MASK ((1UL << 40) - 1) +#define PUD_TYPE_TABLE (_AT(pudval_t, 3) << 0) +#define PUD_TABLE_BIT (_AT(pudval_t, 1) << 1) +#define PUD_TYPE_MASK (_AT(pudval_t, 3) << 0) +#define PUD_TYPE_SECT (_AT(pudval_t, 1) << 0) -#define PMD_TYPE_MASK 3 -#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)) - -#define pte_index(vaddr) (((vaddr) >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) -#define pmd_page_paddr(pmd) (pmd_val(pmd) & PHYS_MASK & (int32_t)PAGE_MASK) -#define pte_offset(dir, vaddr) ((pte_t*)pmd_page_paddr((*dir)) + pte_index(vaddr)) +/* + * Level 2 descriptor (PMD). + */ +#define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0) +#define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) +#define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) +#define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) +#define PMD_TABLE_BIT (_AT(pmdval_t, 1) << 1) -#define pmd_index(vaddr) (((vaddr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) -#define pud_page_paddr(pud) (pud_val(pud) & PHYS_MASK & (int32_t)PAGE_MASK) -#define pmd_offset_pgtbl_lvl_2(pud, vaddr) ((pmd_t *)pud) -#define pmd_offset_pgtbl_lvl_3(pud, vaddr) ((pmd_t *)pud_page_paddr((*pud)) + pmd_index(vaddr)) +/* + * Level 3 descriptor (PTE). + */ +#define PTE_ADDR_LOW (((_AT(pteval_t, 1) << (48 - PAGE_SHIFT)) - 1) << PAGE_SHIFT) +#define PTE_ADDR_HIGH (_AT(pteval_t, 0xf) << 12) + +static inline unsigned long +get_pte_addr_mask_arm64(void) +{ + if (lpa_52_bit_support_available) + return (PTE_ADDR_LOW | PTE_ADDR_HIGH); + else + return PTE_ADDR_LOW; +} + +#define PTE_ADDR_MASK get_pte_addr_mask_arm64() + +#define PAGE_MASK (~(PAGESIZE() - 1)) +#define PAGE_PRESENT (1 << 0) + +/* Helper API to convert between a physical address and its placement + * in a page table entry, taking care of 52-bit addresses. + */ +static inline unsigned long +__pte_to_phys(pte_t pte) +{ + if (lpa_52_bit_support_available) + return ((pte_val(pte) & PTE_ADDR_LOW) | ((pte_val(pte) & PTE_ADDR_HIGH) << 36)); + else + return (pte_val(pte) & PTE_ADDR_MASK); +} + +/* Find an entry in a page-table-directory */ +#define pgd_index(vaddr) (((vaddr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) + +static inline pte_t +pgd_pte(pgd_t pgd) +{ + return __pte(pgd_val(pgd)); +} + +#define __pgd_to_phys(pgd) __pte_to_phys(pgd_pte(pgd)) +#define pgd_offset(pgd, vaddr) ((pgd_t *)(pgd) + pgd_index(vaddr)) + +static inline pte_t pud_pte(pud_t pud) +{ + return __pte(pud_val(pud)); +} + +static inline unsigned long +pgd_page_paddr(pgd_t pgd) +{ + return __pgd_to_phys(pgd); +} +/* Find an entry in the first-level page table. */ #define pud_index(vaddr) (((vaddr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) -#define pgd_page_paddr(pgd) (pgd_val(pgd) & PHYS_MASK & (int32_t)PAGE_MASK) +#define __pud_to_phys(pud) __pte_to_phys(pud_pte(pud)) + +static inline unsigned long +pud_page_paddr(pud_t pud) +{ + return __pud_to_phys(pud); +} + +/* Find an entry in the second-level page table. */ +#define pmd_index(vaddr) (((vaddr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) + +static inline pte_t pmd_pte(pmd_t pmd) +{ + return __pte(pmd_val(pmd)); +} + +#define __pmd_to_phys(pmd) __pte_to_phys(pmd_pte(pmd)) + +static inline unsigned long +pmd_page_paddr(pmd_t pmd) +{ + return __pmd_to_phys(pmd); +} + +/* Find an entry in the third-level page table. */ +#define pte_index(vaddr) (((vaddr) >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) +#define pte_offset(dir, vaddr) (pmd_page_paddr((*dir)) + pte_index(vaddr) * sizeof(pte_t)) static unsigned long long __pa(unsigned long vaddr) @@ -116,32 +228,22 @@ return (vaddr - kimage_voffset); } -static int -get_pud_shift_arm64(void) +static pud_t * +pud_offset(pgd_t *pgda, pgd_t *pgdv, unsigned long vaddr) { - if (pgtable_level == 4) - return ((PAGESHIFT() - 3) * 3 + 3); + if (pgtable_level > 3) + return (pud_t *)(pgd_page_paddr(*pgdv) + pud_index(vaddr) * sizeof(pud_t)); else - return PGDIR_SHIFT; + return (pud_t *)(pgda); } static pmd_t * pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr) { - if (pgtable_level == 2) { - return pmd_offset_pgtbl_lvl_2(puda, vaddr); - } else { - return pmd_offset_pgtbl_lvl_3(pudv, vaddr); - } -} - -static pud_t * -pud_offset(pgd_t *pgda, pgd_t *pgdv, unsigned long vaddr) -{ - if (pgtable_level == 4) - return ((pud_t *)pgd_page_paddr((*pgdv)) + pud_index(vaddr)); + if (pgtable_level > 2) + return (pmd_t *)(pud_page_paddr(*pudv) + pmd_index(vaddr) * sizeof(pmd_t)); else - return (pud_t *)(pgda); + return (pmd_t *)(puda); } static int calculate_plat_config(void) @@ -246,6 +348,14 @@ int get_machdep_info_arm64(void) { + /* Determine if the PA address range is 52-bits: ARMv8.2-LPA */ + if (NUMBER(MAX_PHYSMEM_BITS) != NOT_FOUND_NUMBER) { + info->max_physmem_bits = NUMBER(MAX_PHYSMEM_BITS); + if (info->max_physmem_bits == 52) + lpa_52_bit_support_available = 1; + } else + info->max_physmem_bits = 48; + /* Check if va_bits is still not initialized. If still 0, call * get_versiondep_info() to initialize the same. */ @@ -258,12 +368,11 @@ } kimage_voffset = NUMBER(kimage_voffset); - info->max_physmem_bits = PHYS_MASK_SHIFT; info->section_size_bits = SECTIONS_SIZE_BITS; DEBUG_MSG("kimage_voffset : %lx\n", kimage_voffset); - DEBUG_MSG("max_physmem_bits : %lx\n", info->max_physmem_bits); - DEBUG_MSG("section_size_bits: %lx\n", info->section_size_bits); + DEBUG_MSG("max_physmem_bits : %ld\n", info->max_physmem_bits); + DEBUG_MSG("section_size_bits: %ld\n", info->section_size_bits); return TRUE; } @@ -321,6 +430,19 @@ return TRUE; } +/* 1GB section for Page Table level = 4 and Page Size = 4KB */ +static int +is_pud_sect(pud_t pud) +{ + return ((pud_val(pud) & PUD_TYPE_MASK) == PUD_TYPE_SECT); +} + +static int +is_pmd_sect(pmd_t pmd) +{ + return ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT); +} + /* * vaddr_to_paddr_arm64() - translate arbitrary virtual address to physical * @vaddr: virtual address to translate @@ -358,10 +480,9 @@ 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)); + if (is_pud_sect(pudv)) { + paddr = (pud_page_paddr(pudv) & PUD_MASK) + + (vaddr & (PUD_SIZE - 1)); return paddr; } @@ -371,29 +492,24 @@ return NOT_PADDR; } - switch (pmd_val(pmdv) & PMD_TYPE_MASK) { - case PMD_TYPE_TABLE: - ptea = pte_offset(&pmdv, vaddr); - /* 64k page */ - if (!readmem(PADDR, (unsigned long long)ptea, &ptev, sizeof(ptev))) { - ERRMSG("Can't read pte\n"); - return NOT_PADDR; - } + if (is_pmd_sect(pmdv)) { + paddr = (pmd_page_paddr(pmdv) & PMD_MASK) + + (vaddr & (PMD_SIZE - 1)); + return paddr; + } - if (!(pte_val(ptev) & PAGE_PRESENT)) { - ERRMSG("Can't get a valid pte.\n"); - return NOT_PADDR; - } else { + ptea = (pte_t *)pte_offset(&pmdv, vaddr); + if (!readmem(PADDR, (unsigned long long)ptea, &ptev, sizeof(ptev))) { + ERRMSG("Can't read pte\n"); + return NOT_PADDR; + } - paddr = (PAGEBASE(pte_val(ptev)) & PHYS_MASK) - + (vaddr & (PAGESIZE() - 1)); - } - break; - case PMD_TYPE_SECT: - /* 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; + if (!(pte_val(ptev) & PAGE_PRESENT)) { + ERRMSG("Can't get a valid pte.\n"); + return NOT_PADDR; + } else { + paddr = __pte_to_phys(ptev) + + (vaddr & (PAGESIZE() - 1)); } return paddr; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/arch/ia64.c new/makedumpfile-1.6.8/arch/ia64.c --- old/makedumpfile-1.6.7/arch/ia64.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/arch/ia64.c 2020-11-16 01:29:37.000000000 +0100 @@ -85,7 +85,12 @@ } info->section_size_bits = _SECTION_SIZE_BITS; - info->max_physmem_bits = _MAX_PHYSMEM_BITS; + + /* Check if we can get MAX_PHYSMEM_BITS from vmcoreinfo */ + if (NUMBER(MAX_PHYSMEM_BITS) != NOT_FOUND_NUMBER) + info->max_physmem_bits = NUMBER(MAX_PHYSMEM_BITS); + else + info->max_physmem_bits = _MAX_PHYSMEM_BITS; return TRUE; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/arch/ppc.c new/makedumpfile-1.6.8/arch/ppc.c --- old/makedumpfile-1.6.7/arch/ppc.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/arch/ppc.c 2020-11-16 01:29:37.000000000 +0100 @@ -31,7 +31,13 @@ unsigned long vmlist, vmap_area_list, vmalloc_start; info->section_size_bits = _SECTION_SIZE_BITS; - info->max_physmem_bits = _MAX_PHYSMEM_BITS; + + /* Check if we can get MAX_PHYSMEM_BITS from vmcoreinfo */ + if (NUMBER(MAX_PHYSMEM_BITS) != NOT_FOUND_NUMBER) + info->max_physmem_bits = NUMBER(MAX_PHYSMEM_BITS); + else + info->max_physmem_bits = _MAX_PHYSMEM_BITS; + info->page_offset = __PAGE_OFFSET; if (SYMBOL(_stext) != NOT_FOUND_SYMBOL) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/arch/ppc64.c new/makedumpfile-1.6.8/arch/ppc64.c --- old/makedumpfile-1.6.7/arch/ppc64.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/arch/ppc64.c 2020-11-16 01:29:37.000000000 +0100 @@ -466,6 +466,13 @@ set_ppc64_max_physmem_bits(void) { long array_len = ARRAY_LENGTH(mem_section); + + /* Check if we can get MAX_PHYSMEM_BITS from vmcoreinfo */ + if (NUMBER(MAX_PHYSMEM_BITS) != NOT_FOUND_NUMBER) { + info->max_physmem_bits = NUMBER(MAX_PHYSMEM_BITS); + return TRUE; + } + /* * The older ppc64 kernels uses _MAX_PHYSMEM_BITS as 42 and the * newer kernels 3.7 onwards uses 46 bits. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/arch/s390x.c new/makedumpfile-1.6.8/arch/s390x.c --- old/makedumpfile-1.6.7/arch/s390x.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/arch/s390x.c 2020-11-16 01:29:37.000000000 +0100 @@ -63,6 +63,13 @@ set_s390x_max_physmem_bits(void) { long array_len = ARRAY_LENGTH(mem_section); + + /* Check if we can get MAX_PHYSMEM_BITS from vmcoreinfo */ + if (NUMBER(MAX_PHYSMEM_BITS) != NOT_FOUND_NUMBER) { + info->max_physmem_bits = NUMBER(MAX_PHYSMEM_BITS); + return TRUE; + } + /* * The older s390x kernels uses _MAX_PHYSMEM_BITS as 42 and the * newer kernels uses 46 bits. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/arch/sparc64.c new/makedumpfile-1.6.8/arch/sparc64.c --- old/makedumpfile-1.6.7/arch/sparc64.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/arch/sparc64.c 2020-11-16 01:29:37.000000000 +0100 @@ -25,10 +25,15 @@ { info->section_size_bits = _SECTION_SIZE_BITS; - if (info->kernel_version >= KERNEL_VERSION(3, 8, 13)) + /* Check if we can get MAX_PHYSMEM_BITS from vmcoreinfo */ + if (NUMBER(MAX_PHYSMEM_BITS) != NOT_FOUND_NUMBER) + info->max_physmem_bits = NUMBER(MAX_PHYSMEM_BITS); + else if (info->kernel_version >= KERNEL_VERSION(3, 8, 13)) info->max_physmem_bits = _MAX_PHYSMEM_BITS_L4; - else { + else info->max_physmem_bits = _MAX_PHYSMEM_BITS_L3; + + if (info->kernel_version < KERNEL_VERSION(3, 8, 13)) { info->flag_vmemmap = TRUE; info->vmemmap_start = VMEMMAP_BASE_SPARC64; info->vmemmap_end = VMEMMAP_BASE_SPARC64 + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/arch/x86.c new/makedumpfile-1.6.8/arch/x86.c --- old/makedumpfile-1.6.7/arch/x86.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/arch/x86.c 2020-11-16 01:29:37.000000000 +0100 @@ -87,6 +87,11 @@ DEBUG_MSG("PAE : OFF\n"); info->max_physmem_bits = _MAX_PHYSMEM_BITS; } + + /* Check if we can get MAX_PHYSMEM_BITS from vmcoreinfo */ + if (NUMBER(MAX_PHYSMEM_BITS) != NOT_FOUND_NUMBER) + info->max_physmem_bits = NUMBER(MAX_PHYSMEM_BITS); + info->page_offset = __PAGE_OFFSET; if (SYMBOL(_stext) == NOT_FOUND_SYMBOL) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/arch/x86_64.c new/makedumpfile-1.6.8/arch/x86_64.c --- old/makedumpfile-1.6.7/arch/x86_64.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/arch/x86_64.c 2020-11-16 01:29:37.000000000 +0100 @@ -268,10 +268,10 @@ int get_versiondep_info_x86_64(void) { - /* - * On linux-2.6.26, MAX_PHYSMEM_BITS is changed to 44 from 40. - */ - if (info->kernel_version < KERNEL_VERSION(2, 6, 26)) + /* Check if we can get MAX_PHYSMEM_BITS from vmcoreinfo */ + if (NUMBER(MAX_PHYSMEM_BITS) != NOT_FOUND_NUMBER) + info->max_physmem_bits = NUMBER(MAX_PHYSMEM_BITS); + else if (info->kernel_version < KERNEL_VERSION(2, 6, 26)) info->max_physmem_bits = _MAX_PHYSMEM_BITS_ORIG; else if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) info->max_physmem_bits = _MAX_PHYSMEM_BITS_2_6_26; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/diskdump_mod.h new/makedumpfile-1.6.8/diskdump_mod.h --- old/makedumpfile-1.6.7/diskdump_mod.h 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/diskdump_mod.h 2020-11-16 01:29:37.000000000 +0100 @@ -22,7 +22,7 @@ #define DISK_DUMP_SIGNATURE "DISKDUMP" #define KDUMP_SIGNATURE "KDUMP " #define SIG_LEN (sizeof(DUMP_PARTITION_SIGNATURE) - 1) -#define DISKDUMP_HEADER_BLOCKS (1) +#define DISKDUMP_HEADER_BLOCKS (1UL) /* * These are all remnants of the old "diskdump" facility, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/elf_info.c new/makedumpfile-1.6.8/elf_info.c --- old/makedumpfile-1.6.7/elf_info.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/elf_info.c 2020-11-16 01:29:37.000000000 +0100 @@ -63,7 +63,6 @@ */ static unsigned int num_pt_loads; static struct pt_load_segment *pt_loads; -static off_t offset_pt_load_memory; /* * PT_NOTE information about /proc/vmcore: @@ -502,66 +501,6 @@ return offset; } -unsigned long long -page_head_to_phys_start(unsigned long long head_paddr) -{ - int i; - struct pt_load_segment *pls; - - for (i = 0; i < num_pt_loads; i++) { - pls = &pt_loads[i]; - if ((pls->phys_start <= head_paddr + info->page_size) - && (head_paddr < pls->phys_end)) { - return (pls->phys_start > head_paddr) ? - pls->phys_start : head_paddr; - } - } - - return 0; -} - -unsigned long long -page_head_to_phys_end(unsigned long long head_paddr) -{ - int i; - struct pt_load_segment *pls; - - for (i = 0; i < num_pt_loads; i++) { - pls = &pt_loads[i]; - if ((pls->phys_start <= head_paddr + info->page_size) - && (head_paddr < pls->phys_end)) { - return (pls->phys_end < head_paddr + info->page_size) ? - pls->phys_end : head_paddr + info->page_size; - } - } - - return 0; -} - -/* - * Calculate a start File Offset of PT_LOAD from a File Offset - * of a page. If this function returns 0x0, the input page is - * not in the memory image. - */ -off_t -offset_to_pt_load_start(off_t offset) -{ - int i; - off_t pt_load_start; - struct pt_load_segment *pls; - - for (i = pt_load_start = 0; i < num_pt_loads; i++) { - pls = &pt_loads[i]; - if ((offset >= pls->file_offset) - && (offset < pls->file_offset + - (pls->phys_end - pls->phys_start))) { - pt_load_start = pls->file_offset; - break; - } - } - return pt_load_start; -} - /* * Calculate a end File Offset of PT_LOAD from a File Offset * of a page. If this function returns 0x0, the input page is @@ -903,15 +842,6 @@ return FALSE; } - if (j == 0) { - offset_pt_load_memory = p->file_offset; - if (offset_pt_load_memory == 0) { - ERRMSG("Can't get the offset of page data.\n"); - free(pls); - return FALSE; - } - } - pls[j] = *p; j++; } @@ -989,13 +919,6 @@ if (phdr.p_type != PT_LOAD) continue; - if (j == 0) { - offset_pt_load_memory = phdr.p_offset; - if (offset_pt_load_memory == 0) { - ERRMSG("Can't get the offset of page data.\n"); - return FALSE; - } - } if (j >= num_pt_loads) return FALSE; if(!dump_Elf_load(&phdr, j)) @@ -1120,12 +1043,6 @@ return TRUE; } -off_t -get_offset_pt_load_memory(void) -{ - return offset_pt_load_memory; -} - int get_pt_load(int idx, unsigned long long *phys_start, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/elf_info.h new/makedumpfile-1.6.8/elf_info.h --- old/makedumpfile-1.6.7/elf_info.h 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/elf_info.h 2020-11-16 01:29:37.000000000 +0100 @@ -32,9 +32,6 @@ off_t paddr_to_offset(unsigned long long paddr); off_t paddr_to_offset2(unsigned long long paddr, off_t hint); -unsigned long long page_head_to_phys_start(unsigned long long head_paddr); -unsigned long long page_head_to_phys_end(unsigned long long head_paddr); -off_t offset_to_pt_load_start(off_t offset); off_t offset_to_pt_load_end(off_t offset); unsigned long long vaddr_to_paddr_general(unsigned long long vaddr); off_t vaddr_to_offset_slow(int fd, char *filename, unsigned long long vaddr); @@ -57,7 +54,6 @@ int get_elf64_phnum(int fd, char *filename, Elf64_Ehdr *ehdr, int *phnum); int get_phnum_memory(void); int get_phdr_memory(int index, Elf64_Phdr *phdr); -off_t get_offset_pt_load_memory(void); int get_pt_load(int idx, unsigned long long *phys_start, unsigned long long *phys_end, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/makedumpfile.8 new/makedumpfile-1.6.8/makedumpfile.8 --- old/makedumpfile-1.6.7/makedumpfile.8 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/makedumpfile.8 2020-11-16 01:29:37.000000000 +0100 @@ -1,4 +1,4 @@ -.TH MAKEDUMPFILE 8 "16 Jan 2020" "makedumpfile v1.6.7" "Linux System Administrator's Manual" +.TH MAKEDUMPFILE 8 "16 Nov 2020" "makedumpfile v1.6.8" "Linux System Administrator's Manual" .SH NAME makedumpfile \- make a small dumpfile of kdump .SH SYNOPSIS @@ -632,6 +632,11 @@ \fB\-v\fR Show the version of makedumpfile. +.TP +\fB\-\-check-params\fR +Only check whether the command-line parameters are valid or not, and exit. +Preferable to be given as the first parameter. + .SH ENVIRONMENT VARIABLES .TP 8 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/makedumpfile.c new/makedumpfile-1.6.8/makedumpfile.c --- old/makedumpfile-1.6.7/makedumpfile.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/makedumpfile.c 2020-11-16 01:29:37.000000000 +0100 @@ -3406,8 +3406,6 @@ map = ULONG(mem_section + OFFSET(mem_section.section_mem_map)); mask = SECTION_MAP_MASK; *map_mask = map & ~mask; - if (map == 0x0) - *map_mask |= SECTION_MARKED_PRESENT; map &= mask; free(mem_section); @@ -3453,10 +3451,8 @@ mem_map = NOT_MEMMAP_ADDR; } else { mem_map = section_mem_map_addr(section, &map_mask); + /* for either no mem_map or hot-removed */ if (!(map_mask & SECTION_MARKED_PRESENT)) { - return FALSE; - } - if (mem_map == 0) { mem_map = NOT_MEMMAP_ADDR; } else { mem_map = sparse_decode_mem_map(mem_map, @@ -3476,7 +3472,6 @@ get_mem_section(unsigned int mem_section_size, unsigned long *mem_maps, unsigned int num_section) { - unsigned long mem_section_ptr; int ret = FALSE; unsigned long *mem_sec = NULL; @@ -3488,34 +3483,18 @@ ret = validate_mem_section(mem_sec, SYMBOL(mem_section), mem_section_size, mem_maps, num_section); - if (is_sparsemem_extreme()) { - int symbol_valid = ret; - int pointer_valid; - int mem_maps_size = sizeof(*mem_maps) * num_section; - unsigned long *mem_maps_ex = NULL; + if (!ret && is_sparsemem_extreme()) { + unsigned long mem_section_ptr; + if (!readmem(VADDR, SYMBOL(mem_section), &mem_section_ptr, sizeof(mem_section_ptr))) goto out; - if ((mem_maps_ex = malloc(mem_maps_size)) == NULL) { - ERRMSG("Can't allocate memory for the mem_maps. %s\n", - strerror(errno)); - goto out; - } + ret = validate_mem_section(mem_sec, mem_section_ptr, + mem_section_size, mem_maps, num_section); - pointer_valid = validate_mem_section(mem_sec, - mem_section_ptr, - mem_section_size, - mem_maps_ex, - num_section); - if (pointer_valid) - memcpy(mem_maps, mem_maps_ex, mem_maps_size); - if (mem_maps_ex) - free(mem_maps_ex); - ret = symbol_valid ^ pointer_valid; - if (!ret) { + if (!ret) ERRMSG("Could not validate mem_section.\n"); - } } out: if (mem_sec != NULL) @@ -8406,7 +8385,6 @@ unsigned char buf[info->page_size], *buf_out = NULL; unsigned long len_buf_out; struct timespec ts_start; - const off_t failed = (off_t)-1; int ret = FALSE; z_stream z_stream, *stream = NULL; #ifdef USELZO @@ -8443,16 +8421,6 @@ per = info->num_dumpable / 10000; per = per ? per : 1; - /* - * Set a fileoffset of Physical Address 0x0. - */ - if (lseek(info->fd_memory, get_offset_pt_load_memory(), SEEK_SET) - == failed) { - ERRMSG("Can't seek the dump memory(%s). %s\n", - info->name_memory, strerror(errno)); - goto out; - } - start_pfn = cycle->start_pfn; end_pfn = cycle->end_pfn; @@ -10954,7 +10922,7 @@ return FALSE; if ((info->splitting_info - = malloc(sizeof(splitting_info_t) * info->num_dumpfile)) + = malloc(sizeof(struct splitting_info) * info->num_dumpfile)) == NULL) { MSG("Can't allocate memory for splitting_info.\n"); return FALSE; @@ -10976,12 +10944,6 @@ if (info->flag_generate_vmcoreinfo || info->flag_rearrange) return FALSE; - if ((message_level < MIN_MSG_LEVEL) - || (MAX_MSG_LEVEL < message_level)) { - message_level = DEFAULT_MSG_LEVEL; - MSG("Message_level is invalid.\n"); - return FALSE; - } if ((info->flag_compress && info->flag_elf_dumpfile) || (info->flag_read_vmcoreinfo && info->name_vmlinux) || (info->flag_read_vmcoreinfo && info->name_xen_syms)) @@ -11011,6 +10973,11 @@ if (info->flag_partial_dmesg && !info->flag_dmesg) return FALSE; + if (info->flag_excludevm && !info->working_dir) { + MSG("-%c requires --work-dir\n", OPT_EXCLUDE_UNUSED_VM); + return FALSE; + } + if ((argc == optind + 2) && !info->flag_flatten && !info->flag_split && !info->flag_sadump_diskset) { @@ -11042,7 +11009,7 @@ return FALSE; } if ((info->splitting_info - = malloc(sizeof(splitting_info_t) * info->num_dumpfile)) + = malloc(sizeof(struct splitting_info) * info->num_dumpfile)) == NULL) { MSG("Can't allocate memory for splitting_info.\n"); return FALSE; @@ -11077,13 +11044,13 @@ if (info->num_threads) { if ((info->parallel_info = - malloc(sizeof(parallel_info_t) * info->num_threads)) + malloc(sizeof(struct parallel_info) * info->num_threads)) == NULL) { MSG("Can't allocate memory for parallel_info.\n"); return FALSE; } - memset(info->parallel_info, 0, sizeof(parallel_info_t) + memset(info->parallel_info, 0, sizeof(struct parallel_info) * info->num_threads); } @@ -11406,6 +11373,23 @@ return TRUE; } +static int set_message_level(char *str_ml) +{ + int ml; + + ml = atoi(str_ml); + if ((ml < MIN_MSG_LEVEL) || (MAX_MSG_LEVEL < ml)) { + message_level = DEFAULT_MSG_LEVEL; + MSG("Message_level(%d) is invalid.\n", ml); + return FALSE; + } + + if (info->flag_check_params) + return TRUE; + + message_level = ml; + return TRUE; +} static struct option longopts[] = { {"split", no_argument, NULL, OPT_SPLIT}, @@ -11427,6 +11411,7 @@ {"splitblock-size", required_argument, NULL, OPT_SPLITBLOCK_SIZE}, {"work-dir", required_argument, NULL, OPT_WORKING_DIR}, {"num-threads", required_argument, NULL, OPT_NUM_THREADS}, + {"check-params", no_argument, NULL, OPT_CHECK_PARAMS}, {0, 0, 0, 0} }; @@ -11525,7 +11510,8 @@ info->flag_compress = DUMP_DH_COMPRESSED_LZO; break; case OPT_MESSAGE_LEVEL: - message_level = atoi(optarg); + if (!set_message_level(optarg)) + goto out; break; case OPT_DUMP_DMESG: info->flag_dmesg = 1; @@ -11588,6 +11574,10 @@ case OPT_NUM_THREADS: info->num_threads = MAX(atoi(optarg), 0); break; + case OPT_CHECK_PARAMS: + info->flag_check_params = TRUE; + message_level = DEFAULT_MSG_LEVEL; + break; case '?': MSG("Commandline parameter is invalid.\n"); MSG("Try `makedumpfile --help' for more information.\n"); @@ -11597,11 +11587,9 @@ if (flag_debug) message_level |= ML_PRINT_DEBUG_MSG; - if (info->flag_excludevm && !info->working_dir) { - ERRMSG("Error: -%c requires --work-dir\n", OPT_EXCLUDE_UNUSED_VM); - ERRMSG("Try `makedumpfile --help' for more information\n"); - return COMPLETED; - } + if (info->flag_check_params) + /* suppress debugging messages */ + message_level = DEFAULT_MSG_LEVEL; if (info->flag_show_usage) { print_usage(); @@ -11632,6 +11620,9 @@ MSG("Try `makedumpfile --help' for more information.\n"); goto out; } + if (info->flag_check_params) + goto check_ok; + if (!open_files_for_generating_vmcoreinfo()) goto out; @@ -11655,6 +11646,9 @@ MSG("Try `makedumpfile --help' for more information.\n"); goto out; } + if (info->flag_check_params) + goto check_ok; + if (!check_dump_file(info->name_dumpfile)) goto out; @@ -11675,6 +11669,9 @@ MSG("Try `makedumpfile --help' for more information.\n"); goto out; } + if (info->flag_check_params) + goto check_ok; + if (!check_dump_file(info->name_dumpfile)) goto out; @@ -11688,6 +11685,9 @@ MSG("Try `makedumpfile --help' for more information.\n"); goto out; } + if (info->flag_check_params) + goto check_ok; + if (!check_dump_file(info->name_dumpfile)) goto out; if (!dump_dmesg()) @@ -11701,6 +11701,9 @@ MSG("Try `makedumpfile --help' for more information.\n"); goto out; } + if (info->flag_check_params) + goto check_ok; + if (!populate_kernel_version()) goto out; @@ -11719,6 +11722,9 @@ MSG("Try `makedumpfile --help' for more information.\n"); goto out; } + if (info->flag_check_params) + goto check_ok; + if (info->flag_split) { for (i = 0; i < info->num_dumpfile; i++) { SPLITTING_FD_BITMAP(i) = -1; @@ -11746,13 +11752,16 @@ MSG("The dumpfile is saved to %s.\n", info->name_dumpfile); } } +check_ok: retcd = COMPLETED; out: - MSG("\n"); - if (retcd != COMPLETED) - MSG("makedumpfile Failed.\n"); - else if (!info->flag_mem_usage) - MSG("makedumpfile Completed.\n"); + if (!info->flag_check_params) { + MSG("\n"); + if (retcd != COMPLETED) + MSG("makedumpfile Failed.\n"); + else if (!info->flag_mem_usage) + MSG("makedumpfile Completed.\n"); + } free_for_parallel(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/makedumpfile.conf.5 new/makedumpfile-1.6.8/makedumpfile.conf.5 --- old/makedumpfile-1.6.7/makedumpfile.conf.5 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/makedumpfile.conf.5 2020-11-16 01:29:37.000000000 +0100 @@ -1,4 +1,4 @@ -.TH MAKEDUMPFILE.CONF 5 "16 Jan 2020" "makedumpfile v1.6.7" "Linux System Administrator's Manual" +.TH MAKEDUMPFILE.CONF 5 "16 Nov 2020" "makedumpfile v1.6.8" "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.7/makedumpfile.h new/makedumpfile-1.6.8/makedumpfile.h --- old/makedumpfile-1.6.7/makedumpfile.h 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/makedumpfile.h 2020-11-16 01:29:37.000000000 +0100 @@ -495,7 +495,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(5, 4, 8) /* linux-5.4.8 */ +#define LATEST_VERSION KERNEL_VERSION(5, 9, 4) /* linux-5.9.4 */ /* * vmcoreinfo in /proc/vmcore @@ -1262,7 +1262,7 @@ mdf_pfn_t end_pfn; off_t offset_eraseinfo; unsigned long size_eraseinfo; -} splitting_info_t; +}; struct parallel_info { int fd_memory; @@ -1275,7 +1275,7 @@ #ifdef USELZO lzo_bytep wrkmem; #endif -} parallel_info_t; +}; struct ppc64_vmemmap { unsigned long phys; @@ -1301,6 +1301,7 @@ int flag_read_vmcoreinfo; /* flag of reading vmcoreinfo file */ int flag_show_usage; /* flag of showing usage */ int flag_show_version; /* flag of showing version */ + int flag_check_params; /* only check parameters */ int flag_flatten; /* flag of outputting flattened format to a standard out */ int flag_rearrange; /* flag of creating dumpfile from @@ -2006,8 +2007,8 @@ }; #define CRASH_RESERVED_MEM_NR 8 -struct memory_range crash_reserved_mem[CRASH_RESERVED_MEM_NR]; -int crash_reserved_mem_nr; +extern struct memory_range crash_reserved_mem[CRASH_RESERVED_MEM_NR]; +extern int crash_reserved_mem_nr; unsigned long read_vmcoreinfo_symbol(char *str_symbol); int readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size); @@ -2362,6 +2363,7 @@ #define OPT_WORKING_DIR OPT_START+15 #define OPT_NUM_THREADS OPT_START+16 #define OPT_PARTIAL_DMESG OPT_START+17 +#define OPT_CHECK_PARAMS OPT_START+18 /* * Function Prototype. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/makedumpfile.spec new/makedumpfile-1.6.8/makedumpfile.spec --- old/makedumpfile-1.6.7/makedumpfile.spec 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/makedumpfile.spec 2020-11-16 01:29:37.000000000 +0100 @@ -1,13 +1,13 @@ Name: makedumpfile Summary: makedumpfile package -Version: 1.6.7 +Version: 1.6.8 Release: 1 Group: Applications/Text License: GPL Source: %{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-root Distribution: Linux 2.6 or greater -Packager: Kazuhito Hagio <[email protected]> +Packager: Kazuhito Hagio <[email protected]> ExclusiveOS: Linux ExclusiveArch: i386 ia64 ppc ppc64 ppc64pseries ppc64iseries x86_64 Buildroot: %{_tmppath}/%{name}-root diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/print_info.c new/makedumpfile-1.6.8/print_info.c --- old/makedumpfile-1.6.7/print_info.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/print_info.c 2020-11-16 01:29:37.000000000 +0100 @@ -321,6 +321,10 @@ MSG(" [-v]:\n"); MSG(" Show the version of makedumpfile.\n"); MSG("\n"); + MSG(" [--check-params]:\n"); + MSG(" Only check whether the command-line parameters are valid or not, and exit.\n"); + MSG(" Preferable to be given as the first parameter.\n"); + MSG("\n"); MSG(" VMLINUX:\n"); MSG(" This is a pathname to the first kernel's vmlinux.\n"); MSG(" This file must have the debug information of the first kernel to analyze\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/makedumpfile-1.6.7/sadump_info.c new/makedumpfile-1.6.8/sadump_info.c --- old/makedumpfile-1.6.7/sadump_info.c 2020-01-15 19:09:56.000000000 +0100 +++ new/makedumpfile-1.6.8/sadump_info.c 2020-11-16 01:29:37.000000000 +0100 @@ -1293,6 +1293,30 @@ return ret; } +static int linux_banner_sanity_check(ulong cr3) +{ + unsigned long linux_banner_paddr; + char buf[sizeof("Linux version")]; + + linux_banner_paddr = vtop4_x86_64_pagetable(SYMBOL(linux_banner), cr3); + if (linux_banner_paddr == NOT_PADDR) { + DEBUG_MSG("sadump: linux_banner address translation failed\n"); + return FALSE; + } + + if (!readmem(PADDR, linux_banner_paddr, &buf, sizeof(buf))) { + DEBUG_MSG("sadump: reading linux_banner failed\n"); + return FALSE; + } + + if (!STRNEQ(buf, "Linux version")) { + DEBUG_MSG("sadump: linux_banner sanity check failed\n"); + return FALSE; + } + + return TRUE; +} + /* * Calculate kaslr_offset and phys_base * @@ -1370,59 +1394,85 @@ { struct sadump_header *sh = si->sh_memory; uint64_t idtr = 0, cr3 = 0, idtr_paddr; - struct sadump_smram_cpu_state smram, zero; + struct sadump_smram_cpu_state smram; int apicid; unsigned long divide_error_vmcore, divide_error_vmlinux; unsigned long kaslr_offset, phys_base; unsigned long kaslr_offset_kdump, phys_base_kdump; + int sanity_check_passed = FALSE; - memset(&zero, 0, sizeof(zero)); for (apicid = 0; apicid < sh->nr_cpus; ++apicid) { + + DEBUG_MSG("sadump: apicid: %d\n", 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; - idtr = ((uint64_t)smram.IdtUpper)<<32 | (uint64_t)smram.IdtLower; - if ((SYMBOL(pti_init) != NOT_FOUND_SYMBOL) || - (SYMBOL(kaiser_init) != NOT_FOUND_SYMBOL)) - cr3 = smram.Cr3 & ~(CR3_PCID_MASK|PTI_USER_PGTABLE_MASK); - else - cr3 = smram.Cr3 & ~CR3_PCID_MASK; + if (!smram.Cr3 || !idtr) { + DEBUG_MSG("sadump: cr3: %lx idt: %lx, skipped\n", + smram.Cr3, idtr); + continue; + } - /* Convert virtual address of IDT table to physical address */ - if ((idtr_paddr = vtop4_x86_64_pagetable(idtr, cr3)) == NOT_PADDR) - return FALSE; + if ((SYMBOL(pti_init) != NOT_FOUND_SYMBOL) || + (SYMBOL(kaiser_init) != NOT_FOUND_SYMBOL)) + cr3 = smram.Cr3 & ~(CR3_PCID_MASK|PTI_USER_PGTABLE_MASK); + else + cr3 = smram.Cr3 & ~CR3_PCID_MASK; + + /* Convert virtual address of IDT table to physical address */ + idtr_paddr = vtop4_x86_64_pagetable(idtr, cr3); + if (idtr_paddr == NOT_PADDR) { + DEBUG_MSG("sadump: converting IDT physical address " + "failed.\n"); + continue; + } - /* 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); + /* 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; + /* Reload symbol */ + if (!get_symbol_info()) { + ERRMSG("Reading symbol table failed\n"); + return FALSE; + } + + /* Sanity check */ + if (linux_banner_sanity_check(cr3)) { + sanity_check_passed = TRUE; + break; + } + + info->kaslr_offset = 0; + info->phys_base = 0; + } + + if (!sanity_check_passed) { + ERRMSG("failed to calculate kaslr_offset and phys_base; " + "default to 0\n"); + info->kaslr_offset = 0; + info->phys_base = 0; + return TRUE; + } /* * Check if current kaslr_offset/phys_base is for 1st kernel or 2nd @@ -1430,13 +1480,15 @@ * from vmcoreinfo */ if (get_kaslr_offset_from_vmcoreinfo(cr3, &kaslr_offset_kdump, - &phys_base_kdump)) { + &phys_base_kdump)) { info->kaslr_offset = kaslr_offset_kdump; info->phys_base = phys_base_kdump; /* Reload symbol */ - if (!get_symbol_info()) + if (!get_symbol_info()) { + ERRMSG("Reading symbol table failed\n"); return FALSE; + } } DEBUG_MSG("sadump: kaslr_offset=%lx\n", info->kaslr_offset); @@ -1732,11 +1784,11 @@ return FALSE; } - if (!readmem(VADDR, SYMBOL(__per_cpu_load), &si->__per_cpu_load, - sizeof(unsigned long))) { - ERRMSG("Can't read __per_cpu_load memory.\n"); + if (SYMBOL(__per_cpu_load) == NOT_FOUND_SYMBOL) { + ERRMSG("Can't find __per_cpu_load symbol.\n"); return FALSE; } + si->__per_cpu_load = SYMBOL(__per_cpu_load); DEBUG_MSG("sadump: __per_cpu_load: %#lx\n", si->__per_cpu_load); DEBUG_MSG("sadump: __per_cpu_offset: LENGTH: %ld\n", ++++++ makedumpfile-printk-add-support-for-lockless-ringbuffer.patch ++++++ >From c617ec63339222f3a44d73e36677a9acc8954ccd Mon Sep 17 00:00:00 2001 From: John Ogness <[email protected]> Date: Thu, 19 Nov 2020 02:41:21 +0000 Subject: [PATCH 1/2] [PATCH 1/2] printk: add support for lockless ringbuffer Upstream: merged (expected 1.6.9) Git-commit: c617ec63339222f3a44d73e36677a9acc8954ccd * Required for kernel 5.10 Linux 5.10 introduces a new lockless ringbuffer. The new ringbuffer is structured completely different to the previous iterations. Add support for retrieving the ringbuffer from debug information and/or using vmcoreinfo. The new ringbuffer is detected based on the availability of the "prb" symbol. Signed-off-by: John Ogness <[email protected]> Signed-off-by: Kazuhito Hagio <[email protected]> --- Makefile | 2 +- dwarf_info.c | 36 ++++++++- makedumpfile.c | 103 +++++++++++++++++++++++- makedumpfile.h | 58 ++++++++++++++ printk.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 399 insertions(+), 7 deletions(-) create mode 100644 printk.c diff --git a/Makefile b/Makefile index e5ac71a83778..cb6bd42ce738 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ CFLAGS_ARCH += -m32 endif SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info.h -SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c +SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c printk.c OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART)) SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c arch/sparc64.c OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH)) diff --git a/dwarf_info.c b/dwarf_info.c index e42a9f5857f3..543588ba369b 100644 --- a/dwarf_info.c +++ b/dwarf_info.c @@ -614,6 +614,7 @@ search_structure(Dwarf_Die *die, int *found) { int tag; const char *name; + Dwarf_Die die_type; /* * If we get to here then we don't have any more @@ -622,9 +623,31 @@ search_structure(Dwarf_Die *die, int *found) do { tag = dwarf_tag(die); name = dwarf_diename(die); - if ((tag != DW_TAG_structure_type) || (!name) - || strcmp(name, dwarf_info.struct_name)) + if ((!name) || strcmp(name, dwarf_info.struct_name)) + continue; + + if (tag == DW_TAG_typedef) { + if (!get_die_type(die, &die_type)) { + ERRMSG("Can't get CU die of DW_AT_type.\n"); + break; + } + + /* Resolve typedefs of typedefs. */ + while ((tag = dwarf_tag(&die_type)) == DW_TAG_typedef) { + if (!get_die_type(&die_type, &die_type)) { + ERRMSG("Can't get CU die of DW_AT_type.\n"); + return; + } + } + + if (tag != DW_TAG_structure_type) + continue; + die = &die_type; + + } else if (tag != DW_TAG_structure_type) { continue; + } + /* * Skip if DW_AT_byte_size is not included. */ @@ -740,6 +763,15 @@ search_typedef(Dwarf_Die *die, int *found) ERRMSG("Can't get CU die of DW_AT_type.\n"); break; } + + /* Resolve typedefs of typedefs. */ + while ((tag = dwarf_tag(&die_type)) == DW_TAG_typedef) { + if (!get_die_type(&die_type, &die_type)) { + ERRMSG("Can't get CU die of DW_AT_type.\n"); + return; + } + } + dwarf_info.struct_size = dwarf_bytesize(&die_type); if (dwarf_info.struct_size <= 0) continue; diff --git a/makedumpfile.c b/makedumpfile.c index cdde040e2133..061741f72a5c 100644 --- a/makedumpfile.c +++ b/makedumpfile.c @@ -1555,6 +1555,7 @@ get_symbol_info(void) SYMBOL_INIT(node_data, "node_data"); SYMBOL_INIT(pgdat_list, "pgdat_list"); SYMBOL_INIT(contig_page_data, "contig_page_data"); + SYMBOL_INIT(prb, "prb"); SYMBOL_INIT(log_buf, "log_buf"); SYMBOL_INIT(log_buf_len, "log_buf_len"); SYMBOL_INIT(log_end, "log_end"); @@ -1971,16 +1972,47 @@ get_structure_info(void) OFFSET_INIT(elf64_phdr.p_memsz, "elf64_phdr", "p_memsz"); SIZE_INIT(printk_log, "printk_log"); - if (SIZE(printk_log) != NOT_FOUND_STRUCTURE) { + SIZE_INIT(printk_ringbuffer, "printk_ringbuffer"); + if ((SIZE(printk_ringbuffer) != NOT_FOUND_STRUCTURE)) { + info->flag_use_printk_ringbuffer = TRUE; + info->flag_use_printk_log = FALSE; + + OFFSET_INIT(printk_ringbuffer.desc_ring, "printk_ringbuffer", "desc_ring"); + OFFSET_INIT(printk_ringbuffer.text_data_ring, "printk_ringbuffer", "text_data_ring"); + + OFFSET_INIT(prb_desc_ring.count_bits, "prb_desc_ring", "count_bits"); + OFFSET_INIT(prb_desc_ring.descs, "prb_desc_ring", "descs"); + OFFSET_INIT(prb_desc_ring.infos, "prb_desc_ring", "infos"); + OFFSET_INIT(prb_desc_ring.head_id, "prb_desc_ring", "head_id"); + OFFSET_INIT(prb_desc_ring.tail_id, "prb_desc_ring", "tail_id"); + + SIZE_INIT(prb_desc, "prb_desc"); + OFFSET_INIT(prb_desc.state_var, "prb_desc", "state_var"); + OFFSET_INIT(prb_desc.text_blk_lpos, "prb_desc", "text_blk_lpos"); + + OFFSET_INIT(prb_data_blk_lpos.begin, "prb_data_blk_lpos", "begin"); + OFFSET_INIT(prb_data_blk_lpos.next, "prb_data_blk_lpos", "next"); + + OFFSET_INIT(prb_data_ring.size_bits, "prb_data_ring", "size_bits"); + OFFSET_INIT(prb_data_ring.data, "prb_data_ring", "data"); + + SIZE_INIT(printk_info, "printk_info"); + OFFSET_INIT(printk_info.ts_nsec, "printk_info", "ts_nsec"); + OFFSET_INIT(printk_info.text_len, "printk_info", "text_len"); + + OFFSET_INIT(atomic_long_t.counter, "atomic_long_t", "counter"); + } else if (SIZE(printk_log) != NOT_FOUND_STRUCTURE) { /* * In kernel 3.11-rc4 the log structure name was renamed * to "printk_log". */ + info->flag_use_printk_ringbuffer = FALSE; info->flag_use_printk_log = TRUE; OFFSET_INIT(printk_log.ts_nsec, "printk_log", "ts_nsec"); OFFSET_INIT(printk_log.len, "printk_log", "len"); OFFSET_INIT(printk_log.text_len, "printk_log", "text_len"); } else { + info->flag_use_printk_ringbuffer = FALSE; info->flag_use_printk_log = FALSE; SIZE_INIT(printk_log, "log"); OFFSET_INIT(printk_log.ts_nsec, "log", "ts_nsec"); @@ -2191,6 +2223,7 @@ write_vmcoreinfo_data(void) WRITE_SYMBOL("node_data", node_data); WRITE_SYMBOL("pgdat_list", pgdat_list); WRITE_SYMBOL("contig_page_data", contig_page_data); + WRITE_SYMBOL("prb", prb); WRITE_SYMBOL("log_buf", log_buf); WRITE_SYMBOL("log_buf_len", log_buf_len); WRITE_SYMBOL("log_end", log_end); @@ -2222,7 +2255,11 @@ write_vmcoreinfo_data(void) WRITE_STRUCTURE_SIZE("node_memblk_s", node_memblk_s); WRITE_STRUCTURE_SIZE("nodemask_t", nodemask_t); WRITE_STRUCTURE_SIZE("pageflags", pageflags); - if (info->flag_use_printk_log) + if (info->flag_use_printk_ringbuffer) { + WRITE_STRUCTURE_SIZE("printk_ringbuffer", printk_ringbuffer); + WRITE_STRUCTURE_SIZE("prb_desc", prb_desc); + WRITE_STRUCTURE_SIZE("printk_info", printk_info); + } else if (info->flag_use_printk_log) WRITE_STRUCTURE_SIZE("printk_log", printk_log); else WRITE_STRUCTURE_SIZE("log", printk_log); @@ -2268,7 +2305,30 @@ write_vmcoreinfo_data(void) WRITE_MEMBER_OFFSET("vm_struct.addr", vm_struct.addr); WRITE_MEMBER_OFFSET("vmap_area.va_start", vmap_area.va_start); WRITE_MEMBER_OFFSET("vmap_area.list", vmap_area.list); - if (info->flag_use_printk_log) { + if (info->flag_use_printk_ringbuffer) { + WRITE_MEMBER_OFFSET("printk_ringbuffer.desc_ring", printk_ringbuffer.desc_ring); + WRITE_MEMBER_OFFSET("printk_ringbuffer.text_data_ring", printk_ringbuffer.text_data_ring); + + WRITE_MEMBER_OFFSET("prb_desc_ring.count_bits", prb_desc_ring.count_bits); + WRITE_MEMBER_OFFSET("prb_desc_ring.descs", prb_desc_ring.descs); + WRITE_MEMBER_OFFSET("prb_desc_ring.infos", prb_desc_ring.infos); + WRITE_MEMBER_OFFSET("prb_desc_ring.head_id", prb_desc_ring.head_id); + WRITE_MEMBER_OFFSET("prb_desc_ring.tail_id", prb_desc_ring.tail_id); + + WRITE_MEMBER_OFFSET("prb_desc.state_var", prb_desc.state_var); + WRITE_MEMBER_OFFSET("prb_desc.text_blk_lpos", prb_desc.text_blk_lpos); + + WRITE_MEMBER_OFFSET("prb_data_blk_lpos.begin", prb_data_blk_lpos.begin); + WRITE_MEMBER_OFFSET("prb_data_blk_lpos.next", prb_data_blk_lpos.next); + + WRITE_MEMBER_OFFSET("prb_data_ring.size_bits", prb_data_ring.size_bits); + WRITE_MEMBER_OFFSET("prb_data_ring.data", prb_data_ring.data); + + WRITE_MEMBER_OFFSET("printk_info.ts_nsec", printk_info.ts_nsec); + WRITE_MEMBER_OFFSET("printk_info.text_len", printk_info.text_len); + + WRITE_MEMBER_OFFSET("atomic_long_t.counter", atomic_long_t.counter); + } else if (info->flag_use_printk_log) { WRITE_MEMBER_OFFSET("printk_log.ts_nsec", printk_log.ts_nsec); WRITE_MEMBER_OFFSET("printk_log.len", printk_log.len); WRITE_MEMBER_OFFSET("printk_log.text_len", printk_log.text_len); @@ -2606,6 +2666,7 @@ read_vmcoreinfo(void) READ_SYMBOL("node_data", node_data); READ_SYMBOL("pgdat_list", pgdat_list); READ_SYMBOL("contig_page_data", contig_page_data); + READ_SYMBOL("prb", prb); READ_SYMBOL("log_buf", log_buf); READ_SYMBOL("log_buf_len", log_buf_len); READ_SYMBOL("log_end", log_end); @@ -2684,12 +2745,43 @@ read_vmcoreinfo(void) READ_MEMBER_OFFSET("cpu_spec.mmu_features", cpu_spec.mmu_features); READ_STRUCTURE_SIZE("printk_log", printk_log); - if (SIZE(printk_log) != NOT_FOUND_STRUCTURE) { + READ_STRUCTURE_SIZE("printk_ringbuffer", printk_ringbuffer); + if (SIZE(printk_ringbuffer) != NOT_FOUND_STRUCTURE) { + info->flag_use_printk_ringbuffer = TRUE; + info->flag_use_printk_log = FALSE; + + READ_MEMBER_OFFSET("printk_ringbuffer.desc_ring", printk_ringbuffer.desc_ring); + READ_MEMBER_OFFSET("printk_ringbuffer.text_data_ring", printk_ringbuffer.text_data_ring); + + READ_MEMBER_OFFSET("prb_desc_ring.count_bits", prb_desc_ring.count_bits); + READ_MEMBER_OFFSET("prb_desc_ring.descs", prb_desc_ring.descs); + READ_MEMBER_OFFSET("prb_desc_ring.infos", prb_desc_ring.infos); + READ_MEMBER_OFFSET("prb_desc_ring.head_id", prb_desc_ring.head_id); + READ_MEMBER_OFFSET("prb_desc_ring.tail_id", prb_desc_ring.tail_id); + + READ_STRUCTURE_SIZE("prb_desc", prb_desc); + READ_MEMBER_OFFSET("prb_desc.state_var", prb_desc.state_var); + READ_MEMBER_OFFSET("prb_desc.text_blk_lpos", prb_desc.text_blk_lpos); + + READ_MEMBER_OFFSET("prb_data_blk_lpos.begin", prb_data_blk_lpos.begin); + READ_MEMBER_OFFSET("prb_data_blk_lpos.next", prb_data_blk_lpos.next); + + READ_MEMBER_OFFSET("prb_data_ring.size_bits", prb_data_ring.size_bits); + READ_MEMBER_OFFSET("prb_data_ring.data", prb_data_ring.data); + + READ_STRUCTURE_SIZE("printk_info", printk_info); + READ_MEMBER_OFFSET("printk_info.ts_nsec", printk_info.ts_nsec); + READ_MEMBER_OFFSET("printk_info.text_len", printk_info.text_len); + + READ_MEMBER_OFFSET("atomic_long_t.counter", atomic_long_t.counter); + } else if (SIZE(printk_log) != NOT_FOUND_STRUCTURE) { + info->flag_use_printk_ringbuffer = FALSE; info->flag_use_printk_log = TRUE; READ_MEMBER_OFFSET("printk_log.ts_nsec", printk_log.ts_nsec); READ_MEMBER_OFFSET("printk_log.len", printk_log.len); READ_MEMBER_OFFSET("printk_log.text_len", printk_log.text_len); } else { + info->flag_use_printk_ringbuffer = FALSE; info->flag_use_printk_log = FALSE; READ_STRUCTURE_SIZE("log", printk_log); READ_MEMBER_OFFSET("log.ts_nsec", printk_log.ts_nsec); @@ -5286,6 +5378,9 @@ dump_dmesg() if (!initial()) return FALSE; + if ((SYMBOL(prb) != NOT_FOUND_SYMBOL)) + return dump_lockless_dmesg(); + if ((SYMBOL(log_buf) == NOT_FOUND_SYMBOL) || (SYMBOL(log_buf_len) == NOT_FOUND_SYMBOL)) { ERRMSG("Can't find some symbols for log_buf.\n"); diff --git a/makedumpfile.h b/makedumpfile.h index 698c0547c0f2..47f7e7999014 100644 --- a/makedumpfile.h +++ b/makedumpfile.h @@ -1317,6 +1317,7 @@ struct DumpInfo { int flag_partial_dmesg; /* dmesg dump only from the last cleared index*/ int flag_mem_usage; /*show the page number of memory in different use*/ int flag_use_printk_log; /* did we read printk_log symbol name? */ + int flag_use_printk_ringbuffer; /* using lockless printk ringbuffer? */ int flag_nospace; /* the flag of "No space on device" error */ int flag_vmemmap; /* kernel supports vmemmap address space */ int flag_excludevm; /* -e - excluding unused vmemmap pages */ @@ -1602,6 +1603,7 @@ struct symbol_table { unsigned long long node_data; unsigned long long pgdat_list; unsigned long long contig_page_data; + unsigned long long prb; unsigned long long log_buf; unsigned long long log_buf_len; unsigned long long log_end; @@ -1689,6 +1691,13 @@ struct size_table { long nodemask_t; long printk_log; + /* + * for lockless printk ringbuffer + */ + long printk_ringbuffer; + long prb_desc; + long printk_info; + /* * for Xen extraction */ @@ -1864,6 +1873,52 @@ struct offset_table { long text_len; } printk_log; + /* + * for lockless printk ringbuffer + */ + struct printk_ringbuffer_s { + long desc_ring; + long text_data_ring; + long fail; + } printk_ringbuffer; + + struct prb_desc_ring_s { + long count_bits; + long descs; + long infos; + long head_id; + long tail_id; + } prb_desc_ring; + + struct prb_desc_s { + long state_var; + long text_blk_lpos; + } prb_desc; + + struct prb_data_blk_lpos_s { + long begin; + long next; + } prb_data_blk_lpos; + + struct printk_info_s { + long seq; + long ts_nsec; + long text_len; + long caller_id; + long dev_info; + } printk_info; + + struct prb_data_ring_s { + long size_bits; + long data; + long head_lpos; + long tail_lpos; + } prb_data_ring; + + struct atomic_long_t_s { + long counter; + } atomic_long_t; + /* * symbols on ppc64 arch */ @@ -2390,4 +2445,7 @@ int hexadecimal(char *s, int count); int decimal(char *s, int count); int file_exists(char *file); +int open_dump_file(void); +int dump_lockless_dmesg(void); + #endif /* MAKEDUMPFILE_H */ diff --git a/printk.c b/printk.c new file mode 100644 index 000000000000..acffb6c7a898 --- /dev/null +++ b/printk.c @@ -0,0 +1,207 @@ +#include "makedumpfile.h" +#include <ctype.h> + +#define DESC_SV_BITS (sizeof(unsigned long) * 8) +#define DESC_COMMITTED_MASK (1UL << (DESC_SV_BITS - 1)) +#define DESC_REUSE_MASK (1UL << (DESC_SV_BITS - 2)) +#define DESC_FLAGS_MASK (DESC_COMMITTED_MASK | DESC_REUSE_MASK) +#define DESC_ID_MASK (~DESC_FLAGS_MASK) + +/* convenience struct for passing many values to helper functions */ +struct prb_map { + char *prb; + + char *desc_ring; + unsigned long desc_ring_count; + char *descs; + char *infos; + + char *text_data_ring; + unsigned long text_data_ring_size; + char *text_data; +}; + +static void +dump_record(struct prb_map *m, unsigned long id) +{ + unsigned long long ts_nsec; + unsigned long state_var; + unsigned short text_len; + unsigned long begin; + unsigned long next; + char buf[BUFSIZE]; + ulonglong nanos; + int indent_len; + int buf_need; + char *bufp; + char *text; + char *desc; + char *inf; + ulong rem; + char *p; + int i; + + desc = m->descs + ((id % m->desc_ring_count) * SIZE(prb_desc)); + + /* skip non-committed record */ + state_var = ULONG(desc + OFFSET(prb_desc.state_var) + OFFSET(atomic_long_t.counter)); + if ((state_var & DESC_FLAGS_MASK) != DESC_COMMITTED_MASK) + return; + + begin = ULONG(desc + OFFSET(prb_desc.text_blk_lpos) + OFFSET(prb_data_blk_lpos.begin)) % + m->text_data_ring_size; + next = ULONG(desc + OFFSET(prb_desc.text_blk_lpos) + OFFSET(prb_data_blk_lpos.next)) % + m->text_data_ring_size; + + /* skip data-less text blocks */ + if (begin == next) + return; + + inf = m->infos + ((id % m->desc_ring_count) * SIZE(printk_info)); + + text_len = USHORT(inf + OFFSET(printk_info.text_len)); + + /* handle wrapping data block */ + if (begin > next) + begin = 0; + + /* skip over descriptor ID */ + begin += sizeof(unsigned long); + + /* handle truncated messages */ + if (next - begin < text_len) + text_len = next - begin; + + text = m->text_data + begin; + + ts_nsec = ULONGLONG(inf + OFFSET(printk_info.ts_nsec)); + nanos = (ulonglong)ts_nsec / (ulonglong)1000000000; + rem = (ulonglong)ts_nsec % (ulonglong)1000000000; + + bufp = buf; + bufp += sprintf(buf, "[%5lld.%06ld] ", nanos, rem/1000); + indent_len = strlen(buf); + + /* How much buffer space is needed in the worst case */ + buf_need = MAX(sizeof("\\xXX\n"), sizeof("\n") + indent_len); + + for (i = 0, p = text; i < text_len; i++, p++) { + if (bufp - buf >= sizeof(buf) - buf_need) { + if (write(info->fd_dumpfile, buf, bufp - buf) < 0) + return; + bufp = buf; + } + + if (*p == '\n') + bufp += sprintf(bufp, "\n%-*s", indent_len, ""); + else if (isprint(*p) || isspace(*p)) + *bufp++ = *p; + else + bufp += sprintf(bufp, "\\x%02x", *p); + } + + *bufp++ = '\n'; + + write(info->fd_dumpfile, buf, bufp - buf); +} + +int +dump_lockless_dmesg(void) +{ + unsigned long head_id; + unsigned long tail_id; + unsigned long kaddr; + unsigned long id; + struct prb_map m; + int ret = FALSE; + + /* setup printk_ringbuffer */ + if (!readmem(VADDR, SYMBOL(prb), &kaddr, sizeof(kaddr))) { + ERRMSG("Can't get the prb address.\n"); + return ret; + } + + m.prb = malloc(SIZE(printk_ringbuffer)); + if (!m.prb) { + ERRMSG("Can't allocate memory for prb.\n"); + return ret; + } + if (!readmem(VADDR, kaddr, m.prb, SIZE(printk_ringbuffer))) { + ERRMSG("Can't get prb.\n"); + goto out_prb; + } + + /* setup descriptor ring */ + m.desc_ring = m.prb + OFFSET(printk_ringbuffer.desc_ring); + m.desc_ring_count = 1 << UINT(m.desc_ring + OFFSET(prb_desc_ring.count_bits)); + + kaddr = ULONG(m.desc_ring + OFFSET(prb_desc_ring.descs)); + m.descs = malloc(SIZE(prb_desc) * m.desc_ring_count); + if (!m.descs) { + ERRMSG("Can't allocate memory for prb.desc_ring.descs.\n"); + goto out_prb; + } + if (!readmem(VADDR, kaddr, m.descs, + SIZE(prb_desc) * m.desc_ring_count)) { + ERRMSG("Can't get prb.desc_ring.descs.\n"); + goto out_descs; + } + + kaddr = ULONG(m.desc_ring + OFFSET(prb_desc_ring.infos)); + m.infos = malloc(SIZE(printk_info) * m.desc_ring_count); + if (!m.infos) { + ERRMSG("Can't allocate memory for prb.desc_ring.infos.\n"); + goto out_descs; + } + if (!readmem(VADDR, kaddr, m.infos, SIZE(printk_info) * m.desc_ring_count)) { + ERRMSG("Can't get prb.desc_ring.infos.\n"); + goto out_infos; + } + + /* setup text data ring */ + m.text_data_ring = m.prb + OFFSET(printk_ringbuffer.text_data_ring); + m.text_data_ring_size = 1 << UINT(m.text_data_ring + OFFSET(prb_data_ring.size_bits)); + + kaddr = ULONG(m.text_data_ring + OFFSET(prb_data_ring.data)); + m.text_data = malloc(m.text_data_ring_size); + if (!m.text_data) { + ERRMSG("Can't allocate memory for prb.text_data_ring.data.\n"); + goto out_infos; + } + if (!readmem(VADDR, kaddr, m.text_data, m.text_data_ring_size)) { + ERRMSG("Can't get prb.text_data_ring.\n"); + goto out_text_data; + } + + /* ready to go */ + + tail_id = ULONG(m.desc_ring + OFFSET(prb_desc_ring.tail_id) + + OFFSET(atomic_long_t.counter)); + head_id = ULONG(m.desc_ring + OFFSET(prb_desc_ring.head_id) + + OFFSET(atomic_long_t.counter)); + + if (!open_dump_file()) { + ERRMSG("Can't open output file.\n"); + goto out_text_data; + } + + for (id = tail_id; id != head_id; id = (id + 1) & DESC_ID_MASK) + dump_record(&m, id); + + /* dump head record */ + dump_record(&m, id); + + if (!close_files_for_creating_dumpfile()) + goto out_text_data; + + ret = TRUE; +out_text_data: + free(m.text_data); +out_infos: + free(m.infos); +out_descs: + free(m.descs); +out_prb: + free(m.prb); + return ret; +} -- 2.26.2 ++++++ makedumpfile-printk-use-committed-finalized-state-value.patch ++++++ >From 44b073b7ec467aee0d7de381d455b8ace1199184 Mon Sep 17 00:00:00 2001 From: John Ogness <[email protected]> Date: Wed, 25 Nov 2020 10:10:31 +0106 Subject: [PATCH 2/2] [PATCH 2/2] printk: use committed/finalized state values Upstream: merged (expected 1.6.9) Git-commit: 44b073b7ec467aee0d7de381d455b8ace1199184 * Required for kernel 5.10 The ringbuffer entries use 2 state values (committed and finalized) rather than a single flag to represent being available for reading. Copy the definitions and state lookup function directly from the kernel source and use the new states. Signed-off-by: John Ogness <[email protected]> --- printk.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/printk.c b/printk.c index acffb6c7a898..2af8562201cc 100644 --- a/printk.c +++ b/printk.c @@ -1,12 +1,6 @@ #include "makedumpfile.h" #include <ctype.h> -#define DESC_SV_BITS (sizeof(unsigned long) * 8) -#define DESC_COMMITTED_MASK (1UL << (DESC_SV_BITS - 1)) -#define DESC_REUSE_MASK (1UL << (DESC_SV_BITS - 2)) -#define DESC_FLAGS_MASK (DESC_COMMITTED_MASK | DESC_REUSE_MASK) -#define DESC_ID_MASK (~DESC_FLAGS_MASK) - /* convenience struct for passing many values to helper functions */ struct prb_map { char *prb; @@ -21,12 +15,51 @@ struct prb_map { char *text_data; }; +/* + * desc_state and DESC_* definitions taken from kernel source: + * + * kernel/printk/printk_ringbuffer.h + */ + +/* The possible responses of a descriptor state-query. */ +enum desc_state { + desc_miss = -1, /* ID mismatch (pseudo state) */ + desc_reserved = 0x0, /* reserved, in use by writer */ + desc_committed = 0x1, /* committed by writer, could get reopened */ + desc_finalized = 0x2, /* committed, no further modification allowed */ + desc_reusable = 0x3, /* free, not yet used by any writer */ +}; + +#define DESC_SV_BITS (sizeof(unsigned long) * 8) +#define DESC_FLAGS_SHIFT (DESC_SV_BITS - 2) +#define DESC_FLAGS_MASK (3UL << DESC_FLAGS_SHIFT) +#define DESC_STATE(sv) (3UL & (sv >> DESC_FLAGS_SHIFT)) +#define DESC_ID_MASK (~DESC_FLAGS_MASK) +#define DESC_ID(sv) ((sv) & DESC_ID_MASK) + +/* + * get_desc_state() taken from kernel source: + * + * kernel/printk/printk_ringbuffer.c + */ + +/* Query the state of a descriptor. */ +static enum desc_state get_desc_state(unsigned long id, + unsigned long state_val) +{ + if (id != DESC_ID(state_val)) + return desc_miss; + + return DESC_STATE(state_val); +} + static void dump_record(struct prb_map *m, unsigned long id) { unsigned long long ts_nsec; unsigned long state_var; unsigned short text_len; + enum desc_state state; unsigned long begin; unsigned long next; char buf[BUFSIZE]; @@ -45,7 +78,8 @@ dump_record(struct prb_map *m, unsigned long id) /* skip non-committed record */ state_var = ULONG(desc + OFFSET(prb_desc.state_var) + OFFSET(atomic_long_t.counter)); - if ((state_var & DESC_FLAGS_MASK) != DESC_COMMITTED_MASK) + state = get_desc_state(id, state_var); + if (state != desc_committed && state != desc_finalized) return; begin = ULONG(desc + OFFSET(prb_desc.text_blk_lpos) + OFFSET(prb_data_blk_lpos.begin)) % -- 2.26.2 ++++++ makedumpfile-use-uts_namespace.name-offset-VMCOREINFO.patch ++++++ From: Alexander Egorenkov <[email protected]> Date: Fri, 18 Sep 2020 13:55:56 +0200 Subject: make use of 'uts_namespace.name' offset in VMCOREINFO Upstream: merged Git-commit: 54aec3878b3f91341e6bc735eda158cca5c54ec9 * Required for kernel 5.11 The offset of the field 'init_uts_ns.name' has changed since kernel commit 9a56493f6942 ("uts: Use generic ns_common::count"). Make use of the offset 'uts_namespace.name' if available in VMCOREINFO. Signed-off-by: Alexander Egorenkov <[email protected]> Acked-by: Petr Tesarik <[email protected]> --- makedumpfile.c | 17 +++++++++++++++-- makedumpfile.h | 6 ++++++ 2 files changed, 21 insertions(+), 2 deletions(-) --- a/makedumpfile.c +++ b/makedumpfile.c @@ -1159,7 +1159,10 @@ check_release(void) if (SYMBOL(system_utsname) != NOT_FOUND_SYMBOL) { utsname = SYMBOL(system_utsname); } else if (SYMBOL(init_uts_ns) != NOT_FOUND_SYMBOL) { - utsname = SYMBOL(init_uts_ns) + sizeof(int); + if (OFFSET(uts_namespace.name) != NOT_FOUND_STRUCTURE) + utsname = SYMBOL(init_uts_ns) + OFFSET(uts_namespace.name); + else + utsname = SYMBOL(init_uts_ns) + sizeof(int); } else { ERRMSG("Can't get the symbol of system_utsname.\n"); return FALSE; @@ -2040,6 +2043,11 @@ get_structure_info(void) SIZE_INIT(cpu_spec, "cpu_spec"); OFFSET_INIT(cpu_spec.mmu_features, "cpu_spec", "mmu_features"); + /* + * Get offsets of the uts_namespace's members. + */ + OFFSET_INIT(uts_namespace.name, "uts_namespace", "name"); + return TRUE; } @@ -2109,7 +2117,10 @@ get_str_osrelease_from_vmlinux(void) if (SYMBOL(system_utsname) != NOT_FOUND_SYMBOL) { utsname = SYMBOL(system_utsname); } else if (SYMBOL(init_uts_ns) != NOT_FOUND_SYMBOL) { - utsname = SYMBOL(init_uts_ns) + sizeof(int); + if (OFFSET(uts_namespace.name) != NOT_FOUND_STRUCTURE) + utsname = SYMBOL(init_uts_ns) + OFFSET(uts_namespace.name); + else + utsname = SYMBOL(init_uts_ns) + sizeof(int); } else { ERRMSG("Can't get the symbol of system_utsname.\n"); return FALSE; @@ -2344,6 +2355,7 @@ write_vmcoreinfo_data(void) WRITE_MEMBER_OFFSET("vmemmap_backing.list", vmemmap_backing.list); WRITE_MEMBER_OFFSET("mmu_psize_def.shift", mmu_psize_def.shift); WRITE_MEMBER_OFFSET("cpu_spec.mmu_features", cpu_spec.mmu_features); + WRITE_MEMBER_OFFSET("uts_namespace.name", uts_namespace.name); if (SYMBOL(node_data) != NOT_FOUND_SYMBOL) WRITE_ARRAY_LENGTH("node_data", node_data); @@ -2745,6 +2757,7 @@ read_vmcoreinfo(void) READ_MEMBER_OFFSET("vmemmap_backing.list", vmemmap_backing.list); READ_MEMBER_OFFSET("mmu_psize_def.shift", mmu_psize_def.shift); READ_MEMBER_OFFSET("cpu_spec.mmu_features", cpu_spec.mmu_features); + READ_MEMBER_OFFSET("uts_namespace.name", uts_namespace.name); READ_STRUCTURE_SIZE("printk_log", printk_log); READ_STRUCTURE_SIZE("printk_ringbuffer", printk_ringbuffer); --- a/makedumpfile.h +++ b/makedumpfile.h @@ -1728,6 +1728,8 @@ struct size_table { long cpu_spec; long pageflags; + + long uts_namespace; }; struct offset_table { @@ -1935,6 +1937,10 @@ struct offset_table { struct cpu_spec_s { long mmu_features; } cpu_spec; + + struct uts_namespace_s { + long name; + } uts_namespace; }; /*
