xref: /openbmc/linux/drivers/xen/manage.c (revision 52fb57e7)
1 /*
2  * Handle extern requests for shutdown, reboot and sysrq
3  */
4 
5 #define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
6 
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>
16 
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>
23 
24 #include <asm/xen/hypercall.h>
25 #include <asm/xen/page.h>
26 #include <asm/xen/hypervisor.h>
27 
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,
37 };
38 
39 /* Ignore multiple shutdown requests. */
40 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
41 
42 struct suspend_info {
43 	int cancelled;
44 };
45 
46 static RAW_NOTIFIER_HEAD(xen_resume_notifier);
47 
48 void xen_resume_notifier_register(struct notifier_block *nb)
49 {
50 	raw_notifier_chain_register(&xen_resume_notifier, nb);
51 }
52 EXPORT_SYMBOL_GPL(xen_resume_notifier_register);
53 
54 void xen_resume_notifier_unregister(struct notifier_block *nb)
55 {
56 	raw_notifier_chain_unregister(&xen_resume_notifier, nb);
57 }
58 EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);
59 
60 #ifdef CONFIG_HIBERNATE_CALLBACKS
61 static int xen_suspend(void *data)
62 {
63 	struct suspend_info *si = data;
64 	int err;
65 
66 	BUG_ON(!irqs_disabled());
67 
68 	err = syscore_suspend();
69 	if (err) {
70 		pr_err("%s: system core suspend failed: %d\n", __func__, err);
71 		return err;
72 	}
73 
74 	gnttab_suspend();
75 	xen_arch_pre_suspend();
76 
77 	/*
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.
81 	 */
82 	si->cancelled = HYPERVISOR_suspend(xen_pv_domain()
83                                            ? virt_to_mfn(xen_start_info)
84                                            : 0);
85 
86 	xen_arch_post_suspend(si->cancelled);
87 	gnttab_resume();
88 
89 	if (!si->cancelled) {
90 		xen_irq_resume();
91 		xen_timer_resume();
92 	}
93 
94 	syscore_resume();
95 
96 	return 0;
97 }
98 
99 static void do_suspend(void)
100 {
101 	int err;
102 	struct suspend_info si;
103 
104 	shutting_down = SHUTDOWN_SUSPEND;
105 
106 	err = freeze_processes();
107 	if (err) {
108 		pr_err("%s: freeze processes failed %d\n", __func__, err);
109 		goto out;
110 	}
111 
112 	err = freeze_kernel_threads();
113 	if (err) {
114 		pr_err("%s: freeze kernel threads failed %d\n", __func__, err);
115 		goto out_thaw;
116 	}
117 
118 	err = dpm_suspend_start(PMSG_FREEZE);
119 	if (err) {
120 		pr_err("%s: dpm_suspend_start %d\n", __func__, err);
121 		goto out_thaw;
122 	}
123 
124 	printk(KERN_DEBUG "suspending xenstore...\n");
125 	xs_suspend();
126 
127 	err = dpm_suspend_end(PMSG_FREEZE);
128 	if (err) {
129 		pr_err("dpm_suspend_end failed: %d\n", err);
130 		si.cancelled = 0;
131 		goto out_resume;
132 	}
133 
134 	xen_arch_suspend();
135 
136 	si.cancelled = 1;
137 
138 	err = stop_machine(xen_suspend, &si, cpumask_of(0));
139 
140 	/* Resume console as early as possible. */
141 	if (!si.cancelled)
142 		xen_console_resume();
143 
144 	raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
145 
146 	dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
147 
148 	if (err) {
149 		pr_err("failed to start xen_suspend: %d\n", err);
150 		si.cancelled = 1;
151 	}
152 
153 	xen_arch_resume();
154 
155 out_resume:
156 	if (!si.cancelled)
157 		xs_resume();
158 	else
159 		xs_suspend_cancel();
160 
161 	dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
162 
163 out_thaw:
164 	thaw_processes();
165 out:
166 	shutting_down = SHUTDOWN_INVALID;
167 }
168 #endif	/* CONFIG_HIBERNATE_CALLBACKS */
169 
170 struct shutdown_handler {
171 	const char *command;
172 	void (*cb)(void);
173 };
174 
175 static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused)
176 {
177 	switch (code) {
178 	case SYS_DOWN:
179 	case SYS_HALT:
180 	case SYS_POWER_OFF:
181 		shutting_down = SHUTDOWN_POWEROFF;
182 	default:
183 		break;
184 	}
185 	return NOTIFY_DONE;
186 }
187 static void do_poweroff(void)
188 {
189 	switch (system_state) {
190 	case SYSTEM_BOOTING:
191 		orderly_poweroff(true);
192 		break;
193 	case SYSTEM_RUNNING:
194 		orderly_poweroff(false);
195 		break;
196 	default:
197 		/* Don't do it when we are halting/rebooting. */
198 		pr_info("Ignoring Xen toolstack shutdown.\n");
199 		break;
200 	}
201 }
202 
203 static void do_reboot(void)
204 {
205 	shutting_down = SHUTDOWN_POWEROFF; /* ? */
206 	ctrl_alt_del();
207 }
208 
209 static void shutdown_handler(struct xenbus_watch *watch,
210 			     const char **vec, unsigned int len)
211 {
212 	char *str;
213 	struct xenbus_transaction xbt;
214 	int err;
215 	static struct shutdown_handler handlers[] = {
216 		{ "poweroff",	do_poweroff },
217 		{ "halt",	do_poweroff },
218 		{ "reboot",	do_reboot   },
219 #ifdef CONFIG_HIBERNATE_CALLBACKS
220 		{ "suspend",	do_suspend  },
221 #endif
222 		{NULL, NULL},
223 	};
224 	static struct shutdown_handler *handler;
225 
226 	if (shutting_down != SHUTDOWN_INVALID)
227 		return;
228 
229  again:
230 	err = xenbus_transaction_start(&xbt);
231 	if (err)
232 		return;
233 
234 	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
235 	/* Ignore read errors and empty reads. */
236 	if (XENBUS_IS_ERR_READ(str)) {
237 		xenbus_transaction_end(xbt, 1);
238 		return;
239 	}
240 
241 	for (handler = &handlers[0]; handler->command; handler++) {
242 		if (strcmp(str, handler->command) == 0)
243 			break;
244 	}
245 
246 	/* Only acknowledge commands which we are prepared to handle. */
247 	if (handler->cb)
248 		xenbus_write(xbt, "control", "shutdown", "");
249 
250 	err = xenbus_transaction_end(xbt, 0);
251 	if (err == -EAGAIN) {
252 		kfree(str);
253 		goto again;
254 	}
255 
256 	if (handler->cb) {
257 		handler->cb();
258 	} else {
259 		pr_info("Ignoring shutdown request: %s\n", str);
260 		shutting_down = SHUTDOWN_INVALID;
261 	}
262 
263 	kfree(str);
264 }
265 
266 #ifdef CONFIG_MAGIC_SYSRQ
267 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
268 			  unsigned int len)
269 {
270 	char sysrq_key = '\0';
271 	struct xenbus_transaction xbt;
272 	int err;
273 
274  again:
275 	err = xenbus_transaction_start(&xbt);
276 	if (err)
277 		return;
278 	if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
279 		pr_err("Unable to read sysrq code in control/sysrq\n");
280 		xenbus_transaction_end(xbt, 1);
281 		return;
282 	}
283 
284 	if (sysrq_key != '\0')
285 		xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
286 
287 	err = xenbus_transaction_end(xbt, 0);
288 	if (err == -EAGAIN)
289 		goto again;
290 
291 	if (sysrq_key != '\0')
292 		handle_sysrq(sysrq_key);
293 }
294 
295 static struct xenbus_watch sysrq_watch = {
296 	.node = "control/sysrq",
297 	.callback = sysrq_handler
298 };
299 #endif
300 
301 static struct xenbus_watch shutdown_watch = {
302 	.node = "control/shutdown",
303 	.callback = shutdown_handler
304 };
305 
306 static struct notifier_block xen_reboot_nb = {
307 	.notifier_call = poweroff_nb,
308 };
309 
310 static int setup_shutdown_watcher(void)
311 {
312 	int err;
313 
314 	err = register_xenbus_watch(&shutdown_watch);
315 	if (err) {
316 		pr_err("Failed to set shutdown watcher\n");
317 		return err;
318 	}
319 
320 
321 #ifdef CONFIG_MAGIC_SYSRQ
322 	err = register_xenbus_watch(&sysrq_watch);
323 	if (err) {
324 		pr_err("Failed to set sysrq watcher\n");
325 		return err;
326 	}
327 #endif
328 
329 	return 0;
330 }
331 
332 static int shutdown_event(struct notifier_block *notifier,
333 			  unsigned long event,
334 			  void *data)
335 {
336 	setup_shutdown_watcher();
337 	return NOTIFY_DONE;
338 }
339 
340 int xen_setup_shutdown_event(void)
341 {
342 	static struct notifier_block xenstore_notifier = {
343 		.notifier_call = shutdown_event
344 	};
345 
346 	if (!xen_domain())
347 		return -ENODEV;
348 	register_xenstore_notifier(&xenstore_notifier);
349 	register_reboot_notifier(&xen_reboot_nb);
350 
351 	return 0;
352 }
353 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
354 
355 subsys_initcall(xen_setup_shutdown_event);
356