This patch implements kexec based hibernate/resume. This is based on
the facility provided by kexec_jump. The ACPI methods are called at
specified environment to conform the ACPI specification. Two new
reboot commands are added to trigger hibernate/resume.Signed-off-by: Huang Ying <ying.huang@intel.com>
---
include/linux/kexec.h | 5 +
include/linux/reboot.h | 2
include/linux/suspend.h | 9 ++
kernel/power/disk.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++
kernel/sys.c | 42 +++++++++++++
5 files changed, 212 insertions(+), 1 deletion(-)--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -21,6 +21,7 @@
#include <linux/console.h>
#include <linux/cpu.h>
#include <linux/freezer.h>
+#include <linux/kexec.h>#include "power.h"
@@ -438,6 +439,160 @@ int hibernate(void)
return error;
}+#ifdef CONFIG_KEXEC
+static void kexec_hibernate_power_down(void)
+{
+ switch (hibernation_mode) {
+ case HIBERNATION_TEST:
+ case HIBERNATION_TESTPROC:
+ break;
+ case HIBERNATION_REBOOT:
+ machine_restart(NULL);
+ break;
+ case HIBERNATION_PLATFORM:
+ if (!hibernation_ops)
+ break;
+ hibernation_ops->enter();
+ /* We should never get here */
+ while (1);
+ break;
+ case HIBERNATION_SHUTDOWN:
+ machine_power_off();
+ break;
+ }
+ machine_halt();
+ /*
+ * Valid image is on the disk, if we continue we risk serious data
+ * corruption after resume.
+ */
+ printk(KERN_CRIT "Please power me down manually\n");
+ while (1);
+}
+
+int kexec_hibernate(struct kimage *image)
+{
+ int error;
+ int platform_mode = (hibernation_mode == HIBERNATION_PLATFORM);
+ unsigned long cmd_ret;
+
+ mutex_lock(&pm_mutex);
+
+ pm_prepare_console();
+ suspend_console();
+
+ error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
+ if (error)
+ goto Resume_console;
+
+ error = platform_start(platform_mode);
+ if (error)
+ goto Resume_console;
+
+ error = device_suspend(PM...
Hm, what's the difference between the above function and power_down(),
I wonder if it's viable to merge the above with hibernate() and
It looks like machine_kexec_jump() simply replaces the call to
swsusp_arch_suspend() in create_image(). Is it really necessary to duplicateSame here. Much of the code in this function duplicates the existing code. Is
Apart from the above, there's some new debug code to be added to disk.c
in 2.6.25. It's in the ACPI test tree right now and you can get it as
individual patches from:
http://www.sisk.pl/kernel/hibernation_and_suspend/2.6.24-rc2/patches/
(patches 10-12).-
The power_down will be called with interrupt disabled, device suspended,
non-boot CPU disabled. But the latest hibernate_platform_enter calls the
device_suspend, disable_nonboot_cpus etc function. So, I use
hibernation_ops->enter() directly instead ofYes. Most code are duplicated. But there is one advantage not to merge
them: power_down can called with IRQ disabled to make it possible to
eliminate the freezer.I think it is possible to merge the two implementation. I will try to do
OK, I will do it.
Best Regards,
Huang Ying
-
Hm, you need to call device_power_down(PMSG_SUSPEND) before
hibernation_ops->enter().Also, all of the ACPI global calls need to be carried out before that and the
devices should be suspended rather than shut down in that case.Please leave the freezer alone for now. We'll clean up all that when we decide
Yes, please use as much of the existing code as reasonably possible, so that we
Thanks.
There will be some more cosmetic changes in this area, probably before 2.6.25,
so please stay tuned.Greetings,
Rafael
-
Situation is a little different between u/swsusp and khiberantion.
u/swsusp:
platform_start();
suspend console();
device_suspend(PMSG_FREEZE);
platform_pre_snapshot();
disable_nonboot_cpus();
local_irq_disable();
device_power_down(PMSG_FREEZE);
/* create snapshot */
device_power_up();
local_irq_enable();
enable_nonboot_cpus();
platform_finish();
device_resume();
resume_console();
/* write the image out */
hibernation_ops->start();
suspend_console();
device_suspend(PMSG_SUSPEND);
hibernation_ops->prepare();
disable_nonboot_cpus();
local_irq_disable();
device_power_down(PMSG_SUSPEND);
hibernation_ops->enter();khibernation:
suspend_console();
platform_start();
device_suspend(PMSG_FREEZE);
platform_pre_snapshot();
disable_nonboot_cpus();
local_irq_disable();
device_power_down(PMSG_FREEZE);
/* jump to kexeced (hibernating) kernel */
/* in kexeced kernel */
device_power_up();
local_irq_eanble();
enable_nonboot_cpus();
device_resume();
resume_console();
/* write the image */
suspend_console();
device_suspend(PMSG_FREEZE);
disable_nonboot_cpus();
local_irq_disable();
device_power_down(PMSG_FREEZE);
/* jump to original (hibernated) kernel */
/* in original kernel */
hibernation_ops->enter();The difference is:
- In u/swsusp, ACPI methods are executed twice, before writing out the
image and after writing out the image.
- After writing out the image, the PMSG_SUSPEND is used instead of
PMSG_FREEZE.Some questions:
- What is the difference between PMSG_SUSPEND and PMSG_FREEZE?
- The ACPI methods should be executed once or twice? According to ACPI
specification?Best Regards,
Huang Ying
-
You should call platform_finish() here, or device_resume() will not work
appropriately on some systems.However, after platform_finish() has been executed, the ACPI firmware will
assume that the hibernation has been canceled, so you need to tell it thatFor this reason, you have to call hibernation_ops->start() once again
This looks too fragile to my eyes.
Why don't you call hibernation_ops->enter() directly from the "kexeced" kernel?
Rafael
-
I don't know whether there are ACPI global state inside Linux kernel. So
I restrict all ACPI method calling in original kernel. If the ACPI
global state in Linux kernel is not a issue, I can call
hibernation_ops->enter() directly in the "kexeced" kernel.Best Regards,
Huang Ying
-
Well, I can't say to what extent the Linux ACPI tracks the global state.
Still, even if it does, you don't need to jump back to the hibernated kernel
just to power off the system.Actually, if you really want to include ACPI into the picture, which I'm not
sure is the best idea at this point, you should use all of the appropriate
ACPI hooks in the kexeced kernel and you shouldn't get back to the hibernated
kernel after you've saved the image.Regards,
Rafael
-
SUSPEND means that the system is about to go into a low-power state, so
the driver should take the appropriate action to reduce the device's
power consumption. It should also stop all I/O and DMA to the device.
Interrupts can remain enabled if the device is supposed to be a wakeup
source; otherwise they should be disabled.FREEZE means that the system is going to hibernate, and devices need to
be quiescent (no I/O, no DMA, and no interrupts) so that an atomic
memory snapshot can be captured. The driver should take the
appropriate action to quiesce the device but the power level doesn't
need to change.PRETHAW means that the system is going to resume from hibernation by
loading a previously-saved memory snapshot. The driver should take the
appropriate action to quiesce the device (no I/O, no DMA, and no
interrupts) so that the snapshot can be safely restored, but the power
level doesn't need to change. The driver may also want to put the
device into a special state so that the saved kernel's resume method
will recognize the device has undergone a hibernation cycle and needs
to be reinitialized.Alan Stern
-
Exactly.
For this reason, PMSG_SUSPEND should be used right before calling
hibernation_ops->enter() .Greetings,
Rafael
-
| Tarkan Erimer | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Greg KH | [GIT PATCH] driver core patches against 2.6.24 |
| holzheu | Re: [RFC/PATCH] Documentation of kernel messages |
| FUJITA Tomonori | Re: Integration of SCST in the mainstream Linux kernel |
git: | |
| Jarek Poplawski | [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Gerrit Renker | [PATCH 13/37] dccp: Deprecate Ack Ratio sysctl |
| Arjan van de Ven | Re: [GIT]: Networking |
| Evgeniy Polyakov | Re: [BUG] New Kernel Bugs |
