xref: /openbmc/linux/drivers/xen/manage.c (revision 94cdda6b)
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 	si.cancelled = 1;
135 
136 	err = stop_machine(xen_suspend, &si, cpumask_of(0));
137 
138 	/* Resume console as early as possible. */
139 	if (!si.cancelled)
140 		xen_console_resume();
141 
142 	raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
143 
144 	dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
145 
146 	if (err) {
147 		pr_err("failed to start xen_suspend: %d\n", err);
148 		si.cancelled = 1;
149 	}
150 
151 out_resume:
152 	if (!si.cancelled) {
153 		xen_arch_resume();
154 		xs_resume();
155 	} else
156 		xs_suspend_cancel();
157 
158 	dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
159 
160 out_thaw:
161 	thaw_processes();
162 out:
163 	shutting_down = SHUTDOWN_INVALID;
164 }
165 #endif	/* CONFIG_HIBERNATE_CALLBACKS */
166 
167 struct shutdown_handler {
168 	const char *command;
169 	void (*cb)(void);
170 };
171 
172 static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused)
173 {
174 	switch (code) {
175 	case SYS_DOWN:
176 	case SYS_HALT:
177 	case SYS_POWER_OFF:
178 		shutting_down = SHUTDOWN_POWEROFF;
179 	default:
180 		break;
181 	}
182 	return NOTIFY_DONE;
183 }
184 static void do_poweroff(void)
185 {
186 	switch (system_state) {
187 	case SYSTEM_BOOTING:
188 		orderly_poweroff(true);
189 		break;
190 	case SYSTEM_RUNNING:
191 		orderly_poweroff(false);
192 		break;
193 	default:
194 		/* Don't do it when we are halting/rebooting. */
195 		pr_info("Ignoring Xen toolstack shutdown.\n");
196 		break;
197 	}
198 }
199 
200 static void do_reboot(void)
201 {
202 	shutting_down = SHUTDOWN_POWEROFF; /* ? */
203 	ctrl_alt_del();
204 }
205 
206 static void shutdown_handler(struct xenbus_watch *watch,
207 			     const char **vec, unsigned int len)
208 {
209 	char *str;
210 	struct xenbus_transaction xbt;
211 	int err;
212 	static struct shutdown_handler handlers[] = {
213 		{ "poweroff",	do_poweroff },
214 		{ "halt",	do_poweroff },
215 		{ "reboot",	do_reboot   },
216 #ifdef CONFIG_HIBERNATE_CALLBACKS
217 		{ "suspend",	do_suspend  },
218 #endif
219 		{NULL, NULL},
220 	};
221 	static struct shutdown_handler *handler;
222 
223 	if (shutting_down != SHUTDOWN_INVALID)
224 		return;
225 
226  again:
227 	err = xenbus_transaction_start(&xbt);
228 	if (err)
229 		return;
230 
231 	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
232 	/* Ignore read errors and empty reads. */
233 	if (XENBUS_IS_ERR_READ(str)) {
234 		xenbus_transaction_end(xbt, 1);
235 		return;
236 	}
237 
238 	for (handler = &handlers[0]; handler->command; handler++) {
239 		if (strcmp(str, handler->command) == 0)
240 			break;
241 	}
242 
243 	/* Only acknowledge commands which we are prepared to handle. */
244 	if (handler->cb)
245 		xenbus_write(xbt, "control", "shutdown", "");
246 
247 	err = xenbus_transaction_end(xbt, 0);
248 	if (err == -EAGAIN) {
249 		kfree(str);
250 		goto again;
251 	}
252 
253 	if (handler->cb) {
254 		handler->cb();
255 	} else {
256 		pr_info("Ignoring shutdown request: %s\n", str);
257 		shutting_down = SHUTDOWN_INVALID;
258 	}
259 
260 	kfree(str);
261 }
262 
263 #ifdef CONFIG_MAGIC_SYSRQ
264 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
265 			  unsigned int len)
266 {
267 	char sysrq_key = '\0';
268 	struct xenbus_transaction xbt;
269 	int err;
270 
271  again:
272 	err = xenbus_transaction_start(&xbt);
273 	if (err)
274 		return;
275 	if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
276 		pr_err("Unable to read sysrq code in control/sysrq\n");
277 		xenbus_transaction_end(xbt, 1);
278 		return;
279 	}
280 
281 	if (sysrq_key != '\0')
282 		xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
283 
284 	err = xenbus_transaction_end(xbt, 0);
285 	if (err == -EAGAIN)
286 		goto again;
287 
288 	if (sysrq_key != '\0')
289 		handle_sysrq(sysrq_key);
290 }
291 
292 static struct xenbus_watch sysrq_watch = {
293 	.node = "control/sysrq",
294 	.callback = sysrq_handler
295 };
296 #endif
297 
298 static struct xenbus_watch shutdown_watch = {
299 	.node = "control/shutdown",
300 	.callback = shutdown_handler
301 };
302 
303 static struct notifier_block xen_reboot_nb = {
304 	.notifier_call = poweroff_nb,
305 };
306 
307 static int setup_shutdown_watcher(void)
308 {
309 	int err;
310 
311 	err = register_xenbus_watch(&shutdown_watch);
312 	if (err) {
313 		pr_err("Failed to set shutdown watcher\n");
314 		return err;
315 	}
316 
317 
318 #ifdef CONFIG_MAGIC_SYSRQ
319 	err = register_xenbus_watch(&sysrq_watch);
320 	if (err) {
321 		pr_err("Failed to set sysrq watcher\n");
322 		return err;
323 	}
324 #endif
325 
326 	return 0;
327 }
328 
329 static int shutdown_event(struct notifier_block *notifier,
330 			  unsigned long event,
331 			  void *data)
332 {
333 	setup_shutdown_watcher();
334 	return NOTIFY_DONE;
335 }
336 
337 int xen_setup_shutdown_event(void)
338 {
339 	static struct notifier_block xenstore_notifier = {
340 		.notifier_call = shutdown_event
341 	};
342 
343 	if (!xen_domain())
344 		return -ENODEV;
345 	register_xenstore_notifier(&xenstore_notifier);
346 	register_reboot_notifier(&xen_reboot_nb);
347 
348 	return 0;
349 }
350 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
351 
352 subsys_initcall(xen_setup_shutdown_event);
353