Resolves: bz1018104
Boot with "crashkernel=128M,high", kernel now uses "Crash kernel" in
/proc/iomem for crash kernel memory reservations at both low and high:
commit 157752d
Author: Yinghai Lu <yinghai(a)kernel.org>
kexec: use Crash kernel for Crash kernel low
But kexec is still scanning for "Crash kernel low" in /proc/iomem, and
will fail immediately when load/unload crash kernel.
So let's pull the following commit from kexec upstream to make
it compatible with our kernel:
commit e25e6e7
Author: Yinghai Lu <yinghai(a)kernel.org>
kdump, x86: Process multiple Crash kernel in /proc/iomem
(This patch from upstream is untouched and can be applied cleanly)
Signed-off-by: WANG Chao <chaowang(a)redhat.com>
---
...rocess-multiple-Crash-kernel-in-proc-iome.patch | 230 +++++++++++++++++++++
kexec-tools.spec | 2 +
2 files changed, 232 insertions(+)
create mode 100644
kexec-tools-2.0.4-kdump-x86-Process-multiple-Crash-kernel-in-proc-iome.patch
diff --git a/kexec-tools-2.0.4-kdump-x86-Process-multiple-Crash-kernel-in-proc-iome.patch
b/kexec-tools-2.0.4-kdump-x86-Process-multiple-Crash-kernel-in-proc-iome.patch
new file mode 100644
index 0000000..9e2fb41
--- /dev/null
+++ b/kexec-tools-2.0.4-kdump-x86-Process-multiple-Crash-kernel-in-proc-iome.patch
@@ -0,0 +1,230 @@
+From e25e6e7593cae350ecaa3fcd6d20c7de87f4c309 Mon Sep 17 00:00:00 2001
+From: Yinghai Lu <yinghai(a)kernel.org>
+Date: Fri, 22 Mar 2013 13:54:06 -0700
+Subject: [PATCH] kdump, x86: Process multiple Crash kernel in /proc/iomem
+
+Vivek found specical handling crashkernel low in not good.
+We should extend kexec-tools to handle multiple Crash kernel instead.
+
+Extend crash_reserved_mem to array instead and use
+kexec_iomem_for_each_line directly. After that we can drop
+crashkernel low.
+
+-v2: fix left over calling of parse_iomem_single() found by Vivek.
+
+Suggested-by: Vivek Goyal <vgoyal(a)redhat.com>
+Signed-off-by: Yinghai Lu <yinghai(a)kernel.org>
+Signed-off-by: Simon Horman <horms(a)verge.net.au>
+---
+ kexec/arch/i386/crashdump-x86.c | 107 +++++++++++++++++++++----------------
+ kexec/arch/i386/kexec-x86-common.c | 4 +-
+ kexec/kexec.h | 1 +
+ 3 files changed, 65 insertions(+), 47 deletions(-)
+
+diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
+index 9ab648b..4167e5e 100644
+--- a/kexec/arch/i386/crashdump-x86.c
++++ b/kexec/arch/i386/crashdump-x86.c
+@@ -188,9 +188,9 @@ static int exclude_region(int *nr_ranges, uint64_t start, uint64_t
end);
+ static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
+
+ /* Memory region reserved for storing panic kernel and other data. */
+-static struct memory_range crash_reserved_mem;
+-/* under 4G parts */
+-static struct memory_range crash_reserved_low_mem;
++#define CRASH_RESERVED_MEM_NR 8
++static struct memory_range crash_reserved_mem[CRASH_RESERVED_MEM_NR];
++static int crash_reserved_mem_nr;
+
+ /* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to
+ * create Elf headers. Keeping it separate from get_memory_ranges() as
+@@ -207,7 +207,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int
*ranges,
+ int kexec_flags, unsigned long lowmem_limit)
+ {
+ const char *iomem = proc_iomem();
+- int memory_ranges = 0, gart = 0;
++ int memory_ranges = 0, gart = 0, i;
+ char line[MAX_LINE];
+ FILE *fp;
+ unsigned long long start, end;
+@@ -268,29 +268,28 @@ static int get_crash_memory_ranges(struct memory_range **range, int
*ranges,
+ }
+ fclose(fp);
+ if (kexec_flags & KEXEC_PRESERVE_CONTEXT) {
+- int i;
+ for (i = 0; i < memory_ranges; i++) {
+ if (crash_memory_range[i].end > 0x0009ffff) {
+- crash_reserved_mem.start = \
++ crash_reserved_mem[0].start = \
+ crash_memory_range[i].start;
+ break;
+ }
+ }
+- if (crash_reserved_mem.start >= mem_max) {
++ if (crash_reserved_mem[0].start >= mem_max) {
+ fprintf(stderr, "Too small mem_max: 0x%llx.\n",
+ mem_max);
+ return -1;
+ }
+- crash_reserved_mem.end = mem_max;
+- crash_reserved_mem.type = RANGE_RAM;
++ crash_reserved_mem[0].end = mem_max;
++ crash_reserved_mem[0].type = RANGE_RAM;
++ crash_reserved_mem_nr = 1;
+ }
+- if (exclude_region(&memory_ranges, crash_reserved_mem.start,
+- crash_reserved_mem.end) < 0)
+- return -1;
+- if (crash_reserved_low_mem.start &&
+- exclude_region(&memory_ranges, crash_reserved_low_mem.start,
+- crash_reserved_low_mem.end) < 0)
+- return -1;
++
++ for (i = 0; i < crash_reserved_mem_nr; i++)
++ if (exclude_region(&memory_ranges, crash_reserved_mem[i].start,
++ crash_reserved_mem[i].end) < 0)
++ return -1;
++
+ if (gart) {
+ /* exclude GART region if the system has one */
+ if (exclude_region(&memory_ranges, gart_start, gart_end) < 0)
+@@ -351,9 +350,10 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
+
+ qsort(*range, *ranges, sizeof(struct memory_range), compare_ranges);
+
+- if (exclude_region(ranges, crash_reserved_mem.start,
+- crash_reserved_mem.end) < 0)
+- goto err;
++ for (i = 0; i < crash_reserved_mem_nr; i++)
++ if (exclude_region(ranges, crash_reserved_mem[i].start,
++ crash_reserved_mem[i].end) < 0)
++ goto err;
+
+ ret = 0;
+
+@@ -434,9 +434,10 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
+
+ qsort(*range, *ranges, sizeof(struct memory_range), compare_ranges);
+
+- if (exclude_region(ranges, crash_reserved_mem.start,
+- crash_reserved_mem.end) < 0)
+- goto err;
++ for (i = 0; i < crash_reserved_mem_nr; i++)
++ if (exclude_region(ranges, crash_reserved_mem[i].start,
++ crash_reserved_mem[i].end) < 0)
++ goto err;
+
+ ret = 0;
+
+@@ -1014,15 +1015,10 @@ int load_crashdump_segments(struct kexec_info *info, char*
mod_cmdline,
+ memmap_p = xmalloc(sz);
+ memset(memmap_p, 0, sz);
+ add_memmap(memmap_p, info->backup_src_start, info->backup_src_size);
+- sz = crash_reserved_mem.end - crash_reserved_mem.start +1;
+- if (add_memmap(memmap_p, crash_reserved_mem.start, sz) < 0) {
+- return ENOCRASHKERNEL;
+- }
+-
+- if (crash_reserved_low_mem.start) {
+- sz = crash_reserved_low_mem.end - crash_reserved_low_mem.start
+- +1;
+- add_memmap(memmap_p, crash_reserved_low_mem.start, sz);
++ for (i = 0; i < crash_reserved_mem_nr; i++) {
++ sz = crash_reserved_mem[i].end - crash_reserved_mem[i].start +1;
++ if (add_memmap(memmap_p, crash_reserved_mem[i].start, sz) < 0)
++ return ENOCRASHKERNEL;
+ }
+
+ /* Create a backup region segment to store backup data*/
+@@ -1093,25 +1089,46 @@ int load_crashdump_segments(struct kexec_info *info, char*
mod_cmdline,
+ return 0;
+ }
+
+-int is_crashkernel_mem_reserved(void)
++int get_max_crash_kernel_limit(uint64_t *start, uint64_t *end)
+ {
+- uint64_t start, end;
++ int i, idx = -1;
++ unsigned long sz_max = 0, sz;
+
+- if (parse_iomem_single("Crash kernel\n", &start, &end) || start ==
end)
+- return 0;
++ if (!crash_reserved_mem_nr)
++ return -1;
+
+- crash_reserved_mem.start = start;
+- crash_reserved_mem.end = end;
+- crash_reserved_mem.type = RANGE_RAM;
++ for (i = crash_reserved_mem_nr - 1; i >= 0; i--) {
++ sz = crash_reserved_mem[i].end - crash_reserved_mem[i].start +1;
++ if (sz <= sz_max)
++ continue;
++ sz_max = sz;
++ idx = i;
++ }
++
++ *start = crash_reserved_mem[idx].start;
++ *end = crash_reserved_mem[idx].end;
++
++ return 0;
++}
+
+- /* If there is no Crash low kernel, still can go on */
+- if (parse_iomem_single("Crash kernel low\n", &start, &end) ||
+- start == end)
++static int crashkernel_mem_callback(void *UNUSED(data), int nr,
++ char *UNUSED(str),
++ unsigned long base,
++ unsigned long length)
++{
++ if (nr >= CRASH_RESERVED_MEM_NR)
+ return 1;
+
+- crash_reserved_low_mem.start = start;
+- crash_reserved_low_mem.end = end;
+- crash_reserved_low_mem.type = RANGE_RAM;
++ crash_reserved_mem[nr].start = base;
++ crash_reserved_mem[nr].end = base + length - 1;
++ crash_reserved_mem[nr].type = RANGE_RAM;
++ return 0;
++}
++
++int is_crashkernel_mem_reserved(void)
++{
++ crash_reserved_mem_nr = kexec_iomem_for_each_line("Crash kernel\n",
++ crashkernel_mem_callback, NULL);
+
+- return 1;
++ return !!crash_reserved_mem_nr;
+ }
+diff --git a/kexec/arch/i386/kexec-x86-common.c b/kexec/arch/i386/kexec-x86-common.c
+index 234823c..ed6c950 100644
+--- a/kexec/arch/i386/kexec-x86-common.c
++++ b/kexec/arch/i386/kexec-x86-common.c
+@@ -465,9 +465,9 @@ int get_memory_ranges(struct memory_range **range, int *ranges,
+ !(kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
+ uint64_t start, end;
+
+- ret = parse_iomem_single("Crash kernel\n", &start, &end);
++ ret = get_max_crash_kernel_limit(&start, &end);
+ if (ret != 0) {
+- fprintf(stderr, "parse_iomem_single failed.\n");
++ fprintf(stderr, "get_max_crash_kernel_limit failed.\n");
+ return -1;
+ }
+
+diff --git a/kexec/kexec.h b/kexec/kexec.h
+index 916a24b..5ded390 100644
+--- a/kexec/kexec.h
++++ b/kexec/kexec.h
+@@ -272,6 +272,7 @@ int arch_process_options(int argc, char **argv);
+ int arch_compat_trampoline(struct kexec_info *info);
+ void arch_update_purgatory(struct kexec_info *info);
+ int is_crashkernel_mem_reserved(void);
++int get_max_crash_kernel_limit(uint64_t *start, uint64_t *end);
+ char *get_command_line(void);
+
+ int kexec_iomem_for_each_line(char *match,
+--
+1.8.3.1
+
diff --git a/kexec-tools.spec b/kexec-tools.spec
index a37444c..e3e6cc8 100644
--- a/kexec-tools.spec
+++ b/kexec-tools.spec
@@ -56,6 +56,7 @@ Obsoletes: diskdumputils netdump
#
# Patches 101 through 200 are meant for x86_64 kexec-tools enablement
#
+Patch101: kexec-tools-2.0.4-kdump-x86-Process-multiple-Crash-kernel-in-proc-iome.patch
#
# Patches 201 through 300 are meant for ia64 kexec-tools enablement
@@ -107,6 +108,7 @@ tar -z -x -v -f %{SOURCE9}
tar -z -x -v -f %{SOURCE19}
+%patch101 -p1
%patch301 -p1
%patch601 -p1
%patch604 -p1
--
1.8.3.1