1 #include <linux/kernel.h>
2 #include <linux/unistd.h>
3 #include <linux/init.h>
4 #include <linux/slab.h>
5 #include <linux/reboot.h>
6 #include <linux/sched.h>
7 #include <linux/sysrq.h>
8 #include <asm/hypervisor.h>
9 #include <xen/xenbus.h>
10 #include <xen/evtchn.h>
11 #include <linux/kmod.h>
12 #include <linux/slab.h>
13 #include <linux/workqueue.h>
15 #ifdef HAVE_XEN_PLATFORM_COMPAT_H
16 #include <xen/platform-compat.h>
20 #define SHUTDOWN_INVALID -1
21 #define SHUTDOWN_POWEROFF 0
22 #define SHUTDOWN_SUSPEND 2
23 #define SHUTDOWN_RESUMING 3
24 #define SHUTDOWN_HALT 4
26 /* Ignore multiple shutdown requests. */
27 static int shutting_down = SHUTDOWN_INVALID;
29 /* Can we leave APs online when we suspend? */
30 static int fast_suspend;
32 static void __shutdown_handler(struct work_struct *unused);
33 static DECLARE_DELAYED_WORK(shutdown_work, __shutdown_handler);
35 int __xen_suspend(int fast_suspend, void (*resume_notifier)(int));
37 static int shutdown_process(void *__unused)
39 static char *envp[] = { "HOME=/", "TERM=linux",
40 "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
41 static char *poweroff_argv[] = { "/sbin/poweroff", NULL };
43 extern asmlinkage long sys_reboot(int magic1, int magic2,
44 unsigned int cmd, void *arg);
46 if ((shutting_down == SHUTDOWN_POWEROFF) ||
47 (shutting_down == SHUTDOWN_HALT)) {
48 if (call_usermodehelper("/sbin/poweroff", poweroff_argv,
51 sys_reboot(LINUX_REBOOT_MAGIC1,
53 LINUX_REBOOT_CMD_POWER_OFF,
55 #endif /* CONFIG_XEN */
59 shutting_down = SHUTDOWN_INVALID; /* could try again */
64 #ifdef CONFIG_PM_SLEEP
66 static int setup_suspend_evtchn(void);
68 /* Was last suspend request cancelled? */
69 static int suspend_cancelled;
71 static void xen_resume_notifier(int _suspend_cancelled)
73 int old_state = xchg(&shutting_down, SHUTDOWN_RESUMING);
74 BUG_ON(old_state != SHUTDOWN_SUSPEND);
75 suspend_cancelled = _suspend_cancelled;
78 static int xen_suspend(void *__unused)
83 err = set_cpus_allowed_ptr(current, cpumask_of(0));
85 pr_err("Xen suspend can't run on CPU0 (%d)\n", err);
90 err = __xen_suspend(fast_suspend, xen_resume_notifier);
92 pr_err("Xen suspend failed (%d)\n", err);
95 if (!suspend_cancelled)
96 setup_suspend_evtchn();
98 &shutting_down, SHUTDOWN_RESUMING, SHUTDOWN_INVALID);
99 } while (old_state == SHUTDOWN_SUSPEND);
102 case SHUTDOWN_INVALID:
103 case SHUTDOWN_SUSPEND:
105 case SHUTDOWN_RESUMING:
108 schedule_delayed_work(&shutdown_work, 0);
115 old_state = xchg(&shutting_down, SHUTDOWN_INVALID);
116 BUG_ON(old_state != SHUTDOWN_SUSPEND);
121 # define xen_suspend NULL
124 static void switch_shutdown_state(int new_state)
126 int prev_state, old_state = SHUTDOWN_INVALID;
128 /* We only drive shutdown_state into an active state. */
129 if (new_state == SHUTDOWN_INVALID)
133 /* We drop this transition if already in an active state. */
134 if ((old_state != SHUTDOWN_INVALID) &&
135 (old_state != SHUTDOWN_RESUMING))
137 /* Attempt to transition. */
138 prev_state = old_state;
139 old_state = cmpxchg(&shutting_down, old_state, new_state);
140 } while (old_state != prev_state);
142 /* Either we kick off the work, or we leave it to xen_suspend(). */
143 if (old_state == SHUTDOWN_INVALID)
144 schedule_delayed_work(&shutdown_work, 0);
146 BUG_ON(old_state != SHUTDOWN_RESUMING);
149 static void __shutdown_handler(struct work_struct *unused)
153 err = kernel_thread((shutting_down == SHUTDOWN_SUSPEND) ?
154 xen_suspend : shutdown_process,
155 NULL, CLONE_FS | CLONE_FILES);
158 pr_warning("Error creating shutdown process (%d): "
159 "retrying...\n", -err);
160 schedule_delayed_work(&shutdown_work, HZ/2);
164 static void shutdown_handler(struct xenbus_watch *watch,
165 const char **vec, unsigned int len)
167 extern void ctrl_alt_del(void);
169 struct xenbus_transaction xbt;
170 int err, new_state = SHUTDOWN_INVALID;
172 if ((shutting_down != SHUTDOWN_INVALID) &&
173 (shutting_down != SHUTDOWN_RESUMING))
177 err = xenbus_transaction_start(&xbt);
181 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
182 /* Ignore read errors and empty reads. */
183 if (XENBUS_IS_ERR_READ(str)) {
184 xenbus_transaction_end(xbt, 1);
188 xenbus_write(xbt, "control", "shutdown", "");
190 err = xenbus_transaction_end(xbt, 0);
191 if (err == -EAGAIN) {
196 if (strcmp(str, "poweroff") == 0)
197 new_state = SHUTDOWN_POWEROFF;
198 else if (strcmp(str, "reboot") == 0)
200 #ifdef CONFIG_PM_SLEEP
201 else if (strcmp(str, "suspend") == 0)
202 new_state = SHUTDOWN_SUSPEND;
204 else if (strcmp(str, "halt") == 0)
205 new_state = SHUTDOWN_HALT;
207 pr_warning("Ignoring shutdown request: %s\n", str);
209 switch_shutdown_state(new_state);
214 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
217 char sysrq_key = '\0';
218 struct xenbus_transaction xbt;
222 err = xenbus_transaction_start(&xbt);
225 if (xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key) <= 0) {
226 pr_err("Unable to read sysrq code in control/sysrq\n");
227 xenbus_transaction_end(xbt, 1);
231 if (sysrq_key != '\0')
232 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
234 err = xenbus_transaction_end(xbt, 0);
238 #ifdef CONFIG_MAGIC_SYSRQ
239 if (sysrq_key != '\0')
240 handle_sysrq(sysrq_key);
244 static struct xenbus_watch shutdown_watch = {
245 .node = "control/shutdown",
246 .callback = shutdown_handler
249 static struct xenbus_watch sysrq_watch = {
250 .node = "control/sysrq",
251 .callback = sysrq_handler
254 #ifdef CONFIG_PM_SLEEP
255 static irqreturn_t suspend_int(int irq, void* dev_id)
257 switch_shutdown_state(SHUTDOWN_SUSPEND);
261 static int setup_suspend_evtchn(void)
268 unbind_from_irqhandler(irq, NULL);
270 irq = bind_listening_port_to_irqhandler(0, suspend_int, 0, "suspend",
275 port = irq_to_evtchn_port(irq);
276 pr_info("suspend: event channel %d\n", port);
277 sprintf(portstr, "%d", port);
278 xenbus_write(XBT_NIL, "device/suspend", "event-channel", portstr);
283 #define setup_suspend_evtchn() 0
286 static int setup_shutdown_watcher(void)
290 err = register_xenbus_watch(&sysrq_watch);
292 pr_err("Failed to set sysrq watcher\n");
296 if (is_initial_xendomain())
299 xenbus_scanf(XBT_NIL, "control",
300 "platform-feature-multiprocessor-suspend",
301 "%d", &fast_suspend);
303 err = register_xenbus_watch(&shutdown_watch);
305 pr_err("Failed to set shutdown watcher\n");
309 /* suspend event channel */
310 err = setup_suspend_evtchn();
312 pr_err("Failed to register suspend event channel\n");
321 static int shutdown_event(struct notifier_block *notifier,
325 setup_shutdown_watcher();
329 static int __init setup_shutdown_event(void)
331 static struct notifier_block xenstore_notifier = {
332 .notifier_call = shutdown_event
334 register_xenstore_notifier(&xenstore_notifier);
339 subsys_initcall(setup_shutdown_event);
341 #else /* !defined(CONFIG_XEN) */
343 int xen_reboot_init(void)
345 return setup_shutdown_watcher();
348 #endif /* !defined(CONFIG_XEN) */