diff options
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r-- | kernel/kexec.c | 57 |
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 | ||
1413 | module_init(crash_save_vmcoreinfo_init) | 1423 | module_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 | */ | ||
1431 | int 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 | } | ||