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