public inbox for kexec@lists.infradead.org
 help / color / mirror / Atom feed
From: WANG Chao <chaowang@redhat.com>
To: horms@verge.net.au, vgoyal@redhat.com, ebiederm@xmission.com,
	hpa@zytor.com, trenn@suse.de, dyoung@redhat.com, linn@hp.com
Cc: kexec@lists.infradead.org
Subject: [PATCH v6 9/9] x86: Pass memory range via E820 for kdump
Date: Mon, 14 Apr 2014 22:55:41 +0800	[thread overview]
Message-ID: <1397487341-17287-10-git-send-email-chaowang@redhat.com> (raw)
In-Reply-To: <1397487341-17287-1-git-send-email-chaowang@redhat.com>

command line size is restricted by kernel, sometimes memmap=exactmap has
too many memory ranges to pass to cmdline. And also memmap=exactmap and
kASLR doesn't work together.

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>
Tested-by: Linn Crosetto <linn@hp.com>
Reviewed-by: Linn Crosetto <linn@hp.com>
---
 kexec/arch/i386/crashdump-x86.c   |   6 +-
 kexec/arch/i386/x86-linux-setup.c | 149 +++++++++++++++++++++++++-------------
 kexec/arch/i386/x86-linux-setup.h |   1 +
 3 files changed, 103 insertions(+), 53 deletions(-)

diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 7b618a6..4a1491b 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -979,7 +979,8 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
 	dbgprintf("Created elf header segment at 0x%lx\n", elfcorehdr);
 	if (delete_memmap(memmap_p, &nr_memmap, elfcorehdr, memsz) < 0)
 		return -1;
-	cmdline_add_memmap(mod_cmdline, memmap_p);
+	if (arch_options.pass_memmap_cmdline)
+		cmdline_add_memmap(mod_cmdline, memmap_p);
 	if (!bzImage_support_efi_boot)
 		cmdline_add_efi(mod_cmdline);
 	cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
@@ -995,7 +996,8 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
 		type = mem_range[i].type;
 		size = end - start + 1;
 		add_memmap(memmap_p, &nr_memmap, start, size, type);
-		cmdline_add_memmap_acpi(mod_cmdline, start, end);
+		if (arch_options.pass_memmap_cmdline)
+			cmdline_add_memmap_acpi(mod_cmdline, start, end);
 	}
 
 	/* Store 2nd kernel boot memory ranges for later reference in
diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c
index 9f8355f..4437ed7 100644
--- a/kexec/arch/i386/x86-linux-setup.c
+++ b/kexec/arch/i386/x86-linux-setup.c
@@ -36,8 +36,6 @@
 #include "x86-linux-setup.h"
 #include "../../kexec/kexec-syscall.h"
 
-#define SETUP_EFI	4
-
 void init_linux_parameters(struct x86_linux_param_header *real_mode)
 {
 	/* Fill in the values that are usually provided by the kernel. */
@@ -502,6 +500,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));
@@ -684,6 +687,98 @@ out:
 	return ret;
 }
 
+static void add_e820_map_from_mr(struct x86_linux_param_header *real_mode,
+			struct e820entry *e820, struct memory_range *range, int nr_range)
+{
+	int i;
+
+	for (i = 0; i < nr_range; i++) {
+		e820[i].addr = range[i].start;
+		e820[i].size = range[i].end - range[i].start + 1;
+		switch (range[i].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[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;
+			}
+		}
+	}
+}
+
+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 nr_range_ext;
+
+	nr_range_ext = nr_range - E820MAX;
+	sd = xmalloc(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");
+	add_e820_map_from_mr(real_mode, e820, range + E820MAX, nr_range_ext);
+	add_setup_data(info, real_mode, sd);
+}
+
+static void setup_e820(struct kexec_info *info, struct x86_linux_param_header *real_mode)
+{
+	struct memory_range *range;
+	int nr_range, nr_range_saved;
+
+
+	if (info->kexec_flags & KEXEC_ON_CRASH && !arch_options.pass_memmap_cmdline) {
+		range = info->crash_range;
+		nr_range = info->nr_crash_ranges;
+	} else {
+		range = info->memory_range;
+		nr_range = info->memory_ranges;
+	}
+
+	nr_range_saved = nr_range;
+	if (nr_range > E820MAX) {
+		nr_range = E820MAX;
+	}
+
+	real_mode->e820_map_nr = nr_range;
+	dbgprintf("E820 memmap:\n");
+	add_e820_map_from_mr(real_mode, real_mode->e820_map, range, nr_range);
+
+	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)
 {
@@ -725,10 +820,6 @@ out:
 void setup_linux_system_parameters(struct kexec_info *info,
 				   struct x86_linux_param_header *real_mode)
 {
-	/* Fill in information the BIOS would usually provide */
-	struct memory_range *range;
-	int i, ranges;
-
 	/* get subarch from running kernel */
 	setup_subarch(real_mode);
 	if (bzImage_support_efi_boot)
@@ -769,51 +860,7 @@ 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 + 1;
-		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;
-			}
-		}
-	}
+	setup_e820(info, real_mode);
 
 	/* fill the EDD information */
 	setup_edd_info(real_mode);
