- Update Xen patches to 3.3-rc5 and c/s 1157.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / core / reboot.c
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>
14
15 #ifdef HAVE_XEN_PLATFORM_COMPAT_H
16 #include <xen/platform-compat.h>
17 #undef handle_sysrq
18 #endif
19
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
25
26 /* Ignore multiple shutdown requests. */
27 static int shutting_down = SHUTDOWN_INVALID;
28
29 /* Can we leave APs online when we suspend? */
30 static int fast_suspend;
31
32 static void __shutdown_handler(struct work_struct *unused);
33 static DECLARE_DELAYED_WORK(shutdown_work, __shutdown_handler);
34
35 int __xen_suspend(int fast_suspend, void (*resume_notifier)(int));
36
37 static int shutdown_process(void *__unused)
38 {
39         static char *envp[] = { "HOME=/", "TERM=linux",
40                                 "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
41         static char *poweroff_argv[] = { "/sbin/poweroff", NULL };
42
43         extern asmlinkage long sys_reboot(int magic1, int magic2,
44                                           unsigned int cmd, void *arg);
45
46         if ((shutting_down == SHUTDOWN_POWEROFF) ||
47             (shutting_down == SHUTDOWN_HALT)) {
48                 if (call_usermodehelper("/sbin/poweroff", poweroff_argv,
49                                         envp, 0) < 0) {
50 #ifdef CONFIG_XEN
51                         sys_reboot(LINUX_REBOOT_MAGIC1,
52                                    LINUX_REBOOT_MAGIC2,
53                                    LINUX_REBOOT_CMD_POWER_OFF,
54                                    NULL);
55 #endif /* CONFIG_XEN */
56                 }
57         }
58
59         shutting_down = SHUTDOWN_INVALID; /* could try again */
60
61         return 0;
62 }
63
64 #ifdef CONFIG_PM_SLEEP
65
66 static int setup_suspend_evtchn(void);
67
68 /* Was last suspend request cancelled? */
69 static int suspend_cancelled;
70
71 static void xen_resume_notifier(int _suspend_cancelled)
72 {
73         int old_state = xchg(&shutting_down, SHUTDOWN_RESUMING);
74         BUG_ON(old_state != SHUTDOWN_SUSPEND);
75         suspend_cancelled = _suspend_cancelled;
76 }
77
78 static int xen_suspend(void *__unused)
79 {
80         int err, old_state;
81
82         daemonize("suspend");
83         err = set_cpus_allowed_ptr(current, cpumask_of(0));
84         if (err) {
85                 pr_err("Xen suspend can't run on CPU0 (%d)\n", err);
86                 goto fail;
87         }
88
89         do {
90                 err = __xen_suspend(fast_suspend, xen_resume_notifier);
91                 if (err) {
92                         pr_err("Xen suspend failed (%d)\n", err);
93                         goto fail;
94                 }
95                 if (!suspend_cancelled)
96                         setup_suspend_evtchn();
97                 old_state = cmpxchg(
98                         &shutting_down, SHUTDOWN_RESUMING, SHUTDOWN_INVALID);
99         } while (old_state == SHUTDOWN_SUSPEND);
100
101         switch (old_state) {
102         case SHUTDOWN_INVALID:
103         case SHUTDOWN_SUSPEND:
104                 BUG();
105         case SHUTDOWN_RESUMING:
106                 break;
107         default:
108                 schedule_delayed_work(&shutdown_work, 0);
109                 break;
110         }
111
112         return 0;
113
114  fail:
115         old_state = xchg(&shutting_down, SHUTDOWN_INVALID);
116         BUG_ON(old_state != SHUTDOWN_SUSPEND);
117         return 0;
118 }
119
120 #else
121 # define xen_suspend NULL
122 #endif
123
124 static void switch_shutdown_state(int new_state)
125 {
126         int prev_state, old_state = SHUTDOWN_INVALID;
127
128         /* We only drive shutdown_state into an active state. */
129         if (new_state == SHUTDOWN_INVALID)
130                 return;
131
132         do {
133                 /* We drop this transition if already in an active state. */
134                 if ((old_state != SHUTDOWN_INVALID) &&
135                     (old_state != SHUTDOWN_RESUMING))
136                         return;
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);
141
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);
145         else
146                 BUG_ON(old_state != SHUTDOWN_RESUMING);
147 }
148
149 static void __shutdown_handler(struct work_struct *unused)
150 {
151         int err;
152
153         err = kernel_thread((shutting_down == SHUTDOWN_SUSPEND) ?
154                             xen_suspend : shutdown_process,
155                             NULL, CLONE_FS | CLONE_FILES);
156
157         if (err < 0) {
158                 pr_warning("Error creating shutdown process (%d): "
159                            "retrying...\n", -err);
160                 schedule_delayed_work(&shutdown_work, HZ/2);
161         }
162 }
163
164 static void shutdown_handler(struct xenbus_watch *watch,
165                              const char **vec, unsigned int len)
166 {
167         extern void ctrl_alt_del(void);
168         char *str;
169         struct xenbus_transaction xbt;
170         int err, new_state = SHUTDOWN_INVALID;
171
172         if ((shutting_down != SHUTDOWN_INVALID) &&
173             (shutting_down != SHUTDOWN_RESUMING))
174                 return;
175
176  again:
177         err = xenbus_transaction_start(&xbt);
178         if (err)
179                 return;
180
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);
185                 return;
186         }
187
188         xenbus_write(xbt, "control", "shutdown", "");
189
190         err = xenbus_transaction_end(xbt, 0);
191         if (err == -EAGAIN) {
192                 kfree(str);
193                 goto again;
194         }
195
196         if (strcmp(str, "poweroff") == 0)
197                 new_state = SHUTDOWN_POWEROFF;
198         else if (strcmp(str, "reboot") == 0)
199                 ctrl_alt_del();
200 #ifdef CONFIG_PM_SLEEP
201         else if (strcmp(str, "suspend") == 0)
202                 new_state = SHUTDOWN_SUSPEND;
203 #endif
204         else if (strcmp(str, "halt") == 0)
205                 new_state = SHUTDOWN_HALT;
206         else
207                 pr_warning("Ignoring shutdown request: %s\n", str);
208
209         switch_shutdown_state(new_state);
210
211         kfree(str);
212 }
213
214 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
215                           unsigned int len)
216 {
217         char sysrq_key = '\0';
218         struct xenbus_transaction xbt;
219         int err;
220
221  again:
222         err = xenbus_transaction_start(&xbt);
223         if (err)
224                 return;
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);
228                 return;
229         }
230
231         if (sysrq_key != '\0')
232                 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
233
234         err = xenbus_transaction_end(xbt, 0);
235         if (err == -EAGAIN)
236                 goto again;
237
238 #ifdef CONFIG_MAGIC_SYSRQ
239         if (sysrq_key != '\0')
240                 handle_sysrq(sysrq_key);
241 #endif
242 }
243
244 static struct xenbus_watch shutdown_watch = {
245         .node = "control/shutdown",
246         .callback = shutdown_handler
247 };
248
249 static struct xenbus_watch sysrq_watch = {
250         .node = "control/sysrq",
251         .callback = sysrq_handler
252 };
253
254 #ifdef CONFIG_PM_SLEEP
255 static irqreturn_t suspend_int(int irq, void* dev_id)
256 {
257         switch_shutdown_state(SHUTDOWN_SUSPEND);
258         return IRQ_HANDLED;
259 }
260
261 static int setup_suspend_evtchn(void)
262 {
263         static int irq;
264         int port;
265         char portstr[16];
266
267         if (irq > 0)
268                 unbind_from_irqhandler(irq, NULL);
269
270         irq = bind_listening_port_to_irqhandler(0, suspend_int, 0, "suspend",
271                                                 NULL);
272         if (irq <= 0)
273                 return -1;
274
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);
279
280         return 0;
281 }
282 #else
283 #define setup_suspend_evtchn() 0
284 #endif
285
286 static int setup_shutdown_watcher(void)
287 {
288         int err;
289
290         err = register_xenbus_watch(&sysrq_watch);
291         if (err) {
292                 pr_err("Failed to set sysrq watcher\n");
293                 return err;
294         }
295
296         if (is_initial_xendomain())
297                 return 0;
298
299         xenbus_scanf(XBT_NIL, "control",
300                      "platform-feature-multiprocessor-suspend",
301                      "%d", &fast_suspend);
302
303         err = register_xenbus_watch(&shutdown_watch);
304         if (err) {
305                 pr_err("Failed to set shutdown watcher\n");
306                 return err;
307         }
308
309         /* suspend event channel */
310         err = setup_suspend_evtchn();
311         if (err) {
312                 pr_err("Failed to register suspend event channel\n");
313                 return err;
314         }
315
316         return 0;
317 }
318
319 #ifdef CONFIG_XEN
320
321 static int shutdown_event(struct notifier_block *notifier,
322                           unsigned long event,
323                           void *data)
324 {
325         setup_shutdown_watcher();
326         return NOTIFY_DONE;
327 }
328
329 static int __init setup_shutdown_event(void)
330 {
331         static struct notifier_block xenstore_notifier = {
332                 .notifier_call = shutdown_event
333         };
334         register_xenstore_notifier(&xenstore_notifier);
335
336         return 0;
337 }
338
339 subsys_initcall(setup_shutdown_event);
340
341 #else /* !defined(CONFIG_XEN) */
342
343 int xen_reboot_init(void)
344 {
345         return setup_shutdown_watcher();
346 }
347
348 #endif /* !defined(CONFIG_XEN) */