To support memory backup/restore an option named
--load-preserve-context is added to kexec. When it is specified
toggether with --mem-max, most segments for crash dump support are
loaded, and the memory range between mem_min to mem_max which has no
segments loaded are loaded as backup segments. To support jump back
from kexeced, options named --load-jump-back-helper and --entry are
added to load a helper image with specified entry to jump back.

Signed-off-by: Huang Ying <[EMAIL PROTECTED]>

---
 kexec/arch/i386/crashdump-x86.c     |   51 +++++++---
 kexec/arch/i386/kexec-bzImage.c     |   10 +-
 kexec/arch/i386/kexec-elf-x86.c     |    4 
 kexec/arch/i386/kexec-x86-common.c  |    3 
 kexec/arch/i386/x86-linux-setup.h   |    3 
 kexec/crashdump-elf.c               |    2 
 kexec/crashdump.c                   |    1 
 kexec/kexec-syscall.h               |    5 -
 kexec/kexec.c                       |  177 +++++++++++++++++++++++++++++++++++-
 kexec/kexec.h                       |   12 ++
 purgatory/arch/i386/purgatory-x86.c |   14 ++
 purgatory/arch/i386/setup-x86.S     |    3 
 purgatory/include/purgatory.h       |    1 
 purgatory/printf.c                  |   38 ++++++-
 14 files changed, 291 insertions(+), 33 deletions(-)

--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -75,8 +75,9 @@ static inline long kexec_reboot(void)
 }
 
 
