Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
[cascardo/linux.git] / drivers / xen / manage.c
1 /*
2  * Handle extern requests for shutdown, reboot and sysrq
3  */
4
5 #define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
6
7 #include <linux/kernel.h>
8 #include <linux/err.h>
9 #include <linux/slab.h>
10 #include <linux/reboot.h>
11 #include <linux/sysrq.h>
12 #include <linux/stop_machine.h>
13 #include <linux/freezer.h>
14 #include <linux/syscore_ops.h>
15 #include <linux/export.h>
16
17 #include <xen/xen.h>
18 #include <xen/xenbus.h>
19 #include <xen/grant_table.h>
20 #include <xen/events.h>
21 #include <xen/hvc-console.h>
22 #include <xen/xen-ops.h>
23
24 #include <asm/xen/hypercall.h>
25 #include <asm/xen/page.h>
26 #include <asm/xen/hypervisor.h>
27
28 enum shutdown_state {
29         SHUTDOWN_INVALID = -1,
30         SHUTDOWN_POWEROFF = 0,
31         SHUTDOWN_SUSPEND = 2,
32         /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
33            report a crash, not be instructed to crash!
34            HALT is the same as POWEROFF, as far as we're concerned.  The tools use
35            the distinction when we return the reason code to them.  */
36          SHUTDOWN_HALT = 4,
37 };
38
39 /* Ignore multiple shutdown requests. */
40 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
41
42 struct suspend_info {
43         int cancelled;
44         unsigned long arg; /* extra hypercall argument */
45         void (*pre)(void);
46         void (*post)(int cancelled);
47 };
48
49 static RAW_NOTIFIER_HEAD(xen_resume_notifier);
50
51 void xen_resume_notifier_register(struct notifier_block *nb)
52 {
53         raw_notifier_chain_register(&xen_resume_notifier, nb);
54 }
55 EXPORT_SYMBOL_GPL(xen_resume_notifier_register);
56
57 void xen_resume_notifier_unregister(struct notifier_block *nb)
58 {
59         raw_notifier_chain_unregister(&xen_resume_notifier, nb);
60 }
61 EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);
62
63 #ifdef CONFIG_HIBERNATE_CALLBACKS
64 static void xen_hvm_post_suspend(int cancelled)
65 {
66         xen_arch_hvm_post_suspend(cancelled);
67         gnttab_resume();
68 }
69
70 static void xen_pre_suspend(void)
71 {
72         xen_mm_pin_all();
73         gnttab_suspend();
74         xen_arch_pre_suspend();
75 }
76
77 static void xen_post_suspend(int cancelled)
78 {
79         xen_arch_post_suspend(cancelled);
80         gnttab_resume();
81         xen_mm_unpin_all();
82 }
83
84 static int xen_suspend(void *data)
85 {
86         struct suspend_info *si = data;
87         int err;
88
89         BUG_ON(!irqs_disabled());
90
91         err = syscore_suspend();
92         if (err) {
93                 pr_err("%s: system core suspend failed: %d\n", __func__, err);
94                 return err;
95         }
96
97         if (si->pre)
98                 si->pre();
99
100         /*
101          * This hypercall returns 1 if suspend was cancelled
102          * or the domain was merely checkpointed, and 0 if it
103          * is resuming in a new domain.
104          */
105         si->cancelled = HYPERVISOR_suspend(si->arg);
106
107         if (si->post)
108                 si->post(si->cancelled);
109
110         if (!si->cancelled) {
111                 xen_irq_resume();
112                 xen_console_resume();
113                 xen_timer_resume();
114         }
115
116         syscore_resume();
117
118         return 0;
119 }
120
121 static void do_suspend(void)
122 {
123         int err;
124         struct suspend_info si;
125
126         shutting_down = SHUTDOWN_SUSPEND;
127
128 #ifdef CONFIG_PREEMPT
129         /* If the kernel is preemptible, we need to freeze all the processes
130            to prevent them from being in the middle of a pagetable update
131            during suspend. */
132         err = freeze_processes();
133         if (err) {
134                 pr_err("%s: freeze failed %d\n", __func__, err);
135                 goto out;
136         }
137 #endif
138
139         err = dpm_suspend_start(PMSG_FREEZE);
140         if (err) {
141                 pr_err("%s: dpm_suspend_start %d\n", __func__, err);
142                 goto out_thaw;
143         }
144
145         printk(KERN_DEBUG "suspending xenstore...\n");
146         xs_suspend();
147
148         err = dpm_suspend_end(PMSG_FREEZE);
149         if (err) {
150                 pr_err("dpm_suspend_end failed: %d\n", err);
151                 si.cancelled = 0;
152                 goto out_resume;
153         }
154
155         si.cancelled = 1;
156
157         if (xen_hvm_domain()) {
158                 si.arg = 0UL;
159                 si.pre = NULL;
160                 si.post = &xen_hvm_post_suspend;
161         } else {
162                 si.arg = virt_to_mfn(xen_start_info);
163                 si.pre = &xen_pre_suspend;
164                 si.post = &xen_post_suspend;
165         }
166
167         err = stop_machine(xen_suspend, &si, cpumask_of(0));
168
169         raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
170
171         dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
172
173         if (err) {
174                 pr_err("failed to start xen_suspend: %d\n", err);
175                 si.cancelled = 1;
176         }
177
178 out_resume:
179         if (!si.cancelled) {
180                 xen_arch_resume();
181                 xs_resume();
182         } else
183                 xs_suspend_cancel();
184
185         dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
186
187 out_thaw:
188 #ifdef CONFIG_PREEMPT
189         thaw_processes();
190 out:
191 #endif
192         shutting_down = SHUTDOWN_INVALID;
193 }
194 #endif  /* CONFIG_HIBERNATE_CALLBACKS */
195
196 struct shutdown_handler {
197         const char *command;
198         void (*cb)(void);
199 };
200
201 static void do_poweroff(void)
202 {
203         shutting_down = SHUTDOWN_POWEROFF;
204         orderly_poweroff(false);
205 }
206
207 static void do_reboot(void)
208 {
209         shutting_down = SHUTDOWN_POWEROFF; /* ? */
210         ctrl_alt_del();
211 }
212
213 static void shutdown_handler(struct xenbus_watch *watch,
214                              const char **vec, unsigned int len)
215 {
216         char *str;
217         struct xenbus_transaction xbt;
218         int err;
219         static struct shutdown_handler handlers[] = {
220                 { "poweroff",   do_poweroff },
221                 { "halt",       do_poweroff },
222                 { "reboot",     do_reboot   },
223 #ifdef CONFIG_HIBERNATE_CALLBACKS
224                 { "suspend",    do_suspend  },
225 #endif
226                 {NULL, NULL},
227         };
228         static struct shutdown_handler *handler;
229
230         if (shutting_down != SHUTDOWN_INVALID)
231                 return;
232
233  again:
234         err = xenbus_transaction_start(&xbt);
235         if (err)
236                 return;
237
238         str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
239         /* Ignore read errors and empty reads. */
240         if (XENBUS_IS_ERR_READ(str)) {
241                 xenbus_transaction_end(xbt, 1);
242                 return;
243         }
244
245         for (handler = &handlers[0]; handler->command; handler++) {
246                 if (strcmp(str, handler->command) == 0)
247                         break;
248         }
249
250         /* Only acknowledge commands which we are prepared to handle. */
251         if (handler->cb)
252                 xenbus_write(xbt, "control", "shutdown", "");
253
254         err = xenbus_transaction_end(xbt, 0);
255         if (err == -EAGAIN) {
256                 kfree(str);
257                 goto again;
258         }
259
260         if (handler->cb) {
261                 handler->cb();
262         } else {
263                 pr_info("Ignoring shutdown request: %s\n", str);
264                 shutting_down = SHUTDOWN_INVALID;
265         }
266
267         kfree(str);
268 }
269
270 #ifdef CONFIG_MAGIC_SYSRQ
271 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
272                           unsigned int len)
273 {
274         char sysrq_key = '\0';
275         struct xenbus_transaction xbt;
276         int err;
277
278  again:
279         err = xenbus_transaction_start(&xbt);
280         if (err)
281                 return;
282         if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
283                 pr_err("Unable to read sysrq code in control/sysrq\n");
284                 xenbus_transaction_end(xbt, 1);
285                 return;
286         }
287
288         if (sysrq_key != '\0')
289                 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
290
291         err = xenbus_transaction_end(xbt, 0);
292         if (err == -EAGAIN)
293                 goto again;
294
295         if (sysrq_key != '\0')
296                 handle_sysrq(sysrq_key);
297 }
298
299 static struct xenbus_watch sysrq_watch = {
300         .node = "control/sysrq",
301         .callback = sysrq_handler
302 };
303 #endif
304
305 static struct xenbus_watch shutdown_watch = {
306         .node = "control/shutdown",
307         .callback = shutdown_handler
308 };
309
310 static int setup_shutdown_watcher(void)
311 {
312         int err;
313
314         err = register_xenbus_watch(&shutdown_watch);
315         if (err) {
316                 pr_err("Failed to set shutdown watcher\n");
317                 return err;
318         }
319
320 #ifdef CONFIG_MAGIC_SYSRQ
321         err = register_xenbus_watch(&sysrq_watch);
322         if (err) {
323                 pr_err("Failed to set sysrq watcher\n");
324                 return err;
325         }
326 #endif
327
328         return 0;
329 }
330
331 static int shutdown_event(struct notifier_block *notifier,
332                           unsigned long event,
333                           void *data)
334 {
335         setup_shutdown_watcher();
336         return NOTIFY_DONE;
337 }
338
339 int xen_setup_shutdown_event(void)
340 {
341         static struct notifier_block xenstore_notifier = {
342                 .notifier_call = shutdown_event
343         };
344
345         if (!xen_domain())
346                 return -ENODEV;
347         register_xenstore_notifier(&xenstore_notifier);
348
349         return 0;
350 }
351 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
352
353 subsys_initcall(xen_setup_shutdown_event);