From f4cf831bbb446e48794770b3430baa54fa015109 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 23 2020 22:24:22 +0000 Subject: import kexec-tools-2.0.20-14.el8 --- diff --git a/SOURCES/dracut-kdump.sh b/SOURCES/dracut-kdump.sh index 2ae1c7c..cb22254 100755 --- a/SOURCES/dracut-kdump.sh +++ b/SOURCES/dracut-kdump.sh @@ -1,8 +1,8 @@ #!/bin/sh # continue here only if we have to save dump. -if [ -f /etc/fadump.initramfs ] && [ ! -f /proc/device-tree/rtas/ibm,kernel-dump ]; then - exit 0 +if [ -f /etc/fadump.initramfs ] && [ ! -f /proc/device-tree/rtas/ibm,kernel-dump ] && [ ! -f /proc/device-tree/ibm,opal/dump/mpipl-boot ]; then + exit 0 fi exec &> /dev/console @@ -81,6 +81,7 @@ dump_ssh() ssh -q $_opt $_host mkdir -p $_dir || return 1 save_vmcore_dmesg_ssh ${DMESG_COLLECTOR} ${_dir} "${_opt}" $_host + save_opalcore_ssh ${_dir} "${_opt}" $_host echo "kdump: saving vmcore" @@ -96,6 +97,32 @@ dump_ssh() return 0 } +save_opalcore_ssh() { + local _path=$1 + local _opts="$2" + local _location=$3 + + if [ ! -f $OPALCORE ]; then + # Check if we are on an old kernel that uses a different path + if [ -f /sys/firmware/opal/core ]; then + OPALCORE="/sys/firmware/opal/core" + else + return 0 + fi + fi + + echo "kdump: saving opalcore" + scp $_opts $OPALCORE $_location:$_path/opalcore-incomplete + if [ $? -ne 0 ]; then + echo "kdump: saving opalcore failed" + return 1 + fi + + ssh $_opts $_location mv $_path/opalcore-incomplete $_path/opalcore + echo "kdump: saving opalcore complete" + return 0 +} + save_vmcore_dmesg_ssh() { local _dmesg_collector=$1 local _path=$2 diff --git a/SOURCES/dracut-module-setup.sh b/SOURCES/dracut-module-setup.sh index c6d2d8c..e7a2e63 100755 --- a/SOURCES/dracut-module-setup.sh +++ b/SOURCES/dracut-module-setup.sh @@ -268,10 +268,10 @@ kdump_setup_vlan() { exit 1 elif kdump_is_bond "$_phydev"; then kdump_setup_bond "$_phydev" - echo " vlan=$_netdev:$_phydev" > ${initdir}/etc/cmdline.d/43vlan.conf + echo " vlan=$(kdump_setup_ifname $_netdev):$_phydev" > ${initdir}/etc/cmdline.d/43vlan.conf else _kdumpdev="$(kdump_setup_ifname $_phydev)" - echo " vlan=$_netdev:$_kdumpdev ifname=$_kdumpdev:$_netmac" > ${initdir}/etc/cmdline.d/43vlan.conf + echo " vlan=$(kdump_setup_ifname $_netdev):$_kdumpdev ifname=$_kdumpdev:$_netmac" > ${initdir}/etc/cmdline.d/43vlan.conf fi } diff --git a/SOURCES/kdump-lib-initramfs.sh b/SOURCES/kdump-lib-initramfs.sh index c7f9522..a1ee9cd 100755 --- a/SOURCES/kdump-lib-initramfs.sh +++ b/SOURCES/kdump-lib-initramfs.sh @@ -18,6 +18,7 @@ KDUMP_CONF="/etc/kdump.conf" KDUMP_PRE="" KDUMP_POST="" NEWROOT="/sysroot" +OPALCORE="/sys/firmware/opal/mpipl/core" get_kdump_confs() { @@ -132,6 +133,7 @@ dump_fs() mkdir -p $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR || return 1 save_vmcore_dmesg_fs ${DMESG_COLLECTOR} "$_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/" + save_opalcore_fs "$_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/" echo "kdump: saving vmcore" $CORE_COLLECTOR /proc/vmcore $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore-incomplete || return 1 @@ -168,6 +170,30 @@ save_vmcore_dmesg_fs() { fi } +save_opalcore_fs() { + local _path=$1 + + if [ ! -f $OPALCORE ]; then + # Check if we are on an old kernel that uses a different path + if [ -f /sys/firmware/opal/core ]; then + OPALCORE="/sys/firmware/opal/core" + else + return 0 + fi + fi + + echo "kdump: saving opalcore" + cp $OPALCORE ${_path}/opalcore + if [ $? -ne 0 ]; then + echo "kdump: saving opalcore failed" + return 1 + fi + + sync + echo "kdump: saving opalcore complete" + return 0 +} + dump_to_rootfs() { diff --git a/SOURCES/kdumpctl b/SOURCES/kdumpctl index 694c7ae..89030dd 100755 --- a/SOURCES/kdumpctl +++ b/SOURCES/kdumpctl @@ -242,6 +242,9 @@ check_config() echo "Invalid kdump config value for option $config_opt." return 1; } + if [ -d "/proc/device-tree/ibm,opal/dump" ] && [ "$config_opt" == "raw" ]; then + echo "WARNING: Won't capture opalcore when 'raw' dump target is used." + fi ;; net|options|link_delay|disk_timeout|debug_mem_level|blacklist) echo "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives." diff --git a/SOURCES/kexec-tools-2.0.20-arm64-kdump-deal-with-a-lot-of-resource-entries-in-p.patch b/SOURCES/kexec-tools-2.0.20-arm64-kdump-deal-with-a-lot-of-resource-entries-in-p.patch new file mode 100644 index 0000000..1f51eb2 --- /dev/null +++ b/SOURCES/kexec-tools-2.0.20-arm64-kdump-deal-with-a-lot-of-resource-entries-in-p.patch @@ -0,0 +1,82 @@ +From 2572b8d702e452624bdb8d7b7c39f458e7dcf2ce Mon Sep 17 00:00:00 2001 +From: AKASHI Takahiro +Date: Wed, 18 Dec 2019 11:42:32 -0500 +Subject: [PATCH 3/3] arm64: kdump: deal with a lot of resource entries in + /proc/iomem + +As described in the commit ("arm64: kexec: allocate memory space avoiding +reserved regions"), /proc/iomem now has a lot of "reserved" entries, and +it's not just enough to have a fixed size of memory range array. + +With this patch, kdump is allowed to handle arbitrary number of memory +ranges, using mem_regions_alloc_and_xxx() functions. + +Signed-off-by: AKASHI Takahiro +Tested-by: Bhupesh Sharma +Tested-by: Masayoshi Mizuma +Signed-off-by: Simon Horman +--- + kexec/arch/arm64/crashdump-arm64.c | 25 ++++++++++--------------- + 1 file changed, 10 insertions(+), 15 deletions(-) + +diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c +index 4fd7aa8fd43c..38d1a0f3000d 100644 +--- a/kexec/arch/arm64/crashdump-arm64.c ++++ b/kexec/arch/arm64/crashdump-arm64.c +@@ -23,13 +23,8 @@ + #include "kexec-elf.h" + #include "mem_regions.h" + +-/* memory ranges on crashed kernel */ +-static struct memory_range system_memory_ranges[CRASH_MAX_MEMORY_RANGES]; +-static struct memory_ranges system_memory_rgns = { +- .size = 0, +- .max_size = CRASH_MAX_MEMORY_RANGES, +- .ranges = system_memory_ranges, +-}; ++/* memory ranges of crashed kernel */ ++static struct memory_ranges system_memory_rgns; + + /* memory range reserved for crashkernel */ + struct memory_range crash_reserved_mem; +@@ -82,7 +77,7 @@ static uint64_t get_kernel_page_offset(void) + * + * This function is called once for each memory region found in /proc/iomem. + * It locates system RAM and crashkernel reserved memory and places these to +- * variables, respectively, system_memory_ranges and crash_reserved_mem. ++ * variables, respectively, system_memory_rgns and usablemem_rgns. + */ + + static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr), +@@ -90,11 +85,11 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr), + unsigned long long length) + { + if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) +- return mem_regions_add(&usablemem_rgns, +- base, length, RANGE_RAM); ++ return mem_regions_alloc_and_add(&usablemem_rgns, ++ base, length, RANGE_RAM); + else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) +- return mem_regions_add(&system_memory_rgns, +- base, length, RANGE_RAM); ++ return mem_regions_alloc_and_add(&system_memory_rgns, ++ base, length, RANGE_RAM); + else if (strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) == 0) + elf_info.kern_paddr_start = base; + else if (strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) == 0) +@@ -135,9 +130,9 @@ static int crash_get_memory_ranges(void) + + dbgprint_mem_range("Reserved memory range", &crash_reserved_mem, 1); + +- if (mem_regions_exclude(&system_memory_rgns, &crash_reserved_mem)) { +- fprintf(stderr, +- "Error: Number of crash memory ranges excedeed the max limit\n"); ++ if (mem_regions_alloc_and_exclude(&system_memory_rgns, ++ &crash_reserved_mem)) { ++ fprintf(stderr, "Cannot allocate memory for ranges\n"); + return -ENOMEM; + } + +-- +2.7.4 + diff --git a/SOURCES/kexec-tools-2.0.20-arm64-kexec-allocate-memory-space-avoiding-reserved-.patch b/SOURCES/kexec-tools-2.0.20-arm64-kexec-allocate-memory-space-avoiding-reserved-.patch new file mode 100644 index 0000000..c641b66 --- /dev/null +++ b/SOURCES/kexec-tools-2.0.20-arm64-kexec-allocate-memory-space-avoiding-reserved-.patch @@ -0,0 +1,248 @@ +From f736104f533290b4ce6fbfbca74abde9ffd3888c Mon Sep 17 00:00:00 2001 +From: AKASHI Takahiro +Date: Wed, 18 Dec 2019 11:42:31 -0500 +Subject: [PATCH 2/3] arm64: kexec: allocate memory space avoiding reserved + regions + +On UEFI/ACPI-only system, some memory regions, including but not limited +to UEFI memory map and ACPI tables, must be preserved across kexec'ing. +Otherwise, they can be corrupted and result in early failure in booting +a new kernel. + +In recent kernels, /proc/iomem now has an extended file format like: + + 40000000-5871ffff : System RAM + 41800000-426affff : Kernel code + 426b0000-42aaffff : reserved + 42ab0000-42c64fff : Kernel data + 54400000-583fffff : Crash kernel + 58590000-585effff : reserved + 58700000-5871ffff : reserved + 58720000-58b5ffff : reserved + 58b60000-5be3ffff : System RAM + 58b61000-58b61fff : reserved + +where the "reserved" entries at the top level or under System RAM (and +its descendant resources) are ones of such kind and should not be regarded +as usable memory ranges where several free spaces for loading kexec data +will be allocated. + +With this patch, get_memory_ranges() will handle this format of file +correctly. Note that, for safety, unknown regions, in addition to +"reserved" ones, will also be excluded. + +Signed-off-by: AKASHI Takahiro +Tested-by: Bhupesh Sharma +Tested-by: Masayoshi Mizuma +Signed-off-by: Simon Horman +--- + kexec/arch/arm64/kexec-arm64.c | 153 +++++++++++++++++++++++++---------------- + 1 file changed, 94 insertions(+), 59 deletions(-) + +diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c +index 6ad3b0a134b3..45ebc54a9b6f 100644 +--- a/kexec/arch/arm64/kexec-arm64.c ++++ b/kexec/arch/arm64/kexec-arm64.c +@@ -10,7 +10,9 @@ + #include + #include + #include ++#include + #include ++#include + #include + #include + #include +@@ -29,6 +31,7 @@ + #include "fs2dt.h" + #include "iomem.h" + #include "kexec-syscall.h" ++#include "mem_regions.h" + #include "arch/options.h" + + #define ROOT_NODE_ADDR_CELLS_DEFAULT 1 +@@ -905,19 +908,33 @@ int get_phys_base_from_pt_load(unsigned long *phys_offset) + return 0; + } + ++static bool to_be_excluded(char *str) ++{ ++ if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) || ++ !strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) || ++ !strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) || ++ !strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL))) ++ return false; ++ else ++ return true; ++} ++ + /** +- * get_memory_ranges_iomem_cb - Helper for get_memory_ranges_iomem. ++ * get_memory_ranges - Try to get the memory ranges from ++ * /proc/iomem. + */ +- +-static int get_memory_ranges_iomem_cb(void *data, int nr, char *str, +- unsigned long long base, unsigned long long length) ++int get_memory_ranges(struct memory_range **range, int *ranges, ++ unsigned long kexec_flags) + { +- int ret; + unsigned long phys_offset = UINT64_MAX; +- struct memory_range *r; +- +- if (nr >= KEXEC_SEGMENT_MAX) +- return -1; ++ FILE *fp; ++ const char *iomem = proc_iomem(); ++ char line[MAX_LINE], *str; ++ unsigned long long start, end; ++ int n, consumed; ++ struct memory_ranges memranges; ++ struct memory_range *last, excl_range; ++ int ret; + + if (!try_read_phys_offset_from_kcore) { + /* Since kernel version 4.19, 'kcore' contains +@@ -951,17 +968,72 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str, + try_read_phys_offset_from_kcore = true; + } + +- r = (struct memory_range *)data + nr; ++ fp = fopen(iomem, "r"); ++ if (!fp) ++ die("Cannot open %s\n", iomem); ++ ++ memranges.ranges = NULL; ++ memranges.size = memranges.max_size = 0; ++ ++ while (fgets(line, sizeof(line), fp) != 0) { ++ n = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed); ++ if (n != 2) ++ continue; ++ str = line + consumed; ++ ++ if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM))) { ++ ret = mem_regions_alloc_and_add(&memranges, ++ start, end - start + 1, RANGE_RAM); ++ if (ret) { ++ fprintf(stderr, ++ "Cannot allocate memory for ranges\n"); ++ fclose(fp); ++ return -ENOMEM; ++ } + +- if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM))) +- r->type = RANGE_RAM; +- else if (!strncmp(str, IOMEM_RESERVED, strlen(IOMEM_RESERVED))) +- r->type = RANGE_RESERVED; +- else +- return 1; ++ dbgprintf("%s:+[%d] %016llx - %016llx\n", __func__, ++ memranges.size - 1, ++ memranges.ranges[memranges.size - 1].start, ++ memranges.ranges[memranges.size - 1].end); ++ } else if (to_be_excluded(str)) { ++ if (!memranges.size) ++ continue; ++ ++ /* ++ * Note: mem_regions_exclude() doesn't guarantee ++ * that the ranges are sorted out, but as long as ++ * we cope with /proc/iomem, we only operate on ++ * the last entry and so it is safe. ++ */ + +- r->start = base; +- r->end = base + length - 1; ++ /* The last System RAM range */ ++ last = &memranges.ranges[memranges.size - 1]; ++ ++ if (last->end < start) ++ /* New resource outside of System RAM */ ++ continue; ++ if (end < last->start) ++ /* Already excluded by parent resource */ ++ continue; ++ ++ excl_range.start = start; ++ excl_range.end = end; ++ ret = mem_regions_alloc_and_exclude(&memranges, &excl_range); ++ if (ret) { ++ fprintf(stderr, ++ "Cannot allocate memory for ranges (exclude)\n"); ++ fclose(fp); ++ return -ENOMEM; ++ } ++ dbgprintf("%s:- %016llx - %016llx\n", ++ __func__, start, end); ++ } ++ } ++ ++ fclose(fp); ++ ++ *range = memranges.ranges; ++ *ranges = memranges.size; + + /* As a fallback option, we can try determining the PHYS_OFFSET + * value from the '/proc/iomem' entries as well. +@@ -982,52 +1054,15 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str, + * between the user-space and kernel space 'PHYS_OFFSET' + * value. + */ +- set_phys_offset(r->start, "iomem"); +- +- dbgprintf("%s: %016llx - %016llx : %s", __func__, r->start, +- r->end, str); +- +- return 0; +-} +- +-/** +- * get_memory_ranges_iomem - Try to get the memory ranges from +- * /proc/iomem. +- */ ++ if (memranges.size) ++ set_phys_offset(memranges.ranges[0].start, "iomem"); + +-static int get_memory_ranges_iomem(struct memory_range *array, +- unsigned int *count) +-{ +- *count = kexec_iomem_for_each_line(NULL, +- get_memory_ranges_iomem_cb, array); +- +- if (!*count) { +- dbgprintf("%s: failed: No RAM found.\n", __func__); +- return EFAILED; +- } ++ dbgprint_mem_range("System RAM ranges;", ++ memranges.ranges, memranges.size); + + return 0; + } + +-/** +- * get_memory_ranges - Try to get the memory ranges some how. +- */ +- +-int get_memory_ranges(struct memory_range **range, int *ranges, +- unsigned long kexec_flags) +-{ +- static struct memory_range array[KEXEC_SEGMENT_MAX]; +- unsigned int count; +- int result; +- +- result = get_memory_ranges_iomem(array, &count); +- +- *range = result ? NULL : array; +- *ranges = result ? 0 : count; +- +- return result; +-} +- + int arch_compat_trampoline(struct kexec_info *info) + { + return 0; +-- +2.7.4 + diff --git a/SOURCES/kexec-tools-2.0.20-kexec-add-variant-helper-functions-for-handling-memo.patch b/SOURCES/kexec-tools-2.0.20-kexec-add-variant-helper-functions-for-handling-memo.patch new file mode 100644 index 0000000..cc07c00 --- /dev/null +++ b/SOURCES/kexec-tools-2.0.20-kexec-add-variant-helper-functions-for-handling-memo.patch @@ -0,0 +1,89 @@ +From cf977b1af9ec67fabcc6a625589c49c52d07b11d Mon Sep 17 00:00:00 2001 +From: AKASHI Takahiro +Date: Wed, 18 Dec 2019 11:42:30 -0500 +Subject: [PATCH 1/3] kexec: add variant helper functions for handling memory + regions + +mem_regions_alloc_and_add() and mem_regions_alloc_and_exclude() are +functionally equivalent to, respectively, mem_regions_add() and +mem_regions_exclude() except the formers will re-allocate memory +dynamically when no more entries are available in 'ranges' array. + +Signed-off-by: AKASHI Takahiro +Tested-by: Bhupesh Sharma +Tested-by: Masayoshi Mizuma +Signed-off-by: Simon Horman +--- + kexec/mem_regions.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + kexec/mem_regions.h | 7 +++++++ + 2 files changed, 49 insertions(+) + +diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c +index 50c8abccb93a..ad7d3f13fd84 100644 +--- a/kexec/mem_regions.c ++++ b/kexec/mem_regions.c +@@ -125,3 +125,45 @@ int mem_regions_exclude(struct memory_ranges *ranges, + } + return 0; + } ++ ++#define KEXEC_MEMORY_RANGES 16 ++ ++int mem_regions_alloc_and_add(struct memory_ranges *ranges, ++ unsigned long long base, ++ unsigned long long length, int type) ++{ ++ void *new_ranges; ++ ++ if (ranges->size >= ranges->max_size) { ++ new_ranges = realloc(ranges->ranges, ++ sizeof(struct memory_range) * ++ (ranges->max_size + KEXEC_MEMORY_RANGES)); ++ if (!new_ranges) ++ return -1; ++ ++ ranges->ranges = new_ranges; ++ ranges->max_size += KEXEC_MEMORY_RANGES; ++ } ++ ++ return mem_regions_add(ranges, base, length, type); ++} ++ ++int mem_regions_alloc_and_exclude(struct memory_ranges *ranges, ++ const struct memory_range *range) ++{ ++ void *new_ranges; ++ ++ /* for safety, we should have at least one free entry in ranges */ ++ if (ranges->size >= ranges->max_size) { ++ new_ranges = realloc(ranges->ranges, ++ sizeof(struct memory_range) * ++ (ranges->max_size + KEXEC_MEMORY_RANGES)); ++ if (!new_ranges) ++ return -1; ++ ++ ranges->ranges = new_ranges; ++ ranges->max_size += KEXEC_MEMORY_RANGES; ++ } ++ ++ return mem_regions_exclude(ranges, range); ++} +diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h +index ae9e972b0206..e306d67e3261 100644 +--- a/kexec/mem_regions.h ++++ b/kexec/mem_regions.h +@@ -12,4 +12,11 @@ int mem_regions_exclude(struct memory_ranges *ranges, + int mem_regions_add(struct memory_ranges *ranges, unsigned long long base, + unsigned long long length, int type); + ++int mem_regions_alloc_and_exclude(struct memory_ranges *ranges, ++ const struct memory_range *range); ++ ++int mem_regions_alloc_and_add(struct memory_ranges *ranges, ++ unsigned long long base, ++ unsigned long long length, int type); ++ + #endif +-- +2.7.4 + diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Generalize-get_kaslr_offset_arm64-for-other-ar.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Generalize-get_kaslr_offset_arm64-for-other-ar.patch new file mode 100644 index 0000000..3fc9d83 --- /dev/null +++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Generalize-get_kaslr_offset_arm64-for-other-ar.patch @@ -0,0 +1,219 @@ +From c6992684b51ba9604d50016f36c9139bf54ae03b Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Tue, 17 Dec 2019 11:12:50 -0500 +Subject: [PATCH 1/3] [PATCH] Generalize get_kaslr_offset_arm64() for other + architectures + +Generalize the get_kaslr_offset_arm64() and rename it to +get_kaslr_offset_general() for use by other architectures +supporting KASLR. + +Also, modify the confusing comment in the function and its +x86_64 version. + +Signed-off-by: Kazuhito Hagio +--- + arch/arm64.c | 61 -------------------------------------------------- + arch/x86_64.c | 8 +++---- + makedumpfile.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ + makedumpfile.h | 4 ++-- + 4 files changed, 66 insertions(+), 67 deletions(-) + +diff --git a/makedumpfile-1.6.6/arch/arm64.c b/makedumpfile-1.6.6/arch/arm64.c +index 3516b340adfd..43164ccc32d4 100644 +--- a/makedumpfile-1.6.6/arch/arm64.c ++++ b/makedumpfile-1.6.6/arch/arm64.c +@@ -205,67 +205,6 @@ get_phys_base_arm64(void) + return FALSE; + } + +-unsigned long +-get_kaslr_offset_arm64(unsigned long vaddr) +-{ +- unsigned int i; +- char buf[BUFSIZE_FGETS], *endp; +- static unsigned long _text = NOT_FOUND_SYMBOL; +- static unsigned long _end = NOT_FOUND_SYMBOL; +- +- if (!info->kaslr_offset && info->file_vmcoreinfo) { +- if (fseek(info->file_vmcoreinfo, 0, SEEK_SET) < 0) { +- ERRMSG("Can't seek the vmcoreinfo file(%s). %s\n", +- info->name_vmcoreinfo, strerror(errno)); +- return FALSE; +- } +- +- while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) { +- i = strlen(buf); +- if (!i) +- break; +- if (buf[i - 1] == '\n') +- buf[i - 1] = '\0'; +- if (strncmp(buf, STR_KERNELOFFSET, +- strlen(STR_KERNELOFFSET)) == 0) { +- info->kaslr_offset = +- strtoul(buf+strlen(STR_KERNELOFFSET),&endp,16); +- DEBUG_MSG("info->kaslr_offset: %lx\n", info->kaslr_offset); +- } +- } +- } +- if (!info->kaslr_offset) +- return 0; +- +- if (_text == NOT_FOUND_SYMBOL) { +- /* +- * Currently, the return value of this function is used in +- * resolve_config_entry() only, and in that case, we must +- * have a vmlinux. +- */ +- if (info->name_vmlinux) { +- _text = get_symbol_addr("_text"); +- _end = get_symbol_addr("_end"); +- } +- DEBUG_MSG("_text: %lx, _end: %lx\n", _text, _end); +- if (_text == NOT_FOUND_SYMBOL || _end == NOT_FOUND_SYMBOL) { +- ERRMSG("Cannot determine _text and _end address\n"); +- return FALSE; +- } +- } +- +- if (_text <= vaddr && vaddr <= _end) { +- DEBUG_MSG("info->kaslr_offset: %lx\n", info->kaslr_offset); +- return info->kaslr_offset; +- } else { +- /* +- * TODO: we need to check if it is vmalloc/vmmemmap/module +- * address, we will have different offset +- */ +- return 0; +- } +-} +- + ulong + get_stext_symbol(void) + { +diff --git a/makedumpfile-1.6.6/arch/x86_64.c b/makedumpfile-1.6.6/arch/x86_64.c +index 876644f932be..7a2c05c36809 100644 +--- a/makedumpfile-1.6.6/arch/x86_64.c ++++ b/makedumpfile-1.6.6/arch/x86_64.c +@@ -77,14 +77,14 @@ get_kaslr_offset_x86_64(unsigned long vaddr) + else + kernel_image_size = KERNEL_IMAGE_SIZE_KASLR_ORIG; + ++ /* ++ * Returns the kaslr offset only if the vaddr needs it to be added, ++ * i.e. only kernel text address for now. Otherwise returns 0. ++ */ + if (vaddr >= __START_KERNEL_map && + vaddr < __START_KERNEL_map + kernel_image_size) + return info->kaslr_offset; + else +- /* +- * TODO: we need to check if it is vmalloc/vmmemmap/module +- * address, we will have different offset +- */ + return 0; + } + +diff --git a/makedumpfile-1.6.6/makedumpfile.c b/makedumpfile-1.6.6/makedumpfile.c +index 7586d7c001d4..332b804cd756 100644 +--- a/makedumpfile-1.6.6/makedumpfile.c ++++ b/makedumpfile-1.6.6/makedumpfile.c +@@ -3945,6 +3945,66 @@ free_for_parallel() + } + } + ++unsigned long ++get_kaslr_offset_general(unsigned long vaddr) ++{ ++ unsigned int i; ++ char buf[BUFSIZE_FGETS], *endp; ++ static unsigned long _text = NOT_FOUND_SYMBOL; ++ static unsigned long _end = NOT_FOUND_SYMBOL; ++ ++ if (!info->kaslr_offset && info->file_vmcoreinfo) { ++ if (fseek(info->file_vmcoreinfo, 0, SEEK_SET) < 0) { ++ ERRMSG("Can't seek the vmcoreinfo file(%s). %s\n", ++ info->name_vmcoreinfo, strerror(errno)); ++ return FALSE; ++ } ++ ++ while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) { ++ i = strlen(buf); ++ if (!i) ++ break; ++ if (buf[i - 1] == '\n') ++ buf[i - 1] = '\0'; ++ if (strncmp(buf, STR_KERNELOFFSET, ++ strlen(STR_KERNELOFFSET)) == 0) { ++ info->kaslr_offset = strtoul(buf + ++ strlen(STR_KERNELOFFSET), &endp, 16); ++ DEBUG_MSG("info->kaslr_offset: %lx\n", ++ info->kaslr_offset); ++ } ++ } ++ } ++ if (!info->kaslr_offset) ++ return 0; ++ ++ if (_text == NOT_FOUND_SYMBOL) { ++ /* ++ * Currently, the return value of this function is used in ++ * resolve_config_entry() only, and in that case, we must ++ * have a vmlinux. ++ */ ++ if (info->name_vmlinux) { ++ _text = get_symbol_addr("_text"); ++ _end = get_symbol_addr("_end"); ++ } ++ DEBUG_MSG("_text: %lx, _end: %lx\n", _text, _end); ++ if (_text == NOT_FOUND_SYMBOL || _end == NOT_FOUND_SYMBOL) { ++ ERRMSG("Cannot determine _text and _end address\n"); ++ return FALSE; ++ } ++ } ++ ++ /* ++ * Returns the kaslr offset only if the vaddr needs it to be added, ++ * i.e. only kernel text address for now. Otherwise returns 0. ++ */ ++ if (_text <= vaddr && vaddr <= _end) ++ return info->kaslr_offset; ++ else ++ return 0; ++} ++ + int + find_kaslr_offsets() + { +diff --git a/makedumpfile-1.6.6/makedumpfile.h b/makedumpfile-1.6.6/makedumpfile.h +index ac11e906b5b7..067fa483aa01 100644 +--- a/makedumpfile-1.6.6/makedumpfile.h ++++ b/makedumpfile-1.6.6/makedumpfile.h +@@ -964,6 +964,7 @@ typedef unsigned long pgd_t; + static inline int stub_true() { return TRUE; } + static inline int stub_true_ul(unsigned long x) { return TRUE; } + static inline int stub_false() { return FALSE; } ++unsigned long get_kaslr_offset_general(unsigned long vaddr); + #define paddr_to_vaddr_general(X) ((X) + PAGE_OFFSET) + + #ifdef __aarch64__ +@@ -973,7 +974,6 @@ unsigned long long vaddr_to_paddr_arm64(unsigned long vaddr); + int get_versiondep_info_arm64(void); + int get_xen_basic_info_arm64(void); + int get_xen_info_arm64(void); +-unsigned long get_kaslr_offset_arm64(unsigned long vaddr); + #define paddr_to_vaddr_arm64(X) (((X) - info->phys_base) | PAGE_OFFSET) + + #define find_vmemmap() stub_false() +@@ -982,7 +982,7 @@ unsigned long get_kaslr_offset_arm64(unsigned long vaddr); + #define get_phys_base() get_phys_base_arm64() + #define get_machdep_info() get_machdep_info_arm64() + #define get_versiondep_info() get_versiondep_info_arm64() +-#define get_kaslr_offset(X) get_kaslr_offset_arm64(X) ++#define get_kaslr_offset(X) get_kaslr_offset_general(X) + #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) +-- +2.17.1 + diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Pass-0-to-get_kaslr_offset-in-find_kaslr_offse.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Pass-0-to-get_kaslr_offset-in-find_kaslr_offse.patch new file mode 100644 index 0000000..3db1f56 --- /dev/null +++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Pass-0-to-get_kaslr_offset-in-find_kaslr_offse.patch @@ -0,0 +1,65 @@ +From 60cf280ebfe8b6468bfd1dd592a117e719c56ccf Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Fri, 3 Jan 2020 11:27:41 -0500 +Subject: [PATCH 2/3] [PATCH] Pass 0 to get_kaslr_offset() in + find_kaslr_offsets() + +Currently SYMBOL(_stext) is passed to get_kaslr_offset() in +find_kaslr_offsets(), but it is always zero, because it has not +been set yet at the time. + +On the other hand, the vaddr argument of get_kaslr_offset() is +only used to decide whether to return a KASLR offset or not, but +the return value is not used in find_kaslr_offsets(). + +Therefore, passing SYMBOL(_stext) is meaningless and confusing, +so let's pass it 0 explicitly to avoid confusion. + +Reported-by: Lianbo Jiang +Signed-off-by: Kazuhito Hagio +--- + arch/x86_64.c | 2 +- + makedumpfile.c | 6 ++++-- + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/makedumpfile-1.6.6/arch/x86_64.c b/makedumpfile-1.6.6/arch/x86_64.c +index 7a2c05c36809..b5e295452964 100644 +--- a/makedumpfile-1.6.6/arch/x86_64.c ++++ b/makedumpfile-1.6.6/arch/x86_64.c +@@ -69,7 +69,7 @@ get_kaslr_offset_x86_64(unsigned long vaddr) + strtoul(buf+strlen(STR_KERNELOFFSET),&endp,16); + } + } +- if (!info->kaslr_offset) ++ if (!info->kaslr_offset || !vaddr) + return 0; + + if (NUMBER(KERNEL_IMAGE_SIZE) != NOT_FOUND_NUMBER) +diff --git a/makedumpfile-1.6.6/makedumpfile.c b/makedumpfile-1.6.6/makedumpfile.c +index 332b804cd756..e290fbdb4f9f 100644 +--- a/makedumpfile-1.6.6/makedumpfile.c ++++ b/makedumpfile-1.6.6/makedumpfile.c +@@ -3975,7 +3975,7 @@ get_kaslr_offset_general(unsigned long vaddr) + } + } + } +- if (!info->kaslr_offset) ++ if (!info->kaslr_offset || !vaddr) + return 0; + + if (_text == NOT_FOUND_SYMBOL) { +@@ -4032,8 +4032,10 @@ find_kaslr_offsets() + * function might need to read from vmcoreinfo, therefore we have + * called this function between open_vmcoreinfo() and + * close_vmcoreinfo() ++ * And the argument is not needed, because we don't use the return ++ * value here. So pass it 0 explicitly. + */ +- get_kaslr_offset(SYMBOL(_stext)); ++ get_kaslr_offset(0); + + close_vmcoreinfo(); + +-- +2.17.1 + diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-arm64-fix-get_kaslr_offset_arm64-to-return-kas.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-arm64-fix-get_kaslr_offset_arm64-to-return-kas.patch new file mode 100644 index 0000000..368996e --- /dev/null +++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-arm64-fix-get_kaslr_offset_arm64-to-return-kas.patch @@ -0,0 +1,85 @@ +From 76f9cc0f3de2f4727a1f838ce9f10d848b92e1a4 Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Tue, 4 Jun 2019 15:00:15 -0400 +Subject: [PATCH] [PATCH] arm64: fix get_kaslr_offset_arm64() to return + kaslr_offset correctly + +Currently, the get_kaslr_offset_arm64() function has the following +condition to return info->kaslr_offset, but kernel text mapping is +placed in another range on arm64 by default, so it returns 0 for +kernel text addresses. + + if (vaddr >= __START_KERNEL_map && + vaddr < __START_KERNEL_map + info->kaslr_offset) + +Consequently, kernel text symbols in erase config are resolved wrongly +with KASLR enabled vmcore, and makedumpfile erases unintended data. + +Since the return value of get_kaslr_offset_arm64() is used in +resolve_config_entry() only, and in that case, we must have a vmlinux, +so get the addresses of _text and _end from vmlinux and use them. + +Signed-off-by: Kazuhito Hagio +--- + arch/arm64.c | 24 ++++++++++++++++++++++-- + makedumpfile.h | 1 - + 2 files changed, 22 insertions(+), 3 deletions(-) + +diff --git a/makedumpfile-1.6.6/arch/arm64.c b/makedumpfile-1.6.6/arch/arm64.c +index 053519359cbc..3516b340adfd 100644 +--- a/makedumpfile-1.6.6/arch/arm64.c ++++ b/makedumpfile-1.6.6/arch/arm64.c +@@ -210,6 +210,8 @@ get_kaslr_offset_arm64(unsigned long vaddr) + { + unsigned int i; + char buf[BUFSIZE_FGETS], *endp; ++ static unsigned long _text = NOT_FOUND_SYMBOL; ++ static unsigned long _end = NOT_FOUND_SYMBOL; + + if (!info->kaslr_offset && info->file_vmcoreinfo) { + if (fseek(info->file_vmcoreinfo, 0, SEEK_SET) < 0) { +@@ -232,9 +234,27 @@ get_kaslr_offset_arm64(unsigned long vaddr) + } + } + } ++ if (!info->kaslr_offset) ++ return 0; ++ ++ if (_text == NOT_FOUND_SYMBOL) { ++ /* ++ * Currently, the return value of this function is used in ++ * resolve_config_entry() only, and in that case, we must ++ * have a vmlinux. ++ */ ++ if (info->name_vmlinux) { ++ _text = get_symbol_addr("_text"); ++ _end = get_symbol_addr("_end"); ++ } ++ DEBUG_MSG("_text: %lx, _end: %lx\n", _text, _end); ++ if (_text == NOT_FOUND_SYMBOL || _end == NOT_FOUND_SYMBOL) { ++ ERRMSG("Cannot determine _text and _end address\n"); ++ return FALSE; ++ } ++ } + +- if (vaddr >= __START_KERNEL_map && +- vaddr < __START_KERNEL_map + info->kaslr_offset) { ++ if (_text <= vaddr && vaddr <= _end) { + DEBUG_MSG("info->kaslr_offset: %lx\n", info->kaslr_offset); + return info->kaslr_offset; + } else { +diff --git a/makedumpfile-1.6.6/makedumpfile.h b/makedumpfile-1.6.6/makedumpfile.h +index df745b9f53e5..ac11e906b5b7 100644 +--- a/makedumpfile-1.6.6/makedumpfile.h ++++ b/makedumpfile-1.6.6/makedumpfile.h +@@ -542,7 +542,6 @@ do { \ + #ifdef __aarch64__ + unsigned long get_kvbase_arm64(void); + #define KVBASE get_kvbase_arm64() +-#define __START_KERNEL_map (0xffffffff80000000UL) + + #endif /* aarch64 */ + +-- +2.17.1 + diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-s390-Use-get_kaslr_offset_general-for-s390x.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-s390-Use-get_kaslr_offset_general-for-s390x.patch new file mode 100644 index 0000000..6958ee9 --- /dev/null +++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-s390-Use-get_kaslr_offset_general-for-s390x.patch @@ -0,0 +1,30 @@ +From 577854dd62a6b22aa2c0dce59f0541ac1c0c7ab5 Mon Sep 17 00:00:00 2001 +From: Mikhail Zaslonko +Date: Tue, 7 Jan 2020 13:38:14 +0100 +Subject: [PATCH 3/3] [PATCH] s390: Use get_kaslr_offset_general() for s390x + +Since kernel v5.2 KASLR is supported on s390. Use recently introduced +get_kaslr_offset_general() for s390x in order to derive kaslr offset +from vmcoreinfo when -x makedumpfile option specified. + +Signed-off-by: Mikhail Zaslonko +--- + makedumpfile.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/makedumpfile-1.6.6/makedumpfile.h b/makedumpfile-1.6.6/makedumpfile.h +index 067fa483aa01..e6c815da6775 100644 +--- a/makedumpfile-1.6.6/makedumpfile.h ++++ b/makedumpfile-1.6.6/makedumpfile.h +@@ -1075,7 +1075,7 @@ int is_iomem_phys_addr_s390x(unsigned long addr); + #define get_phys_base() stub_true() + #define get_machdep_info() get_machdep_info_s390x() + #define get_versiondep_info() stub_true() +-#define get_kaslr_offset(X) stub_false() ++#define get_kaslr_offset(X) get_kaslr_offset_general(X) + #define vaddr_to_paddr(X) vaddr_to_paddr_s390x(X) + #define paddr_to_vaddr(X) paddr_to_vaddr_general(X) + #define is_phys_addr(X) is_iomem_phys_addr_s390x(X) +-- +2.17.1 + diff --git a/SOURCES/supported-kdump-targets.txt b/SOURCES/supported-kdump-targets.txt index 64b7f59..f540f59 100644 --- a/SOURCES/supported-kdump-targets.txt +++ b/SOURCES/supported-kdump-targets.txt @@ -42,6 +42,9 @@ storage: hardware RAID (cciss, hpsa, megaraid_sas, mpt2sas, aacraid) SCSI/SATA disks iSCSI HBA (all offload) + hardware FCoE (qla2xxx, lpfc) + software FCoE (bnx2fc) (Extra configuration required, + please read "Note on FCoE" section below) network: Hardware using kernel modules: (tg3, igb, ixgbe, sfc, e1000e, bna, @@ -104,6 +107,21 @@ hypervisor: Hyper-V 2012 +Note on FCoE +===================== +If you are trying to dump to a software FCoE target, you may encounter OOM +issue, because some software FCoE requires more memory to work. In such case, +you may need to increase the kdump reserved memory size in "crashkernel=" +kernel parameter. + +By default, RHEL systems have "crashkernel=auto" in kernel boot arguments. +The auto reserved memory size is designed to balance the coverage of use cases +and an acceptable memory overhead, so not every use case could fit in, software +FCoE is one of the case. + +For hardware FCoE, kdump should work naturally as firmware will do the +initialization job. The capture kernel and kdump tools will run just fine. + Useful Links ============ [1] RHEL6: Enabling kdump for full-virt (HVM) Xen DomU diff --git a/SPECS/kexec-tools.spec b/SPECS/kexec-tools.spec index 1df65a1..cfeae25 100644 --- a/SPECS/kexec-tools.spec +++ b/SPECS/kexec-tools.spec @@ -1,6 +1,6 @@ Name: kexec-tools Version: 2.0.20 -Release: 9%{?dist} +Release: 14%{?dist} License: GPLv2 Group: Applications/System Summary: The kexec/kdump userspace component @@ -104,6 +104,13 @@ Patch610: kexec-tools-2.0.20-makedumpfile-Increase-SECTION_MAP_LAST_BIT-to-4.pat Patch611: kexec-tools-2.0.20-makedumpfile-Fix-off-by-one-issue-in-exclude_nodata_pages.patch Patch612: rhelonly-kexec-tools-2.0.20-makedumpfile-remove-lebl.patch Patch613: kexec-tools-2.0.20-makedumpfile-assign-bitmap1-2-fd-for-subprocess-in-non-cycl.patch +Patch614: kexec-tools-2.0.20-kexec-add-variant-helper-functions-for-handling-memo.patch +Patch615: kexec-tools-2.0.20-arm64-kexec-allocate-memory-space-avoiding-reserved-.patch +Patch616: kexec-tools-2.0.20-arm64-kdump-deal-with-a-lot-of-resource-entries-in-p.patch +Patch617: kexec-tools-2.0.20-makedumpfile-arm64-fix-get_kaslr_offset_arm64-to-return-kas.patch +Patch618: kexec-tools-2.0.20-makedumpfile-Generalize-get_kaslr_offset_arm64-for-other-ar.patch +Patch619: kexec-tools-2.0.20-makedumpfile-Pass-0-to-get_kaslr_offset-in-find_kaslr_offse.patch +Patch620: kexec-tools-2.0.20-makedumpfile-s390-Use-get_kaslr_offset_general-for-s390x.patch %description kexec-tools provides /usr/sbin/kexec binary that facilitates a new @@ -132,6 +139,13 @@ tar -z -x -v -f %{SOURCE19} %patch611 -p1 %patch612 -p1 %patch613 -p1 +%patch614 -p1 +%patch615 -p1 +%patch616 -p1 +%patch617 -p1 +%patch618 -p1 +%patch619 -p1 +%patch620 -p1 %ifarch ppc %define archdef ARCH=ppc @@ -357,6 +371,23 @@ done %endif %changelog +* Tue Feb 18 2020 Pingfan Liu - 2.0.20-14 +- kexec-tools/module-setup: Ensure eth devices get IP address for VLAN + +* Wed Feb 12 2020 Pingfan Liu - 2.0.20-13 +- Add document to declare FCoE support + +* Wed Feb 12 2020 Pingfan Liu - 2.0.20-12 +- powerpc: enable the scripts to capture dump on POWERNV platform + +* Tue Feb 4 2020 Pingfan Liu - 2.0.20-11 +- s390: Use get_kaslr_offset_general() for s390x + +* Fri Jan 10 2020 Pingfan Liu - 2.0.20-10 +- arm64: kdump: deal with a lot of resource entries in /proc/iomem +- arm64: kexec: allocate memory space avoiding reserved regions +- kexec: add variant helper functions for handling memory regions + * Thu Dec 12 2019 Pingfan Liu - 2.0.20-9 - makedumpfile: assign bitmap1/2 fd for subprocess in non-cyclic mode