diff --git a/kexec/arch/i386/x86-linux-setup.h b/kexec/arch/i386/x86-linux-setup.h
index 6fb84b4..f5d23d3 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 struct arch_options_t arch_options;
 
 #endif /* X86_LINUX_SETUP_H */
-- 
1.9.0


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

  parent reply	other threads:[~2014-04-14 14:56 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-14 14:55 [PATCH v6 0/9] kexec-tools, x86: E820 memmap pass for kdump WANG Chao
2014-04-14 14:55 ` [PATCH v6 1/9] x86, cleanup: add extra arguments to add_memmap() and delete_memmap() WANG Chao
2014-04-14 14:55 ` [PATCH v6 2/9] x86, cleanup: add_memmap() only do alignment check on RANGE_RAM WANG Chao
2014-04-14 14:55 ` [PATCH v6 3/9] x86, cleanup: add other types of memory range for 2nd kernel boot to memmap_p WANG Chao
2014-04-14 14:55 ` [PATCH v6 4/9] x86, cleanup: use dbgprint_mem_range for memory range debugging WANG Chao
2014-04-14 14:55 ` [PATCH v6 5/9] x86, cleanup: increase CRASH_MAX_MEMMAP_NR up to CRASH_MAX_MEMORY_RANGES WANG Chao
2014-04-14 14:55 ` [PATCH v6 6/9] x86, cleanup: Store crash memory ranges kexec_info WANG Chao
2014-04-14 14:55 ` [PATCH v6 7/9] x86, cleanup: kexec memory range .end to be inclusive WANG Chao
2014-04-14 14:55 ` [PATCH v6 8/9] x86: add --pass-memmap-cmdline option WANG Chao
2014-04-14 14:55 ` WANG Chao [this message]
2014-04-17  5:29   ` [PATCH v6 9/9] x86: Pass memory range via E820 for kdump Dave Young
2014-04-17  5:35     ` Dave Young
2014-04-17  6:17       ` WANG Chao
2014-04-17  6:32         ` Dave Young
2014-04-17  6:44           ` Dave Young
2014-04-17  6:52             ` Dave Young
2014-04-17  7:05             ` WANG Chao
2014-04-17  6:57           ` WANG Chao
2014-04-17  7:07             ` Dave Young
2014-04-17  7:17               ` WANG Chao
2014-04-17  7:30                 ` Dave Young
2014-04-17  8:42                   ` WANG Chao
2014-04-17  9:45                     ` Dave Young
2014-04-17 10:38                       ` WANG Chao
2014-04-17  5:48     ` WANG Chao
2014-04-17  5:58       ` Dave Young
2014-04-21  0:01         ` Simon Horman
2014-04-21  2:49           ` WANG Chao
2014-04-21 15:16             ` Dave Young
2014-04-17  5:38 ` [PATCH v6 0/9] kexec-tools, x86: E820 memmap pass " Dave Young
2014-04-17  6:24 ` WANG Chao
2014-04-17 21:38   ` Linn Crosetto
2014-04-18 19:57   ` Linn Crosetto
2014-04-17  7:32 ` Dave Young

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1397487341-17287-10-git-send-email-chaowang@redhat.com \
    --to=chaowang@redhat.com \
    --cc=dyoung@redhat.com \
    --cc=ebiederm@xmission.com \
    --cc=horms@verge.net.au \
    --cc=hpa@zytor.com \
    --cc=kexec@lists.infradead.org \
    --cc=linn@hp.com \
    --cc=trenn@suse.de \
    --cc=vgoyal@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox