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