KVM: SVM: Add manipulation functions for exception intercepts
[linux/fpc-iii.git] / drivers / xen / manage.c
blobdb8c4c4ac88086bf7c2e9d1dfa946da399e91b27
1 /*
2 * Handle extern requests for shutdown, reboot and sysrq
3 */
4 #include <linux/kernel.h>
5 #include <linux/err.h>
6 #include <linux/slab.h>
7 #include <linux/reboot.h>
8 #include <linux/sysrq.h>
9 #include <linux/stop_machine.h>
10 #include <linux/freezer.h>
12 #include <xen/xen.h>
13 #include <xen/xenbus.h>
14 #include <xen/grant_table.h>
15 #include <xen/events.h>
16 #include <xen/hvc-console.h>
17 #include <xen/xen-ops.h>
19 #include <asm/xen/hypercall.h>
20 #include <asm/xen/page.h>
21 #include <asm/xen/hypervisor.h>
23 enum 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,
34 /* Ignore multiple shutdown requests. */
35 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
37 #ifdef CONFIG_PM_SLEEP
38 static int xen_hvm_suspend(void *data)
40 struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
41 int *cancelled = data;
43 BUG_ON(!irqs_disabled());
45 *cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
47 xen_hvm_post_suspend(*cancelled);
48 gnttab_resume();
50 if (!*cancelled) {
51 xen_irq_resume();
52 xen_console_resume();
53 xen_timer_resume();
56 return 0;
59 static int xen_suspend(void *data)
61 int err;
62 int *cancelled = data;
64 BUG_ON(!irqs_disabled());
66 err = sysdev_suspend(PMSG_SUSPEND);
67 if (err) {
68 printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
69 err);
70 return err;
73 xen_mm_pin_all();
74 gnttab_suspend();
75 xen_pre_suspend();
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.
82 *cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
84 xen_post_suspend(*cancelled);
85 gnttab_resume();
86 xen_mm_unpin_all();
88 if (!*cancelled) {
89 xen_irq_resume();
90 xen_console_resume();
91 xen_timer_resume();
94 sysdev_resume();
96 return 0;
99 static void do_suspend(void)
101 int err;
102 int cancelled = 1;
104 shutting_down = SHUTDOWN_SUSPEND;
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) {
112 printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
113 goto out;
115 #endif
117 err = dpm_suspend_start(PMSG_SUSPEND);
118 if (err) {
119 printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
120 goto out_thaw;
123 printk(KERN_DEBUG "suspending xenstore...\n");
124 xs_suspend();
126 err = dpm_suspend_noirq(PMSG_SUSPEND);
127 if (err) {
128 printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
129 goto out_resume;
132 if (xen_hvm_domain())
133 err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0));
134 else
135 err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
137 dpm_resume_noirq(PMSG_RESUME);
139 if (err) {
140 printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
141 cancelled = 1;
144 out_resume:
145 if (!cancelled) {
146 xen_arch_resume();
147 xs_resume();
148 } else
149 xs_suspend_cancel();
151 dpm_resume_end(PMSG_RESUME);
153 /* Make sure timer events get retriggered on all CPUs */
154 clock_was_set();
156 out_thaw:
157 #ifdef CONFIG_PREEMPT
158 thaw_processes();
159 out:
160 #endif
161 shutting_down = SHUTDOWN_INVALID;
163 #endif /* CONFIG_PM_SLEEP */
165 static void shutdown_handler(struct xenbus_watch *watch,
166 const char **vec, unsigned int len)
168 char *str;
169 struct xenbus_transaction xbt;
170 int err;
172 if (shutting_down != SHUTDOWN_INVALID)
173 return;
175 again:
176 err = xenbus_transaction_start(&xbt);
177 if (err)
178 return;
180 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
181 /* Ignore read errors and empty reads. */
182 if (XENBUS_IS_ERR_READ(str)) {
183 xenbus_transaction_end(xbt, 1);
184 return;
187 xenbus_write(xbt, "control", "shutdown", "");
189 err = xenbus_transaction_end(xbt, 0);
190 if (err == -EAGAIN) {
191 kfree(str);
192 goto again;
195 if (strcmp(str, "poweroff") == 0 ||
196 strcmp(str, "halt") == 0) {
197 shutting_down = SHUTDOWN_POWEROFF;
198 orderly_poweroff(false);
199 } else if (strcmp(str, "reboot") == 0) {
200 shutting_down = SHUTDOWN_POWEROFF; /* ? */
201 ctrl_alt_del();
202 #ifdef CONFIG_PM_SLEEP
203 } else if (strcmp(str, "suspend") == 0) {
204 do_suspend();
205 #endif
206 } else {
207 printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
208 shutting_down = SHUTDOWN_INVALID;
211 kfree(str);
214 #ifdef CONFIG_MAGIC_SYSRQ
215 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
216 unsigned int len)
218 char sysrq_key = '\0';
219 struct xenbus_transaction xbt;
220 int err;
222 again:
223 err = xenbus_transaction_start(&xbt);
224 if (err)
225 return;
226 if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
227 printk(KERN_ERR "Unable to read sysrq code in "
228 "control/sysrq\n");
229 xenbus_transaction_end(xbt, 1);
230 return;
233 if (sysrq_key != '\0')
234 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
236 err = xenbus_transaction_end(xbt, 0);
237 if (err == -EAGAIN)
238 goto again;
240 if (sysrq_key != '\0')
241 handle_sysrq(sysrq_key);
244 static struct xenbus_watch sysrq_watch = {
245 .node = "control/sysrq",
246 .callback = sysrq_handler
248 #endif
250 static struct xenbus_watch shutdown_watch = {
251 .node = "control/shutdown",
252 .callback = shutdown_handler
255 static int setup_shutdown_watcher(void)
257 int err;
259 err = register_xenbus_watch(&shutdown_watch);
260 if (err) {
261 printk(KERN_ERR "Failed to set shutdown watcher\n");
262 return err;
265 #ifdef CONFIG_MAGIC_SYSRQ
266 err = register_xenbus_watch(&sysrq_watch);
267 if (err) {
268 printk(KERN_ERR "Failed to set sysrq watcher\n");
269 return err;
271 #endif
273 return 0;
276 static int shutdown_event(struct notifier_block *notifier,
277 unsigned long event,
278 void *data)
280 setup_shutdown_watcher();
281 return NOTIFY_DONE;
284 static int __init __setup_shutdown_event(void)
286 /* Delay initialization in the PV on HVM case */
287 if (xen_hvm_domain())
288 return 0;
290 if (!xen_pv_domain())
291 return -ENODEV;
293 return xen_setup_shutdown_event();
296 int xen_setup_shutdown_event(void)
298 static struct notifier_block xenstore_notifier = {
299 .notifier_call = shutdown_event
301 register_xenstore_notifier(&xenstore_notifier);
303 return 0;
305 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
307 subsys_initcall(__setup_shutdown_event);