
From: "Eric W. Biederman" <ebiederm@xmission.com>

With the recent refactoring of the kexec code this patch is a shadow
of it's former self.  The user space code in /sbin/kexec has been
enhanced so it can contain copy the first 640k.  And the strong tying
between the crashdump capturecode paths and the kexec on panic code
paths have been removed.

From: Hariprasad Nellitheertha <hari@in.ibm.com>

This patch contains the code that does the memory preserving reboot.  It
copies over the first 640k into a backup region before handing over to kexec. 
The second kernel will boot using only the backup region.

Signed off by Hariprasad Nellitheertha <hari@in.ibm.com>
Signed off by Adam Litke <litke@us.ibm.com>
Signed-off-by: Eric Biederman <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/i386/Kconfig             |   21 +++++++++++++++++++++
 25-akpm/arch/i386/kernel/setup.c      |    8 ++++++++
 25-akpm/include/asm-i386/crash_dump.h |   20 ++++++++++++++++++++
 25-akpm/include/linux/bootmem.h       |    3 +++
 25-akpm/include/linux/crash_dump.h    |   10 ++++++++++
 25-akpm/kernel/Makefile               |    1 +
 25-akpm/kernel/crash_dump.c           |   13 +++++++++++++
 25-akpm/mm/bootmem.c                  |    7 +++++++
 8 files changed, 83 insertions(+)

diff -puN arch/i386/Kconfig~crashdump-memory-preserving-reboot-using-kexec arch/i386/Kconfig
--- 25/arch/i386/Kconfig~crashdump-memory-preserving-reboot-using-kexec	Thu Feb 17 17:03:17 2005
+++ 25-akpm/arch/i386/Kconfig	Thu Feb 17 17:03:17 2005
@@ -935,6 +935,27 @@ config KEXEC
 	  support.  As of this writing the exact hardware interface is
 	  strongly in flux, so no good recommendation can be made.
 
+config CRASH_DUMP
+	bool "kernel crash dumps (EXPERIMENTAL)"
+	depends on EMBEDDED
+	depends on EXPERIMENTAL
+	help
+	  Generate crash dump after being started by kexec.
+
+config BACKUP_BASE
+	int "location from where the crash dumping kernel will boot (MB)"
+	depends on CRASH_DUMP
+	default 16
+	help
+	This is the location where the second kernel will boot from.
+
+config BACKUP_SIZE
+	int "Size of memory used by the crash dumping kernel (MB)"
+	depends on CRASH_DUMP
+	range 16 64
+	default 32
+	help
+	The size of the second kernel's memory.
 endmenu
 
 
diff -puN arch/i386/kernel/setup.c~crashdump-memory-preserving-reboot-using-kexec arch/i386/kernel/setup.c
--- 25/arch/i386/kernel/setup.c~crashdump-memory-preserving-reboot-using-kexec	Thu Feb 17 17:03:17 2005
+++ 25-akpm/arch/i386/kernel/setup.c	Thu Feb 17 17:03:17 2005
@@ -51,6 +51,7 @@
 #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>
 
@@ -715,6 +716,13 @@ static void __init parse_cmdline_early (
 			if (to != command_line)
 				to--;
 			if (!memcmp(from+7, "exactmap", 8)) {
+#ifdef CONFIG_CRASH_DUMP
+				/* If we are doing a crash dump, we
+				 * still need to know the real mem
+				 * size.
+				 */
+				set_saved_max_pfn();
+#endif
 				from += 8+7;
 				e820.nr_map = 0;
 				userdef = 1;
diff -puN /dev/null include/asm-i386/crash_dump.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/include/asm-i386/crash_dump.h	Thu Feb 17 17:03:17 2005
@@ -0,0 +1,20 @@
+/* asm-i386/crash_dump.h */
+#include <linux/bootmem.h>
+
+#ifdef CONFIG_CRASH_DUMP
+extern unsigned long __init find_max_low_pfn(void);
+extern void __init find_max_pfn(void);
+
+#define CRASH_BACKUP_BASE ((unsigned long)CONFIG_BACKUP_BASE * 0x100000)
+#define CRASH_BACKUP_SIZE ((unsigned long)CONFIG_BACKUP_SIZE * 0x100000)
+#define CRASH_RELOCATE_SIZE 0xa0000
+
+static inline void set_saved_max_pfn(void)
+{
+	find_max_pfn();
+	saved_max_pfn = find_max_low_pfn();
+}
+
+#else
+#define set_saved_max_pfn() do { } while(0)
+#endif
diff -puN include/linux/bootmem.h~crashdump-memory-preserving-reboot-using-kexec include/linux/bootmem.h
--- 25/include/linux/bootmem.h~crashdump-memory-preserving-reboot-using-kexec	Thu Feb 17 17:03:17 2005
+++ 25-akpm/include/linux/bootmem.h	Thu Feb 17 17:03:17 2005
@@ -21,6 +21,9 @@ extern unsigned long min_low_pfn;
  * highest page
  */
 extern unsigned long max_pfn;
+#ifdef CONFIG_CRASH_DUMP
+extern unsigned long saved_max_pfn;
+#endif
 
 /*
  * node_bootmem_map is a map pointer - the bits represent all physical 
diff -puN /dev/null include/linux/crash_dump.h
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/include/linux/crash_dump.h	Thu Feb 17 17:03:17 2005
@@ -0,0 +1,10 @@
+#include <linux/kexec.h>
+#include <linux/smp_lock.h>
+#include <linux/device.h>
+#ifdef CONFIG_CRASH_DUMP
+#include <asm/crash_dump.h>
+#endif
+
+#ifdef CONFIG_CRASH_DUMP
+#else
+#endif
diff -puN /dev/null kernel/crash_dump.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/kernel/crash_dump.c	Thu Feb 17 17:03:17 2005
@@ -0,0 +1,13 @@
+/*
+ *	kernel/crash_dump.c - Memory preserving reboot related code.
+ *
+ *	Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ *	Copyright (C) IBM Corporation, 2004. All rights reserved
+ */
+
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
diff -puN kernel/Makefile~crashdump-memory-preserving-reboot-using-kexec kernel/Makefile
--- 25/kernel/Makefile~crashdump-memory-preserving-reboot-using-kexec	Thu Feb 17 17:03:17 2005
+++ 25-akpm/kernel/Makefile	Thu Feb 17 17:03:36 2005
@@ -28,6 +28,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o
 obj-$(CONFIG_SYSFS) += ksysfs.o
 obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
 obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
+obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
 obj-$(CONFIG_SECCOMP) += seccomp.o
 
 ifneq ($(CONFIG_IA64),y)
diff -puN mm/bootmem.c~crashdump-memory-preserving-reboot-using-kexec mm/bootmem.c
--- 25/mm/bootmem.c~crashdump-memory-preserving-reboot-using-kexec	Thu Feb 17 17:03:17 2005
+++ 25-akpm/mm/bootmem.c	Thu Feb 17 17:03:17 2005
@@ -28,6 +28,13 @@
 unsigned long max_low_pfn;
 unsigned long min_low_pfn;
 unsigned long max_pfn;
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * If we have booted due to a crash, max_pfn will be a very low value. We need
+ * to know the amount of memory that the previous kernel used.
+ */
+unsigned long saved_max_pfn;
+#endif
 
 EXPORT_SYMBOL(max_pfn);		/* This is exported so
 				 * dma_get_required_mask(), which uses
_
