xref: /linux/drivers/xen/manage.c (revision 0d456bad36d42d16022be045c8a53ddbb59ee478)
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 #include <linux/syscore_ops.h>
12 #include <linux/export.h>
13 
14 #include <xen/xen.h>
15 #include <xen/xenbus.h>
16 #include <xen/grant_table.h>
17 #include <xen/events.h>
18 #include <xen/hvc-console.h>
19 #include <xen/xen-ops.h>
20 
21 #include <asm/xen/hypercall.h>
22 #include <asm/xen/page.h>
23 #include <asm/xen/hypervisor.h>
24 
25 enum 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 };
35 
36 /* Ignore multiple shutdown requests. */
37 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
38 
39 struct suspend_info {
40 	int cancelled;
41 	unsigned long arg; /* extra hypercall argument */
42 	void (*pre)(void);
43 	void (*post)(int cancelled);
44 };
45 
46 static void xen_hvm_post_suspend(int cancelled)
47 {
48 	xen_arch_hvm_post_suspend(cancelled);
49 	gnttab_resume();
50 }
51 
52 static void xen_pre_suspend(void)
53 {
54 	xen_mm_pin_all();
55 	gnttab_suspend();
56 	xen_arch_pre_suspend();
57 }
58 
59 static void xen_post_suspend(int cancelled)
60 {
61 	xen_arch_post_suspend(cancelled);
62 	gnttab_resume();
63 	xen_mm_unpin_all();
64 }
65 
66 #ifdef CONFIG_HIBERNATE_CALLBACKS
67 static int xen_suspend(void *data)
68 {
69 	struct suspend_info *si = data;
70 	int err;
71 
72 	BUG_ON(!irqs_disabled());
73 
74 	err = syscore_suspend();
75 	if (err) {
76 		printk(KERN_ERR "xen_suspend: system core suspend failed: %d\n",
77 			err);
78 		return err;
79 	}
80 
81 	if (si->pre)
82 		si->pre();
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 	 */
89 	si->cancelled = HYPERVISOR_suspend(si->arg);
90 
91 	if (si->post)
92 		si->post(si->cancelled);
93 
94 	if (!si->cancelled) {
95 		xen_irq_resume();
96 		xen_console_resume();
97 		xen_timer_resume();
98 	}
99 
100 	syscore_resume();
101 
102 	return 0;
103 }
104 
105 static void do_suspend(void)
106 {
107 	int err;
108 	struct suspend_info si;
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);
119 		goto out;
120 	}
121 #endif
122 
123 	err = dpm_suspend_start(PMSG_FREEZE);
124 	if (err) {
125 		printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
126 		goto out_thaw;
127 	}
128 
129 	printk(KERN_DEBUG "suspending xenstore...\n");
130 	xs_suspend();
131 
132 	err = dpm_suspend_end(PMSG_FREEZE);
133 	if (err) {
134 		printk(KERN_ERR "dpm_suspend_end failed: %d\n", err);
135 		si.cancelled = 0;
136 		goto out_resume;
137 	}
138 
139 	si.cancelled = 1;
140 
141 	if (xen_hvm_domain()) {
142 		si.arg = 0UL;
143 		si.pre = NULL;
144 		si.post = &xen_hvm_post_suspend;
145 	} else {
146 		si.arg = virt_to_mfn(xen_start_info);
147 		si.pre = &xen_pre_suspend;
148 		si.post = &xen_post_suspend;
149 	}
150 
151 	err = stop_machine(xen_suspend, &si, cpumask_of(0));
152 
153 	dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
154 
155 	if (err) {
156 		printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
157 		si.cancelled = 1;
158 	}
159 
160 out_resume:
161 	if (!si.cancelled) {
162 		xen_arch_resume();
163 		xs_resume();
164 	} else
165 		xs_suspend_cancel();
166 
167 	dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
168 
169 	/* Make sure timer events get retriggered on all CPUs */
170 	clock_was_set();
171 
172 out_thaw:
173 #ifdef CONFIG_PREEMPT
174 	thaw_processes();
175 out:
176 #endif
177 	shutting_down = SHUTDOWN_INVALID;
178 }
179 #endif	/* CONFIG_HIBERNATE_CALLBACKS */
180 
181 struct shutdown_handler {
182 	const char *command;
183 	void (*cb)(void);
184 };
185 
186 static void do_poweroff(void)
187 {
188 	shutting_down = SHUTDOWN_POWEROFF;
189 	orderly_poweroff(false);
190 }
191 
192 static void do_reboot(void)
193 {
194 	shutting_down = SHUTDOWN_POWEROFF; /* ? */
195 	ctrl_alt_del();
196 }
197 
198 static 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;
204 	static struct shutdown_handler handlers[] = {
205 		{ "poweroff",	do_poweroff },
206 		{ "halt",	do_poweroff },
207 		{ "reboot",	do_reboot   },
208 #ifdef CONFIG_HIBERNATE_CALLBACKS
209 		{ "suspend",	do_suspend  },
210 #endif
211 		{NULL, NULL},
212 	};
213 	static struct shutdown_handler *handler;
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 
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", "");
238 
239 	err = xenbus_transaction_end(xbt, 0);
240 	if (err == -EAGAIN) {
241 		kfree(str);
242 		goto again;
243 	}
244 
245 	if (handler->cb) {
246 		handler->cb();
247 	} else {
248 		printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
249 		shutting_down = SHUTDOWN_INVALID;
250 	}
251 
252 	kfree(str);
253 }
254 
255 #ifdef CONFIG_MAGIC_SYSRQ
256 static 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')
282 		handle_sysrq(sysrq_key);
283 }
284 
285 static struct xenbus_watch sysrq_watch = {
286 	.node = "control/sysrq",
287 	.callback = sysrq_handler
288 };
289 #endif
290 
291 static struct xenbus_watch shutdown_watch = {
292 	.node = "control/shutdown",
293 	.callback = shutdown_handler
294 };
295 
296 static 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 
306 #ifdef CONFIG_MAGIC_SYSRQ
307 	err = register_xenbus_watch(&sysrq_watch);
308 	if (err) {
309 		printk(KERN_ERR "Failed to set sysrq watcher\n");
310 		return err;
311 	}
312 #endif
313 
314 	return 0;
315 }
316 
317 static 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 
325 int xen_setup_shutdown_event(void)
326 {
327 	static struct notifier_block xenstore_notifier = {
328 		.notifier_call = shutdown_event
329 	};
330 
331 	if (!xen_domain())
332 		return -ENODEV;
333 	register_xenstore_notifier(&xenstore_notifier);
334 
335 	return 0;
336 }
337 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
338 
339 subsys_initcall(xen_setup_shutdown_event);
340