xen/acpi-processor: fix enabling interrupts on syscore_resume
[linux-2.6/btrfs-unstable.git] / drivers / xen / manage.c
blobfc6c94c0b436f53c8d49b1849096d2f7ad441fbe
1 /*
2 * Handle extern requests for shutdown, reboot and sysrq
3 */
5 #define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
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>
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>
24 #include <asm/xen/hypercall.h>
25 #include <asm/xen/page.h>
26 #include <asm/xen/hypervisor.h>
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,
39 /* Ignore multiple shutdown requests. */
40 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
42 struct suspend_info {
43 int cancelled;
44 unsigned long arg; /* extra hypercall argument */
45 void (*pre)(void);
46 void (*post)(int cancelled);
49 static RAW_NOTIFIER_HEAD(xen_resume_notifier);
51 void xen_resume_notifier_register(struct notifier_block *nb)
53 raw_notifier_chain_register(&xen_resume_notifier, nb);
55 EXPORT_SYMBOL_GPL(xen_resume_notifier_register);
57 void xen_resume_notifier_unregister(struct notifier_block *nb)
59 raw_notifier_chain_unregister(&xen_resume_notifier, nb);
61 EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);
63 #ifdef CONFIG_HIBERNATE_CALLBACKS
64 static void xen_hvm_post_suspend(int cancelled)
66 xen_arch_hvm_post_suspend(cancelled);
67 gnttab_resume();
70 static void xen_pre_suspend(void)
72 xen_mm_pin_all();
73 gnttab_suspend();
74 xen_arch_pre_suspend();
77 static void xen_post_suspend(int cancelled)
79 xen_arch_post_suspend(cancelled);
80 gnttab_resume();
81 xen_mm_unpin_all();
84 static int xen_suspend(void *data)
86 struct suspend_info *si = data;
87 int err;
89 BUG_ON(!irqs_disabled());
91 err = syscore_suspend();
92 if (err) {
93 pr_err("%s: system core suspend failed: %d\n", __func__, err);
94 return err;
97 if (si->pre)
98 si->pre();
101 * This hypercall returns 1 if suspend was cancelled
102 * or the domain was merely checkpointed, and 0 if it
103 * is resuming in a new domain.
105 si->cancelled = HYPERVISOR_suspend(si->arg);
107 if (si->post)
108 si->post(si->cancelled);
110 if (!si->cancelled) {
111 xen_irq_resume();
112 xen_console_resume();
113 xen_timer_resume();
116 syscore_resume();
118 return 0;
121 static void do_suspend(void)
123 int err;
124 struct suspend_info si;
126 shutting_down = SHUTDOWN_SUSPEND;
128 #ifdef CONFIG_PREEMPT
129 /* If the kernel is preemptible, we need to freeze all the processes
130 to prevent them from being in the middle of a pagetable update
131 during suspend. */
132 err = freeze_processes();
133 if (err) {
134 pr_err("%s: freeze failed %d\n", __func__, err);
135 goto out;
137 #endif
139 err = dpm_suspend_start(PMSG_FREEZE);
140 if (err) {
141 pr_err("%s: dpm_suspend_start %d\n", __func__, err);
142 goto out_thaw;
145 printk(KERN_DEBUG "suspending xenstore...\n");
146 xs_suspend();
148 err = dpm_suspend_end(PMSG_FREEZE);
149 if (err) {
150 pr_err("dpm_suspend_end failed: %d\n", err);
151 si.cancelled = 0;
152 goto out_resume;
155 si.cancelled = 1;
157 if (xen_hvm_domain()) {
158 si.arg = 0UL;
159 si.pre = NULL;
160 si.post = &xen_hvm_post_suspend;
161 } else {
162 si.arg = virt_to_mfn(xen_start_info);
163 si.pre = &xen_pre_suspend;
164 si.post = &xen_post_suspend;
167 err = stop_machine(xen_suspend, &si, cpumask_of(0));
169 raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
171 dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
173 if (err) {
174 pr_err("failed to start xen_suspend: %d\n", err);
175 si.cancelled = 1;
178 out_resume:
179 if (!si.cancelled) {
180 xen_arch_resume();
181 xs_resume();
182 } else
183 xs_suspend_cancel();
185 dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
187 out_thaw:
188 #ifdef CONFIG_PREEMPT
189 thaw_processes();
190 out:
191 #endif
192 shutting_down = SHUTDOWN_INVALID;
194 #endif /* CONFIG_HIBERNATE_CALLBACKS */
196 struct shutdown_handler {
197 const char *command;
198 void (*cb)(void);
201 static void do_poweroff(void)
203 shutting_down = SHUTDOWN_POWEROFF;
204 orderly_poweroff(false);
207 static void do_reboot(void)
209 shutting_down = SHUTDOWN_POWEROFF; /* ? */
210 ctrl_alt_del();
213 static void shutdown_handler(struct xenbus_watch *watch,
214 const char **vec, unsigned int len)
216 char *str;
217 struct xenbus_transaction xbt;
218 int err;
219 static struct shutdown_handler handlers[] = {
220 { "poweroff", do_poweroff },
221 { "halt", do_poweroff },
222 { "reboot", do_reboot },
223 #ifdef CONFIG_HIBERNATE_CALLBACKS
224 { "suspend", do_suspend },
225 #endif
226 {NULL, NULL},
228 static struct shutdown_handler *handler;
230 if (shutting_down != SHUTDOWN_INVALID)
231 return;
233 again:
234 err = xenbus_transaction_start(&xbt);
235 if (err)
236 return;
238 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
239 /* Ignore read errors and empty reads. */
240 if (XENBUS_IS_ERR_READ(str)) {
241 xenbus_transaction_end(xbt, 1);
242 return;
245 for (handler = &handlers[0]; handler->command; handler++) {
246 if (strcmp(str, handler->command) == 0)
247 break;
250 /* Only acknowledge commands which we are prepared to handle. */
251 if (handler->cb)
252 xenbus_write(xbt, "control", "shutdown", "");
254 err = xenbus_transaction_end(xbt, 0);
255 if (err == -EAGAIN) {
256 kfree(str);
257 goto again;
260 if (handler->cb) {
261 handler->cb();
262 } else {
263 pr_info("Ignoring shutdown request: %s\n", str);
264 shutting_down = SHUTDOWN_INVALID;
267 kfree(str);
270 #ifdef CONFIG_MAGIC_SYSRQ
271 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
272 unsigned int len)
274 char sysrq_key = '\0';
275 struct xenbus_transaction xbt;
276 int err;
278 again:
279 err = xenbus_transaction_start(&xbt);
280 if (err)
281 return;
282 if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
283 pr_err("Unable to read sysrq code in control/sysrq\n");
284 xenbus_transaction_end(xbt, 1);
285 return;
288 if (sysrq_key != '\0')
289 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
291 err = xenbus_transaction_end(xbt, 0);
292 if (err == -EAGAIN)
293 goto again;
295 if (sysrq_key != '\0')
296 handle_sysrq(sysrq_key);
299 static struct xenbus_watch sysrq_watch = {
300 .node = "control/sysrq",
301 .callback = sysrq_handler
303 #endif
305 static struct xenbus_watch shutdown_watch = {
306 .node = "control/shutdown",
307 .callback = shutdown_handler
310 static int setup_shutdown_watcher(void)
312 int err;
314 err = register_xenbus_watch(&shutdown_watch);
315 if (err) {
316 pr_err("Failed to set shutdown watcher\n");
317 return err;
320 #ifdef CONFIG_MAGIC_SYSRQ
321 err = register_xenbus_watch(&sysrq_watch);
322 if (err) {
323 pr_err("Failed to set sysrq watcher\n");
324 return err;
326 #endif
328 return 0;
331 static int shutdown_event(struct notifier_block *notifier,
332 unsigned long event,
333 void *data)
335 setup_shutdown_watcher();
336 return NOTIFY_DONE;
339 int xen_setup_shutdown_event(void)
341 static struct notifier_block xenstore_notifier = {
342 .notifier_call = shutdown_event
345 if (!xen_domain())
346 return -ENODEV;
347 register_xenstore_notifier(&xenstore_notifier);
349 return 0;
351 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
353 subsys_initcall(xen_setup_shutdown_event);