[RFC][PATCH 1/3] Kdump: Backup Region Handling

From: Vivek Goyal (vgoyal_at_in.ibm.com)
Date: 02/24/05

  • Next message: Vivek Goyal: "[RFC][PATCH 2/3] Kdump: Elf core Header generation"
    To: "Eric W. Biederman" <ebiederm@xmission.com>
    Date:	24 Feb 2005 21:47:11 +0530
    
    
    

    
    

    This patch adds support for reserving space for backup region. Also adds code
    in purgatory to copy the first 640K to backup region.

    ---
    Signed-off-by: Vivek Goyal <vgoyal@in.ibm.com>
    ---
    diff -puN /dev/null kexec/arch/i386/crashdump-x86.h
    --- /dev/null	2004-06-16 19:10:55.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/i386/crashdump-x86.h	2005-02-24 18:55:46.000000000 +0530
    @@ -0,0 +1,9 @@
    +#ifndef CRASHDUMP_X86_H
    +#define CRASHDUMP_X86_H
    +
    +/* Backup Region, First 640K of System RAM. */
    +#define BACKUP_START	0x00000000
    +#define BACKUP_END	0x0009ffff
    +#define BACKUP_SIZE	(BACKUP_END - BACKUP_START + 1)
    +
    +#endif /* CRASHDUMP_X86_H */
    diff -puN kexec/arch/i386/kexec-beoboot-x86.c~kexec-tools-crashdump-backup-x86 kexec/arch/i386/kexec-beoboot-x86.c
    --- kexec-tools-1.101/kexec/arch/i386/kexec-beoboot-x86.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/i386/kexec-beoboot-x86.c	2005-02-24 18:55:46.000000000 +0530
    @@ -76,7 +76,7 @@ void beoboot_usage(void)
     #define INITRD_BASE 0x1000000 /* 16MB */
     
     int beoboot_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info)
    +	struct kexec_info *info, unsigned long kexec_flags)
     {
     	struct beoboot_header bb_header;
     	const unsigned char *command_line, *kernel, *initrd;
    diff -puN kexec/arch/i386/kexec-bzImage.c~kexec-tools-crashdump-backup-x86 kexec/arch/i386/kexec-bzImage.c
    --- kexec-tools-1.101/kexec/arch/i386/kexec-bzImage.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/i386/kexec-bzImage.c	2005-02-24 18:55:46.000000000 +0530
    @@ -221,7 +221,7 @@ int do_bzImage_load(struct kexec_info *i
     }
     	
     int bzImage_load(int argc, char **argv, const char *buf, off_t len, 
    -	struct kexec_info *info)
    +	struct kexec_info *info, unsigned long kexec_flags)
     {
     	const char *command_line;
     	const char *ramdisk;
    diff -puN kexec/arch/i386/kexec-elf-x86.c~kexec-tools-crashdump-backup-x86 kexec/arch/i386/kexec-elf-x86.c
    --- kexec-tools-1.101/kexec/arch/i386/kexec-elf-x86.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/i386/kexec-elf-x86.c	2005-02-24 18:55:46.000000000 +0530
    @@ -32,10 +32,12 @@
     #include <elf.h>
     #include <x86/x86-linux.h>
     #include "../../kexec.h"
    +#include "../../kexec-syscall.h"
     #include "../../kexec-elf.h"
     #include "../../kexec-elf-boot.h"
     #include "x86-linux-setup.h"
     #include "kexec-x86.h"
    +#include "crashdump-x86.h"
     #include <arch/options.h>
     
     static const int probe_debug = 0;
    @@ -82,7 +84,7 @@ void elf_x86_usage(void)
     }
     
     int elf_x86_load(int argc, char **argv, const char *buf, off_t len, 
    -	struct kexec_info *info)
    +	struct kexec_info *info, unsigned long kexec_flags)
     {
     	struct mem_ehdr ehdr;
     	const char *command_line;
    @@ -221,6 +223,21 @@ int elf_x86_load(int argc, char **argv, 
     			ramdisk_buf = slurp_file(ramdisk, &ramdisk_length);
     		}
     
    +		/* If panic kernel is being loaded, additional segments need
    +		 * to be created. */
    +		if (kexec_flags & KEXEC_ON_CRASH) {
    +			void *tmp;
    +			unsigned long sz;
    +			int nr_ranges, align = 1024;
    +			/* Create a backup region segment to store first 638K
    +			 * memory*/
    +			sz = (BACKUP_SIZE + align - 1) & ~(align - 1);
    +			tmp = xmalloc(sz);
    +			memset(tmp, 0, sz);
    +			info->backup_start = add_buffer(info, tmp, sz, sz, 1024,
    +						0, max_addr, 1);
    +		}
    +
     		/* Tell the kernel what is going on */
     		setup_linux_bootloader_parameters(info, &hdr->hdr, param_base, 
     			offsetof(struct x86_linux_faked_param_header, command_line),
    diff -puN kexec/arch/i386/kexec-multiboot-x86.c~kexec-tools-crashdump-backup-x86 kexec/arch/i386/kexec-multiboot-x86.c
    --- kexec-tools-1.101/kexec/arch/i386/kexec-multiboot-x86.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/i386/kexec-multiboot-x86.c	2005-02-24 18:55:46.000000000 +0530
    @@ -138,7 +138,7 @@ void multiboot_x86_usage(void)
     }
     
     int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info)
    +	struct kexec_info *info, unsigned long kexec_flags)
     /* Marshal up a multiboot-style kernel */
     {
     	struct multiboot_info *mbi;
    @@ -246,7 +246,7 @@ int multiboot_x86_load(int argc, char **
     	mbi->boot_loader_name = sizeof(*mbi) + command_line_len; 
     
     	/* Memory map */
    -	if ((get_memory_ranges(&range, &ranges) < 0) || ranges == 0) {
    +	if ((get_memory_ranges(&range, &ranges, kexec_flags) < 0) || ranges == 0) {
     		fprintf(stderr, "Cannot get memory information\n");
     		return -1;
     	}
    diff -puN kexec/arch/i386/kexec-x86.c~kexec-tools-crashdump-backup-x86 kexec/arch/i386/kexec-x86.c
    --- kexec-tools-1.101/kexec/arch/i386/kexec-x86.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/i386/kexec-x86.c	2005-02-24 18:55:46.000000000 +0530
    @@ -37,7 +37,8 @@
     static struct memory_range memory_range[MAX_MEMORY_RANGES];
     
     /* Return a sorted list of memory ranges. */
    -int get_memory_ranges(struct memory_range **range, int *ranges)
    +int get_memory_ranges(struct memory_range **range, int *ranges,
    +				unsigned long kexec_flags)
     {
     	const char iomem[]= "/proc/iomem";
     	int memory_ranges = 0;
    @@ -79,6 +80,20 @@ int get_memory_ranges(struct memory_rang
     		else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
     			type = RANGE_ACPI_NVS;
     		}
    +		else if (memcmp(str, "Crash kernel\n", 13) == 0) {
    +		/* Redefine the memory region boundaries if kernel
    +		 * exports the limits and if it is panic kernel.
    +		 * Override user values only if kernel exported values are
    +		 * subset of user defined values.
    +		 */
    +			if (kexec_flags & KEXEC_ON_CRASH) {
    +				if (start > mem_min)
    +					mem_min = start;
    +				if (end < mem_max)
    +					mem_max = end;
    +			}
    +			continue;
    +		}
     		else {
     			continue;
     		}
    @@ -247,8 +262,10 @@ int arch_compat_trampoline(struct kexec_
     	return 0;
     }
     
    -void arch_update_purgatory(struct kexec_info *info)
    +void arch_update_purgatory(struct kexec_info *info, unsigned long kexec_flags)
     {
    +	uint8_t panic_kernel = 0;
    +
     	elf_rel_set_symbol(&info->rhdr, "reset_vga",
     		&arch_options.reset_vga, sizeof(arch_options.reset_vga));
     	elf_rel_set_symbol(&info->rhdr, "serial_base",
    @@ -259,4 +276,11 @@ void arch_update_purgatory(struct kexec_
     		&arch_options.console_vga, sizeof(arch_options.console_vga));
     	elf_rel_set_symbol(&info->rhdr, "console_serial", 
     		&arch_options.console_serial, sizeof(arch_options.console_serial));
    +	if (kexec_flags & KEXEC_ON_CRASH) {
    +		panic_kernel = 1;
    +		elf_rel_set_symbol(&info->rhdr, "backup_start",
    +				&info->backup_start, sizeof(info->backup_start));
    +	}
    +	elf_rel_set_symbol(&info->rhdr, "panic_kernel",
    +		&panic_kernel, sizeof(panic_kernel));
     }
    diff -puN kexec/arch/i386/kexec-x86.h~kexec-tools-crashdump-backup-x86 kexec/arch/i386/kexec-x86.h
    --- kexec-tools-1.101/kexec/arch/i386/kexec-x86.h~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/i386/kexec-x86.h	2005-02-24 18:55:46.000000000 +0530
    @@ -37,17 +37,17 @@ struct entry16_regs {
     
     int multiboot_x86_probe(const char *buf, off_t len);
     int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info);
    +	struct kexec_info *info, unsigned long kexec_flags);
     void multiboot_x86_usage(void);
     
     int elf_x86_probe(const char *buf, off_t len);
     int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info);
    +	struct kexec_info *info, unsigned long kexec_flags);
     void elf_x86_usage(void);
     
     int bzImage_probe(const char *buf, off_t len);
     int bzImage_load(int argc, char **argv, const char *buf, off_t len, 
    -	struct kexec_info *info);
    +	struct kexec_info *info, unsigned long kexec_flags);
     void bzImage_usage(void);
     int do_bzImage_load(struct kexec_info *info,
     	const char *kernel, off_t kernel_len,
    @@ -57,7 +57,7 @@ int do_bzImage_load(struct kexec_info *i
     
     int beoboot_probe(const char *buf, off_t len);
     int beoboot_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info);
    +	struct kexec_info *info, unsigned long kexec_flags);
     void beoboot_usage(void);
     
     int nbi_probe(const char *buf, off_t len);
    diff -puN kexec/arch/i386/x86-linux-setup.c~kexec-tools-crashdump-backup-x86 kexec/arch/i386/x86-linux-setup.c
    --- kexec-tools-1.101/kexec/arch/i386/x86-linux-setup.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/i386/x86-linux-setup.c	2005-02-24 18:55:46.000000000 +0530
    @@ -99,6 +99,7 @@ void setup_linux_system_parameters(struc
     	/* Fill in information the BIOS would usually provide */
     	struct memory_range *range;
     	int i, ranges;
    +	unsigned long kexec_flags = 0;
     	
     	/* Default screen size */
     	real_mode->orig_x = 0;
    @@ -135,7 +136,7 @@ void setup_linux_system_parameters(struc
     	real_mode->aux_device_info = 0;
     
     	/* Fill in the memory info */
    -	if ((get_memory_ranges(&range, &ranges) < 0) || ranges == 0) {
    +	if ((get_memory_ranges(&range, &ranges, kexec_flags) < 0) || ranges == 0) {
     		die("Cannot get memory information\n");
     	}
     	if (ranges > E820MAX) {
    diff -puN kexec/arch/ia64/kexec-elf-ia64.c~kexec-tools-crashdump-backup-x86 kexec/arch/ia64/kexec-elf-ia64.c
    --- kexec-tools-1.101/kexec/arch/ia64/kexec-elf-ia64.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/ia64/kexec-elf-ia64.c	2005-02-24 18:55:46.000000000 +0530
    @@ -78,7 +78,7 @@ void elf_ia64_usage(void)
     }
     
     int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info)
    +	struct kexec_info *info, unsigned long kexec_flags)
     {
     	struct mem_ehdr ehdr;
     	const char *command_line;
    diff -puN kexec/arch/ia64/kexec-ia64.c~kexec-tools-crashdump-backup-x86 kexec/arch/ia64/kexec-ia64.c
    --- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/ia64/kexec-ia64.c	2005-02-24 18:55:46.000000000 +0530
    @@ -38,7 +38,8 @@
     static struct memory_range memory_range[MAX_MEMORY_RANGES];
     
     /* Return a sorted list of available memory ranges. */
    -int get_memory_ranges(struct memory_range **range, int *ranges)
    +int get_memory_ranges(struct memory_range **range, int *ranges,
    +				unsigned long kexec_flags)
     {
     	int memory_ranges;
     	/*
    @@ -150,7 +151,7 @@ int arch_compat_trampoline(struct kexec_
     	return 0;
     }
     
    -void arch_update_purgatory(struct kexec_info *info)
    +void arch_update_purgatory(struct kexec_info *info, unsigned long kexec_flags)
     {
     }
     
    diff -puN kexec/arch/ia64/kexec-ia64.h~kexec-tools-crashdump-backup-x86 kexec/arch/ia64/kexec-ia64.h
    --- kexec-tools-1.101/kexec/arch/ia64/kexec-ia64.h~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/ia64/kexec-ia64.h	2005-02-24 18:55:46.000000000 +0530
    @@ -3,7 +3,7 @@
     
     int elf_ia64_probe(const char *buf, off_t len);
     int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info);
    +	struct kexec_info *info, unsigned long kexec_flags);
     void elf_ia64_usage(void);
     
     #endif /* KEXEC_IA64_H */
    diff -puN kexec/arch/ppc/kexec-dol-ppc.c~kexec-tools-crashdump-backup-x86 kexec/arch/ppc/kexec-dol-ppc.c
    --- kexec-tools-1.101/kexec/arch/ppc/kexec-dol-ppc.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/ppc/kexec-dol-ppc.c	2005-02-24 18:55:46.000000000 +0530
    @@ -320,7 +320,7 @@ void dol_ppc_usage(void)
     }
     
     int dol_ppc_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info)
    +	struct kexec_info *info, unsigned long kexec_flags)
     {
     	dol_header header, *h;
     	unsigned long entry;
    diff -puN kexec/arch/ppc/kexec-elf-ppc.c~kexec-tools-crashdump-backup-x86 kexec/arch/ppc/kexec-elf-ppc.c
    --- kexec-tools-1.101/kexec/arch/ppc/kexec-elf-ppc.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/ppc/kexec-elf-ppc.c	2005-02-24 18:55:46.000000000 +0530
    @@ -124,7 +124,7 @@ static void gamecube_hack_addresses(stru
     }
     
     int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len, 
    -	struct kexec_info *info)
    +	struct kexec_info *info, unsigned long kexec_flags)
     {
     	struct mem_ehdr ehdr;
     	char *arg_buf;
    diff -puN kexec/arch/ppc/kexec-ppc.c~kexec-tools-crashdump-backup-x86 kexec/arch/ppc/kexec-ppc.c
    --- kexec-tools-1.101/kexec/arch/ppc/kexec-ppc.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/ppc/kexec-ppc.c	2005-02-24 18:55:46.000000000 +0530
    @@ -23,7 +23,8 @@
     static struct memory_range memory_range[MAX_MEMORY_RANGES];
     
     /* Return a sorted list of memory ranges. */
    -int get_memory_ranges(struct memory_range **range, int *ranges)
    +int get_memory_ranges(struct memory_range **range, int *ranges,
    +					unsigned long kexec_flags)
     {
     	int memory_ranges = 0;
     #ifdef CONFIG_GAMECUBE
    @@ -145,7 +146,7 @@ int arch_compat_trampoline(struct kexec_
     	return 0;
     }
     
    -void arch_update_purgatory(struct kexec_info *info)
    +void arch_update_purgatory(struct kexec_info *info, unsigned long kexec_flags)
     {
     }
     
    diff -puN kexec/arch/ppc/kexec-ppc.h~kexec-tools-crashdump-backup-x86 kexec/arch/ppc/kexec-ppc.h
    --- kexec-tools-1.101/kexec/arch/ppc/kexec-ppc.h~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/ppc/kexec-ppc.h	2005-02-24 18:55:46.000000000 +0530
    @@ -17,12 +17,12 @@ extern struct {
     
     int elf_ppc_probe(const char *buf, off_t len);
     int elf_ppc_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info);
    +	struct kexec_info *info, unsigned long kexec_flags);
     void elf_ppc_usage(void);
     
     int dol_ppc_probe(const char *buf, off_t len);
     int dol_ppc_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info);
    +	struct kexec_info *info, unsigned long kexec_flags);
     void dol_ppc_usage(void);
     
     #endif /* KEXEC_PPC_H */
    diff -puN kexec/arch/ppc64/kexec-elf-ppc64.c~kexec-tools-crashdump-backup-x86 kexec/arch/ppc64/kexec-elf-ppc64.c
    --- kexec-tools-1.101/kexec/arch/ppc64/kexec-elf-ppc64.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/ppc64/kexec-elf-ppc64.c	2005-02-24 18:55:46.000000000 +0530
    @@ -95,7 +95,7 @@ int elf_ppc64_probe(const char *buf, off
     }
     
     int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len, 
    -	struct kexec_info *info)
    +	struct kexec_info *info, unsigned long kexec_flags)
     {
     	struct mem_ehdr ehdr;
     
    diff -puN kexec/arch/ppc64/kexec-ppc64.h~kexec-tools-crashdump-backup-x86 kexec/arch/ppc64/kexec-ppc64.h
    --- kexec-tools-1.101/kexec/arch/ppc64/kexec-ppc64.h~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/ppc64/kexec-ppc64.h	2005-02-24 18:55:46.000000000 +0530
    @@ -3,7 +3,7 @@
     
     int elf_ppc64_probe(const char *buf, off_t len);
     int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info);
    +	struct kexec_info *info, unsigned long kexec_flags);
     void elf_ppc64_usage(void);
     
     #endif /* KEXEC_PPC_H */
    diff -puN kexec/arch/x86_64/kexec-elf-x86_64.c~kexec-tools-crashdump-backup-x86 kexec/arch/x86_64/kexec-elf-x86_64.c
    --- kexec-tools-1.101/kexec/arch/x86_64/kexec-elf-x86_64.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/x86_64/kexec-elf-x86_64.c	2005-02-24 18:55:46.000000000 +0530
    @@ -81,7 +81,7 @@ void elf_x86_64_usage(void)
     }
     
     int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len, 
    -	struct kexec_info *info)
    +	struct kexec_info *info, unsigned long kexec_flags)
     {
     	struct mem_ehdr ehdr;
     	const char *command_line;
    diff -puN kexec/arch/x86_64/kexec-x86_64.c~kexec-tools-crashdump-backup-x86 kexec/arch/x86_64/kexec-x86_64.c
    --- kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/x86_64/kexec-x86_64.c	2005-02-24 18:55:46.000000000 +0530
    @@ -37,7 +37,8 @@
     static struct memory_range memory_range[MAX_MEMORY_RANGES];
     
     /* Return a sorted list of memory ranges. */
    -int get_memory_ranges(struct memory_range **range, int *ranges)
    +int get_memory_ranges(struct memory_range **range, int *ranges,
    +					unsigned long kexec_flags)
     {
     	const char iomem[]= "/proc/iomem";
     	int memory_ranges = 0;
    @@ -232,7 +233,7 @@ int arch_compat_trampoline(struct kexec_
     	return 0;
     }
     
    -void arch_update_purgatory(struct kexec_info *info)
    +void arch_update_purgatory(struct kexec_info *info, unsigned long kexec_flags)
     {
     	elf_rel_set_symbol(&info->rhdr, "reset_vga",
     		&arch_options.reset_vga, sizeof(arch_options.reset_vga));
    diff -puN kexec/arch/x86_64/kexec-x86_64.h~kexec-tools-crashdump-backup-x86 kexec/arch/x86_64/kexec-x86_64.h
    --- kexec-tools-1.101/kexec/arch/x86_64/kexec-x86_64.h~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/arch/x86_64/kexec-x86_64.h	2005-02-24 18:55:46.000000000 +0530
    @@ -25,7 +25,7 @@ struct entry64_regs {
     
     int elf_x86_64_probe(const char *buf, off_t len);
     int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
    -	struct kexec_info *info);
    +	struct kexec_info *info, unsigned long kexec_flags);
     void elf_x86_64_usage(void);
     
     #endif /* KEXEC_X86_64_H */
    diff -puN kexec/kexec.c~kexec-tools-crashdump-backup-x86 kexec/kexec.c
    --- kexec-tools-1.101/kexec/kexec.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/kexec.c	2005-02-24 18:55:46.000000000 +0530
    @@ -38,8 +38,8 @@
     #include "kexec-elf.h"
     #include "kexec-sha256.h"
     
    -static unsigned long long mem_min = 0;
    -static unsigned long long mem_max = ULONG_MAX;
    +unsigned long long mem_min = 0;
    +unsigned long long mem_max = ULONG_MAX;
     
     void die(char *fmt, ...)
     {
    @@ -445,7 +445,7 @@ char *slurp_decompress_file(const char *
     }
     #endif
     
    -static void update_purgatory(struct kexec_info *info)
    +static void update_purgatory(struct kexec_info *info, unsigned long kexec_flags)
     {
     	static const uint8_t null_buf[256];
     	sha256_context ctx;
    @@ -456,7 +456,7 @@ static void update_purgatory(struct kexe
     	if (!info->rhdr.e_shdr) {
     		return;
     	}
    -	arch_update_purgatory(info);
    +	arch_update_purgatory(info, kexec_flags);
     	memset(region, 0, sizeof(region));
     	sha256_starts(&ctx);
     	/* Compute a hash of the loaded kernel */
    @@ -470,6 +470,10 @@ static void update_purgatory(struct kexe
     		if (info->segment[i].mem == (void *)info->rhdr.rel_addr) {
     			continue;
     		}
    +		/* Don't include backup region in the checksum */
    +		if (info->segment[i].mem == (void *)info->backup_start) {
    +			continue;
    +		}
     		sha256_update(&ctx, info->segment[i].buf, info->segment[i].bufsz);
     		nullsz = info->segment[i].memsz - info->segment[i].bufsz;
     		while(nullsz) {
    @@ -507,6 +511,7 @@ static int my_load(const char *type, int
     	info.segment = NULL;
     	info.nr_segments = 0;
     	info.entry = NULL;
    +	info.backup_start = 0;
     
     	result = 0;
     	if (argc - fileind <= 0) {
    @@ -522,7 +527,7 @@ static int my_load(const char *type, int
     		kernel_buf, kernel_size);
     #endif
     
    -	if (get_memory_ranges(&memory_range, &memory_ranges) < 0) {
    +	if (get_memory_ranges(&memory_range, &memory_ranges, kexec_flags) < 0) {
     		fprintf(stderr, "Could not get memory layout\n");
     		return -1;
     	}
    @@ -559,7 +564,8 @@ static int my_load(const char *type, int
     			}
     		}
     	}
    -	if (file_type[i].load(argc, argv, kernel_buf, kernel_size, &info) < 0) {
    +	if (file_type[i].load(argc, argv, kernel_buf, kernel_size, &info,
    +				kexec_flags) < 0) {
     		fprintf(stderr, "Cannot load %s\n", kernel);
     		return -1;
     	}
    @@ -582,7 +588,7 @@ static int my_load(const char *type, int
     		return -1;
     	}
     	/* if purgatory is loaded update it */
    -	update_purgatory(&info);
    +	update_purgatory(&info, kexec_flags);
     #if 0
     	fprintf(stderr, "kexec_load: entry = %p flags = %lx\n", 
     		info.entry, kexec_flags);
    diff -puN kexec/kexec.h~kexec-tools-crashdump-backup-x86 kexec/kexec.h
    --- kexec-tools-1.101/kexec/kexec.h~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/kexec/kexec.h	2005-02-24 18:55:46.000000000 +0530
    @@ -91,6 +91,8 @@ do { \
     } while(0)
     #endif
     
    +extern unsigned long long mem_min, mem_max;
    +
     struct kexec_segment {
     	const void *buf;
     	size_t bufsz;
    @@ -112,10 +114,12 @@ struct kexec_info {
     	int nr_segments;
     	void *entry;
     	struct mem_ehdr rhdr;
    +	unsigned long backup_start;
     };
     
     void usage(void);
    -int get_memory_ranges(struct memory_range **range, int *ranges);
    +int get_memory_ranges(struct memory_range **range, int *ranges,
    +						unsigned long kexec_flags);
     int valid_memory_range(unsigned long sstart, unsigned long send);
     int valid_memory_segment(struct kexec_segment *segment);
     void print_segments(FILE *file, struct kexec_info *info);
    @@ -128,7 +132,7 @@ unsigned long locate_hole(struct kexec_i
     typedef int (probe_t)(const char *kernel_buf, off_t kernel_size);
     typedef int (load_t )(int argc, char **argv,
     	const char *kernel_buf, off_t kernel_size, 
    -	struct kexec_info *info);
    +	struct kexec_info *info, unsigned long kexec_flags);
     typedef void (usage_t)(void);
     struct file_type {
     	const char *name;
    @@ -189,6 +193,6 @@ extern size_t purgatory_size;
     void arch_usage(void);
     int arch_process_options(int argc, char **argv);
     int arch_compat_trampoline(struct kexec_info *info, unsigned long *flags);
    -void arch_update_purgatory(struct kexec_info *info);
    +void arch_update_purgatory(struct kexec_info *info, unsigned long kexec_flags);
     
     #endif /* KEXEC_H */
    diff -puN purgatory/arch/i386/Makefile~kexec-tools-crashdump-backup-x86 purgatory/arch/i386/Makefile
    --- kexec-tools-1.101/purgatory/arch/i386/Makefile~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/purgatory/arch/i386/Makefile	2005-02-24 18:55:46.000000000 +0530
    @@ -12,3 +12,4 @@ PURGATORY_C_SRCS+= purgatory/arch/i386/p
     PURGATORY_C_SRCS+= purgatory/arch/i386/console-x86.c
     PURGATORY_C_SRCS+= purgatory/arch/i386/vga.c
     PURGATORY_C_SRCS+= purgatory/arch/i386/pic.c
    +PURGATORY_C_SRCS+= purgatory/arch/i386/crashdump_backup.c
    diff -puN /dev/null purgatory/arch/i386/crashdump_backup.c
    --- /dev/null	2004-06-16 19:10:55.000000000 +0530
    +++ kexec-tools-1.101-root/purgatory/arch/i386/crashdump_backup.c	2005-02-24 18:55:46.000000000 +0530
    @@ -0,0 +1,44 @@
    +/*
    + * kexec: Linux boots Linux
    + *
    + * Created by:  Vivek goyal (vgoyal@in.ibm.com)
    + * Copyright (C) IBM Corporation, 2005. All rights reserved
    + *
    + * This program is free software; you can redistribute it and/or modify
    + * it under the terms of the GNU General Public License as published by
    + * the Free Software Foundation (version 2 of the License).
    + *
    + * This program is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    + * GNU General Public License for more details.
    + *
    + * You should have received a copy of the GNU General Public License
    + * along with this program; if not, write to the Free Software
    + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    + */
    +
    +#include <stdint.h>
    +#include <string.h>
    +
    +#define BACKUP_REGION_SOURCE 0x00000000
    +#define BACKUP_REGION_SIZE 0xa0000
    +
    +/* Backup region start gets set after /proc/iomem has been parsed. */
    +uint32_t backup_start = 0;
    +
    +/* Backup first 640K of memory to backup region as reserved by kexec.
    + * Assuming first 640K has to be present on i386 machines and no address
    + * validity checks have to be performed. */
    +
    +void crashdump_backup_memory(void)
    +{
    +	void *dest, *src;
    +
    +	src = (void *) BACKUP_REGION_SOURCE;
    +
    +	if (backup_start) {
    +		dest = (void *)(backup_start);
    +		memcpy(dest, src, BACKUP_REGION_SIZE);
    +	}
    +}
    diff -puN purgatory/arch/i386/purgatory-x86.c~kexec-tools-crashdump-backup-x86 purgatory/arch/i386/purgatory-x86.c
    --- kexec-tools-1.101/purgatory/arch/i386/purgatory-x86.c~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/purgatory/arch/i386/purgatory-x86.c	2005-02-24 18:55:46.000000000 +0530
    @@ -30,6 +30,7 @@ void x86_setup_cpu(void)
     uint8_t reset_vga = 0;
     uint8_t legacy_timer = 0;
     uint8_t legacy_pic   = 0;
    +uint8_t panic_kernel = 0;
     
     void setup_arch(void)
     {
    @@ -37,4 +38,5 @@ void setup_arch(void)
     	if (reset_vga)    x86_reset_vga();
     	if (legacy_pic)   x86_setup_legacy_pic();
     	/* if (legacy_timer) x86_setup_legacy_timer(); */
    +	if (panic_kernel)   crashdump_backup_memory();
     }
    diff -puN purgatory/arch/i386/purgatory-x86.h~kexec-tools-crashdump-backup-x86 purgatory/arch/i386/purgatory-x86.h
    --- kexec-tools-1.101/purgatory/arch/i386/purgatory-x86.h~kexec-tools-crashdump-backup-x86	2005-02-24 18:55:46.000000000 +0530
    +++ kexec-tools-1.101-root/purgatory/arch/i386/purgatory-x86.h	2005-02-24 18:55:46.000000000 +0530
    @@ -4,5 +4,6 @@
     void x86_reset_vga(void);
     void x86_setup_legacy_pic(void);
     void x86_setup_legacy_timer(void);
    +void crashdump_backup_memory(void);
     
     #endif /* PURGATORY_X86_H */
    _
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at  http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at  http://www.tux.org/lkml/
    

  • Next message: Vivek Goyal: "[RFC][PATCH 2/3] Kdump: Elf core Header generation"

    Relevant Pages