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