Merge tag 'locks-v3.17-2' of git://git.samba.org/jlayton/linux
[deliverable/linux.git] / drivers / xen / manage.c
CommitLineData
3e2b8fbe
JF
1/*
2 * Handle extern requests for shutdown, reboot and sysrq
3 */
283c0972
JP
4
5#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
6
3e2b8fbe
JF
7#include <linux/kernel.h>
8#include <linux/err.h>
5a0e3ad6 9#include <linux/slab.h>
3e2b8fbe
JF
10#include <linux/reboot.h>
11#include <linux/sysrq.h>
0e91398f
JF
12#include <linux/stop_machine.h>
13#include <linux/freezer.h>
19234c08 14#include <linux/syscore_ops.h>
63c9744b 15#include <linux/export.h>
3e2b8fbe 16
016b6f5f 17#include <xen/xen.h>
3e2b8fbe 18#include <xen/xenbus.h>
0e91398f
JF
19#include <xen/grant_table.h>
20#include <xen/events.h>
21#include <xen/hvc-console.h>
22#include <xen/xen-ops.h>
3e2b8fbe 23
0e91398f
JF
24#include <asm/xen/hypercall.h>
25#include <asm/xen/page.h>
016b6f5f 26#include <asm/xen/hypervisor.h>
0e91398f
JF
27
28enum 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};
3e2b8fbe
JF
38
39/* Ignore multiple shutdown requests. */
0e91398f
JF
40static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
41
ceb18029
IC
42struct suspend_info {
43 int cancelled;
44};
45
cd979883
SG
46static RAW_NOTIFIER_HEAD(xen_resume_notifier);
47
48void xen_resume_notifier_register(struct notifier_block *nb)
49{
50 raw_notifier_chain_register(&xen_resume_notifier, nb);
51}
52EXPORT_SYMBOL_GPL(xen_resume_notifier_register);
53
54void xen_resume_notifier_unregister(struct notifier_block *nb)
55{
56 raw_notifier_chain_unregister(&xen_resume_notifier, nb);
57}
58EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);
59
65e053a7 60#ifdef CONFIG_HIBERNATE_CALLBACKS
016b6f5f
SS
61static int xen_suspend(void *data)
62{
ceb18029 63 struct suspend_info *si = data;
359cdd3f 64 int err;
0e91398f
JF
65
66 BUG_ON(!irqs_disabled());
67
2e711c04 68 err = syscore_suspend();
770824bd 69 if (err) {
283c0972 70 pr_err("%s: system core suspend failed: %d\n", __func__, err);
770824bd
RW
71 return err;
72 }
359cdd3f 73
aa8532c3
DV
74 gnttab_suspend();
75 xen_arch_pre_suspend();
0e91398f
JF
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 */
aa8532c3
DV
82 si->cancelled = HYPERVISOR_suspend(xen_pv_domain()
83 ? virt_to_mfn(xen_start_info)
84 : 0);
0e91398f 85
aa8532c3
DV
86 xen_arch_post_suspend(si->cancelled);
87 gnttab_resume();
0e91398f 88
ceb18029 89 if (!si->cancelled) {
0e91398f 90 xen_irq_resume();
ad55db9f 91 xen_timer_resume();
0e91398f
JF
92 }
93
19234c08 94 syscore_resume();
1e6fcf84 95
0e91398f
JF
96 return 0;
97}
98
99static void do_suspend(void)
100{
101 int err;
ceb18029 102 struct suspend_info si;
0e91398f
JF
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) {
283c0972 112 pr_err("%s: freeze failed %d\n", __func__, err);
3fc1f1e2 113 goto out;
0e91398f
JF
114 }
115#endif
116
b3e96c0c 117 err = dpm_suspend_start(PMSG_FREEZE);
0e91398f 118 if (err) {
283c0972 119 pr_err("%s: dpm_suspend_start %d\n", __func__, err);
65f63384 120 goto out_thaw;
0e91398f
JF
121 }
122
c5cae661
IC
123 printk(KERN_DEBUG "suspending xenstore...\n");
124 xs_suspend();
125
cf579dfb 126 err = dpm_suspend_end(PMSG_FREEZE);
2ed8d2b3 127 if (err) {
283c0972 128 pr_err("dpm_suspend_end failed: %d\n", err);
186bab1c 129 si.cancelled = 0;
65f63384 130 goto out_resume;
2ed8d2b3
RW
131 }
132
ceb18029
IC
133 si.cancelled = 1;
134
b056b6a0 135 err = stop_machine(xen_suspend, &si, cpumask_of(0));
922cc38a 136
1b647823
DV
137 /* Resume console as early as possible. */
138 if (!si.cancelled)
139 xen_console_resume();
140
cd979883
SG
141 raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
142
cf579dfb 143 dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
922cc38a 144
0e91398f 145 if (err) {
283c0972 146 pr_err("failed to start xen_suspend: %d\n", err);
ceb18029 147 si.cancelled = 1;
0e91398f
JF
148 }
149
c5cae661 150out_resume:
ceb18029 151 if (!si.cancelled) {
ad55db9f 152 xen_arch_resume();
de5b31bd 153 xs_resume();
ad55db9f 154 } else
de5b31bd 155 xs_suspend_cancel();
0e91398f 156
b3e96c0c 157 dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
0e91398f 158
65f63384 159out_thaw:
0e91398f
JF
160#ifdef CONFIG_PREEMPT
161 thaw_processes();
65f63384 162out:
3fc1f1e2 163#endif
0e91398f
JF
164 shutting_down = SHUTDOWN_INVALID;
165}
1f112cee 166#endif /* CONFIG_HIBERNATE_CALLBACKS */
3e2b8fbe 167
55271723
IC
168struct shutdown_handler {
169 const char *command;
170 void (*cb)(void);
171};
172
eb47f712
KRW
173static 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}
55271723
IC
185static void do_poweroff(void)
186{
eb47f712
KRW
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 }
55271723
IC
199}
200
201static void do_reboot(void)
202{
203 shutting_down = SHUTDOWN_POWEROFF; /* ? */
204 ctrl_alt_del();
205}
206
3e2b8fbe
JF
207static 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;
55271723
IC
213 static struct shutdown_handler handlers[] = {
214 { "poweroff", do_poweroff },
215 { "halt", do_poweroff },
216 { "reboot", do_reboot },
1f112cee 217#ifdef CONFIG_HIBERNATE_CALLBACKS
55271723
IC
218 { "suspend", do_suspend },
219#endif
220 {NULL, NULL},
221 };
222 static struct shutdown_handler *handler;
3e2b8fbe
JF
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
55271723
IC
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", "");
3e2b8fbe
JF
247
248 err = xenbus_transaction_end(xbt, 0);
249 if (err == -EAGAIN) {
250 kfree(str);
251 goto again;
252 }
253
55271723
IC
254 if (handler->cb) {
255 handler->cb();
0e91398f 256 } else {
283c0972 257 pr_info("Ignoring shutdown request: %s\n", str);
3e2b8fbe
JF
258 shutting_down = SHUTDOWN_INVALID;
259 }
260
261 kfree(str);
262}
263
f3bc3189 264#ifdef CONFIG_MAGIC_SYSRQ
3e2b8fbe
JF
265static 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)) {
283c0972 277 pr_err("Unable to read sysrq code in control/sysrq\n");
3e2b8fbe
JF
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')
f335397d 290 handle_sysrq(sysrq_key);
3e2b8fbe
JF
291}
292
3e2b8fbe
JF
293static struct xenbus_watch sysrq_watch = {
294 .node = "control/sysrq",
295 .callback = sysrq_handler
296};
f3bc3189
RD
297#endif
298
299static struct xenbus_watch shutdown_watch = {
300 .node = "control/shutdown",
301 .callback = shutdown_handler
302};
3e2b8fbe 303
eb47f712
KRW
304static struct notifier_block xen_reboot_nb = {
305 .notifier_call = poweroff_nb,
306};
307
3e2b8fbe
JF
308static int setup_shutdown_watcher(void)
309{
310 int err;
311
312 err = register_xenbus_watch(&shutdown_watch);
313 if (err) {
283c0972 314 pr_err("Failed to set shutdown watcher\n");
3e2b8fbe
JF
315 return err;
316 }
317
eb47f712 318
f3bc3189 319#ifdef CONFIG_MAGIC_SYSRQ
3e2b8fbe
JF
320 err = register_xenbus_watch(&sysrq_watch);
321 if (err) {
283c0972 322 pr_err("Failed to set sysrq watcher\n");
3e2b8fbe
JF
323 return err;
324 }
f3bc3189 325#endif
3e2b8fbe
JF
326
327 return 0;
328}
329
330static 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
016b6f5f 338int xen_setup_shutdown_event(void)
3e2b8fbe
JF
339{
340 static struct notifier_block xenstore_notifier = {
341 .notifier_call = shutdown_event
342 };
702d4eb9
SS
343
344 if (!xen_domain())
345 return -ENODEV;
3e2b8fbe 346 register_xenstore_notifier(&xenstore_notifier);
eb47f712 347 register_reboot_notifier(&xen_reboot_nb);
3e2b8fbe
JF
348
349 return 0;
350}
183d03cc 351EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
3e2b8fbe 352
702d4eb9 353subsys_initcall(xen_setup_shutdown_event);
This page took 0.499095 seconds and 5 git commands to generate.