summaryrefslogtreecommitdiff
path: root/kexec
diff options
context:
space:
mode:
authorHuang Ying <ying.huang@intel.com>2009-12-09 15:04:57 +0800
committerSimon Horman <horms@verge.net.au>2009-12-10 10:17:30 +1100
commit0f89d6658e077b043b6481af6a04715bf49472b8 (patch)
tree18bb3a914ed2072b3931611fd7ec8fe6a7a0bcb1 /kexec
parent523cc35be9ba3cae86b145de5b540c5b7e3bb43f (diff)
kexec jump support for x86_64
x86_64 specific support, including crash memory range and purgatory setup. Corresponding kernel support has been merged already. Together with the kexec jump features in Linux kernel, kexec jump can be used for following: - A simple hibernation implementation without ACPI support. You can kexec a hibernating kernel, save the memory image of original system and shutdown the system. When resuming, you restore the memory image of original system via ordinary kexec load then jump back. - Kernel/system debug through making system snapshot. You can make system snapshot with kexec/kdump, jump back, do some thing and make another system snapshot. - Cooperative multi-kernel/system. With kexec jump, you can switch between several kernels/systems quickly without boot process except the first time. This appears like swap a whole kernel/system out/in. - A general method to call program in physical mode (paging turning off). This can be used to invoke BIOS code under Linux. Signed-off-by: Huang Ying <ying.huang@intel.com> Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'kexec')
-rw-r--r--kexec/arch/x86_64/crashdump-x86_64.c48
1 files changed, 35 insertions, 13 deletions
diff --git a/kexec/arch/x86_64/crashdump-x86_64.c b/kexec/arch/x86_64/crashdump-x86_64.c
index 9129458..8e33177 100644
--- 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_reserved_mem;
* 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(struct memory_range **range, int *ranges)
/* 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(struct memory_range **range, int *ranges)
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_info *info, char* mod_cmdline,
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_info *info, char* mod_cmdline,
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,