diff options
-rw-r--r-- | arch/x86/Kconfig | 5 | ||||
-rw-r--r-- | arch/x86/kernel/machine_kexec_32.c | 12 | ||||
-rw-r--r-- | include/linux/suspend.h | 2 | ||||
-rw-r--r-- | kernel/kexec.c | 39 | ||||
-rw-r--r-- | kernel/power/power.h | 2 |
5 files changed, 56 insertions, 4 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 7ecb679f0130..6b2debfabddc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -1282,9 +1282,10 @@ config CRASH_DUMP | |||
1282 | config KEXEC_JUMP | 1282 | config KEXEC_JUMP |
1283 | bool "kexec jump (EXPERIMENTAL)" | 1283 | bool "kexec jump (EXPERIMENTAL)" |
1284 | depends on EXPERIMENTAL | 1284 | depends on EXPERIMENTAL |
1285 | depends on KEXEC && PM_SLEEP && X86_32 | 1285 | depends on KEXEC && HIBERNATION && X86_32 |
1286 | help | 1286 | help |
1287 | Invoke code in physical address mode via KEXEC | 1287 | Jump between original kernel and kexeced kernel and invoke |
1288 | code in physical address mode via KEXEC | ||
1288 | 1289 | ||
1289 | config PHYSICAL_START | 1290 | config PHYSICAL_START |
1290 | hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) | 1291 | hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) |
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c index 2b67609d0a1c..9fe478d98406 100644 --- a/arch/x86/kernel/machine_kexec_32.c +++ b/arch/x86/kernel/machine_kexec_32.c | |||
@@ -125,6 +125,18 @@ void machine_kexec(struct kimage *image) | |||
125 | /* Interrupts aren't acceptable while we reboot */ | 125 | /* Interrupts aren't acceptable while we reboot */ |
126 | local_irq_disable(); | 126 | local_irq_disable(); |
127 | 127 | ||
128 | if (image->preserve_context) { | ||
129 | #ifdef CONFIG_X86_IO_APIC | ||
130 | /* We need to put APICs in legacy mode so that we can | ||
131 | * get timer interrupts in second kernel. kexec/kdump | ||
132 | * paths already have calls to disable_IO_APIC() in | ||
133 | * one form or other. kexec jump path also need | ||
134 | * one. | ||
135 | */ | ||
136 | disable_IO_APIC(); | ||
137 | #endif | ||
138 | } | ||
139 | |||
128 | control_page = page_address(image->control_code_page); | 140 | control_page = page_address(image->control_code_page); |
129 | memcpy(control_page, relocate_kernel, PAGE_SIZE/2); | 141 | memcpy(control_page, relocate_kernel, PAGE_SIZE/2); |
130 | 142 | ||
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index e8e69159af71..c63435095970 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -278,4 +278,6 @@ static inline void register_nosave_region_late(unsigned long b, unsigned long e) | |||
278 | } | 278 | } |
279 | #endif | 279 | #endif |
280 | 280 | ||
281 | extern struct mutex pm_mutex; | ||
282 | |||
281 | #endif /* _LINUX_SUSPEND_H */ | 283 | #endif /* _LINUX_SUSPEND_H */ |
diff --git a/kernel/kexec.c b/kernel/kexec.c index a0d920915b38..c8a4370e2a34 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -26,6 +26,10 @@ | |||
26 | #include <linux/numa.h> | 26 | #include <linux/numa.h> |
27 | #include <linux/suspend.h> | 27 | #include <linux/suspend.h> |
28 | #include <linux/device.h> | 28 | #include <linux/device.h> |
29 | #include <linux/freezer.h> | ||
30 | #include <linux/pm.h> | ||
31 | #include <linux/cpu.h> | ||
32 | #include <linux/console.h> | ||
29 | 33 | ||
30 | #include <asm/page.h> | 34 | #include <asm/page.h> |
31 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
@@ -1441,7 +1445,31 @@ int kernel_kexec(void) | |||
1441 | 1445 | ||
1442 | if (kexec_image->preserve_context) { | 1446 | if (kexec_image->preserve_context) { |
1443 | #ifdef CONFIG_KEXEC_JUMP | 1447 | #ifdef CONFIG_KEXEC_JUMP |
1448 | mutex_lock(&pm_mutex); | ||
1449 | pm_prepare_console(); | ||
1450 | error = freeze_processes(); | ||
1451 | if (error) { | ||
1452 | error = -EBUSY; | ||
1453 | goto Restore_console; | ||
1454 | } | ||
1455 | suspend_console(); | ||
1456 | error = device_suspend(PMSG_FREEZE); | ||
1457 | if (error) | ||
1458 | goto Resume_console; | ||
1459 | error = disable_nonboot_cpus(); | ||
1460 | if (error) | ||
1461 | goto Resume_devices; | ||
1444 | local_irq_disable(); | 1462 | local_irq_disable(); |
1463 | /* At this point, device_suspend() has been called, | ||
1464 | * but *not* device_power_down(). We *must* | ||
1465 | * device_power_down() now. Otherwise, drivers for | ||
1466 | * some devices (e.g. interrupt controllers) become | ||
1467 | * desynchronized with the actual state of the | ||
1468 | * hardware at resume time, and evil weirdness ensues. | ||
1469 | */ | ||
1470 | error = device_power_down(PMSG_FREEZE); | ||
1471 | if (error) | ||
1472 | goto Enable_irqs; | ||
1445 | save_processor_state(); | 1473 | save_processor_state(); |
1446 | #endif | 1474 | #endif |
1447 | } else { | 1475 | } else { |
@@ -1459,7 +1487,18 @@ int kernel_kexec(void) | |||
1459 | if (kexec_image->preserve_context) { | 1487 | if (kexec_image->preserve_context) { |
1460 | #ifdef CONFIG_KEXEC_JUMP | 1488 | #ifdef CONFIG_KEXEC_JUMP |
1461 | restore_processor_state(); | 1489 | restore_processor_state(); |
1490 | device_power_up(PMSG_RESTORE); | ||
1491 | Enable_irqs: | ||
1462 | local_irq_enable(); | 1492 | local_irq_enable(); |
1493 | enable_nonboot_cpus(); | ||
1494 | Resume_devices: | ||
1495 | device_resume(PMSG_RESTORE); | ||
1496 | Resume_console: | ||
1497 | resume_console(); | ||
1498 | thaw_processes(); | ||
1499 | Restore_console: | ||
1500 | pm_restore_console(); | ||
1501 | mutex_unlock(&pm_mutex); | ||
1463 | #endif | 1502 | #endif |
1464 | } | 1503 | } |
1465 | 1504 | ||
diff --git a/kernel/power/power.h b/kernel/power/power.h index 700f44ec8406..acc0c101dbd5 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
@@ -53,8 +53,6 @@ extern int hibernation_platform_enter(void); | |||
53 | 53 | ||
54 | extern int pfn_is_nosave(unsigned long); | 54 | extern int pfn_is_nosave(unsigned long); |
55 | 55 | ||
56 | extern struct mutex pm_mutex; | ||
57 | |||
58 | #define power_attr(_name) \ | 56 | #define power_attr(_name) \ |
59 | static struct kobj_attribute _name##_attr = { \ | 57 | static struct kobj_attribute _name##_attr = { \ |
60 | .attr = { \ | 58 | .attr = { \ |