/* * We'll stop somewhere inside this hypercall. When it returns, * we'll start resuming after the restore. */ HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); shutting_down = SHUTDOWN_INVALID; post_suspend(); gnttab_resume(); irq_resume(); time_resume(); switch_idle_mm(); local_irq_enable(); xencons_resume(); xenbus_resume(); smp_resume(); return err; } #endif /* CONFIG_XEN */ extern int __xen_suspend(int fast_suspend); static int shutdown_process(void *__unused) { static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; static char *poweroff_argv[] = { "/sbin/poweroff", NULL }; #ifdef CONFIG_XEN extern asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void *arg); #endif if ((shutting_down == SHUTDOWN_POWEROFF) || (shutting_down == SHUTDOWN_HALT)) { if (call_usermodehelper("/sbin/poweroff", poweroff_argv, envp, 0) < 0) { #ifdef CONFIG_XEN sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL); #endif /* CONFIG_XEN */ } } shutting_down = SHUTDOWN_INVALID; /* could try again */ return 0; } #ifndef CONFIG_XEN /* pv-on-hvm */ static int xen_suspend(void *__unused) { int err = __xen_suspend(fast_suspend); if (err) printk(KERN_ERR "Xen suspend failed (%d)\n", err); shutting_down = SHUTDOWN_INVALID; return 0; }
static int xen_suspend(void *__unused) { int err, old_state; daemonize("suspend"); err = set_cpus_allowed(current, cpumask_of_cpu(0)); if (err) { printk(KERN_ERR "Xen suspend can't run on CPU0 (%d)\n", err); goto fail; } do { err = __xen_suspend(fast_suspend, xen_resume_notifier); if (err) { printk(KERN_ERR "Xen suspend failed (%d)\n", err); goto fail; } if (!suspend_cancelled) setup_suspend_evtchn(); old_state = cmpxchg( &shutting_down, SHUTDOWN_RESUMING, SHUTDOWN_INVALID); } while (old_state == SHUTDOWN_SUSPEND); switch (old_state) { case SHUTDOWN_INVALID: case SHUTDOWN_SUSPEND: BUG(); case SHUTDOWN_RESUMING: break; default: schedule_work(&shutdown_work); break; } return 0; fail: old_state = xchg(&shutting_down, SHUTDOWN_INVALID); BUG_ON(old_state != SHUTDOWN_SUSPEND); return 0; }