From: Vivek Goyal <vgoyal@in.ibm.com>

This patch adds support for reserving 640k memory as backup region as
required by crashdump kernel for x86.

Signed-off-by: Vivek Goyal <vgoyal@in.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/Documentation/kernel-parameters.txt |    5 +++++
 25-akpm/arch/i386/kernel/setup.c            |   26 ++++++++++++++++++++++++--
 25-akpm/arch/i386/mm/discontig.c            |    8 ++++++++
 25-akpm/include/linux/crash_dump.h          |    1 +
 25-akpm/include/linux/kexec.h               |    6 +++++-
 25-akpm/kernel/crash_dump.c                 |    3 +++
 25-akpm/kernel/kexec.c                      |    8 ++++++++
 7 files changed, 54 insertions(+), 3 deletions(-)

diff -puN arch/i386/kernel/setup.c~crashdump-reserving-backup-region-for-kexec-based arch/i386/kernel/setup.c
--- 25/arch/i386/kernel/setup.c~crashdump-reserving-backup-region-for-kexec-based	2005-01-23 01:51:11.604628880 -0800
+++ 25-akpm/arch/i386/kernel/setup.c	2005-01-23 01:51:11.617626904 -0800
@@ -41,6 +41,7 @@
 #include <linux/init.h>
 #include <linux/edd.h>
 #include <linux/kexec.h>
+#include <linux/crash_dump.h>
 #include <video/edid.h>
 #include <asm/apic.h>
 #include <asm/e820.h>
@@ -51,7 +52,6 @@
 #include <asm/io_apic.h>
 #include <asm/ist.h>
 #include <asm/io.h>
-#include <asm/crash_dump.h>
 #include "setup_arch_pre.h"
 #include <bios_ebda.h>
 
@@ -854,7 +854,20 @@ static void __init parse_cmdline_early (
 			}
 		}
 #endif
-
+#ifdef CONFIG_CRASH_DUMP
+		/* crashbackup=size@addr specifies the location of backup
+		 * region where, crashed kernel has stored some backup data.
+		 */
+		else if (!memcmp(from, "crashbackup=", 12)) {
+			unsigned long size, base;
+			size = memparse(from+12, &from);
+			if (*from == '@') {
+				base = memparse(from+1, &from);
+				crashbackup_start = base;
+				crashbackup_end  = base + size - 1;
+			}
+		}
+#endif
 		/*
 		 * highmem=size forces highmem to be exactly 'size' bytes.
 		 * This works even on boxes that have no highmem otherwise.
@@ -1161,6 +1174,14 @@ static unsigned long __init setup_memory
 #ifdef CONFIG_KEXEC
 	if (crashk_res.start != crashk_res.end) {
 		reserve_bootmem(crashk_res.start, crashk_res.end - crashk_res.start + 1);
+
+#define CRASHDUMP_BACKUP_SZ 0xa0000
+		/* Steal 640K from top of reserved region for crash kernel */
+		if ((crashk_res.end - crashk_res.start) > CRASHDUMP_BACKUP_SZ) {
+			crashdumpk_res.end = crashk_res.end;
+			crashk_res.end = crashk_res.end - CRASHDUMP_BACKUP_SZ;
+			crashdumpk_res.start = crashk_res.end + 1;
+		}
 	}
 #endif
 	return max_low_pfn;
@@ -1204,6 +1225,7 @@ legacy_init_iomem_resources(struct resou
 			request_resource(res, data_resource);
 #ifdef CONFIG_KEXEC
 			request_resource(res, &crashk_res);
+			request_resource(res, &crashdumpk_res);
 #endif
 		}
 	}
diff -puN arch/i386/mm/discontig.c~crashdump-reserving-backup-region-for-kexec-based arch/i386/mm/discontig.c
--- 25/arch/i386/mm/discontig.c~crashdump-reserving-backup-region-for-kexec-based	2005-01-23 01:51:11.605628728 -0800
+++ 25-akpm/arch/i386/mm/discontig.c	2005-01-23 01:51:11.618626752 -0800
@@ -29,6 +29,7 @@
 #include <linux/highmem.h>
 #include <linux/initrd.h>
 #include <linux/nodemask.h>
+#include <linux/ioport.h>
 #include <linux/kexec.h>
 #include <asm/e820.h>
 #include <asm/setup.h>
@@ -371,6 +372,13 @@ unsigned long __init setup_memory(void)
 #ifdef CONFIG_KEXEC
 	if (crashk_res.start != crashk_res.end) {
 		reserve_bootmem(crashk_res.start, crashk_res.end - crashk_res.start + 1);
+#define CRASHDUMP_BACKUP_SZ 0xa0000
+		/* Steal 640K from top of reserved region for crash kernel */
+		if ((crashk_res.end - crashk_res.start) > CRASHDUMP_BACKUP_SZ) {
+			crashdumpk_res.end = crashk_res.end;
+			crashk_res.end = crashk_res.end - CRASHDUMP_BACKUP_SZ;
+			crashdumpk_res.start = crashk_res.end + 1;
+		}
 	}
 #endif
 	return system_max_low_pfn;
