xref: /openbmc/linux/drivers/xen/manage.c (revision 67f43c9c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Handle extern requests for shutdown, reboot and sysrq
4  */
5 
6 #define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
7 
8 #include <linux/kernel.h>
9 #include <linux/err.h>
10 #include <linux/slab.h>
11 #include <linux/reboot.h>
12 #include <linux/sysrq.h>
13 #include <linux/stop_machine.h>
14 #include <linux/freezer.h>
15 #include <linux/syscore_ops.h>
16 #include <linux/export.h>
17 
18 #include <xen/xen.h>
19 #include <xen/xenbus.h>
20 #include <xen/grant_table.h>
21 #include <xen/events.h>
22 #include <xen/hvc-console.h>
23 #include <xen/page.h>
24 #include <xen/xen-ops.h>
25 
26 #include <asm/xen/hypercall.h>
27 #include <asm/xen/hypervisor.h>
28 
29 enum shutdown_state {
30 	SHUTDOWN_INVALID = -1,
31 	SHUTDOWN_POWEROFF = 0,
32 	SHUTDOWN_SUSPEND = 2,
33 	/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
34 	   report a crash, not be instructed to crash!
35 	   HALT is the same as POWEROFF, as far as we're concerned.  The tools use
36 	   the distinction when we return the reason code to them.  */
37 	 SHUTDOWN_HALT = 4,
38 };
39 
40 /* Ignore multiple shutdown requests. */
41 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
42 
43 struct suspend_info {
44 	int cancelled;
45 };
46 
47 static RAW_NOTIFIER_HEAD(xen_resume_notifier);
48 
xen_resume_notifier_register(struct notifier_block * nb)49 void xen_resume_notifier_register(struct notifier_block *nb)
50 {
51 	raw_notifier_chain_register(&xen_resume_notifier, nb);
52 }
53 EXPORT_SYMBOL_GPL(xen_resume_notifier_register);
54 
xen_resume_notifier_unregister(struct notifier_block * nb)55 void xen_resume_notifier_unregister(struct notifier_block *nb)
56 {
57 	raw_notifier_chain_unregister(&xen_resume_notifier, nb);
58 }
59 EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);
60 
61 #ifdef CONFIG_HIBERNATE_CALLBACKS
xen_suspend(void * data)62 static int xen_suspend(void *data)
63 {
64 	struct suspend_info *si = data;
65 	int err;
66 
67 	BUG_ON(!irqs_disabled());
68 
69 	err = syscore_suspend();
70 	if (err) {
71 		pr_err("%s: system core suspend failed: %d\n", __func__, err);
72 		return err;
73 	}
74 
75 	gnttab_suspend();
76 	xen_manage_runstate_time(-1);
77 	xen_arch_pre_suspend();
78 
79 	si->cancelled = HYPERVISOR_suspend(xen_pv_domain()
80                                            ? virt_to_gfn(xen_start_info)
81                                            : 0);
82 
83 	xen_arch_post_suspend(si->cancelled);
84 	xen_manage_runstate_time(si->cancelled ? 1 : 0);
85 	gnttab_resume();
86 
87 	if (!si->cancelled) {
88 		xen_irq_resume();
89 		xen_timer_resume();
90 	}
91 
92 	syscore_resume();
93 
94 	return 0;
95 }
96 
do_suspend(void)97 static void do_suspend(void)
98 {
99 	int err;
100 	struct suspend_info si;
101 
102 	shutting_down = SHUTDOWN_SUSPEND;
103 
104 	err = freeze_processes();
105 	if (err) {
106 		pr_err("%s: freeze processes failed %d\n", __func__, err);
107 		goto out;
108 	}
109 
110 	err = freeze_kernel_threads();
111 	if (err) {
112 		pr_err("%s: freeze kernel threads failed %d\n", __func__, err);
113 		goto out_thaw;
114 	}
115 
116 	err = dpm_suspend_start(PMSG_FREEZE);
117 	if (err) {
118 		pr_err("%s: dpm_suspend_start %d\n", __func__, err);
119 		goto out_thaw;
120 	}
121 
122 	printk(KERN_DEBUG "suspending xenstore...\n");
123 	xs_suspend();
124 
125 	err = dpm_suspend_end(PMSG_FREEZE);
126 	if (err) {
127 		pr_err("dpm_suspend_end failed: %d\n", err);
128 		si.cancelled = 0;
129 		goto out_resume;
130 	}
131 
132 	xen_arch_suspend();
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 	xen_arch_resume();
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 out_resume:
154 	if (!si.cancelled)
155 		xs_resume();
156 	else
157 		xs_suspend_cancel();
158 
159 	dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
160 
161 out_thaw:
162 	thaw_processes();
163 out:
164 	shutting_down = SHUTDOWN_INVALID;
165 }
166 #endif	/* CONFIG_HIBERNATE_CALLBACKS */
167 
168 struct shutdown_handler {
169 #define SHUTDOWN_CMD_SIZE 11
170 	const char command[SHUTDOWN_CMD_SIZE];
171 	bool flag;
172 	void (*cb)(void);
173 };
174 
poweroff_nb(struct notifier_block * cb,unsigned long code,void * unused)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 		break;
183 	default:
184 		break;
185 	}
186 	return NOTIFY_DONE;
187 }
do_poweroff(void)188 static void do_poweroff(void)
189 {
190 	switch (system_state) {
191 	case SYSTEM_BOOTING:
192 	case SYSTEM_SCHEDULING:
193 		orderly_poweroff(true);
194 		break;
195 	case SYSTEM_RUNNING:
196 		orderly_poweroff(false);
197 		break;
198 	default:
199 		/* Don't do it when we are halting/rebooting. */
200 		pr_info("Ignoring Xen toolstack shutdown.\n");
201 		break;
202 	}
203 }
204 
do_reboot(void)205 static void do_reboot(void)
206 {
207 	shutting_down = SHUTDOWN_POWEROFF; /* ? */
208 	orderly_reboot();
209 }
210 
211 static struct shutdown_handler shutdown_handlers[] = {
212 	{ "poweroff",	true,	do_poweroff },
213 	{ "halt",	false,	do_poweroff },
214 	{ "reboot",	true,	do_reboot   },
215 #ifdef CONFIG_HIBERNATE_CALLBACKS
216 	{ "suspend",	true,	do_suspend  },
217 #endif
218 };
219 
shutdown_handler(struct xenbus_watch * watch,const char * path,const char * token)220 static void shutdown_handler(struct xenbus_watch *watch,
221 			     const char *path, const char *token)
222 {
223 	char *str;
224 	struct xenbus_transaction xbt;
225 	int err;
226 	int idx;
227 
228 	if (shutting_down != SHUTDOWN_INVALID)
229 		return;
230 
231  again:
232 	err = xenbus_transaction_start(&xbt);
233 	if (err)
234 		return;
235 
236 	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
237 	/* Ignore read errors and empty reads. */
238 	if (XENBUS_IS_ERR_READ(str)) {
239 		xenbus_transaction_end(xbt, 1);
240 		return;
241 	}
242 
243 	for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) {
244 		if (strcmp(str, shutdown_handlers[idx].command) == 0)
245 			break;
246 	}
247 
248 	/* Only acknowledge commands which we are prepared to handle. */
249 	if (idx < ARRAY_SIZE(shutdown_handlers))
250 		xenbus_write(xbt, "control", "shutdown", "");
251 
252 	err = xenbus_transaction_end(xbt, 0);
253 	if (err == -EAGAIN) {
254 		kfree(str);
255 		goto again;
256 	}
257 
258 	if (idx < ARRAY_SIZE(shutdown_handlers)) {
259 		shutdown_handlers[idx].cb();
260 	} else {
261 		pr_info("Ignoring shutdown request: %s\n", str);
262 		shutting_down = SHUTDOWN_INVALID;
263 	}
264 
265 	kfree(str);
266 }
267 
268 #ifdef CONFIG_MAGIC_SYSRQ
sysrq_handler(struct xenbus_watch * watch,const char * path,const char * token)269 static void sysrq_handler(struct xenbus_watch *watch, const char *path,
270 			  const char *token)
271 {
272 	char sysrq_key = '\0';
273 	struct xenbus_transaction xbt;
274 	int err;
275 
276  again:
277 	err = xenbus_transaction_start(&xbt);
278 	if (err)
279 		return;
280 	err = xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key);
281 	if (err < 0) {
282 		/*
283 		 * The Xenstore watch fires directly after registering it and
284 		 * after a suspend/resume cycle. So ENOENT is no error but
285 		 * might happen in those cases. ERANGE is observed when we get
286 		 * an empty value (''), this happens when we acknowledge the
287 		 * request by writing '\0' below.
288 		 */
289 		if (err != -ENOENT && err != -ERANGE)
290 			pr_err("Error %d reading sysrq code in control/sysrq\n",
291 			       err);
292 		xenbus_transaction_end(xbt, 1);
293 		return;
294 	}
295 
296 	if (sysrq_key != '\0') {
297 		err = xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
298 		if (err) {
299 			pr_err("%s: Error %d writing sysrq in control/sysrq\n",
300 			       __func__, err);
301 			xenbus_transaction_end(xbt, 1);
302 			return;
303 		}
304 	}
305 
306 	err = xenbus_transaction_end(xbt, 0);
307 	if (err == -EAGAIN)
308 		goto again;
309 
310 	if (sysrq_key != '\0')
311 		handle_sysrq(sysrq_key);
312 }
313 
314 static struct xenbus_watch sysrq_watch = {
315 	.node = "control/sysrq",
316 	.callback = sysrq_handler
317 };
318 #endif
319 
320 static struct xenbus_watch shutdown_watch = {
321 	.node = "control/shutdown",
322 	.callback = shutdown_handler
323 };
324 
325 static struct notifier_block xen_reboot_nb = {
326 	.notifier_call = poweroff_nb,
327 };
328 
setup_shutdown_watcher(void)329 static int setup_shutdown_watcher(void)
330 {
331 	int err;
332 	int idx;
333 #define FEATURE_PATH_SIZE (SHUTDOWN_CMD_SIZE + sizeof("feature-"))
334 	char node[FEATURE_PATH_SIZE];
335 
336 	err = register_xenbus_watch(&shutdown_watch);
337 	if (err) {
338 		pr_err("Failed to set shutdown watcher\n");
339 		return err;
340 	}
341 
342 
343 #ifdef CONFIG_MAGIC_SYSRQ
344 	err = register_xenbus_watch(&sysrq_watch);
345 	if (err) {
346 		pr_err("Failed to set sysrq watcher\n");
347 		return err;
348 	}
349 #endif
350 
351 	for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) {
352 		if (!shutdown_handlers[idx].flag)
353 			continue;
354 		snprintf(node, FEATURE_PATH_SIZE, "feature-%s",
355 			 shutdown_handlers[idx].command);
356 		err = xenbus_printf(XBT_NIL, "control", node, "%u", 1);
357 		if (err) {
358 			pr_err("%s: Error %d writing %s\n", __func__,
359 				err, node);
360 			return err;
361 		}
362 	}
363 
364 	return 0;
365 }
366 
shutdown_event(struct notifier_block * notifier,unsigned long event,void * data)367 static int shutdown_event(struct notifier_block *notifier,
368 			  unsigned long event,
369 			  void *data)
370 {
371 	setup_shutdown_watcher();
372 	return NOTIFY_DONE;
373 }
374 
xen_setup_shutdown_event(void)375 int xen_setup_shutdown_event(void)
376 {
377 	static struct notifier_block xenstore_notifier = {
378 		.notifier_call = shutdown_event
379 	};
380 
381 	if (!xen_domain())
382 		return -ENODEV;
383 	register_xenstore_notifier(&xenstore_notifier);
384 	register_reboot_notifier(&xen_reboot_nb);
385 
386 	return 0;
387 }
388 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
389 
390 subsys_initcall(xen_setup_shutdown_event);
391