Merge tag 'drm/panel/for-3.17-rc1' of git://anongit.freedesktop.org/tegra/linux into...
[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 };
45
46 static RAW_NOTIFIER_HEAD(xen_resume_notifier);
47
48 void xen_resume_notifier_register(struct notifier_block *nb)
49 {
50         raw_notifier_chain_register(&xen_resume_notifier, nb);
51 }
52 EXPORT_SYMBOL_GPL(xen_resume_notifier_register);
53
54 void xen_resume_notifier_unregister(struct notifier_block *nb)
55 {
56         raw_notifier_chain_unregister(&xen_resume_notifier, nb);
57 }
58 EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);
59
60 #ifdef CONFIG_HIBERNATE_CALLBACKS
61 static int xen_suspend(void *data)
62 {
63         struct suspend_info *si = data;
64         int err;
65
66         BUG_ON(!irqs_disabled());
67
68         err = syscore_suspend();
69         if (err) {
70                 pr_err("%s: system core suspend failed: %d\n", __func__, err);
71                 return err;
72         }
73
74         gnttab_suspend();
75         xen_arch_pre_suspend();
76
77         /*
78          * This hypercall returns 1 if suspend was cancelled
79          * or the domain was merely checkpointed, and 0 if it
80          * is resuming in a new domain.
81          */
82         si->cancelled = HYPERVISOR_suspend(xen_pv_domain()
83                                            ? virt_to_mfn(xen_start_info)
84                                            : 0);
85
86         xen_arch_post_suspend(si->cancelled);
87         gnttab_resume();
88
89         if (!si->cancelled) {
90                 xen_irq_resume();
91                 xen_timer_resume();
92         }
93
94         syscore_resume();
95
96         return 0;
97 }
98
99 static void do_suspend(void)
100 {
101         int err;
102         struct suspend_info si;
103
104         shutting_down = SHUTDOWN_SUSPEND;
105
106 #ifdef CONFIG_PREEMPT
107         /* If the kernel is preemptible, we need to freeze all the processes
108            to prevent them from being in the middle of a pagetable update
109            during suspend. */
110         err = freeze_processes();
111         if (err) {
112                 pr_err("%s: freeze failed %d\n", __func__, err);
113                 goto out;
114         }
115 #endif
116
117         err = dpm_suspend_start(PMSG_FREEZE);
118         if (err) {
119                 pr_err("%s: dpm_suspend_start %d\n", __func__, err);
120                 goto out_thaw;
121         }
122
123         printk(KERN_DEBUG "suspending xenstore...\n");
124         xs_suspend();
125
126         err = dpm_suspend_end(PMSG_FREEZE);
127         if (err) {
128                 pr_err("dpm_suspend_end failed: %d\n", err);
129                 si.cancelled = 0;
130                 goto out_resume;
131         }
132
133         si.cancelled = 1;
134
135         err = stop_machine(xen_suspend, &si, cpumask_of(0));
136
137         /* Resume console as early as possible. */
138         if (!si.cancelled)
139                 xen_console_resume();
140
141         raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
142
143         dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
144
145         if (err) {
146                 pr_err("failed to start xen_suspend: %d\n", err);
147                 si.cancelled = 1;
148         }
149
150 out_resume:
151         if (!si.cancelled) {
152                 xen_arch_resume();
153                 xs_resume();
154         } else
155                 xs_suspend_cancel();
156
157         dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
158
159 out_thaw:
160 #ifdef CONFIG_PREEMPT
161         thaw_processes();
162 out:
163 #endif
164         shutting_down = SHUTDOWN_INVALID;
165 }
166 #endif  /* CONFIG_HIBERNATE_CALLBACKS */
167
168 struct shutdown_handler {
169         const char *command;
170         void (*cb)(void);
171 };
172
173 static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused)
174 {
175         switch (code) {
176         case SYS_DOWN:
177         case SYS_HALT:
178         case SYS_POWER_OFF:
179                 shutting_down = SHUTDOWN_POWEROFF;
180         default:
181                 break;
182         }
183         return NOTIFY_DONE;
184 }
185 static void do_poweroff(void)
186 {
187         switch (system_state) {
188         case SYSTEM_BOOTING:
189                 orderly_poweroff(true);
190                 break;
191         case SYSTEM_RUNNING:
192                 orderly_poweroff(false);
193                 break;
194         default:
195                 /* Don't do it when we are halting/rebooting. */
196                 pr_info("Ignoring Xen toolstack shutdown.\n");
197                 break;
198         }
199 }
200
201 static void do_reboot(void)
202 {
203         shutting_down = SHUTDOWN_POWEROFF; /* ? */
204         ctrl_alt_del();
205 }
206
207 static void shutdown_handler(struct xenbus_watch *watch,
208                              const char **vec, unsigned int len)
209 {
210         char *str;
211         struct xenbus_transaction xbt;
212         int err;
213         static struct shutdown_handler handlers[] = {
214                 { "poweroff",   do_poweroff },
215                 { "halt",       do_poweroff },
216                 { "reboot",     do_reboot   },
217 #ifdef CONFIG_HIBERNATE_CALLBACKS
218                 { "suspend",    do_suspend  },
219 #endif
220                 {NULL, NULL},
221         };
222         static struct shutdown_handler *handler;
223
224         if (shutting_down != SHUTDOWN_INVALID)
225                 return;
226
227  again:
228         err = xenbus_transaction_start(&xbt);
229         if (err)
230                 return;
231
232         str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
233         /* Ignore read errors and empty reads. */
234         if (XENBUS_IS_ERR_READ(str)) {
235                 xenbus_transaction_end(xbt, 1);
236                 return;
237         }
238
239         for (handler = &handlers[0]; handler->command; handler++) {
240                 if (strcmp(str, handler->command) == 0)
241                         break;
242         }
243
244         /* Only acknowledge commands which we are prepared to handle. */
245         if (handler->cb)
246                 xenbus_write(xbt, "control", "shutdown", "");
247
248         err = xenbus_transaction_end(xbt, 0);
249         if (err == -EAGAIN) {
250                 kfree(str);
251                 goto again;
252         }
253
254         if (handler->cb) {
255                 handler->cb();
256         } else {
257                 pr_info("Ignoring shutdown request: %s\n", str);
258                 shutting_down = SHUTDOWN_INVALID;
259         }
260
261         kfree(str);
262 }
263
264 #ifdef CONFIG_MAGIC_SYSRQ
265 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
266                           unsigned int len)
267 {
268         char sysrq_key = '\0';
269         struct xenbus_transaction xbt;
270         int err;
271
272  again:
273         err = xenbus_transaction_start(&xbt);
274         if (err)
275                 return;
276         if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
277                 pr_err("Unable to read sysrq code in control/sysrq\n");
278                 xenbus_transaction_end(xbt, 1);
279                 return;
280         }
281
282         if (sysrq_key != '\0')
283                 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
284
285         err = xenbus_transaction_end(xbt, 0);
286         if (err == -EAGAIN)
287                 goto again;
288
289         if (sysrq_key != '\0')
290                 handle_sysrq(sysrq_key);
291 }
292
293 static struct xenbus_watch sysrq_watch = {
294         .node = "control/sysrq",
295         .callback = sysrq_handler
296 };
297 #endif
298
299 static struct xenbus_watch shutdown_watch = {
300         .node = "control/shutdown",
301         .callback = shutdown_handler
302 };
303
304 static struct notifier_block xen_reboot_nb = {
305         .notifier_call = poweroff_nb,
306 };
307
308 static int setup_shutdown_watcher(void)
309 {
310         int err;
311
312         err = register_xenbus_watch(&shutdown_watch);
313         if (err) {
314                 pr_err("Failed to set shutdown watcher\n");
315                 return err;
316         }
317
318
319 #ifdef CONFIG_MAGIC_SYSRQ
320         err = register_xenbus_watch(&sysrq_watch);
321         if (err) {
322                 pr_err("Failed to set sysrq watcher\n");
323                 return err;
324         }
325 #endif
326
327         return 0;
328 }
329
330 static int shutdown_event(struct notifier_block *notifier,
331                           unsigned long event,
332                           void *data)
333 {
334         setup_shutdown_watcher();
335         return NOTIFY_DONE;
336 }
337
338 int xen_setup_shutdown_event(void)
339 {
340         static struct notifier_block xenstore_notifier = {
341                 .notifier_call = shutdown_event
342         };
343
344         if (!xen_domain())
345                 return -ENODEV;
346         register_xenstore_notifier(&xenstore_notifier);
347         register_reboot_notifier(&xen_reboot_nb);
348
349         return 0;
350 }
351 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
352
353 subsys_initcall(xen_setup_shutdown_event);