aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kexec.c
diff options
context:
space:
mode:
authorHuang Ying <ying.huang@intel.com>2008-07-25 22:45:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-26 15:00:04 -0400
commit3ab83521378268044a448113c6aa9a9e245f4d2f (patch)
treee9e8496577e4b2e994edf204e9a8ae7c026eec95 /kernel/kexec.c
parent7fccf0326536c1b245b98740d489abb9aab69a12 (diff)
kexec jump
This patch provides an enhancement to kexec/kdump. It implements the following features: - Backup/restore memory used by the original kernel before/after kexec. - Save/restore CPU state before/after kexec. The features of this patch can be used as a general method to call program in physical mode (paging turning off). This can be used to call BIOS code under Linux. kexec-tools needs to be patched to support kexec jump. The patches and the precompiled kexec can be download from the following URL: source: http://khibernation.sourceforge.net/download/release_v10/kexec-tools/kexec-tools-src_git_kh10.tar.bz2 patches: http://khibernation.sourceforge.net/download/release_v10/kexec-tools/kexec-tools-patches_git_kh10.tar.bz2 binary: http://khibernation.sourceforge.net/download/release_v10/kexec-tools/kexec_git_kh10 Usage example of calling some physical mode code and return: 1. Compile and install patched kernel with following options selected: CONFIG_X86_32=y CONFIG_KEXEC=y CONFIG_PM=y CONFIG_KEXEC_JUMP=y 2. Build patched kexec-tool or download the pre-built one. 3. Build some physical mode executable named such as "phy_mode" 4. Boot kernel compiled in step 1. 5. Load physical mode executable with /sbin/kexec. The shell command line can be as follow: /sbin/kexec --load-preserve-context --args-none phy_mode 6. Call physical mode executable with following shell command line: /sbin/kexec -e Implementation point: To support jumping without reserving memory. One shadow backup page (source page) is allocated for each page used by kexeced code image (destination page). When do kexec_load, the image of kexeced code is loaded into source pages, and before executing, the destination pages and the source pages are swapped, so the contents of destination pages are backupped. Before jumping to the kexeced code image and after jumping back to the original kernel, the destination pages and the source pages are swapped too. C ABI (calling convention) is used as communication protocol between kernel and called code. A flag named KEXEC_PRESERVE_CONTEXT for sys_kexec_load is added to indicate that the loaded kernel image is used for jumping back. Now, only the i386 architecture is supported. Signed-off-by: Huang Ying <ying.huang@intel.com> Acked-by: Vivek Goyal <vgoyal@redhat.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Pavel Machek <pavel@ucw.cz> Cc: Nigel Cunningham <nigel@nigel.suspend2.net> Cc: "Rafael J. Wysocki" <rjw@sisk.pl> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r--kernel/kexec.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 6db42ff8d520..a0d920915b38 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -24,6 +24,8 @@
24#include <linux/utsrelease.h> 24#include <linux/utsrelease.h>
25#include <linux/utsname.h> 25#include <linux/utsname.h>
26#include <linux/numa.h> 26#include <linux/numa.h>
27#include <linux/suspend.h>
28#include <linux/device.h>
27 29
28#include <asm/page.h> 30#include <asm/page.h>
29#include <asm/uaccess.h> 31#include <asm/uaccess.h>
@@ -242,6 +244,12 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
242 goto out; 244 goto out;
243 } 245 }
244 246
247 image->swap_page = kimage_alloc_control_pages(image, 0);
248 if (!image->swap_page) {
249 printk(KERN_ERR "Could not allocate swap buffer\n");
250 goto out;
251 }
252
245 result = 0; 253 result = 0;
246 out: 254 out:
247 if (result == 0) 255 if (result == 0)
@@ -986,6 +994,8 @@ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
986 if (result) 994 if (result)
987 goto out; 995 goto out;
988 996
997 if (flags & KEXEC_PRESERVE_CONTEXT)
998 image->preserve_context = 1;
989 result = machine_kexec_prepare(image); 999 result = machine_kexec_prepare(image);
990 if (result) 1000 if (result)
991 goto out; 1001 goto out;
@@ -1411,3 +1421,50 @@ static int __init crash_save_vmcoreinfo_init(void)
1411} 1421}
1412 1422
1413module_init(crash_save_vmcoreinfo_init) 1423module_init(crash_save_vmcoreinfo_init)
1424
1425/**
1426 * kernel_kexec - reboot the system
1427 *
1428 * Move into place and start executing a preloaded standalone
1429 * executable. If nothing was preloaded return an error.
1430 */
1431int kernel_kexec(void)
1432{
1433 int error = 0;
1434
1435 if (xchg(&kexec_lock, 1))
1436 return -EBUSY;
1437 if (!kexec_image) {
1438 error = -EINVAL;
1439 goto Unlock;
1440 }
1441
1442 if (kexec_image->preserve_context) {
1443#ifdef CONFIG_KEXEC_JUMP
1444 local_irq_disable();
1445 save_processor_state();
1446#endif
1447 } else {
1448 blocking_notifier_call_chain(&reboot_notifier_list,
1449 SYS_RESTART, NULL);
1450 system_state = SYSTEM_RESTART;
1451 device_shutdown();
1452 sysdev_shutdown();
1453 printk(KERN_EMERG "Starting new kernel\n");
1454 machine_shutdown();
1455 }
1456
1457 machine_kexec(kexec_image);
1458
1459 if (kexec_image->preserve_context) {
1460#ifdef CONFIG_KEXEC_JUMP
1461 restore_processor_state();
1462 local_irq_enable();
1463#endif
1464 }
1465
1466 Unlock:
1467 xchg(&kexec_lock, 0);
1468
1469 return error;
1470}