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