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/SPECS/kexec-tools.spec b/SPECS/kexec-tools.spec index 2ddeee1..313a730 100644 --- a/SPECS/kexec-tools.spec +++ b/SPECS/kexec-tools.spec @@ -1,6 +1,6 @@ Name: kexec-tools Version: 2.0.19 -Release: 12%{?dist}.1 +Release: 12%{?dist}.2 License: GPLv2 Group: Applications/System Summary: The kexec/kdump userspace component @@ -99,6 +99,9 @@ Patch603: kexec-tools-2.0.18-makedumpfiles-honor-the-CFLAGS-from-environment.pat Patch604: kexec-tools-2.0.18-eppic-fix-issues-with-hardening-flags.patch Patch605: kexec-tools-2.0.18-makedumpfiles-exclude-pages-that-are-logically-offline.patch Patch606: rhonly-kexec-tools-2.0.18-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch +Patch607: kexec-tools-2.0.20-kexec-add-variant-helper-functions-for-handling-memo.patch +Patch608: kexec-tools-2.0.20-arm64-kexec-allocate-memory-space-avoiding-reserved-.patch +Patch609: kexec-tools-2.0.20-arm64-kdump-deal-with-a-lot-of-resource-entries-in-p.patch %description kexec-tools provides /sbin/kexec binary that facilitates a new @@ -125,6 +128,9 @@ tar -z -x -v -f %{SOURCE19} %patch605 -p1 %patch606 -p1 %patch102 -p1 +%patch607 -p1 +%patch608 -p1 +%patch609 -p1 %ifarch ppc %define archdef ARCH=ppc @@ -151,7 +157,7 @@ cp %{SOURCE27} . cp %{SOURCE28} . make -%ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 %{arm} +%ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 make -C eppic/libeppic make -C makedumpfile-1.6.5 LINKTYPE=dynamic USELZO=on USESNAPPY=on make -C makedumpfile-1.6.5 LDFLAGS="$LDFLAGS -I../eppic/libeppic -L../eppic/libeppic" eppic_makedumpfile.so @@ -204,7 +210,7 @@ install -m 644 %{SOURCE15} $RPM_BUILD_ROOT%{_mandir}/man5/kdump.conf.5 install -m 644 %{SOURCE16} $RPM_BUILD_ROOT%{_unitdir}/kdump.service install -m 755 -D %{SOURCE22} $RPM_BUILD_ROOT%{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh -%ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 %{arm} +%ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 install -m 755 makedumpfile-1.6.5/makedumpfile $RPM_BUILD_ROOT/sbin/makedumpfile install -m 644 makedumpfile-1.6.5/makedumpfile.8.gz $RPM_BUILD_ROOT/%{_mandir}/man8/makedumpfile.8.gz install -m 644 makedumpfile-1.6.5/makedumpfile.conf.5.gz $RPM_BUILD_ROOT/%{_mandir}/man5/makedumpfile.conf.5.gz @@ -317,7 +323,7 @@ done %{_bindir}/* %{_datadir}/kdump %{_prefix}/lib/kdump -%ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 %{arm} +%ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 %{_sysconfdir}/makedumpfile.conf.sample %endif %config(noreplace,missingok) %{_sysconfdir}/sysconfig/kdump @@ -344,12 +350,17 @@ done %doc supported-kdump-targets.txt %doc kdump-in-cluster-environment.txt %doc live-image-kdump-howto.txt -%ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 %{arm} +%ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64 %{_libdir}/eppic_makedumpfile.so /usr/share/makedumpfile/ %endif %changelog +* Fri Jan 10 2020 Pingfan Liu - 2.0.19-12.2 +- 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 Nov 14 2019 Pingfan Liu - 2.0.19-12.1 - Don't execute final_action if failure_action terminates the system - dracut-module-setup.sh: Don't use squash module for fadump