diff --git a/arm64-support-more-than-one-crash-kernel-regions.patch b/arm64-support-more-than-one-crash-kernel-regions.patch index ab20a18aff248211e822cb6c0905739571a6a2a6..d8b4b332e5bf1eae059671b76d791ba8fb22b45a 100644 --- a/arm64-support-more-than-one-crash-kernel-regions.patch +++ b/arm64-support-more-than-one-crash-kernel-regions.patch @@ -26,251 +26,283 @@ Signed-off-by: Chen Zhou kexec/arch/arm64/kexec-arm64.c | 57 +++++++++++++++++++++++++++++--------- 3 files changed, 72 insertions(+), 32 deletions(-) -diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c -index 4fd7aa8..158e778 100644 ---- 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; -@@ -108,7 +108,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; - } - - /* -@@ -122,6 +122,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 region 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_exclude(&system_memory_rgns, &crash_reserved_mem[i])) { -+ fprintf(stderr, -+ "Error: Number of crash memory ranges excedeed the max limit\n"); -+ return -ENOMEM; -+ } - } - - /* -@@ -199,7 +204,8 @@ int load_crashdump_segments(struct kexec_info *info) - 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; -@@ -217,21 +223,23 @@ int load_crashdump_segments(struct kexec_info *info) - * 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); - } - } - -@@ -240,11 +248,11 @@ int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) - 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; - } -diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h -index 880b83a..c07233f 100644 ---- a/kexec/arch/arm64/crashdump-arm64.h -+++ b/kexec/arch/arm64/crashdump-arm64.h -@@ -15,9 +15,10 @@ - #include "kexec.h" - - #define CRASH_MAX_MEMORY_RANGES 32 -+#define CRASH_MAX_RESERVED_RANGES 8 - - 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); -diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c -index 2992bce..2bf8b66 100644 ---- a/kexec/arch/arm64/kexec-arm64.c -+++ b/kexec/arch/arm64/kexec-arm64.c -@@ -414,6 +414,34 @@ static int fdt_setprop_range(void *fdt, int nodeoffset, - return result; - } - -+static int fdt_setprop_ranges(void *fdt, int nodeoffset, -+ const char *name, struct memory_ranges *ranges, -+ uint32_t address_cells, uint32_t size_cells) -+{ -+ void *buf, *prop; -+ size_t buf_size; -+ int i, result; -+ -+ buf_size = (address_cells + size_cells) * sizeof(uint32_t) * -+ ranges->size; -+ prop = buf = xmalloc(buf_size); -+ -+ for (i = 0; i < ranges->size; i++) { -+ fill_property(prop, ranges->ranges[i].start, address_cells); -+ prop += address_cells * sizeof(uint32_t); -+ -+ fill_property(prop, ranges->ranges[i].end - -+ ranges->ranges[i].start + 1, size_cells); -+ prop += size_cells * sizeof(uint32_t); -+ } -+ -+ result = fdt_setprop(fdt, nodeoffset, name, buf, buf_size); -+ -+ free(buf); -+ -+ return result; -+} -+ - /** - * setup_2nd_dtb - Setup the 2nd stage kernel's dtb. - */ -@@ -428,7 +456,7 @@ static int setup_2nd_dtb(struct dtb *dtb, char *command_line, int on_crash) - int len, range_len; - int nodeoffset; - int new_size; -- int result, kaslr_seed; -+ int i, result, kaslr_seed; - - result = fdt_check_header(dtb->buf); - -@@ -459,18 +487,21 @@ static int setup_2nd_dtb(struct dtb *dtb, char *command_line, int on_crash) - 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); -@@ -565,8 +596,8 @@ static int setup_2nd_dtb(struct dtb *dtb, char *command_line, int on_crash) - - /* add linux,usable-memory-range */ - 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, - address_cells, size_cells); - if (result) { - dbgprintf("%s: fdt_setprop failed: %s\n", __func__, -@@ -599,13 +630,13 @@ unsigned long arm64_locate_kernel_segment(struct kexec_info *info) - 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; - } -@@ -673,7 +704,7 @@ int arm64_load_other_segments(struct kexec_info *info, - - 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; - --- -2.7.4 - +diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c +index 38d1a0f..d8338eb 100644 +--- 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; +@@ -84,7 +84,10 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr), + char *str, unsigned long long base, + unsigned long long length) + { +- if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) ++ if (strncmp(str, CRASH_KERNEL_LOW, strlen(CRASH_KERNEL_LOW)) == 0) ++ return mem_regions_alloc_and_add(&usablemem_rgns, ++ base, length, RANGE_RAM); ++ else if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) + return mem_regions_alloc_and_add(&usablemem_rgns, + base, length, RANGE_RAM); + else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) +@@ -103,7 +106,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 +120,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 +129,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 region 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 +202,8 @@ int load_crashdump_segments(struct kexec_info *info) + 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 +221,23 @@ int load_crashdump_segments(struct kexec_info *info) + * 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 +246,11 @@ int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) + 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; + } +diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h +index 880b83a..12f4308 100644 +--- 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); +diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h +index d4864bb..45d7953 100644 +--- a/kexec/arch/arm64/iomem.h ++++ b/kexec/arch/arm64/iomem.h +@@ -4,6 +4,7 @@ + #define SYSTEM_RAM "System RAM\n" + #define KERNEL_CODE "Kernel code\n" + #define KERNEL_DATA "Kernel data\n" ++#define CRASH_KERNEL_LOW "Crash kernel (low)\n" + #define CRASH_KERNEL "Crash kernel\n" + #define IOMEM_RESERVED "reserved\n" + +diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c +index 45ebc54..6346f83 100644 +--- a/kexec/arch/arm64/kexec-arm64.c ++++ b/kexec/arch/arm64/kexec-arm64.c +@@ -418,6 +418,42 @@ static int fdt_setprop_range(void *fdt, int nodeoffset, + return result; + } + ++/* ++ * fdt_setprop_ranges - Used for linux,usable-memory-range ++ */ ++static int fdt_setprop_ranges(void *fdt, int nodeoffset, ++ const char *name, struct memory_ranges *ranges, ++ uint32_t address_cells, uint32_t size_cells) ++{ ++ void *buf, *prop; ++ size_t buf_size; ++ int i, result; ++ ++ buf_size = (address_cells + size_cells) * sizeof(uint32_t) * ++ ranges->size; ++ prop = buf = xmalloc(buf_size); ++ ++ /* ++ * crash dump kernel support at most two regions, low_region and high region. ++ * To make compatibility with existing user-space and older kdump, the low ++ * region is always the last range of linux,usable-memory-range if exist. ++ */ ++ for (i = ranges->size - 1; i >= 0; i--) { ++ fill_property(prop, ranges->ranges[i].start, address_cells); ++ prop += address_cells * sizeof(uint32_t); ++ ++ fill_property(prop, ranges->ranges[i].end - ++ ranges->ranges[i].start + 1, size_cells); ++ prop += size_cells * sizeof(uint32_t); ++ } ++ ++ result = fdt_setprop(fdt, nodeoffset, name, buf, buf_size); ++ ++ free(buf); ++ ++ return result; ++} ++ + /** + * setup_2nd_dtb - Setup the 2nd stage kernel's dtb. + */ +@@ -431,7 +467,7 @@ static int setup_2nd_dtb(struct dtb *dtb, char *command_line, int on_crash) + int len, range_len; + int nodeoffset; + int new_size; +- int result, kaslr_seed; ++ int i, result, kaslr_seed; + + result = fdt_check_header(dtb->buf); + +@@ -462,18 +498,21 @@ static int setup_2nd_dtb(struct dtb *dtb, char *command_line, int on_crash) + 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); +@@ -569,8 +608,8 @@ static int setup_2nd_dtb(struct dtb *dtb, char *command_line, int on_crash) + + /* add linux,usable-memory-range */ + 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, + address_cells, size_cells); + if (result) { + dbgprintf("%s: fdt_setprop failed: %s\n", __func__, +@@ -603,13 +642,13 @@ unsigned long arm64_locate_kernel_segment(struct kexec_info *info) + 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; + } +@@ -677,7 +716,7 @@ int arm64_load_other_segments(struct kexec_info *info, + + 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; + +-- +2.20.1 diff --git a/kexec-Quick-kexec-implementation-for-arm64.patch b/kexec-Quick-kexec-implementation-for-arm64.patch index b1329f1284e3600e1db66fb6823bc4cbe7b96054..efe0209347f7712eed50f60a7751d73293e8eadc 100644 --- a/kexec-Quick-kexec-implementation-for-arm64.patch +++ b/kexec-Quick-kexec-implementation-for-arm64.patch @@ -13,14 +13,14 @@ Locate kernel segments from reserved memory of range "Quick kexec". 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h -index d4864bb..108871e 100644 +index 45d7953..f283f50 100644 --- a/kexec/arch/arm64/iomem.h +++ b/kexec/arch/arm64/iomem.h -@@ -6,5 +6,6 @@ - #define KERNEL_DATA "Kernel data\n" +@@ -7,5 +7,6 @@ + #define CRASH_KERNEL_LOW "Crash kernel (low)\n" #define CRASH_KERNEL "Crash kernel\n" #define IOMEM_RESERVED "reserved\n" -+#define QUICK_KEXEC "Quick kexec\n" ++#define QUICK_KEXEC "Quick kexec\n" #endif diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c diff --git a/kexec-tools.spec b/kexec-tools.spec index d8a5844fc6e98dcc2eb113b4f964ee74f1006d5d..11a1912e7c3a1a994a79ab34aa4679ef3f324275 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -4,7 +4,7 @@ Name: kexec-tools Version: 2.0.20 -Release: 5 +Release: 6 License: GPLv2 Summary: The kexec/kdump userspace component URL: https://www.kernel.org/ @@ -339,6 +339,9 @@ done %endif %changelog +* Mon Mar 22 2021 yangzhuangzhuang - 2.0.20-6 +- support more than one crash kernel regions + * Mon Mar 1 2021 snoweay - 2.0.20-5 - Fix bugs of unuseable quick kexec on arm64, becaues of arm64-kexec-allocate-memory-space-avoiding-reserved-regions excluding QUICK_KEXEC memory region.