* [PATCH 2/4] x86: Store memory ranges globally used for crash kernel to boot into
2014-02-13 13:10 [PATCH 0/4] kexec-tools, x86: E820 memmap pass for kdump WANG Chao
2014-02-13 13:10 ` [PATCH 1/4] add macro dbgprint_mem_range WANG Chao
@ 2014-02-13 13:10 ` WANG Chao
2014-02-13 21:46 ` Vivek Goyal
2014-02-13 13:10 ` [PATCH 3/4] x86: add --pass-memmap-cmdline option WANG Chao
2014-02-13 13:10 ` [PATCH] x86: Pass memory range via E820 for kdump WANG Chao
3 siblings, 1 reply; 9+ messages in thread
From: WANG Chao @ 2014-02-13 13:10 UTC (permalink / raw)
To: horms, vgoyal, ebiederm, hpa, trenn, dyoung; +Cc: kexec
Use these two variables to store the memory ranges and the number of
memory ranges for crash kernel to boot into:
struct memory_range crash_memory_range;
int crash_memory_range;
crash_memory_range also will store RANGE_RESERVED ranges which is
discarded previously, but will be filtered out when exactmap case.
These two variables are not static now, so can be used in other file
later.
Signed-off-by: WANG Chao <chaowang@redhat.com>
---
kexec/arch/i386/crashdump-x86.c | 136 ++++++++++++++++++++++------------------
kexec/arch/i386/crashdump-x86.h | 5 +-
2 files changed, 79 insertions(+), 62 deletions(-)
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 979c2bd..b2c2442 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -179,7 +179,8 @@ static int exclude_region(int *nr_ranges, uint64_t start, uint64_t end);
/* Stores a sorted list of RAM memory ranges for which to create elf headers.
* A separate program header is created for backup region */
-static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
+struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
+int crash_memory_ranges;
/* Memory region reserved for storing panic kernel and other data. */
#define CRASH_RESERVED_MEM_NR 8
@@ -201,7 +202,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, i;
+ int gart = 0, i;
char line[MAX_LINE];
FILE *fp;
unsigned long long start, end;
@@ -218,7 +219,7 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
char *str;
int type, consumed, count;
- if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
+ if (crash_memory_ranges >= CRASH_MAX_MEMORY_RANGES)
break;
count = sscanf(line, "%Lx-%Lx : %n",
&start, &end, &consumed);
@@ -230,6 +231,8 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
/* Only Dumping memory of type System RAM. */
if (memcmp(str, "System RAM\n", 11) == 0) {
type = RANGE_RAM;
+ } else if (memcmp(str, "reserved\n", 9) == 0) {
+ type = RANGE_RESERVED;
} else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
/*
* ACPI Tables area need to be passed to new
@@ -250,17 +253,17 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
continue;
}
- crash_memory_range[memory_ranges].start = start;
- crash_memory_range[memory_ranges].end = end;
- crash_memory_range[memory_ranges].type = type;
+ crash_memory_range[crash_memory_ranges].start = start;
+ crash_memory_range[crash_memory_ranges].end = end;
+ crash_memory_range[crash_memory_ranges].type = type;
- segregate_lowmem_region(&memory_ranges, lowmem_limit);
+ segregate_lowmem_region(&crash_memory_ranges, lowmem_limit);
- memory_ranges++;
+ crash_memory_ranges++;
}
fclose(fp);
if (kexec_flags & KEXEC_PRESERVE_CONTEXT) {
- for (i = 0; i < memory_ranges; i++) {
+ for (i = 0; i < crash_memory_ranges; i++) {
if (crash_memory_range[i].end > 0x0009ffff) {
crash_reserved_mem[0].start = \
crash_memory_range[i].start;
@@ -278,17 +281,17 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
}
for (i = 0; i < crash_reserved_mem_nr; i++)
- if (exclude_region(&memory_ranges, crash_reserved_mem[i].start,
+ if (exclude_region(&crash_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)
+ if (exclude_region(&crash_memory_ranges, gart_start, gart_end) < 0)
return -1;
}
*range = crash_memory_range;
- *ranges = memory_ranges;
+ *ranges = crash_memory_ranges;
return 0;
}
@@ -324,7 +327,7 @@ static int get_crash_memory_ranges_xen(struct memory_range **range,
}
*range = crash_memory_range;
- *ranges = j;
+ *ranges = crash_memory_ranges = j;
qsort(*range, *ranges, sizeof(struct memory_range), compare_ranges);
@@ -417,8 +420,8 @@ static int exclude_region(int *nr_ranges, uint64_t start, uint64_t end)
/* Adds a segment from list of memory regions which new kernel can use to
* boot. Segment start and end should be aligned to 1K boundary. */
-static int add_memmap(struct memory_range *memmap_p, unsigned long long addr,
- size_t size)
+static int add_memmap(struct memory_range *memmap_p, int *nr_range,
+ unsigned long long addr, size_t size)
{
int i, j, nr_entries = 0, tidx = 0, align = 1024;
unsigned long long mstart, mend;
@@ -450,29 +453,23 @@ static int add_memmap(struct memory_range *memmap_p, unsigned long long addr,
else if (addr > mend)
tidx = i+1;
}
- /* Insert the memory region. */
- for (j = nr_entries-1; j >= tidx; j--)
- memmap_p[j+1] = memmap_p[j];
- memmap_p[tidx].start = addr;
- memmap_p[tidx].end = addr + size - 1;
+ /* Insert the memory region. */
+ for (j = nr_entries-1; j >= tidx; j--)
+ memmap_p[j+1] = memmap_p[j];
+ memmap_p[tidx].start = addr;
+ memmap_p[tidx].end = addr + size - 1;
+ memmap_p[tidx].type = RANGE_RAM;
+ *nr_range = nr_entries + 1;
- dbgprintf("Memmap after adding segment\n");
- for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
- mstart = memmap_p[i].start;
- mend = memmap_p[i].end;
- if (mstart == 0 && mend == 0)
- break;
- dbgprintf("%016llx - %016llx\n",
- mstart, mend);
- }
+ dbgprint_mem_range("Memmap after adding segment", memmap_p, *nr_range);
return 0;
}
/* Removes a segment from list of memory regions which new kernel can use to
* boot. Segment start and end should be aligned to 1K boundary. */
-static int delete_memmap(struct memory_range *memmap_p, unsigned long long addr,
- size_t size)
+static int delete_memmap(struct memory_range *memmap_p, int *nr_range,
+ unsigned long long addr, size_t size)
{
int i, j, nr_entries = 0, tidx = -1, operation = 0, align = 1024;
unsigned long long mstart, mend;
@@ -534,24 +531,17 @@ static int delete_memmap(struct memory_range *memmap_p, unsigned long long addr,
for (j = nr_entries-1; j > tidx; j--)
memmap_p[j+1] = memmap_p[j];
memmap_p[tidx+1] = temp_region;
+ *nr_range = nr_entries + 1;
}
if ((operation == -1) && tidx >=0) {
/* Delete the exact match memory region. */
for (j = i+1; j < CRASH_MAX_MEMMAP_NR; j++)
memmap_p[j-1] = memmap_p[j];
memmap_p[j-1].start = memmap_p[j-1].end = 0;
+ *nr_range = nr_entries - 1;
}
- dbgprintf("Memmap after deleting segment\n");
- for (i = 0; i < CRASH_MAX_MEMMAP_NR; i++) {
- mstart = memmap_p[i].start;
- mend = memmap_p[i].end;
- if (mstart == 0 && mend == 0) {
- break;
- }
- dbgprintf("%016llx - %016llx\n",
- mstart, mend);
- }
+ dbgprint_mem_range("Memmap after deleting segment", memmap_p, *nr_range);
return 0;
}
@@ -626,6 +616,9 @@ static int cmdline_add_memmap(char *cmdline, struct memory_range *memmap_p)
/* All regions traversed. */
break;
+ if (memmap_p[i].type != RANGE_RAM)
+ continue;
+
/* A region is not worth adding if region size < 100K. It eats
* up precious command line length. */
if ((endk - startk) < min_sizek)
@@ -797,6 +790,25 @@ static void get_backup_area(struct kexec_info *info,
info->backup_src_size = BACKUP_SRC_END - BACKUP_SRC_START + 1;
}
+static void exclude_ram(struct memory_range *mr, int *nr_mr)
+{
+ int ranges, i, j, m;
+
+ ranges = *nr_mr;
+ for (i = 0, j = 0; i < ranges; i++) {
+ if (mr[j].type == RANGE_RAM) {
+ dbgprintf("Remove RAM %016llx-%016llxx: (%d)\n", mr[j].start, mr[j].end, mr[j].type);
+ for (m = j; m < *nr_mr; m++)
+ mr[m] = mr[m+1];
+ (*nr_mr)--;
+ } else {
+ j++;
+ }
+ }
+
+ dbgprint_mem_range("After remove RAM", mr, *nr_mr);
+}
+
/* Loads additional segments in case of a panic kernel is being loaded.
* One segment for backup region, another segment for storing elf headers
* for crash memory image.
@@ -807,7 +819,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
void *tmp;
unsigned long sz, bufsz, memsz, elfcorehdr;
int nr_ranges = 0, align = 1024, i;
- struct memory_range *mem_range, *memmap_p;
+ struct memory_range *mem_range;
struct crash_elf_info elf_info;
unsigned kexec_arch;
@@ -850,10 +862,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
get_backup_area(info, mem_range, nr_ranges);
- dbgprintf("CRASH MEMORY RANGES\n");
-
- for(i = 0; i < nr_ranges; ++i)
- dbgprintf("%016Lx-%016Lx\n", mem_range[i].start, mem_range[i].end);
+ dbgprint_mem_range("CRASH MEMORY RANGES", mem_range, nr_ranges);
/*
* if the core type has not been set on command line, set it here
@@ -878,17 +887,6 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
if (get_kernel_vaddr_and_size(info, &elf_info))
return -1;
- /* Memory regions which panic kernel can safely use to boot into */
- sz = (sizeof(struct memory_range) * CRASH_MAX_MEMMAP_NR);
- memmap_p = xmalloc(sz);
- memset(memmap_p, 0, sz);
- add_memmap(memmap_p, info->backup_src_start, info->backup_src_size);
- 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*/
if (!(info->kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
sz = _ALIGN(info->backup_src_size, align);
@@ -898,8 +896,6 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
0, max_addr, -1);
dbgprintf("Created backup segment at 0x%lx\n",
info->backup_start);
- if (delete_memmap(memmap_p, info->backup_start, sz) < 0)
- return EFAILED;
}
/* Create elf header segment and store crash image data. */
@@ -915,6 +911,23 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
ELF_CORE_HEADER_ALIGN) < 0)
return EFAILED;
}
+
+ /* Memory regions which panic kernel can safely use to boot into */
+ exclude_ram(crash_memory_range, &crash_memory_ranges);
+
+ add_memmap(crash_memory_range, &crash_memory_ranges, info->backup_src_start, info->backup_src_size);
+ for (i = 0; i < crash_reserved_mem_nr; i++) {
+ sz = crash_reserved_mem[i].end - crash_reserved_mem[i].start +1;
+ if (add_memmap(crash_memory_range, &crash_memory_ranges, crash_reserved_mem[i].start, sz) < 0)
+ return ENOCRASHKERNEL;
+ }
+
+ /* exclude backup region from crash dump memory range */
+ sz = _ALIGN(info->backup_src_size, align);
+ if (delete_memmap(crash_memory_range, &crash_memory_ranges, info->backup_start, sz) < 0) {
+ return EFAILED;
+ }
+
/* the size of the elf headers allocated is returned in 'bufsz' */
/* Hack: With some ld versions (GNU ld version 2.14.90.0.4 20030523),
@@ -934,9 +947,9 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
elfcorehdr = add_buffer(info, tmp, bufsz, memsz, align, min_base,
max_addr, -1);
dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
- if (delete_memmap(memmap_p, elfcorehdr, memsz) < 0)
+ if (delete_memmap(crash_memory_range, &crash_memory_ranges, elfcorehdr, memsz) < 0)
return -1;
- cmdline_add_memmap(mod_cmdline, memmap_p);
+ cmdline_add_memmap(mod_cmdline, crash_memory_range);
if (!bzImage_support_efi_boot)
cmdline_add_efi(mod_cmdline);
cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
@@ -951,6 +964,7 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
end = mem_range[i].end;
cmdline_add_memmap_acpi(mod_cmdline, start, end);
}
+
return 0;
}
diff --git a/kexec/arch/i386/crashdump-x86.h b/kexec/arch/i386/crashdump-x86.h
index b61cf0a..633ee0e 100644
--- a/kexec/arch/i386/crashdump-x86.h
+++ b/kexec/arch/i386/crashdump-x86.h
@@ -20,7 +20,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
/* Kernel text size */
#define X86_64_KERNEL_TEXT_SIZE (512UL*1024*1024)
-#define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1)
+#define CRASH_MAX_MEMMAP_NR CRASH_MAX_MEMORY_RANGES
#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2)
/* Backup Region, First 640K of System RAM. */
@@ -28,4 +28,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
#define BACKUP_SRC_END 0x0009ffff
#define BACKUP_SRC_SIZE (BACKUP_SRC_END - BACKUP_SRC_START + 1)
+extern struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
+extern int crash_memory_ranges;
+
#endif /* CRASHDUMP_X86_H */
--
1.8.5.3
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/4] x86: add --pass-memmap-cmdline option
2014-02-13 13:10 [PATCH 0/4] kexec-tools, x86: E820 memmap pass for kdump WANG Chao
2014-02-13 13:10 ` [PATCH 1/4] add macro dbgprint_mem_range WANG Chao
2014-02-13 13:10 ` [PATCH 2/4] x86: Store memory ranges globally used for crash kernel to boot into WANG Chao
@ 2014-02-13 13:10 ` WANG Chao
2014-02-13 13:10 ` [PATCH] x86: Pass memory range via E820 for kdump WANG Chao
3 siblings, 0 replies; 9+ messages in thread
From: WANG Chao @ 2014-02-13 13:10 UTC (permalink / raw)
To: horms, vgoyal, ebiederm, hpa, trenn, dyoung; +Cc: kexec
--pass-memmap-cmdline is used for pass memmap=exactmap cmdline for 2nd
kernel. Later we will use this option to disable passing E820 memmap
method but use the old exactmap method.
Signed-off-by: WANG Chao <chaowang@redhat.com>
---
kexec/arch/i386/include/arch/options.h | 2 ++
kexec/arch/i386/kexec-x86.c | 4 ++++
kexec/arch/i386/kexec-x86.h | 1 +
kexec/arch/i386/x86-linux-setup.h | 1 +
kexec/arch/x86_64/kexec-x86_64.c | 5 +++++
5 files changed, 13 insertions(+)
diff --git a/kexec/arch/i386/include/arch/options.h b/kexec/arch/i386/include/arch/options.h
index aaac731..e5300b5 100644
--- a/kexec/arch/i386/include/arch/options.h
+++ b/kexec/arch/i386/include/arch/options.h
@@ -30,6 +30,7 @@
#define OPT_VGA (OPT_ARCH_MAX+8)
#define OPT_REAL_MODE (OPT_ARCH_MAX+9)
#define OPT_ENTRY_32BIT (OPT_ARCH_MAX+10)
+#define OPT_PASS_MEMMAP_CMDLINE (OPT_ARCH_MAX+11)
/* Options relevant to the architecture (excluding loader-specific ones): */
#define KEXEC_ARCH_OPTIONS \
@@ -41,6 +42,7 @@
{ "console-serial", 0, 0, OPT_CONSOLE_SERIAL }, \
{ "elf32-core-headers", 0, 0, OPT_ELF32_CORE }, \
{ "elf64-core-headers", 0, 0, OPT_ELF64_CORE }, \
+ { "pass-memmap-cmdline", 0, 0, OPT_PASS_MEMMAP_CMDLINE }, \
#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
diff --git a/kexec/arch/i386/kexec-x86.c b/kexec/arch/i386/kexec-x86.c
index 014ecd5..0b58dff 100644
--- a/kexec/arch/i386/kexec-x86.c
+++ b/kexec/arch/i386/kexec-x86.c
@@ -54,6 +54,7 @@ void arch_usage(void)
" --console-serial Enable the serial console\n"
" --elf32-core-headers Prepare core headers in ELF32 format\n"
" --elf64-core-headers Prepare core headers in ELF64 format\n"
+ " --pass--memmap-cmdline Pass memory map via command line in kexec on panic case\n"
);
}
@@ -64,6 +65,7 @@ struct arch_options_t arch_options = {
.console_vga = 0,
.console_serial = 0,
.core_header_type = CORE_TYPE_UNDEF,
+ .pass_memmap_cmdline = 0,
};
int arch_process_options(int argc, char **argv)
@@ -133,6 +135,8 @@ int arch_process_options(int argc, char **argv)
case OPT_ELF64_CORE:
arch_options.core_header_type = CORE_TYPE_ELF64;
break;
+ case OPT_PASS_MEMMAP_CMDLINE:
+ arch_options.pass_memmap_cmdline = 1;
}
}
/* Reset getopt for the next pass; called in other source modules */
diff --git a/kexec/arch/i386/kexec-x86.h b/kexec/arch/i386/kexec-x86.h
index 5aa2a46..e8c9188 100644
--- a/kexec/arch/i386/kexec-x86.h
+++ b/kexec/arch/i386/kexec-x86.h
@@ -50,6 +50,7 @@ struct arch_options_t {
uint8_t console_vga;
uint8_t console_serial;
enum coretype core_header_type;
+ uint8_t pass_memmap_cmdline;
};
int multiboot_x86_probe(const char *buf, off_t len);
diff --git a/kexec/arch/i386/x86-linux-setup.h b/kexec/arch/i386/x86-linux-setup.h
index 6fb84b4..b0ccd26 100644
--- a/kexec/arch/i386/x86-linux-setup.h
+++ b/kexec/arch/i386/x86-linux-setup.h
@@ -30,5 +30,6 @@ void setup_linux_system_parameters(struct kexec_info *info,
/* command line parameter may be appended by purgatory */
#define PURGATORY_CMDLINE_SIZE 64
extern int bzImage_support_efi_boot;
+extern int pass_memmap_cmdline;
#endif /* X86_LINUX_SETUP_H */
diff --git a/kexec/arch/x86_64/kexec-x86_64.c b/kexec/arch/x86_64/kexec-x86_64.c
index 5c23e01..f70851d 100644
--- a/kexec/arch/x86_64/kexec-x86_64.c
+++ b/kexec/arch/x86_64/kexec-x86_64.c
@@ -53,6 +53,7 @@ void arch_usage(void)
" --serial-baud=<baud_rate> Specify the serial port baud rate\n"
" --console-vga Enable the vga console\n"
" --console-serial Enable the serial console\n"
+ " --pass-memmap-cmdline Pass memory map via command line in kexec on panic case\n"
);
}
@@ -63,6 +64,7 @@ struct arch_options_t arch_options = {
.console_vga = 0,
.console_serial = 0,
.core_header_type = CORE_TYPE_ELF64,
+ .pass_memmap_cmdline = 0,
};
int arch_process_options(int argc, char **argv)
@@ -126,6 +128,9 @@ int arch_process_options(int argc, char **argv)
}
arch_options.serial_baud = value;
break;
+ case OPT_PASS_MEMMAP_CMDLINE:
+ arch_options.pass_memmap_cmdline = 1;
+ break;
}
}
/* Reset getopt for the next pass; called in other source modules */
--
1.8.5.3
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH] x86: Pass memory range via E820 for kdump
2014-02-13 13:10 [PATCH 0/4] kexec-tools, x86: E820 memmap pass for kdump WANG Chao
` (2 preceding siblings ...)
2014-02-13 13:10 ` [PATCH 3/4] x86: add --pass-memmap-cmdline option WANG Chao
@ 2014-02-13 13:10 ` WANG Chao
3 siblings, 0 replies; 9+ messages in thread
From: WANG Chao @ 2014-02-13 13:10 UTC (permalink / raw)
To: horms, vgoyal, ebiederm, hpa, trenn, dyoung; +Cc: kexec
command line size is restricted by kernel, sometimes memmap=exactmap has
too many memory ranges to pass to cmdline. A better approach, to pass the
memory ranges for crash kernel to boot into, is filling the memory
ranges into E820.
boot_params only got 128 slots for E820 map to fit in, when the number of
memory map exceeds 128, use setup_data to pass the rest as extended E820
memory map.
kexec boot could also benefit from setup_data in case E820 memory map
exceeds 128.
Now this new approach becomes default instead of memmap=exactmap.
saved_max_pfn users can specify --pass-memmap-cmdline to use the
exactmap approach.
Signed-off-by: WANG Chao <chaowang@redhat.com>
---
kexec/arch/i386/crashdump-x86.c | 25 +++--
kexec/arch/i386/crashdump-x86.h | 1 +
kexec/arch/i386/x86-linux-setup.c | 195 +++++++++++++++++++++++++++-----------
3 files changed, 158 insertions(+), 63 deletions(-)
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index b2c2442..9a74fba 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -182,6 +182,8 @@ static int exclude_region(int *nr_ranges, uint64_t start, uint64_t end);
struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
int crash_memory_ranges;
+int pass_memmap_cmdline;
+
/* Memory region reserved for storing panic kernel and other data. */
#define CRASH_RESERVED_MEM_NR 8
static struct memory_range crash_reserved_mem[CRASH_RESERVED_MEM_NR];
@@ -949,20 +951,23 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
if (delete_memmap(crash_memory_range, &crash_memory_ranges, elfcorehdr, memsz) < 0)
return -1;
- cmdline_add_memmap(mod_cmdline, crash_memory_range);
if (!bzImage_support_efi_boot)
cmdline_add_efi(mod_cmdline);
cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
- /* Inform second kernel about the presence of ACPI tables. */
- for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) {
- unsigned long start, end;
- if ( !( mem_range[i].type == RANGE_ACPI
- || mem_range[i].type == RANGE_ACPI_NVS) )
- continue;
- start = mem_range[i].start;
- end = mem_range[i].end;
- cmdline_add_memmap_acpi(mod_cmdline, start, end);
+ pass_memmap_cmdline = arch_options.pass_memmap_cmdline;
+ if (pass_memmap_cmdline) {
+ cmdline_add_memmap(mod_cmdline, crash_memory_range);
+ /* Inform second kernel about the presence of ACPI tables. */
+ for (i = 0; i < CRASH_MAX_MEMORY_RANGES; i++) {
+ unsigned long start, end;
+ if ( !( mem_range[i].type == RANGE_ACPI
+ || mem_range[i].type == RANGE_ACPI_NVS) )
+ continue;
+ start = mem_range[i].start;
+ end = mem_range[i].end;
+ cmdline_add_memmap_acpi(mod_cmdline, start, end);
+ }
}
return 0;
diff --git a/kexec/arch/i386/crashdump-x86.h b/kexec/arch/i386/crashdump-x86.h
index 633ee0e..e68b626 100644
--- a/kexec/arch/i386/crashdump-x86.h
+++ b/kexec/arch/i386/crashdump-x86.h
@@ -30,5 +30,6 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
extern struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
extern int crash_memory_ranges;
+extern int pass_memmap_cmdline;
#endif /* CRASHDUMP_X86_H */
diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
index 5884f4d..209652c 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -35,8 +35,7 @@
#include "kexec-x86.h"
#include "x86-linux-setup.h"
#include "../../kexec/kexec-syscall.h"
-
-#define SETUP_EFI 4
+#include "crashdump-x86.h"
void init_linux_parameters(struct x86_linux_param_header *real_mode)
{
@@ -502,6 +501,11 @@ struct efi_setup_data {
struct setup_data {
uint64_t next;
uint32_t type;
+#define SETUP_NONE 0
+#define SETUP_E820_EXT 1
+#define SETUP_DTB 2
+#define SETUP_PCI 3
+#define SETUP_EFI 4
uint32_t len;
uint8_t data[0];
} __attribute__((packed));
@@ -602,6 +606,17 @@ struct efi_info {
uint32_t efi_memmap_hi;
};
+static void add_setup_data(struct kexec_info *info,
+ struct x86_linux_param_header *real_mode,
+ struct setup_data *sd)
+{
+ int sdsize = sizeof(struct setup_data) + sd->len;
+
+ sd->next = real_mode->setup_data;
+ real_mode->setup_data = add_buffer(info, sd, sdsize, sdsize, getpagesize(),
+ 0x100000, ULONG_MAX, INT_MAX);
+}
+
/*
* setup_efi_data will collect below data and pass them to 2nd kernel.
* 1) SMBIOS, fw_vendor, runtime, config_table, they are passed via x86
@@ -611,11 +626,11 @@ struct efi_info {
static int setup_efi_data(struct kexec_info *info,
struct x86_linux_param_header *real_mode)
{
- int64_t setup_data_paddr, memmap_paddr;
+ int64_t memmap_paddr;
struct setup_data *sd;
struct efi_setup_data *esd;
struct efi_mem_descriptor *maps;
- int nr_maps, size, sdsize, ret = 0;
+ int nr_maps, size, ret = 0;
struct efi_info *ei = (struct efi_info *)real_mode->efi_info;
ret = access("/sys/firmware/efi/systab", F_OK);
@@ -648,10 +663,8 @@ static int setup_efi_data(struct kexec_info *info,
sd->len = sizeof(*esd);
memcpy(sd->data, esd, sizeof(*esd));
free(esd);
- sdsize = sd->len + sizeof(struct setup_data);
- setup_data_paddr = add_buffer(info, sd, sdsize, sdsize, getpagesize(),
- 0x100000, ULONG_MAX, INT_MAX);
- real_mode->setup_data = setup_data_paddr;
+
+ add_setup_data(info, real_mode, sd);
size = nr_maps * sizeof(struct efi_mem_descriptor);
memmap_paddr = add_buffer(info, maps, size, size, getpagesize(),
@@ -669,6 +682,119 @@ out:
return ret;
}
+static void setup_e820_ext(struct kexec_info *info, struct x86_linux_param_header *real_mode,
+ struct memory_range *range, int nr_range)
+{
+ struct setup_data *sd;
+ struct e820entry *e820;
+ int i, j, nr_range_ext;
+
+ nr_range_ext = nr_range - E820MAX;
+ sd = malloc(sizeof(struct setup_data) + nr_range_ext * sizeof(struct e820entry));
+ sd->next = 0;
+ sd->len = nr_range_ext * sizeof(struct e820entry);
+ sd->type = SETUP_E820_EXT;
+
+ e820 = (struct e820entry *) sd->data;
+ dbgprintf("Extended E820 via setup_data:\n");
+ for(i = 0, j = E820MAX; i < nr_range_ext; i++, j++) {
+ e820[i].addr = range[j].start;
+ e820[i].size = range[j].end - range[j].start;
+ switch (range[j].type) {
+ case RANGE_RAM:
+ e820[i].type = E820_RAM;
+ break;
+ case RANGE_ACPI:
+ e820[i].type = E820_ACPI;
+ break;
+ case RANGE_ACPI_NVS:
+ e820[i].type = E820_NVS;
+ break;
+ default:
+ case RANGE_RESERVED:
+ e820[i].type = E820_RESERVED;
+ break;
+ }
+ dbgprintf("%016lx-%016lx (%d)\n",
+ e820[i].addr,
+ e820[i].addr + e820[i].size - 1,
+ e820[i].type);
+
+ if (range[j].type != RANGE_RAM)
+ continue;
+ if ((range[j].start <= 0x100000) && range[j].end > 0x100000) {
+ unsigned long long mem_k = (range[j].end >> 10) - (0x100000 >> 10);
+ real_mode->ext_mem_k = mem_k;
+ real_mode->alt_mem_k = mem_k;
+ if (mem_k > 0xfc00) {
+ real_mode->ext_mem_k = 0xfc00; /* 64M */
+ }
+ if (mem_k > 0xffffffff) {
+ real_mode->alt_mem_k = 0xffffffff;
+ }
+ }
+ }
+ add_setup_data(info, real_mode, sd);
+ free(sd);
+}
+
+static void setup_e820(struct kexec_info *info, struct x86_linux_param_header *real_mode,
+ struct memory_range *range, int nr_range)
+{
+
+ int nr_range_saved = nr_range;
+ int i;
+
+ if (nr_range > E820MAX) {
+ nr_range = E820MAX;
+ }
+
+ real_mode->e820_map_nr = nr_range;
+ dbgprintf("E820 memmap:\n");
+ for(i = 0; i < nr_range; i++) {
+ real_mode->e820_map[i].addr = range[i].start;
+ real_mode->e820_map[i].size = range[i].end - range[i].start;
+ switch (range[i].type) {
+ case RANGE_RAM:
+ real_mode->e820_map[i].type = E820_RAM;
+ break;
+ case RANGE_ACPI:
+ real_mode->e820_map[i].type = E820_ACPI;
+ break;
+ case RANGE_ACPI_NVS:
+ real_mode->e820_map[i].type = E820_NVS;
+ break;
+ default:
+ case RANGE_RESERVED:
+ real_mode->e820_map[i].type = E820_RESERVED;
+ break;
+ }
+ dbgprintf("%016lx-%016lx (%d)\n",
+ real_mode->e820_map[i].addr,
+ real_mode->e820_map[i].addr + real_mode->e820_map[i].size - 1,
+ real_mode->e820_map[i].type);
+
+ if (range[i].type != RANGE_RAM)
+ continue;
+ if ((range[i].start <= 0x100000) && range[i].end > 0x100000) {
+ unsigned long long mem_k = (range[i].end >> 10) - (0x100000 >> 10);
+ real_mode->ext_mem_k = mem_k;
+ real_mode->alt_mem_k = mem_k;
+ if (mem_k > 0xfc00) {
+ real_mode->ext_mem_k = 0xfc00; /* 64M */
+ }
+ if (mem_k > 0xffffffff) {
+ real_mode->alt_mem_k = 0xffffffff;
+ }
+ }
+ }
+
+ if (nr_range_saved > E820MAX) {
+ dbgprintf("extra E820 memmap are passed via setup_data\n");
+ setup_e820_ext(info, real_mode, range, nr_range_saved);
+ }
+}
+
static int
get_efi_mem_desc_version(struct x86_linux_param_header *real_mode)
{
@@ -704,7 +830,7 @@ void setup_linux_system_parameters(struct kexec_info *info,
{
/* Fill in information the BIOS would usually provide */
struct memory_range *range;
- int i, ranges;
+ int ranges;
/* get subarch from running kernel */
setup_subarch(real_mode);
@@ -746,51 +872,14 @@ void setup_linux_system_parameters(struct kexec_info *info,
/* another safe default */
real_mode->aux_device_info = 0;
- range = info->memory_range;
- ranges = info->memory_ranges;
- if (ranges > E820MAX) {
- if (!(info->kexec_flags & KEXEC_ON_CRASH))
- /*
- * this e820 not used for capture kernel, see
- * do_bzImage_load()
- */
- fprintf(stderr,
- "Too many memory ranges, truncating...\n");
- ranges = E820MAX;
- }
- real_mode->e820_map_nr = ranges;
- for(i = 0; i < ranges; i++) {
- real_mode->e820_map[i].addr = range[i].start;
- real_mode->e820_map[i].size = range[i].end - range[i].start;
- switch (range[i].type) {
- case RANGE_RAM:
- real_mode->e820_map[i].type = E820_RAM;
- break;
- case RANGE_ACPI:
- real_mode->e820_map[i].type = E820_ACPI;
- break;
- case RANGE_ACPI_NVS:
- real_mode->e820_map[i].type = E820_NVS;
- break;
- default:
- case RANGE_RESERVED:
- real_mode->e820_map[i].type = E820_RESERVED;
- break;
- }
- if (range[i].type != RANGE_RAM)
- continue;
- if ((range[i].start <= 0x100000) && range[i].end > 0x100000) {
- unsigned long long mem_k = (range[i].end >> 10) - (0x100000 >> 10);
- real_mode->ext_mem_k = mem_k;
- real_mode->alt_mem_k = mem_k;
- if (mem_k > 0xfc00) {
- real_mode->ext_mem_k = 0xfc00; /* 64M */
- }
- if (mem_k > 0xffffffff) {
- real_mode->alt_mem_k = 0xffffffff;
- }
- }
+ if (info->kexec_flags & KEXEC_ON_CRASH && !pass_memmap_cmdline) {
+ range = crash_memory_range;
+ ranges = crash_memory_ranges;
+ } else {
+ range = info->memory_range;
+ ranges = info->memory_ranges;
}
+ setup_e820(info, real_mode, range, ranges);
/* fill the EDD information */
setup_edd_info(real_mode);
--
1.8.5.3
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply related [flat|nested] 9+ messages in thread