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