• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	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 	xen_arch_resume();
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 	default:
183 		break;
184 	}
185 	return NOTIFY_DONE;
186 }
do_poweroff(void)187 static void do_poweroff(void)
188 {
189 	switch (system_state) {
190 	case SYSTEM_BOOTING:
191 	case SYSTEM_SCHEDULING:
192 		orderly_poweroff(true);
193 		break;
194 	case SYSTEM_RUNNING:
195 		orderly_poweroff(false);
196 		break;
197 	default:
198 		/* Don't do it when we are halting/rebooting. */
199 		pr_info("Ignoring Xen toolstack shutdown.\n");
200 		break;
201 	}
202 }
203 
do_reboot(void)204 static void do_reboot(void)
205 {
206 	shutting_down = SHUTDOWN_POWEROFF; /* ? */
207 	ctrl_alt_del();
208 }
209 
210 static struct shutdown_handler shutdown_handlers[] = {
211 	{ "poweroff",	true,	do_poweroff },
212 	{ "halt",	false,	do_poweroff },
213 	{ "reboot",	true,	do_reboot   },
214 #ifdef CONFIG_HIBERNATE_CALLBACKS
215 	{ "suspend",	true,	do_suspend  },
216 #endif
217 };
218 
shutdown_handler(struct xenbus_watch * watch,const char * path,const char * token)219 static void shutdown_handler(struct xenbus_watch *watch,
220 			     const char *path, const char *token)
221 {
222 	char *str;
223 	struct xenbus_transaction xbt;
224 	int err;
225 	int idx;
226 
227 	if (shutting_down != SHUTDOWN_INVALID)
228 		return;
229 
230  again:
231 	err = xenbus_transaction_start(&xbt);
232 	if (err)
233 		return;
234 
235 	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
236 	/* Ignore read errors and empty reads. */
237 	if (XENBUS_IS_ERR_READ(str)) {
238 		xenbus_transaction_end(xbt, 1);
239 		return;
240 	}
241 
242 	for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) {
243 		if (strcmp(str, shutdown_handlers[idx].command) == 0)
244 			break;
245 	}
246 
247 	/* Only acknowledge commands which we are prepared to handle. */
248 	if (idx < ARRAY_SIZE(shutdown_handlers))
249 		xenbus_write(xbt, "control", "shutdown", "");
250 
251 	err = xenbus_transaction_end(xbt, 0);
252 	if (err == -EAGAIN) {
253 		kfree(str);
254 		goto again;
255 	}
256 
257 	if (idx < ARRAY_SIZE(shutdown_handlers)) {
258 		shutdown_handlers[idx].cb();
259 	} else {
260 		pr_info("Ignoring shutdown request: %s\n", str);
261 		shutting_down = SHUTDOWN_INVALID;
262 	}
263 
264 	kfree(str);
265 }
266 
267 #ifdef CONFIG_MAGIC_SYSRQ
sysrq_handler(struct xenbus_watch * watch,const char * path,const char * token)268 static void sysrq_handler(struct xenbus_watch *watch, const char *path,
269 			  const char *token)
270 {
271 	char sysrq_key = '\0';
272 	struct xenbus_transaction xbt;
273 	int err;
274 
275  again:
276 	err = xenbus_transaction_start(&xbt);
277 	if (err)
278 		return;
279 	err = xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key);
280 	if (err < 0) {
281 		/*
282 		 * The Xenstore watch fires directly after registering it and
283 		 * after a suspend/resume cycle. So ENOENT is no error but
284 		 * might happen in those cases. ERANGE is observed when we get
285 		 * an empty value (''), this happens when we acknowledge the
286 		 * request by writing '\0' below.
287 		 */
288 		if (err != -ENOENT && err != -ERANGE)
289 			pr_err("Error %d reading sysrq code in control/sysrq\n",
290 			       err);
291 		xenbus_transaction_end(xbt, 1);
292 		return;
293 	}
294 
295 	if (sysrq_key != '\0') {
296 		err = xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
297 		if (err) {
298 			pr_err("%s: Error %d writing sysrq in control/sysrq\n",
299 			       __func__, err);
300 			xenbus_transaction_end(xbt, 1);
301 			return;
302 		}
303 	}
304 
305 	err = xenbus_transaction_end(xbt, 0);
306 	if (err == -EAGAIN)
307 		goto again;
308 
309 	if (sysrq_key != '\0')
310 		handle_sysrq(sysrq_key);
311 }
312 
313 static struct xenbus_watch sysrq_watch = {
314 	.node = "control/sysrq",
315 	.callback = sysrq_handler
316 };
317 #endif
318 
319 static struct xenbus_watch shutdown_watch = {
320 	.node = "control/shutdown",
321 	.callback = shutdown_handler
322 };
323 
324 static struct notifier_block xen_reboot_nb = {
325 	.notifier_call = poweroff_nb,
326 };
327 
setup_shutdown_watcher(void)328 static int setup_shutdown_watcher(void)
329 {
330 	int err;
331 	int idx;
332 #define FEATURE_PATH_SIZE (SHUTDOWN_CMD_SIZE + sizeof("feature-"))
333 	char node[FEATURE_PATH_SIZE];
334 
335 	err = register_xenbus_watch(&shutdown_watch);
336 	if (err) {
337 		pr_err("Failed to set shutdown watcher\n");
338 		return err;
339 	}
340 
341 
342 #ifdef CONFIG_MAGIC_SYSRQ
343 	err = register_xenbus_watch(&sysrq_watch);
344 	if (err) {
345 		pr_err("Failed to set sysrq watcher\n");
346 		return err;
347 	}
348 #endif
349 
350 	for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) {
351 		if (!shutdown_handlers[idx].flag)
352 			continue;
353 		snprintf(node, FEATURE_PATH_SIZE, "feature-%s",
354 			 shutdown_handlers[idx].command);
355 		err = xenbus_printf(XBT_NIL, "control", node, "%u", 1);
356 		if (err) {
357 			pr_err("%s: Error %d writing %s\n", __func__,
358 				err, node);
359 			return err;
360 		}
361 	}
362 
363 	return 0;
364 }
365 
shutdown_event(struct notifier_block * notifier,unsigned long event,void * data)366 static int shutdown_event(struct notifier_block *notifier,
367 			  unsigned long event,
368 			  void *data)
369 {
370 	setup_shutdown_watcher();
371 	return NOTIFY_DONE;
372 }
373 
xen_setup_shutdown_event(void)374 int xen_setup_shutdown_event(void)
375 {
376 	static struct notifier_block xenstore_notifier = {
377 		.notifier_call = shutdown_event
378 	};
379 
380 	if (!xen_domain())
381 		return -ENODEV;
382 	register_xenstore_notifier(&xenstore_notifier);
383 	register_reboot_notifier(&xen_reboot_nb);
384 
385 	return 0;
386 }
387 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
388 
389 subsys_initcall(xen_setup_shutdown_event);
390