diff options
Diffstat (limited to 'kernel/kexec.c')
| -rw-r--r-- | kernel/kexec.c | 66 |
1 files changed, 24 insertions, 42 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index c8a4370e2a34..59f3f0df35d4 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
| 14 | #include <linux/kexec.h> | 14 | #include <linux/kexec.h> |
| 15 | #include <linux/spinlock.h> | 15 | #include <linux/mutex.h> |
| 16 | #include <linux/list.h> | 16 | #include <linux/list.h> |
| 17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
| 18 | #include <linux/syscalls.h> | 18 | #include <linux/syscalls.h> |
| @@ -77,7 +77,7 @@ int kexec_should_crash(struct task_struct *p) | |||
| 77 | * | 77 | * |
| 78 | * The code for the transition from the current kernel to the | 78 | * The code for the transition from the current kernel to the |
| 79 | * the new kernel is placed in the control_code_buffer, whose size | 79 | * the new kernel is placed in the control_code_buffer, whose size |
| 80 | * is given by KEXEC_CONTROL_CODE_SIZE. In the best case only a single | 80 | * is given by KEXEC_CONTROL_PAGE_SIZE. In the best case only a single |
| 81 | * page of memory is necessary, but some architectures require more. | 81 | * page of memory is necessary, but some architectures require more. |
| 82 | * Because this memory must be identity mapped in the transition from | 82 | * Because this memory must be identity mapped in the transition from |
| 83 | * virtual to physical addresses it must live in the range | 83 | * virtual to physical addresses it must live in the range |
| @@ -242,7 +242,7 @@ static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry, | |||
| 242 | */ | 242 | */ |
| 243 | result = -ENOMEM; | 243 | result = -ENOMEM; |
| 244 | image->control_code_page = kimage_alloc_control_pages(image, | 244 | image->control_code_page = kimage_alloc_control_pages(image, |
| 245 | get_order(KEXEC_CONTROL_CODE_SIZE)); | 245 | get_order(KEXEC_CONTROL_PAGE_SIZE)); |
| 246 | if (!image->control_code_page) { | 246 | if (!image->control_code_page) { |
| 247 | printk(KERN_ERR "Could not allocate control_code_buffer\n"); | 247 | printk(KERN_ERR "Could not allocate control_code_buffer\n"); |
| 248 | goto out; | 248 | goto out; |
| @@ -317,7 +317,7 @@ static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry, | |||
| 317 | */ | 317 | */ |
| 318 | result = -ENOMEM; | 318 | result = -ENOMEM; |
| 319 | image->control_code_page = kimage_alloc_control_pages(image, | 319 | image->control_code_page = kimage_alloc_control_pages(image, |
| 320 | get_order(KEXEC_CONTROL_CODE_SIZE)); | 320 | get_order(KEXEC_CONTROL_PAGE_SIZE)); |
| 321 | if (!image->control_code_page) { | 321 | if (!image->control_code_page) { |
| 322 | printk(KERN_ERR "Could not allocate control_code_buffer\n"); | 322 | printk(KERN_ERR "Could not allocate control_code_buffer\n"); |
| 323 | goto out; | 323 | goto out; |
| @@ -924,19 +924,14 @@ static int kimage_load_segment(struct kimage *image, | |||
| 924 | */ | 924 | */ |
| 925 | struct kimage *kexec_image; | 925 | struct kimage *kexec_image; |
| 926 | struct kimage *kexec_crash_image; | 926 | struct kimage *kexec_crash_image; |
| 927 | /* | 927 | |
| 928 | * A home grown binary mutex. | 928 | static DEFINE_MUTEX(kexec_mutex); |
| 929 | * Nothing can wait so this mutex is safe to use | ||
| 930 | * in interrupt context :) | ||
| 931 | */ | ||
| 932 | static int kexec_lock; | ||
| 933 | 929 | ||
| 934 | asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, | 930 | asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, |
| 935 | struct kexec_segment __user *segments, | 931 | struct kexec_segment __user *segments, |
| 936 | unsigned long flags) | 932 | unsigned long flags) |
| 937 | { | 933 | { |
| 938 | struct kimage **dest_image, *image; | 934 | struct kimage **dest_image, *image; |
| 939 | int locked; | ||
| 940 | int result; | 935 | int result; |
| 941 | 936 | ||
| 942 | /* We only trust the superuser with rebooting the system. */ | 937 | /* We only trust the superuser with rebooting the system. */ |
| @@ -972,8 +967,7 @@ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, | |||
| 972 | * | 967 | * |
| 973 | * KISS: always take the mutex. | 968 | * KISS: always take the mutex. |
| 974 | */ | 969 | */ |
| 975 | locked = xchg(&kexec_lock, 1); | 970 | if (!mutex_trylock(&kexec_mutex)) |
| 976 | if (locked) | ||
| 977 | return -EBUSY; | 971 | return -EBUSY; |
| 978 | 972 | ||
| 979 | dest_image = &kexec_image; | 973 | dest_image = &kexec_image; |
| @@ -1015,8 +1009,7 @@ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, | |||
| 1015 | image = xchg(dest_image, image); | 1009 | image = xchg(dest_image, image); |
| 1016 | 1010 | ||
| 1017 | out: | 1011 | out: |
| 1018 | locked = xchg(&kexec_lock, 0); /* Release the mutex */ | 1012 | mutex_unlock(&kexec_mutex); |
| 1019 | BUG_ON(!locked); | ||
| 1020 | kimage_free(image); | 1013 | kimage_free(image); |
| 1021 | 1014 | ||
| 1022 | return result; | 1015 | return result; |
| @@ -1063,10 +1056,7 @@ asmlinkage long compat_sys_kexec_load(unsigned long entry, | |||
| 1063 | 1056 | ||
| 1064 | void crash_kexec(struct pt_regs *regs) | 1057 | void crash_kexec(struct pt_regs *regs) |
| 1065 | { | 1058 | { |
| 1066 | int locked; | 1059 | /* Take the kexec_mutex here to prevent sys_kexec_load |
| 1067 | |||
| 1068 | |||
| 1069 | /* Take the kexec_lock here to prevent sys_kexec_load | ||
| 1070 | * running on one cpu from replacing the crash kernel | 1060 | * running on one cpu from replacing the crash kernel |
| 1071 | * we are using after a panic on a different cpu. | 1061 | * we are using after a panic on a different cpu. |
| 1072 | * | 1062 | * |
| @@ -1074,8 +1064,7 @@ void crash_kexec(struct pt_regs *regs) | |||
| 1074 | * of memory the xchg(&kexec_crash_image) would be | 1064 | * of memory the xchg(&kexec_crash_image) would be |
| 1075 | * sufficient. But since I reuse the memory... | 1065 | * sufficient. But since I reuse the memory... |
| 1076 | */ | 1066 | */ |
| 1077 | locked = xchg(&kexec_lock, 1); | 1067 | if (mutex_trylock(&kexec_mutex)) { |
| 1078 | if (!locked) { | ||
| 1079 | if (kexec_crash_image) { | 1068 | if (kexec_crash_image) { |
| 1080 | struct pt_regs fixed_regs; | 1069 | struct pt_regs fixed_regs; |
| 1081 | crash_setup_regs(&fixed_regs, regs); | 1070 | crash_setup_regs(&fixed_regs, regs); |
| @@ -1083,8 +1072,7 @@ void crash_kexec(struct pt_regs *regs) | |||
| 1083 | machine_crash_shutdown(&fixed_regs); | 1072 | machine_crash_shutdown(&fixed_regs); |
| 1084 | machine_kexec(kexec_crash_image); | 1073 | machine_kexec(kexec_crash_image); |
| 1085 | } | 1074 | } |
| 1086 | locked = xchg(&kexec_lock, 0); | 1075 | mutex_unlock(&kexec_mutex); |
| 1087 | BUG_ON(!locked); | ||
| 1088 | } | 1076 | } |
| 1089 | } | 1077 | } |
| 1090 | 1078 | ||
| @@ -1426,25 +1414,23 @@ static int __init crash_save_vmcoreinfo_init(void) | |||
| 1426 | 1414 | ||
| 1427 | module_init(crash_save_vmcoreinfo_init) | 1415 | module_init(crash_save_vmcoreinfo_init) |
| 1428 | 1416 | ||
| 1429 | /** | 1417 | /* |
| 1430 | * kernel_kexec - reboot the system | 1418 | * Move into place and start executing a preloaded standalone |
| 1431 | * | 1419 | * executable. If nothing was preloaded return an error. |
| 1432 | * Move into place and start executing a preloaded standalone | ||
| 1433 | * executable. If nothing was preloaded return an error. | ||
| 1434 | */ | 1420 | */ |
| 1435 | int kernel_kexec(void) | 1421 | int kernel_kexec(void) |
| 1436 | { | 1422 | { |
| 1437 | int error = 0; | 1423 | int error = 0; |
| 1438 | 1424 | ||
| 1439 | if (xchg(&kexec_lock, 1)) | 1425 | if (!mutex_trylock(&kexec_mutex)) |
| 1440 | return -EBUSY; | 1426 | return -EBUSY; |
| 1441 | if (!kexec_image) { | 1427 | if (!kexec_image) { |
| 1442 | error = -EINVAL; | 1428 | error = -EINVAL; |
| 1443 | goto Unlock; | 1429 | goto Unlock; |
| 1444 | } | 1430 | } |
| 1445 | 1431 | ||
| 1446 | if (kexec_image->preserve_context) { | ||
| 1447 | #ifdef CONFIG_KEXEC_JUMP | 1432 | #ifdef CONFIG_KEXEC_JUMP |
| 1433 | if (kexec_image->preserve_context) { | ||
| 1448 | mutex_lock(&pm_mutex); | 1434 | mutex_lock(&pm_mutex); |
| 1449 | pm_prepare_console(); | 1435 | pm_prepare_console(); |
| 1450 | error = freeze_processes(); | 1436 | error = freeze_processes(); |
| @@ -1459,6 +1445,7 @@ int kernel_kexec(void) | |||
| 1459 | error = disable_nonboot_cpus(); | 1445 | error = disable_nonboot_cpus(); |
| 1460 | if (error) | 1446 | if (error) |
| 1461 | goto Resume_devices; | 1447 | goto Resume_devices; |
| 1448 | device_pm_lock(); | ||
| 1462 | local_irq_disable(); | 1449 | local_irq_disable(); |
| 1463 | /* At this point, device_suspend() has been called, | 1450 | /* At this point, device_suspend() has been called, |
| 1464 | * but *not* device_power_down(). We *must* | 1451 | * but *not* device_power_down(). We *must* |
| @@ -1470,26 +1457,22 @@ int kernel_kexec(void) | |||
| 1470 | error = device_power_down(PMSG_FREEZE); | 1457 | error = device_power_down(PMSG_FREEZE); |
| 1471 | if (error) | 1458 | if (error) |
| 1472 | goto Enable_irqs; | 1459 | goto Enable_irqs; |
| 1473 | save_processor_state(); | 1460 | } else |
| 1474 | #endif | 1461 | #endif |
| 1475 | } else { | 1462 | { |
| 1476 | blocking_notifier_call_chain(&reboot_notifier_list, | 1463 | kernel_restart_prepare(NULL); |
| 1477 | SYS_RESTART, NULL); | ||
| 1478 | system_state = SYSTEM_RESTART; | ||
| 1479 | device_shutdown(); | ||
| 1480 | sysdev_shutdown(); | ||
| 1481 | printk(KERN_EMERG "Starting new kernel\n"); | 1464 | printk(KERN_EMERG "Starting new kernel\n"); |
| 1482 | machine_shutdown(); | 1465 | machine_shutdown(); |
| 1483 | } | 1466 | } |
| 1484 | 1467 | ||
| 1485 | machine_kexec(kexec_image); | 1468 | machine_kexec(kexec_image); |
| 1486 | 1469 | ||
| 1487 | if (kexec_image->preserve_context) { | ||
| 1488 | #ifdef CONFIG_KEXEC_JUMP | 1470 | #ifdef CONFIG_KEXEC_JUMP |
| 1489 | restore_processor_state(); | 1471 | if (kexec_image->preserve_context) { |
| 1490 | device_power_up(PMSG_RESTORE); | 1472 | device_power_up(PMSG_RESTORE); |
| 1491 | Enable_irqs: | 1473 | Enable_irqs: |
| 1492 | local_irq_enable(); | 1474 | local_irq_enable(); |
| 1475 | device_pm_unlock(); | ||
| 1493 | enable_nonboot_cpus(); | 1476 | enable_nonboot_cpus(); |
| 1494 | Resume_devices: | 1477 | Resume_devices: |
| 1495 | device_resume(PMSG_RESTORE); | 1478 | device_resume(PMSG_RESTORE); |
| @@ -1499,11 +1482,10 @@ int kernel_kexec(void) | |||
| 1499 | Restore_console: | 1482 | Restore_console: |
| 1500 | pm_restore_console(); | 1483 | pm_restore_console(); |
| 1501 | mutex_unlock(&pm_mutex); | 1484 | mutex_unlock(&pm_mutex); |
| 1502 | #endif | ||
| 1503 | } | 1485 | } |
| 1486 | #endif | ||
| 1504 | 1487 | ||
| 1505 | Unlock: | 1488 | Unlock: |
| 1506 | xchg(&kexec_lock, 0); | 1489 | mutex_unlock(&kexec_mutex); |
| 1507 | |||
| 1508 | return error; | 1490 | return error; |
| 1509 | } | 1491 | } |