-#define KEXEC_ON_CRASH  0x00000001
-#define KEXEC_ARCH_MASK 0xffff0000
+#define KEXEC_ON_CRASH         0x00000001
+#define KEXEC_PRESERVE_CONTEXT 0x00000002
+#define KEXEC_ARCH_MASK                0xffff0000
 
 /* These values match the ELF architecture values. 
  * Unless there is a good reason that should continue to be the case.
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -378,6 +378,91 @@ unsigned long add_buffer_virt(struct kex
                                    buf_min, buf_max, buf_end, 0);
 }
 
+static int find_memory_range(struct kexec_info *info,
+                            unsigned long *base, unsigned long *size)
+{
+       int i;
+       unsigned long start, end;
+
+       for (i = 0; i < info->memory_ranges; i++) {
+               if (info->memory_range[i].type != RANGE_RAM)
+                       continue;
+               start = info->memory_range[i].start;
+               end = info->memory_range[i].end;
+               if (end > *base && start < *base + *size) {
+                       if (start > *base) {
+                               *size = *base + *size - start;
+                               *base = start;
+                       }
+                       if (end < *base + *size)
+                               *size = end - *base;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static int find_segment_hole(struct kexec_info *info,
+                            unsigned long *base, unsigned long *size)
+{
+       int i;
+       unsigned long seg_base, seg_size;
+
+       for (i = 0; i < info->nr_segments; i++) {
+               seg_base = (unsigned long)info->segment[i].mem;
+               seg_size = info->segment[i].memsz;
+
+               if (seg_base + seg_size <= *base)
+                       continue;
+               else if (seg_base >= *base + *size)
+                       break;
+               else if (*base < seg_base) {
+                       *size = seg_base - *base;
+                       break;
+               } else if (seg_base + seg_size < *base + *size) {
+                       *size = *base + *size - (seg_base + seg_size);
+                       *base = seg_base + seg_size;
+               } else {
+                       *size = 0;
+                       break;
+               }
+       }
+       return *size;
+}
+
+int add_backup_segments(struct kexec_info *info, unsigned long backup_base,
+                       unsigned long backup_size)
+{
+       unsigned long mem_base, mem_size, bkseg_base, bkseg_size, start, end;
+       unsigned long pagesize;
+
+       pagesize = getpagesize();
+       while (backup_size) {
+               mem_base = backup_base;
+               mem_size = backup_size;
+               if (!find_memory_range(info, &mem_base, &mem_size))
+                       break;
+               backup_size = backup_base + backup_size - \
+                       (mem_base + mem_size);
+               backup_base = mem_base + mem_size;
+               while (mem_size) {
+                       bkseg_base = mem_base;
+                       bkseg_size = mem_size;
+                       if (sort_segments(info) < 0)
+                               return -1;
+                       if (!find_segment_hole(info, &bkseg_base, &bkseg_size))
+                               break;
+                       start = (bkseg_base + pagesize - 1) & ~(pagesize - 1);
+                       end = (bkseg_base + bkseg_size) & ~(pagesize - 1);
+                       add_segment(info, NULL, 0, start, end-start);
+                       mem_size = mem_base + mem_size - \
+                               (bkseg_base + bkseg_size);
+                       mem_base = bkseg_base + bkseg_size;
+               }
+       }
+       return 0;
+}
+
 char *slurp_file(const char *filename, off_t *r_size)
 {
        int fd;
@@ -581,7 +666,7 @@ static void update_purgatory(struct kexe
  *     Load the new kernel
  */
 static int my_load(const char *type, int fileind, int argc, char **argv,
-       unsigned long kexec_flags)
+                  unsigned long kexec_flags, unsigned long entry)
 {
        char *kernel;
        char *kernel_buf;
@@ -665,6 +750,9 @@ static int my_load(const char *type, int
        if (arch_compat_trampoline(&info) < 0) {
                return -1;
        }
+       if (info.kexec_flags & KEXEC_PRESERVE_CONTEXT) {
+               add_backup_segments(&info, mem_min, mem_max - mem_min + 1);
+       }
        /* Verify all of the segments load to a valid location in memory */
        for (i = 0; i < info.nr_segments; i++) {
                if (!valid_memory_segment(&info, info.segment +i)) {
@@ -681,6 +769,8 @@ static int my_load(const char *type, int
        }
        /* if purgatory is loaded update it */
        update_purgatory(&info);
+       if (entry)
+               info.entry = entry;
 #if 0
        fprintf(stderr, "kexec_load: entry = %p flags = %lx\n", 
                info.entry, info.kexec_flags);
@@ -754,6 +844,47 @@ static int my_exec(void)
        return -1;
 }
 
+static int kexec_loaded(void);
+
+static int load_jump_back_helper_image(unsigned long kexec_flags,
+                                      unsigned long entry)
+{
+       int result;
+       struct kexec_segment seg;
+
+       memset(&seg, 0, sizeof(seg));
+       result = kexec_load((void *)entry, 1, &seg,
+                           kexec_flags);
+       return result;
+}
+
+/*
+ *     Jump back to the original kernel
+ */
+static int my_load_jump_back_helper(unsigned long kexec_flags,
+                                   unsigned long entry)
+{
+       int result;
+
+       if (kexec_loaded()) {
+               fprintf(stderr, "There is kexec kernel loaded, make sure "
+                       "you are in kexeced kernel.\n");
+               return -1;
+       }
+       if (!entry) {
+               fprintf(stderr, "Please specify jump back entry "
+                       "in command line\n");
+               return -1;
+       }
+       result = load_jump_back_helper_image(kexec_flags, entry);
+       if (result) {
+               fprintf(stderr, "load jump back kernel failed: %s\n",
+                       strerror(errno));
+               return result;
+       }
+       return result;
+}
+
 static void version(void)
 {
        printf(PACKAGE_STRING " released " PACKAGE_DATE "\n");
@@ -787,6 +918,10 @@ void usage(void)
               "     --mem-max=<addr> Specify the highest memory address to\n"
               "                      load code into.\n"
               "     --reuseinird     Reuse initrd from first boot.\n"
+              "     --load-preserve-context Load the new kernel and preserve\n"
+              "                      context of current kernel during kexec.\n"
+              "     --load-jump-back-helper Load a helper image to jump back\n"
+              "                      to original kernel.\n"
               "\n"
               "Supported kernel file types and options: \n");
        for (i = 0; i < file_types; i++) {
@@ -895,11 +1030,13 @@ int main(int argc, char *argv[])
 {
        int do_load = 1;
        int do_exec = 0;
+       int do_load_jump_back_helper = 0;
        int do_shutdown = 1;
        int do_sync = 1;
        int do_ifdown = 0;
        int do_unload = 0;
        int do_reuse_initrd = 0;
+       unsigned long entry = 0;
        char *type = 0;
        char *endptr;
        int opt;
@@ -949,6 +1086,32 @@ int main(int argc, char *argv[])
                        do_ifdown = 1;
                        do_exec = 1;
                        break;
+               case OPT_LOAD_JUMP_BACK_HELPER:
+                       do_load = 0;
+                       do_shutdown = 0;
+                       do_sync = 1;
+                       do_ifdown = 1;
+                       do_exec = 0;
+                       do_load_jump_back_helper = 1;
+                       kexec_flags = KEXEC_PRESERVE_CONTEXT;
+                       break;
+               case OPT_ENTRY:
+                       entry = strtoul(optarg, &endptr, 0);
+                       if (*endptr) {
+                               fprintf(stderr,
+                                       "Bad option value in 
--load-jump-back-helper=%s\n",
+                                       optarg);
+                               usage();
+                               return 1;
+                       }
+                       break;
+               case OPT_LOAD_PRESERVE_CONTEXT:
+                       do_load = 1;
+                       do_exec = 0;
+                       do_shutdown = 0;
+                       do_sync = 1;
+                       kexec_flags = KEXEC_PRESERVE_CONTEXT;
+                       break;
                case OPT_TYPE:
                        type = optarg;
                        break;
@@ -994,6 +1157,13 @@ int main(int argc, char *argv[])
                die("Then try loading kdump kernel\n");
        }
 
+       if (do_load && (kexec_flags & KEXEC_PRESERVE_CONTEXT) &&
+           mem_max == ULONG_MAX) {
+               printf("Please specify memory range used by kexeced kernel\n");
+               printf("to preserve the context of original kernel with \n");
+               die("\"--mem-max\" parameter\n");
+       }
+
        fileind = optind;
        /* Reset getopt for the next pass; called in other source modules */
        opterr = 1;
@@ -1021,7 +1191,7 @@ int main(int argc, char *argv[])
                result = k_unload(kexec_flags);
        }
        if (do_load && (result == 0)) {
-               result = my_load(type, fileind, argc, argv, kexec_flags);
+               result = my_load(type, fileind, argc, argv, kexec_flags, entry);
        }
        /* Don't shutdown unless there is something to reboot to! */
        if ((result == 0) && (do_shutdown || do_exec) && !kexec_loaded()) {
@@ -1039,6 +1209,9 @@ int main(int argc, char *argv[])
        if ((result == 0) && do_exec) {
                result = my_exec();
        }
+       if ((result == 0) && do_load_jump_back_helper) {
+               result = my_load_jump_back_helper(kexec_flags, entry);
+       }
 
        fflush(stdout);
        fflush(stderr);
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -174,7 +174,10 @@ extern int file_types;
 #define OPT_MEM_MIN             256
 #define OPT_MEM_MAX             257
 #define OPT_REUSE_INITRD       258
-#define OPT_MAX                        259
+#define OPT_LOAD_PRESERVE_CONTEXT 259
+#define OPT_LOAD_JUMP_BACK_HELPER 260
+#define OPT_ENTRY              261
+#define OPT_MAX                        262
 #define KEXEC_OPTIONS \
        { "help",               0, 0, OPT_HELP }, \
        { "version",            0, 0, OPT_VERSION }, \
@@ -183,6 +186,9 @@ extern int file_types;
        { "load",               0, 0, OPT_LOAD }, \
        { "unload",             0, 0, OPT_UNLOAD }, \
        { "exec",               0, 0, OPT_EXEC }, \
+       { "load-preserve-context", 0, 0, OPT_LOAD_PRESERVE_CONTEXT}, \
+       { "load-jump-back-helper", 0, 0, OPT_LOAD_JUMP_BACK_HELPER }, \
+       { "entry",              1, 0, OPT_ENTRY }, \
        { "type",               1, 0, OPT_TYPE }, \
        { "load-panic",         0, 0, OPT_PANIC }, \
        { "mem-min",            1, 0, OPT_MEM_MIN }, \
@@ -242,6 +248,10 @@ int kexec_iomem_for_each_line(char *matc
 int parse_iomem_single(char *str, uint64_t *start, uint64_t *end);
 const char * proc_iomem(void);
 
+extern int add_backup_segments(struct kexec_info *info,
+                              unsigned long backup_base,
+                              unsigned long backup_size);
+
 #define MAX_LINE       160
 
 #ifdef DEBUG
--- a/kexec/arch/i386/kexec-bzImage.c
+++ b/kexec/arch/i386/kexec-bzImage.c
@@ -114,6 +114,7 @@ int do_bzImage_load(struct kexec_info *i
        unsigned int relocatable_kernel = 0;
        unsigned long kernel32_load_addr;
        char *modified_cmdline;
+       unsigned long cmdline_end;
 
        /*
         * Find out about the file I am about to load.
@@ -166,7 +167,7 @@ int do_bzImage_load(struct kexec_info *i
        /* Need to append some command line parameters internally in case of
         * taking crash dumps.
         */
-       if (info->kexec_flags & KEXEC_ON_CRASH) {
+       if (info->kexec_flags & (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT)) {
                modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
                memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE);
                if (command_line) {
@@ -205,11 +206,11 @@ int do_bzImage_load(struct kexec_info *i
                                        0x3000, 640*1024, -1, 0);
        dbgprintf("Loaded purgatory at addr 0x%lx\n", info->rhdr.rel_addr);
        /* The argument/parameter segment */
-       setup_size = kern16_size + command_line_len;
+       setup_size = kern16_size + command_line_len + PURGATORY_CMDLINE_SIZE;
        real_mode = xmalloc(setup_size);
        memcpy(real_mode, kernel, kern16_size);
 
-       if (info->kexec_flags & KEXEC_ON_CRASH) {
+       if (info->kexec_flags & (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT)) {
                /* If using bzImage for capture kernel, then we will not be
                 * executing real mode code. setup segment can be loaded
                 * anywhere as we will be just reading command line.
@@ -316,6 +317,9 @@ int do_bzImage_load(struct kexec_info *i
        elf_rel_set_symbol(&info->rhdr, "entry16_regs", &regs16, 
sizeof(regs16));
        elf_rel_set_symbol(&info->rhdr, "entry16_debug_regs", &regs16, 
sizeof(regs16));
        elf_rel_set_symbol(&info->rhdr, "entry32_regs", &regs32, 
sizeof(regs32));
+       cmdline_end = setup_base + kern16_size + command_line_len - 1;
+       elf_rel_set_symbol(&info->rhdr, "cmdline_end", &cmdline_end,
+                          sizeof(unsigned long));
 
        /* Fill in the information BIOS calls would normally provide. */
        if (!real_mode_entry) {
--- a/kexec/arch/i386/x86-linux-setup.h
+++ b/kexec/arch/i386/x86-linux-setup.h
@@ -15,4 +15,7 @@ void setup_linux_system_parameters(struc
 #define KERN32_BASE  0x100000 /* 1MB */
 #define INITRD_BASE 0x1000000 /* 16MB */
 
+/* command line parameter may be appended by purgatory */
+#define PURGATORY_CMDLINE_SIZE 64
+
 #endif /* X86_LINUX_SETUP_H */
--- a/purgatory/arch/i386/purgatory-x86.c
+++ b/purgatory/arch/i386/purgatory-x86.c
@@ -31,6 +31,8 @@ uint8_t reset_vga = 0;
 uint8_t legacy_timer = 0;
 uint8_t legacy_pic   = 0;
 uint8_t panic_kernel = 0;
+unsigned long jump_back_entry = 0;
+char *cmdline_end = 0;
 
 void setup_arch(void)
 {
@@ -40,8 +42,18 @@ void setup_arch(void)
        /* if (legacy_timer) x86_setup_legacy_timer(); */
 }
 
+extern void x86_setup_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();
+}
+
+void x86_setup_jump_back_entry()
+{
+       if (cmdline_end)
+               sprintf(cmdline_end, " kexec_jump_back_entry=0x%x",
+                       jump_back_entry);
 }
--- a/purgatory/arch/i386/setup-x86.S
+++ b/purgatory/arch/i386/setup-x86.S
@@ -41,6 +41,9 @@ purgatory_start:
        ljmp    $0x10,$1f
 1:             
 
+       movl    0(%esp), %eax
+       movl    %eax, jump_back_entry
+
        /* Setup a stack */
        movl    $lstack_end, %esp
 
--- a/purgatory/printf.c
+++ b/purgatory/printf.c
@@ -33,19 +33,23 @@ PRINTF and friends
                %s      - string
        Note: width specification not supported
 **************************************************************************/
-void printf(const char *fmt, ...)
+void vsprintf(char *buffer, const char *fmt, va_list args)
 {
-       va_list args;
        char *p;
-       va_start(args, fmt);
        for ( ; *fmt != '\0'; ++fmt) {
                if (*fmt != '%') {
-                       putchar(*fmt);
+                       if (buffer)
+                               *buffer++ = *fmt;
+                       else
+                               putchar(*fmt);
                        continue;
                }
                if (*++fmt == 's') {
                        for(p = va_arg(args, char *); *p != '\0'; p++) 
-                               putchar(*p);
+                               if (buffer)
+                                       *buffer++ = *p;
+                               else
+                                       putchar(*p);
                }
                else {  /* Length of item is bounded */
                        char tmp[40], *q = tmp;
@@ -121,8 +125,30 @@ void printf(const char *fmt, ...)
                                *q++ = *fmt;
                        /* now output the saved string */
                        for (p = tmp; p < q; ++p)
-                               putchar(*p);
+                               if (buffer)
+                                       *buffer++ = *p;
+                               else
+                                       putchar(*p);
                }
        }
+       if (buffer)
+               *buffer = '\0';
+}
+
+void sprintf(char *buffer, const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       vsprintf(buffer, fmt, args);
+       va_end(args);
+}
+
+void printf(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       vsprintf(0, fmt, args);
        va_end(args);
 }
--- a/purgatory/include/purgatory.h
+++ b/purgatory/include/purgatory.h
@@ -2,6 +2,7 @@
 #define PURGATORY_H
 
 void putchar(int ch);
+void sprintf(char *buffer, const char *fmt, ...);
 void printf(const char *fmt, ...);
 void setup_arch(void);
 void post_verification_setup_arch(void);
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -57,7 +57,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;
@@ -74,10 +75,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;
@@ -128,6 +131,22 @@ static int get_crash_memory_ranges(struc
                }
        }
        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("Too small mem_max: 0x%lx.\n", mem_max);
+                       return -1;
+               }
+               crash_reserved_mem.end = mem_max;
+               crash_reserved_mem.type = RANGE_RAM;
+       }
        if (exclude_crash_reserve_region(&memory_ranges) < 0)
                return -1;
        *range = crash_memory_range;
@@ -514,7 +533,8 @@ int load_crashdump_segments(struct kexec
        int nr_ranges, align = 1024;
        struct memory_range *mem_range, *memmap_p;
 
-       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;
 
        /*
@@ -535,14 +555,17 @@ 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);
-       dbgprintf("Created backup segment at 0x%lx\n", info->backup_start);
-       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);
+               dbgprintf("Created backup segment at 0x%lx\n",
+                         info->backup_start);
+               if (delete_memmap(memmap_p, info->backup_start, sz) < 0)
+                       return -1;
+       }
 
        /* Create elf header segment and store crash image data. */
        if (arch_options.core_header_type == CORE_TYPE_ELF64) {
--- a/kexec/crashdump-elf.c
+++ b/kexec/crashdump-elf.c
@@ -164,7 +164,7 @@ int FUNC(struct kexec_info *info,
                dbgprintf_phdr("Elf header", phdr);
        }
 
-       if (has_vmcoreinfo) {
+       if (has_vmcoreinfo && !(info->kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
                phdr = (PHDR *) bufp;
                bufp += sizeof(PHDR);
                phdr->p_type    = PT_NOTE;
--- a/kexec/arch/i386/kexec-elf-x86.c
+++ b/kexec/arch/i386/kexec-elf-x86.c
@@ -170,7 +170,7 @@ int elf_x86_load(int argc, char **argv, 
        /* Need to append some command line parameters internally in case of
         * taking crash dumps.
         */
-       if (info->kexec_flags & KEXEC_ON_CRASH) {
+       if (info->kexec_flags & (KEXEC_ON_CRASH|KEXEC_PRESERVE_CONTEXT)) {
                modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
                memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE);
                if (command_line) {
@@ -257,7 +257,7 @@ int elf_x86_load(int argc, char **argv, 
 
                /* If panic kernel is being loaded, additional segments need
                 * to be created. */
-               if (info->kexec_flags & KEXEC_ON_CRASH) {
+               if (info->kexec_flags & 
(KEXEC_ON_CRASH|KEXEC_PRESERVE_CONTEXT)) {
                        rc = load_crashdump_segments(info, modified_cmdline,
                                                max_addr, 0);
                        if (rc < 0)
--- a/kexec/arch/i386/kexec-x86-common.c
+++ b/kexec/arch/i386/kexec-x86-common.c
@@ -174,7 +174,8 @@ int get_memory_ranges(struct memory_rang
         * Override user values only if kernel exported values are
         * subset of user defined values.
         */
-       if (kexec_flags & KEXEC_ON_CRASH) {
+       if ((kexec_flags & KEXEC_ON_CRASH) &&
+           !(kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
                unsigned long long start, end;
 
                ret = parse_iomem_single("Crash kernel\n", &start, &end);
--- a/kexec/crashdump.c
+++ b/kexec/crashdump.c
@@ -29,6 +29,7 @@
 #include <elf.h>
 #include "kexec.h"
 #include "crashdump.h"
+#include "kexec-syscall.h"
 
 /* include "crashdump-elf.c" twice to create two functions from one */
 

Attachment: signature.asc
Description: This is a digitally signed message part

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to