From 0dda2041cd02e633fd8752c99454756992e8f9e7 Mon Sep 17 00:00:00 2001 From: zhangruifang2020 Date: Thu, 10 Sep 2020 11:48:21 +0800 Subject: [PATCH] Thu Sep 10 2020 zhangruifang2020 - 2.0.20-3 Type:bugfix ID:NA SUG:NA DESC:fix issue about iomem file that contains too many contens.As a result,the kdump service failed. --- ...mory-space-avoiding-reserved-regions.patch | 244 ++++++++++++++++++ ...unctions-for-handling-memory-regions.patch | 86 ++++++ kexec-tools.spec | 53 ++-- 3 files changed, 364 insertions(+), 19 deletions(-) create mode 100644 arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch create mode 100644 kexec-add-variant-helper-functions-for-handling-memory-regions.patch diff --git a/arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch b/arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch new file mode 100644 index 0000000..de5fd45 --- /dev/null +++ b/arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch @@ -0,0 +1,244 @@ +From f736104f533290b4ce6fbfbca74abde9ffd3888c Mon Sep 17 00:00:00 2001 +From: AKASHI Takahiro +Date: Wed, 18 Dec 2019 11:42:31 -0500 +Subject: [PATCH] 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 6ad3b0a..45ebc54 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; diff --git a/kexec-add-variant-helper-functions-for-handling-memory-regions.patch b/kexec-add-variant-helper-functions-for-handling-memory-regions.patch new file mode 100644 index 0000000..74a9e8e --- /dev/null +++ b/kexec-add-variant-helper-functions-for-handling-memory-regions.patch @@ -0,0 +1,86 @@ +From cf977b1af9ec67fabcc6a625589c49c52d07b11d Mon Sep 17 00:00:00 2001 +From: AKASHI Takahiro +Date: Wed, 18 Dec 2019 11:42:30 -0500 +Subject: [PATCH] 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 50c8abc..ad7d3f1 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 ae9e972..e306d67 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 diff --git a/kexec-tools.spec b/kexec-tools.spec index 6148777..752e632 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -4,7 +4,7 @@ Name: kexec-tools Version: 2.0.20 -Release: 2 +Release: 3 License: GPLv2 Summary: The kexec/kdump userspace component URL: https://www.kernel.org/ @@ -69,24 +69,27 @@ Requires: systemd-udev%{?_isa} %undefine _hardened_build -Patch6000: kexec-tools-2.0.20-fix-broken-multiboot2-buliding-for-i386.patch +Patch0: kexec-tools-2.0.20-fix-broken-multiboot2-buliding-for-i386.patch -Patch6001: kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch -Patch6002: kexec-tools-2.0.20-makedumpfile-Remove-duplicated-variable-declarations.patch -Patch6003: kexec-tools-2.0.20-Remove-duplicated-variable-declarations.patch -Patch6004: kexec-tools-2.0.20-makedumpfile-Introduce-check-params-option.patch +Patch1: kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch +Patch2: kexec-tools-2.0.20-makedumpfile-Remove-duplicated-variable-declarations.patch +Patch3: kexec-tools-2.0.20-Remove-duplicated-variable-declarations.patch +Patch4: kexec-tools-2.0.20-makedumpfile-Introduce-check-params-option.patch + +Patch5: kexec-add-variant-helper-functions-for-handling-memory-regions.patch +Patch6: arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch %ifarch aarch64 -Patch9000: arm64-support-more-than-one-crash-kernel-regions.patch +Patch7: arm64-support-more-than-one-crash-kernel-regions.patch %endif -Patch9001: add-secure-compile-options-for-makedumpfile.patch +Patch8: add-secure-compile-options-for-makedumpfile.patch -Patch9002: bugfix-get-the-paddr-of-mem_section-return-error-address.patch -Patch9003: fix-header-offset-overflow-when-large-pfn.patch -Patch9004: kexec-Add-quick-kexec-support.patch +Patch9: bugfix-get-the-paddr-of-mem_section-return-error-address.patch +Patch10: fix-header-offset-overflow-when-large-pfn.patch +Patch11: kexec-Add-quick-kexec-support.patch %ifarch aarch64 -Patch9005: kexec-Quick-kexec-implementation-for-arm64.patch +Patch12: kexec-Quick-kexec-implementation-for-arm64.patch %endif %description @@ -110,18 +113,24 @@ mkdir -p -m755 kcp tar -z -x -v -f %{SOURCE9} tar -z -x -v -f %{SOURCE19} -%{lua:for i=0,4 do print(string.format("%%patch600%u -p1\n", i)) end} +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 %ifarch aarch64 -%patch9000 -p1 +%patch7 -p1 %endif -%patch9001 -p1 -%patch9002 -p1 -%patch9003 -p1 -%patch9004 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 %ifarch aarch64 -%patch9005 -p1 +%patch12 -p1 %endif @@ -309,6 +318,12 @@ done %endif %changelog +* Thu Sep 10 2020 zhangruifang2020 - 2.0.20-3 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix issue about iomem file that contains too many contens.As a result,the kdump service failed. + * Thu Aug 13 2020 snoweay - 2.0.20-2 - Add support for quick kexec kexec: Add quick kexec support -- Gitee