[PATCH] kexec jump support for x86_64

Huang Ying ying.huang at intel.com
Tue Dec 8 20:45:42 EST 2009


x86_64 specific support, including crash memory range and purgatory setup.
Corresponding kernel support has been merged already.

Signed-off-by: Huang Ying <ying.huang at intel.com>

---
 kexec/arch/x86_64/crashdump-x86_64.c     |   48 ++++++++++++++++++++++---------
 purgatory/arch/x86_64/purgatory-x86_64.c |   11 ++++++-
 purgatory/arch/x86_64/setup-x86_64.S     |    3 +
 3 files changed, 48 insertions(+), 14 deletions(-)

--- a/kexec/arch/x86_64/crashdump-x86_64.c
+++ b/kexec/arch/x86_64/crashdump-x86_64.c
@@ -161,7 +161,8 @@ static struct memory_range crash_reserve
  * to look into down the line. May be something like /proc/kernelmem or may
  * be zone data structures exported from kernel.
  */
-static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
+static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
+				   int kexec_flags)
 {
 	const char *iomem= proc_iomem();
 	int memory_ranges = 0, gart = 0;
@@ -179,10 +180,12 @@ static int get_crash_memory_ranges(struc
 
 	/* First entry is for first 640K region. Different bios report first
 	 * 640K in different manner hence hardcoding it */
-	crash_memory_range[0].start = 0x00000000;
-	crash_memory_range[0].end = 0x0009ffff;
-	crash_memory_range[0].type = RANGE_RAM;
-	memory_ranges++;
+	if (!(kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
+		crash_memory_range[0].start = 0x00000000;
+		crash_memory_range[0].end = 0x0009ffff;
+		crash_memory_range[0].type = RANGE_RAM;
+		memory_ranges++;
+	}
 
 	while(fgets(line, sizeof(line), fp) != 0) {
 		char *str;
@@ -239,6 +242,22 @@ static int get_crash_memory_ranges(struc
 		memory_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_memory_range[i].start;
+				break;
+			}
+		}
+		if (crash_reserved_mem.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;
+	}
 	if (exclude_region(&memory_ranges, crash_reserved_mem.start,
 				crash_reserved_mem.end) < 0)
 		return -1;
@@ -590,7 +609,8 @@ int load_crashdump_segments(struct kexec
 	if (get_kernel_vaddr_and_size(info))
 		return -1;
 
-	if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
+	if (get_crash_memory_ranges(&mem_range, &nr_ranges,
+				    info->kexec_flags) < 0)
 		return -1;
 
 	/* Memory regions which panic kernel can safely use to boot into */
@@ -602,13 +622,15 @@ int load_crashdump_segments(struct kexec
 	add_memmap(memmap_p, crash_reserved_mem.start, sz);
 
 	/* Create a backup region segment to store backup data*/
-	sz = (BACKUP_SRC_SIZE + align - 1) & ~(align - 1);
-	tmp = xmalloc(sz);
-	memset(tmp, 0, sz);
-	info->backup_start = add_buffer(info, tmp, sz, sz, align,
-				0, max_addr, 1);
-	if (delete_memmap(memmap_p, info->backup_start, sz) < 0)
-		return -1;
+	if (!(info->kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
+		sz = (BACKUP_SRC_SIZE + align - 1) & ~(align - 1);
+		tmp = xmalloc(sz);
+		memset(tmp, 0, sz);
+		info->backup_start = add_buffer(info, tmp, sz, sz, align,
+						0, max_addr, 1);
+		if (delete_memmap(memmap_p, info->backup_start, sz) < 0)
+			return -1;
+	}
 
 	/* Create elf header segment and store crash image data. */
 	if (crash_create_elf64_headers(info, &elf_info,
--- a/purgatory/arch/x86_64/purgatory-x86_64.c
+++ b/purgatory/arch/x86_64/purgatory-x86_64.c
@@ -6,6 +6,7 @@
 uint8_t reset_vga = 0;
 uint8_t legacy_pic = 0;
 uint8_t panic_kernel = 0;
+unsigned long jump_back_entry = 0;
 char *cmdline_end = NULL;
 
 void setup_arch(void)
@@ -14,8 +15,16 @@ void setup_arch(void)
 	if (legacy_pic)   x86_setup_legacy_pic();
 }
 
+void x86_setup_jump_back_entry(void)
+{
+	if (cmdline_end)
+		sprintf(cmdline_end, " kexec_jump_back_entry=0x%lx",
+			jump_back_entry);
+}
+
 /* This function can be used to execute after the SHA256 verification. */
 void post_verification_setup_arch(void)
 {
-	 if (panic_kernel)   crashdump_backup_memory();
+	if (panic_kernel)    crashdump_backup_memory();
+	if (jump_back_entry) x86_setup_jump_back_entry();
 }
--- a/purgatory/arch/x86_64/setup-x86_64.S
+++ b/purgatory/arch/x86_64/setup-x86_64.S
@@ -41,6 +41,9 @@ purgatory_start:
 
 	/* In 64bit mode the code segment is meaningless */
 
+	movq	0(%rsp), %rax
+	movq	%rax, jump_back_entry
+
 	/* Setup a stack */
 	movq	$lstack_end, %rsp
 





More information about the kexec mailing list