[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