xen: fix compile issue if XEN is enabled but XEN_PVHVM is disabled
[deliverable/linux.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>
3e2b8fbe 11
016b6f5f 12#include <xen/xen.h>
3e2b8fbe 13#include <xen/xenbus.h>
0e91398f
JF
14#include <xen/grant_table.h>
15#include <xen/events.h>
16#include <xen/hvc-console.h>
17#include <xen/xen-ops.h>
3e2b8fbe 18
0e91398f
JF
19#include <asm/xen/hypercall.h>
20#include <asm/xen/page.h>
016b6f5f 21#include <asm/xen/hypervisor.h>
0e91398f
JF
22
23enum shutdown_state {
24 SHUTDOWN_INVALID = -1,
25 SHUTDOWN_POWEROFF = 0,
26 SHUTDOWN_SUSPEND = 2,
27 /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
28 report a crash, not be instructed to crash!
29 HALT is the same as POWEROFF, as far as we're concerned. The tools use
30 the distinction when we return the reason code to them. */
31 SHUTDOWN_HALT = 4,
32};
3e2b8fbe
JF
33
34/* Ignore multiple shutdown requests. */
0e91398f
JF
35static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
36
c7827728 37#ifdef CONFIG_PM_SLEEP
016b6f5f 38static int xen_hvm_suspend(void *data)
0e91398f 39{
8dd38383 40 int err;
016b6f5f 41 struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
0e91398f 42 int *cancelled = data;
016b6f5f
SS
43
44 BUG_ON(!irqs_disabled());
45
8dd38383
IC
46 err = sysdev_suspend(PMSG_SUSPEND);
47 if (err) {
48 printk(KERN_ERR "xen_hvm_suspend: sysdev_suspend failed: %d\n",
49 err);
50 return err;
51 }
52
016b6f5f
SS
53 *cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
54
55 xen_hvm_post_suspend(*cancelled);
56 gnttab_resume();
57
58 if (!*cancelled) {
59 xen_irq_resume();
6411fe69 60 xen_console_resume();
016b6f5f
SS
61 xen_timer_resume();
62 }
63
8dd38383
IC
64 sysdev_resume();
65
016b6f5f
SS
66 return 0;
67}
68
69static int xen_suspend(void *data)
70{
359cdd3f 71 int err;
016b6f5f 72 int *cancelled = data;
0e91398f
JF
73
74 BUG_ON(!irqs_disabled());
75
770824bd
RW
76 err = sysdev_suspend(PMSG_SUSPEND);
77 if (err) {
78 printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
79 err);
770824bd
RW
80 return err;
81 }
359cdd3f 82
0e91398f
JF
83 xen_mm_pin_all();
84 gnttab_suspend();
0e91398f
JF
85 xen_pre_suspend();
86
87 /*
88 * This hypercall returns 1 if suspend was cancelled
89 * or the domain was merely checkpointed, and 0 if it
90 * is resuming in a new domain.
91 */
92 *cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
93
94 xen_post_suspend(*cancelled);
0e91398f
JF
95 gnttab_resume();
96 xen_mm_unpin_all();
97
98 if (!*cancelled) {
99 xen_irq_resume();
100 xen_console_resume();
ad55db9f 101 xen_timer_resume();
0e91398f
JF
102 }
103
1e6fcf84 104 sysdev_resume();
1e6fcf84 105
0e91398f
JF
106 return 0;
107}
108
109static void do_suspend(void)
110{
111 int err;
112 int cancelled = 1;
113
114 shutting_down = SHUTDOWN_SUSPEND;
115
116#ifdef CONFIG_PREEMPT
117 /* If the kernel is preemptible, we need to freeze all the processes
118 to prevent them from being in the middle of a pagetable update
119 during suspend. */
120 err = freeze_processes();
121 if (err) {
122 printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
3fc1f1e2 123 goto out;
0e91398f
JF
124 }
125#endif
126
d1616302 127 err = dpm_suspend_start(PMSG_SUSPEND);
0e91398f 128 if (err) {
d1616302 129 printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
65f63384 130 goto out_thaw;
0e91398f
JF
131 }
132
c5cae661
IC
133 printk(KERN_DEBUG "suspending xenstore...\n");
134 xs_suspend();
135
d1616302 136 err = dpm_suspend_noirq(PMSG_SUSPEND);
2ed8d2b3 137 if (err) {
d1616302 138 printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
65f63384 139 goto out_resume;
2ed8d2b3
RW
140 }
141
016b6f5f
SS
142 if (xen_hvm_domain())
143 err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0));
144 else
145 err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
922cc38a
JF
146
147 dpm_resume_noirq(PMSG_RESUME);
148
0e91398f
JF
149 if (err) {
150 printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
65f63384 151 cancelled = 1;
0e91398f
JF
152 }
153
c5cae661 154out_resume:
ad55db9f
IY
155 if (!cancelled) {
156 xen_arch_resume();
de5b31bd 157 xs_resume();
ad55db9f 158 } else
de5b31bd 159 xs_suspend_cancel();
0e91398f 160
d1616302 161 dpm_resume_end(PMSG_RESUME);
0e91398f 162
359cdd3f
JF
163 /* Make sure timer events get retriggered on all CPUs */
164 clock_was_set();
65f63384
IC
165
166out_thaw:
0e91398f
JF
167#ifdef CONFIG_PREEMPT
168 thaw_processes();
65f63384 169out:
3fc1f1e2 170#endif
0e91398f
JF
171 shutting_down = SHUTDOWN_INVALID;
172}
c7827728 173#endif /* CONFIG_PM_SLEEP */
3e2b8fbe
JF
174
175static void shutdown_handler(struct xenbus_watch *watch,
176 const char **vec, unsigned int len)
177{
178 char *str;
179 struct xenbus_transaction xbt;
180 int err;
181
182 if (shutting_down != SHUTDOWN_INVALID)
183 return;
184
185 again:
186 err = xenbus_transaction_start(&xbt);
187 if (err)
188 return;
189
190 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
191 /* Ignore read errors and empty reads. */
192 if (XENBUS_IS_ERR_READ(str)) {
193 xenbus_transaction_end(xbt, 1);
194 return;
195 }
196
197 xenbus_write(xbt, "control", "shutdown", "");
198
199 err = xenbus_transaction_end(xbt, 0);
200 if (err == -EAGAIN) {
201 kfree(str);
202 goto again;
203 }
204
205 if (strcmp(str, "poweroff") == 0 ||
0e91398f
JF
206 strcmp(str, "halt") == 0) {
207 shutting_down = SHUTDOWN_POWEROFF;
3e2b8fbe 208 orderly_poweroff(false);
0e91398f
JF
209 } else if (strcmp(str, "reboot") == 0) {
210 shutting_down = SHUTDOWN_POWEROFF; /* ? */
3e2b8fbe 211 ctrl_alt_del();
0e91398f
JF
212#ifdef CONFIG_PM_SLEEP
213 } else if (strcmp(str, "suspend") == 0) {
214 do_suspend();
215#endif
216 } else {
3e2b8fbe
JF
217 printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
218 shutting_down = SHUTDOWN_INVALID;
219 }
220
221 kfree(str);
222}
223
f3bc3189 224#ifdef CONFIG_MAGIC_SYSRQ
3e2b8fbe
JF
225static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
226 unsigned int len)
227{
228 char sysrq_key = '\0';
229 struct xenbus_transaction xbt;
230 int err;
231
232 again:
233 err = xenbus_transaction_start(&xbt);
234 if (err)
235 return;
236 if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
237 printk(KERN_ERR "Unable to read sysrq code in "
238 "control/sysrq\n");
239 xenbus_transaction_end(xbt, 1);
240 return;
241 }
242
243 if (sysrq_key != '\0')
244 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
245
246 err = xenbus_transaction_end(xbt, 0);
247 if (err == -EAGAIN)
248 goto again;
249
250 if (sysrq_key != '\0')
f335397d 251 handle_sysrq(sysrq_key);
3e2b8fbe
JF
252}
253
3e2b8fbe
JF
254static struct xenbus_watch sysrq_watch = {
255 .node = "control/sysrq",
256 .callback = sysrq_handler
257};
f3bc3189
RD
258#endif
259
260static struct xenbus_watch shutdown_watch = {
261 .node = "control/shutdown",
262 .callback = shutdown_handler
263};
3e2b8fbe
JF
264
265static int setup_shutdown_watcher(void)
266{
267 int err;
268
269 err = register_xenbus_watch(&shutdown_watch);
270 if (err) {
271 printk(KERN_ERR "Failed to set shutdown watcher\n");
272 return err;
273 }
274
f3bc3189 275#ifdef CONFIG_MAGIC_SYSRQ
3e2b8fbe
JF
276 err = register_xenbus_watch(&sysrq_watch);
277 if (err) {
278 printk(KERN_ERR "Failed to set sysrq watcher\n");
279 return err;
280 }
f3bc3189 281#endif
3e2b8fbe
JF
282
283 return 0;
284}
285
286static int shutdown_event(struct notifier_block *notifier,
287 unsigned long event,
288 void *data)
289{
290 setup_shutdown_watcher();
291 return NOTIFY_DONE;
292}
293
016b6f5f 294int xen_setup_shutdown_event(void)
3e2b8fbe
JF
295{
296 static struct notifier_block xenstore_notifier = {
297 .notifier_call = shutdown_event
298 };
702d4eb9
SS
299
300 if (!xen_domain())
301 return -ENODEV;
3e2b8fbe
JF
302 register_xenstore_notifier(&xenstore_notifier);
303
304 return 0;
305}
183d03cc 306EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
3e2b8fbe 307
702d4eb9 308subsys_initcall(xen_setup_shutdown_event);
This page took 0.328025 seconds and 5 git commands to generate.