diff -puN Documentation/kernel-parameters.txt~crashdump-reserving-backup-region-for-kexec-based Documentation/kernel-parameters.txt
--- 25/Documentation/kernel-parameters.txt~crashdump-reserving-backup-region-for-kexec-based	2005-01-23 01:51:11.607628424 -0800
+++ 25-akpm/Documentation/kernel-parameters.txt	2005-01-23 01:51:11.619626600 -0800
@@ -27,6 +27,7 @@ restrictions referred to are that the re
 	APM	Advanced Power Management support is enabled.
 	AX25	Appropriate AX.25 support is enabled.
 	CD	Appropriate CD support is enabled.
+	CRASHDUMP Crash Dump support is enabled.
 	DEVFS	devfs support is enabled. 
 	DRM	Direct Rendering Management support is enabled. 
 	EDD	BIOS Enhanced Disk Drive Services (EDD) is enabled
@@ -345,6 +346,10 @@ running once the system is up.
 			[KNL] Reserve a chunk of physical memory to
 			hold a kernel to switch to with kexec on panic.
 
+	crashbackup=nn[KMG]@ss[KMG]
+			[KNL, CRASHDUMP] Specifies the location of crash data
+			backup region.
+
 	cs4232=		[HW,OSS]
 			Format: <io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>
 
diff -puN include/linux/crash_dump.h~crashdump-reserving-backup-region-for-kexec-based include/linux/crash_dump.h
--- 25/include/linux/crash_dump.h~crashdump-reserving-backup-region-for-kexec-based	2005-01-23 01:51:11.609628120 -0800
+++ 25-akpm/include/linux/crash_dump.h	2005-01-23 01:51:11.619626600 -0800
@@ -15,6 +15,7 @@ extern void elf_kcore_store_hdr(char *, 
 #ifdef CONFIG_CRASH_DUMP
 extern struct file_operations proc_vmcore_operations;
 extern struct proc_dir_entry *proc_vmcore;
+extern unsigned long crashbackup_start, crashbackup_end;
 
 extern ssize_t copy_oldmem_page(unsigned long, char *, size_t, int);
 extern void crash_create_proc_entry(void);
diff -puN include/linux/kexec.h~crashdump-reserving-backup-region-for-kexec-based include/linux/kexec.h
--- 25/include/linux/kexec.h~crashdump-reserving-backup-region-for-kexec-based	2005-01-23 01:51:11.610627968 -0800
+++ 25-akpm/include/linux/kexec.h	2005-01-23 01:51:11.620626448 -0800
@@ -79,7 +79,7 @@ struct kimage {
 	unsigned long control_page;
 
 	/* Flags to indicate special processing */
-	int type : 1;
+	unsigned int type : 1;
 #define KEXEC_TYPE_DEFAULT 0
 #define KEXEC_TYPE_CRASH   1
 };
@@ -122,6 +122,10 @@ extern struct kimage *kexec_crash_image;
  */
 extern struct resource crashk_res;
 
+/* Location of backup region to hold the crashdump kernel data.
+ */
+extern struct resource crashdumpk_res;
+
 #else /* !CONFIG_KEXEC */
 static inline void crash_kexec(void) { }
 #endif /* CONFIG_KEXEC */
diff -puN kernel/crash_dump.c~crashdump-reserving-backup-region-for-kexec-based kernel/crash_dump.c
--- 25/kernel/crash_dump.c~crashdump-reserving-backup-region-for-kexec-based	2005-01-23 01:51:11.612627664 -0800
+++ 25-akpm/kernel/crash_dump.c	2005-01-23 01:51:11.620626448 -0800
@@ -15,6 +15,9 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
+/* Location of crashdump backup region if there is one. */
+unsigned long crashbackup_start, crashbackup_end;
+
 /*
  * Copy a page from "oldmem". For this page, there is no pte mapped
  * in the current kernel. We stitch up a pte, similar to kmap_atomic.
diff -puN kernel/kexec.c~crashdump-reserving-backup-region-for-kexec-based kernel/kexec.c
--- 25/kernel/kexec.c~crashdump-reserving-backup-region-for-kexec-based	2005-01-23 01:51:11.613627512 -0800
+++ 25-akpm/kernel/kexec.c	2005-01-23 01:51:11.621626296 -0800
@@ -32,6 +32,14 @@ struct resource crashk_res = {
 	.flags = IORESOURCE_BUSY | IORESOURCE_MEM
 };
 
+/* Location of the backup area for the crash dump kernel */
+struct resource crashdumpk_res = {
+	.name  = "Crash Dump Backup",
+	.start = 0,
+	.end   = 0,
+	.flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
 /*
  * When kexec transitions to the new kernel there is a one-to-one
  * mapping between physical and virtual addresses.  On processors
_