• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
xen_resume_notifier_register(struct notifier_block * nb)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 
xen_resume_notifier_unregister(struct notifier_block * nb)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
xen_suspend(void * data)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 
do_suspend(void)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 
poweroff_nb(struct notifier_block * cb,unsigned long code,void * unused)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 }
do_poweroff(void)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 
do_reboot(void)200 static void do_reboot(void)
201 {
202 	shutting_down = SHUTDOWN_POWEROFF; /* ? */
203 	ctrl_alt_del();
204 }
205 
shutdown_handler(struct xenbus_watch * watch,const char ** vec,unsigned int len)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
sysrq_handler(struct xenbus_watch * watch,const char ** vec,unsigned int len)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 	err = xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key);
276 	if (err < 0) {
277 		/*
278 		 * The Xenstore watch fires directly after registering it and
279 		 * after a suspend/resume cycle. So ENOENT is no error but
280 		 * might happen in those cases.
281 		 */
282 		if (err != -ENOENT)
283 			pr_err("Error %d reading sysrq code in control/sysrq\n",
284 			       err);
285 		xenbus_transaction_end(xbt, 1);
286 		return;
287 	}
288 
289 	if (sysrq_key != '\0')
290 		xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
291 
292 	err = xenbus_transaction_end(xbt, 0);
293 	if (err == -EAGAIN)
294 		goto again;
295 
296 	if (sysrq_key != '\0')
297 		handle_sysrq(sysrq_key);
298 }
299 
300 static struct xenbus_watch sysrq_watch = {
301 	.node = "control/sysrq",
302 	.callback = sysrq_handler
303 };
304 #endif
305 
306 static struct xenbus_watch shutdown_watch = {
307 	.node = "control/shutdown",
308 	.callback = shutdown_handler
309 };
310 
311 static struct notifier_block xen_reboot_nb = {
312 	.notifier_call = poweroff_nb,
313 };
314 
setup_shutdown_watcher(void)315 static int setup_shutdown_watcher(void)
316 {
317 	int err;
318 
319 	err = register_xenbus_watch(&shutdown_watch);
320 	if (err) {
321 		pr_err("Failed to set shutdown watcher\n");
322 		return err;
323 	}
324 
325 
326 #ifdef CONFIG_MAGIC_SYSRQ
327 	err = register_xenbus_watch(&sysrq_watch);
328 	if (err) {
329 		pr_err("Failed to set sysrq watcher\n");
330 		return err;
331 	}
332 #endif
333 
334 	return 0;
335 }
336 
shutdown_event(struct notifier_block * notifier,unsigned long event,void * data)337 static int shutdown_event(struct notifier_block *notifier,
338 			  unsigned long event,
339 			  void *data)
340 {
341 	setup_shutdown_watcher();
342 	return NOTIFY_DONE;
343 }
344 
xen_setup_shutdown_event(void)345 int xen_setup_shutdown_event(void)
346 {
347 	static struct notifier_block xenstore_notifier = {
348 		.notifier_call = shutdown_event
349 	};
350 
351 	if (!xen_domain())
352 		return -ENODEV;
353 	register_xenstore_notifier(&xenstore_notifier);
354 	register_reboot_notifier(&xen_reboot_nb);
355 
356 	return 0;
357 }
358 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
359 
360 subsys_initcall(xen_setup_shutdown_event);
361