From ecb8836282be194b339519e302a2123fcdd00b6c904bdc4235fe2c20d76e9151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Tesa=C5=99=C3=ADk?= Date: Wed, 18 Dec 2019 13:18:08 +0000 Subject: [PATCH] Accepting request 757390 from home:clin:branches:Kernel:kdump Update version to 2.0.20 and apply arm64-related patches in order to prevent kexec from corrupting reserved regions in /proc/iomem OBS-URL: https://build.opensuse.org/request/show/757390 OBS-URL: https://build.opensuse.org/package/show/Kernel:kdump/kexec-tools?expand=0&rev=114 --- kexec-tools-2.0.19.tar.xz | 3 - kexec-tools-2.0.20.tar.xz | 3 + ...c-tools-add-variant-helper-functions.patch | 84 ++++++ ...-with-resource-entries-in-proc-iomem.patch | 77 ++++++ ...mory-space-avoiding-reserved-regions.patch | 247 ++++++++++++++++++ kexec-tools.changes | 11 + kexec-tools.spec | 14 +- 7 files changed, 432 insertions(+), 7 deletions(-) delete mode 100644 kexec-tools-2.0.19.tar.xz create mode 100644 kexec-tools-2.0.20.tar.xz create mode 100644 kexec-tools-add-variant-helper-functions.patch create mode 100644 kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch create mode 100644 kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch diff --git a/kexec-tools-2.0.19.tar.xz b/kexec-tools-2.0.19.tar.xz deleted file mode 100644 index bd3e215..0000000 --- a/kexec-tools-2.0.19.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ed8001b335ac8f8a9631387d1b91f6e61e8d6f1f45a8e198a78cfb4318895e0e -size 292348 diff --git a/kexec-tools-2.0.20.tar.xz b/kexec-tools-2.0.20.tar.xz new file mode 100644 index 0000000..629ead4 --- /dev/null +++ b/kexec-tools-2.0.20.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd4bc27bd64569153df57859157d4e1e1ae76aed4ef614e36cb23b5dd5675ab0 +size 276284 diff --git a/kexec-tools-add-variant-helper-functions.patch b/kexec-tools-add-variant-helper-functions.patch new file mode 100644 index 0000000..ce572cd --- /dev/null +++ b/kexec-tools-add-variant-helper-functions.patch @@ -0,0 +1,84 @@ +From: AKASHI Takahiro +Date: Fri, 11 Jan 2019 01:59:44 +0900 +Subject: kexec: add variant helper functions for handling memory regions +References: jsc#SLE-9943 +Upstream: not yet, it's under review in upstream + +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 +Signed-off-by: Chester Lin +--- + 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 diff --git a/kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch b/kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch new file mode 100644 index 0000000..2abc986 --- /dev/null +++ b/kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch @@ -0,0 +1,77 @@ +From: AKASHI Takahiro +Date: Fri, 11 Jan 2019 01:59:46 +0900 +Subject: arm64: kdump: deal with a lot of resource entries in /proc/iomem +References: jsc#SLE-9943 +Upstream: not yet, it's under review in upstream + +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 +Signed-off-by: Chester Lin +--- + 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; + } + diff --git a/kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch b/kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch new file mode 100644 index 0000000..65e7ca4 --- /dev/null +++ b/kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch @@ -0,0 +1,247 @@ +From: AKASHI Takahiro +Date: Fri, 11 Jan 2019 01:59:45 +0900 +Subject: arm64: kexec: allocate memory space avoiding reserved regions +References: jsc#SLE-9943 +Upstream: not yet, it's under review in upstream + +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 + 59a77000-59a77fff : reserved + 5be40000-5becffff : reserved + 5bed0000-5bedffff : System RAM + 5bee0000-5bffffff : reserved + 5c000000-5fffffff : System RAM + 5da00000-5e9fffff : reserved + 5ec00000-5edfffff : reserved + 5ef6a000-5ef6afff : reserved + 5ef6b000-5efcafff : reserved + 5efcd000-5efcffff : reserved + 5efd0000-5effffff : reserved + 5f000000-5fffffff : 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 +Signed-off-by: Chester Lin +--- + kexec/arch/arm64/kexec-arm64.c | 146 ++++++++++++++++++++------------- + 1 file changed, 87 insertions(+), 59 deletions(-) + +diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c +index 1cde75d1a771..2e923b54f5b1 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 +@@ -899,19 +902,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 +@@ -945,17 +962,65 @@ 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"); ++ 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; ++ mem_regions_alloc_and_exclude(&memranges, &excl_range); ++ 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. +@@ -976,52 +1041,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"); ++ if (memranges.size) ++ set_phys_offset(memranges.ranges[0].start, "iomem"); + +- dbgprintf("%s: %016llx - %016llx : %s", __func__, r->start, +- r->end, str); ++ dbgprint_mem_range("System RAM ranges;", ++ memranges.ranges, memranges.size); + + return 0; + } + +-/** +- * get_memory_ranges_iomem - Try to get the memory ranges from +- * /proc/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; +- } +- +- 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-tools.changes b/kexec-tools.changes index 00c52f5..ae7fa0b 100644 --- a/kexec-tools.changes +++ b/kexec-tools.changes @@ -1,3 +1,14 @@ +------------------------------------------------------------------- +Mon Dec 16 15:45:05 UTC 2019 - Chester Lin + +- Bump to version 2.0.20 + Changelog: https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git/log/?id=refs/tags/v2.0.19..v2.0.20 +- Backport a upstream patch series: [jsc#SLE-9943] + Subject: [PATCH v2 0/3] arm64: handle "reserved" entries in /proc/iomem + * kexec-tools-add-variant-helper-functions.patch + * kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch + * kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch + ------------------------------------------------------------------- Fri Jun 14 12:11:18 UTC 2019 - Petr Tesarik diff --git a/kexec-tools.spec b/kexec-tools.spec index 199babd..15f0ff1 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -1,7 +1,7 @@ # # spec file for package kexec-tools # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: kexec-tools -Version: 2.0.19 +Version: 2.0.20 Release: 0 Summary: Tools for loading replacement kernels into memory License: GPL-2.0-or-later @@ -29,7 +29,10 @@ Source3: kexec-load.service Source4: %{name}-rpmlintrc Patch2: %{name}-xen-balloon-up.patch Patch3: %{name}-disable-test.patch -Patch14: %{name}-vmcoreinfo-in-xen.patch +Patch4: %{name}-vmcoreinfo-in-xen.patch +Patch5: %{name}-add-variant-helper-functions.patch +Patch6: %{name}-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch +Patch7: %{name}-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: systemd-rpm-macros @@ -55,7 +58,10 @@ the loaded kernel after it panics. %setup -q %patch2 -p1 %patch3 -p1 -%patch14 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 %build autoreconf -fvi