diff -Nru kexec-tools-2.0.22/debian/changelog kexec-tools-2.0.22/debian/changelog --- kexec-tools-2.0.22/debian/changelog 2022-03-24 14:07:40.000000000 +0200 +++ kexec-tools-2.0.22/debian/changelog 2023-07-03 15:34:26.000000000 +0300 @@ -1,3 +1,10 @@ +kexec-tools (1:2.0.22-2ubuntu2.22.04.1) jammy; urgency=medium + + * Support more than one crash kernel regions for arm64 (LP: #2024479) + - d/p/lp2024479-0001-arm64-support-more-than-one-crash-kernel-regions.patch + + -- Ioanna Alifieraki Mon, 03 Jul 2023 15:34:26 +0300 + kexec-tools (1:2.0.22-2ubuntu2) jammy; urgency=high * No change rebuild for ppc64el baseline bump. diff -Nru kexec-tools-2.0.22/debian/patches/lp2024479-0001-arm64-support-more-than-one-crash-kernel-regions.patch kexec-tools-2.0.22/debian/patches/lp2024479-0001-arm64-support-more-than-one-crash-kernel-regions.patch --- kexec-tools-2.0.22/debian/patches/lp2024479-0001-arm64-support-more-than-one-crash-kernel-regions.patch 1970-01-01 02:00:00.000000000 +0200 +++ kexec-tools-2.0.22/debian/patches/lp2024479-0001-arm64-support-more-than-one-crash-kernel-regions.patch 2023-07-03 15:34:26.000000000 +0300 @@ -0,0 +1,330 @@ +From b5a34a20984c4ad27cc5054d9957af8130b42a50 Mon Sep 17 00:00:00 2001 +From: Chen Zhou +Origin: upstream, https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git/commit?id=b5a34a20984c4ad27cc5054d9957af8130b42a50 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/2024479 +Date: Mon, 10 Jan 2022 18:20:08 +0800 +Subject: [PATCH] arm64: support more than one crash kernel regions + +When crashkernel is reserved above 4G in memory, kernel should +reserve some amount of low memory for swiotlb and some DMA buffers. +So there may be two crash kernel regions, one is below 4G, the other +is above 4G. + +Currently, there is only one crash kernel region on arm64, and pass +"linux,usable-memory-range = " property to crash dump +kernel. +Now, we pass "linux,usable-memory-range = " +to crash dump kernel to support two crash kernel regions and load crash +kernel high. Make the low memory region as the second range "BASE2 SIZE2" +to keep compatibility with existing user-space and older kdump kernels. + +Signed-off-by: Chen Zhou +Co-developed-by: Zhen Lei +Signed-off-by: Zhen Lei +Signed-off-by: Simon Horman +--- + kexec/arch/arm64/crashdump-arm64.c | 44 +++++++++------- + kexec/arch/arm64/crashdump-arm64.h | 5 +- + kexec/arch/arm64/kexec-arm64.c | 84 ++++++++++++++++++++---------- + 3 files changed, 86 insertions(+), 47 deletions(-) + +--- a/kexec/arch/arm64/crashdump-arm64.c ++++ b/kexec/arch/arm64/crashdump-arm64.c +@@ -27,11 +27,11 @@ + static struct memory_ranges system_memory_rgns; + + /* memory range reserved for crashkernel */ +-struct memory_range crash_reserved_mem; ++struct memory_range crash_reserved_mem[CRASH_MAX_RESERVED_RANGES]; + struct memory_ranges usablemem_rgns = { + .size = 0, +- .max_size = 1, +- .ranges = &crash_reserved_mem, ++ .max_size = CRASH_MAX_RESERVED_RANGES, ++ .ranges = crash_reserved_mem, + }; + + struct memory_range elfcorehdr_mem; +@@ -103,7 +103,7 @@ int is_crashkernel_mem_reserved(void) + if (!usablemem_rgns.size) + kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); + +- return crash_reserved_mem.start != crash_reserved_mem.end; ++ return usablemem_rgns.size; + } + + /* +@@ -117,6 +117,8 @@ int is_crashkernel_mem_reserved(void) + */ + static int crash_get_memory_ranges(void) + { ++ int i; ++ + /* + * First read all memory regions that can be considered as + * system memory including the crash area. +@@ -124,16 +126,19 @@ static int crash_get_memory_ranges(void) + if (!usablemem_rgns.size) + kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); + +- /* allow only a single region for crash dump kernel */ +- if (usablemem_rgns.size != 1) ++ /* allow one or two regions for crash dump kernel */ ++ if (!usablemem_rgns.size) + return -EINVAL; + +- dbgprint_mem_range("Reserved memory range", &crash_reserved_mem, 1); ++ dbgprint_mem_range("Reserved memory range", ++ usablemem_rgns.ranges, usablemem_rgns.size); + +- if (mem_regions_alloc_and_exclude(&system_memory_rgns, +- &crash_reserved_mem)) { +- fprintf(stderr, "Cannot allocate memory for ranges\n"); +- return -ENOMEM; ++ for (i = 0; i < usablemem_rgns.size; i++) { ++ if (mem_regions_alloc_and_exclude(&system_memory_rgns, ++ &crash_reserved_mem[i])) { ++ fprintf(stderr, "Cannot allocate memory for ranges\n"); ++ return -ENOMEM; ++ } + } + + /* +@@ -194,7 +199,8 @@ int load_crashdump_segments(struct kexec + return EFAILED; + + elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 0, +- crash_reserved_mem.start, crash_reserved_mem.end, ++ crash_reserved_mem[usablemem_rgns.size - 1].start, ++ crash_reserved_mem[usablemem_rgns.size - 1].end, + -1, 0); + + elfcorehdr_mem.start = elfcorehdr; +@@ -212,21 +218,23 @@ int load_crashdump_segments(struct kexec + * virt_to_phys() in add_segment(). + * So let's fix up those values for later use so the memory base + * (arm64_mm.phys_offset) will be correctly replaced with +- * crash_reserved_mem.start. ++ * crash_reserved_mem[usablemem_rgns.size - 1].start. + */ + void fixup_elf_addrs(struct mem_ehdr *ehdr) + { + struct mem_phdr *phdr; + int i; + +- ehdr->e_entry += - arm64_mem.phys_offset + crash_reserved_mem.start; ++ ehdr->e_entry += -arm64_mem.phys_offset + ++ crash_reserved_mem[usablemem_rgns.size - 1].start; + + for (i = 0; i < ehdr->e_phnum; i++) { + phdr = &ehdr->e_phdr[i]; + if (phdr->p_type != PT_LOAD) + continue; + phdr->p_paddr += +- (-arm64_mem.phys_offset + crash_reserved_mem.start); ++ (-arm64_mem.phys_offset + ++ crash_reserved_mem[usablemem_rgns.size - 1].start); + } + } + +@@ -235,11 +243,11 @@ int get_crash_kernel_load_range(uint64_t + if (!usablemem_rgns.size) + kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); + +- if (!crash_reserved_mem.end) ++ if (!usablemem_rgns.size) + return -1; + +- *start = crash_reserved_mem.start; +- *end = crash_reserved_mem.end; ++ *start = crash_reserved_mem[usablemem_rgns.size - 1].start; ++ *end = crash_reserved_mem[usablemem_rgns.size - 1].end; + + return 0; + } +--- a/kexec/arch/arm64/crashdump-arm64.h ++++ b/kexec/arch/arm64/crashdump-arm64.h +@@ -16,8 +16,11 @@ + + #define CRASH_MAX_MEMORY_RANGES 32 + ++/* crash dump kernel support at most two regions, low_region and high region. */ ++#define CRASH_MAX_RESERVED_RANGES 2 ++ + extern struct memory_ranges usablemem_rgns; +-extern struct memory_range crash_reserved_mem; ++extern struct memory_range crash_reserved_mem[]; + extern struct memory_range elfcorehdr_mem; + + extern int load_crashdump_segments(struct kexec_info *info); +--- a/kexec/arch/arm64/kexec-arm64.c ++++ b/kexec/arch/arm64/kexec-arm64.c +@@ -456,22 +456,32 @@ static void fill_property(void *buf, uin + } + } + +-static int fdt_setprop_range(void *fdt, int nodeoffset, +- const char *name, struct memory_range *range, ++static int fdt_setprop_ranges(void *fdt, int nodeoffset, const char *name, ++ struct memory_range *ranges, int nr_ranges, bool reverse, + uint32_t address_cells, uint32_t size_cells) + { + void *buf, *prop; + size_t buf_size; +- int result; ++ int i, result; ++ struct memory_range *range; + +- buf_size = (address_cells + size_cells) * sizeof(uint32_t); ++ buf_size = (address_cells + size_cells) * sizeof(uint32_t) * nr_ranges; + prop = buf = xmalloc(buf_size); ++ if (!buf) ++ return -ENOMEM; ++ ++ for (i = 0; i < nr_ranges; i++) { ++ if (reverse) ++ range = ranges + (nr_ranges - 1 - i); ++ else ++ range = ranges + i; + +- fill_property(prop, range->start, address_cells); +- prop += address_cells * sizeof(uint32_t); ++ fill_property(prop, range->start, address_cells); ++ prop += address_cells * sizeof(uint32_t); + +- fill_property(prop, range->end - range->start + 1, size_cells); +- prop += size_cells * sizeof(uint32_t); ++ fill_property(prop, range->end - range->start + 1, size_cells); ++ prop += size_cells * sizeof(uint32_t); ++ } + + result = fdt_setprop(fdt, nodeoffset, name, buf, buf_size); + +@@ -493,7 +503,7 @@ static int setup_2nd_dtb(struct dtb *dtb + int len, range_len; + int nodeoffset; + int new_size; +- int result, kaslr_seed; ++ int i, result, kaslr_seed; + + result = fdt_check_header(dtb->buf); + +@@ -524,18 +534,20 @@ static int setup_2nd_dtb(struct dtb *dtb + goto on_error; + } + +- if (!cells_size_fitted(address_cells, size_cells, +- &crash_reserved_mem)) { +- fprintf(stderr, "kexec: usable memory range doesn't fit cells-size.\n"); +- result = -EINVAL; +- goto on_error; ++ for (i = 0; i < usablemem_rgns.size; i++) { ++ if (!cells_size_fitted(address_cells, size_cells, ++ &crash_reserved_mem[i])) { ++ fprintf(stderr, "kexec: usable memory range doesn't fit cells-size.\n"); ++ result = -EINVAL; ++ goto on_error; ++ } + } + + /* duplicate dt blob */ + range_len = sizeof(uint32_t) * (address_cells + size_cells); + new_size = fdt_totalsize(dtb->buf) + + fdt_prop_len(PROP_ELFCOREHDR, range_len) +- + fdt_prop_len(PROP_USABLE_MEM_RANGE, range_len); ++ + fdt_prop_len(PROP_USABLE_MEM_RANGE, range_len * usablemem_rgns.size); + + new_buf = xmalloc(new_size); + result = fdt_open_into(dtb->buf, new_buf, new_size); +@@ -619,8 +631,8 @@ static int setup_2nd_dtb(struct dtb *dtb + if (on_crash) { + /* add linux,elfcorehdr */ + nodeoffset = fdt_path_offset(new_buf, "/chosen"); +- result = fdt_setprop_range(new_buf, nodeoffset, +- PROP_ELFCOREHDR, &elfcorehdr_mem, ++ result = fdt_setprop_ranges(new_buf, nodeoffset, ++ PROP_ELFCOREHDR, &elfcorehdr_mem, 1, false, + address_cells, size_cells); + if (result) { + dbgprintf("%s: fdt_setprop failed: %s\n", __func__, +@@ -629,10 +641,17 @@ static int setup_2nd_dtb(struct dtb *dtb + goto on_error; + } + +- /* add linux,usable-memory-range */ ++ /* ++ * add linux,usable-memory-range ++ * ++ * crash dump kernel support one or two regions, to make ++ * compatibility with existing user-space and older kdump, the ++ * low region is always the last one. ++ */ + nodeoffset = fdt_path_offset(new_buf, "/chosen"); +- result = fdt_setprop_range(new_buf, nodeoffset, +- PROP_USABLE_MEM_RANGE, &crash_reserved_mem, ++ result = fdt_setprop_ranges(new_buf, nodeoffset, ++ PROP_USABLE_MEM_RANGE, ++ usablemem_rgns.ranges, usablemem_rgns.size, true, + address_cells, size_cells); + if (result) { + dbgprintf("%s: fdt_setprop failed: %s\n", __func__, +@@ -665,13 +684,13 @@ unsigned long arm64_locate_kernel_segmen + if (info->kexec_flags & KEXEC_ON_CRASH) { + unsigned long hole_end; + +- hole = (crash_reserved_mem.start < mem_min ? +- mem_min : crash_reserved_mem.start); ++ hole = (crash_reserved_mem[usablemem_rgns.size - 1].start < mem_min ? ++ mem_min : crash_reserved_mem[usablemem_rgns.size - 1].start); + hole = _ALIGN_UP(hole, MiB(2)); + hole_end = hole + arm64_mem.text_offset + arm64_mem.image_size; + + if ((hole_end > mem_max) || +- (hole_end > crash_reserved_mem.end)) { ++ (hole_end > crash_reserved_mem[usablemem_rgns.size - 1].end)) { + dbgprintf("%s: Crash kernel out of range\n", __func__); + hole = ULONG_MAX; + } +@@ -745,7 +764,7 @@ int arm64_load_other_segments(struct kex + + hole_min = image_base + arm64_mem.image_size; + if (info->kexec_flags & KEXEC_ON_CRASH) +- hole_max = crash_reserved_mem.end; ++ hole_max = crash_reserved_mem[usablemem_rgns.size - 1].end; + else + hole_max = ULONG_MAX; + +@@ -979,12 +998,21 @@ int get_phys_base_from_pt_load(unsigned + return 0; + } + +-static bool to_be_excluded(char *str) ++static bool to_be_excluded(char *str, unsigned long long start, unsigned long long end) + { ++ if (!strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL))) { ++ uint64_t load_start, load_end; ++ ++ if (!get_crash_kernel_load_range(&load_start, &load_end) && ++ (load_start == start) && (load_end == end)) ++ return false; ++ ++ return true; ++ } ++ + 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))) ++ !strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA))) + return false; + else + return true; +@@ -1066,7 +1094,7 @@ int get_memory_ranges(struct memory_rang + memranges.size - 1, + memranges.ranges[memranges.size - 1].start, + memranges.ranges[memranges.size - 1].end); +- } else if (to_be_excluded(str)) { ++ } else if (to_be_excluded(str, start, end)) { + if (!memranges.size) + continue; + diff -Nru kexec-tools-2.0.22/debian/patches/series kexec-tools-2.0.22/debian/patches/series --- kexec-tools-2.0.22/debian/patches/series 2021-07-16 01:42:59.000000000 +0300 +++ kexec-tools-2.0.22/debian/patches/series 2023-07-03 15:34:26.000000000 +0300 @@ -7,3 +7,4 @@ powerpcspe_support.patch vmcore-dmesg_man_page_fix.patch 0001-kexec-tools-Remove-duplicate-definition-of-ramdisk.patch +lp2024479-0001-arm64-support-more-than-one-crash-kernel-regions.patch