xref: /openbmc/linux/drivers/xen/manage.c (revision 7caf62de)
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 	unsigned long arg; /* extra hypercall argument */
45 	void (*pre)(void);
46 	void (*post)(int cancelled);
47 };
48 
49 #ifdef CONFIG_HIBERNATE_CALLBACKS
50 static void xen_hvm_post_suspend(int cancelled)
51 {
52 	xen_arch_hvm_post_suspend(cancelled);
53 	gnttab_resume();
54 }
55 
56 static void xen_pre_suspend(void)
57 {
58 	xen_mm_pin_all();
59 	gnttab_suspend();
60 	xen_arch_pre_suspend();
61 }
62 
63 static void xen_post_suspend(int cancelled)
64 {
65 	xen_arch_post_suspend(cancelled);
66 	gnttab_resume();
67 	xen_mm_unpin_all();
68 }
69 
70 static int xen_suspend(void *data)
71 {
72 	struct suspend_info *si = data;
73 	int err;
74 
75 	BUG_ON(!irqs_disabled());
76 
77 	err = syscore_suspend();
78 	if (err) {
79 		pr_err("%s: system core suspend failed: %d\n", __func__, err);
80 		return err;
81 	}
82 
83 	if (si->pre)
84 		si->pre();
85 
86 	/*
87 	 * This hypercall returns 1 if suspend was cancelled
88 	 * or the domain was merely checkpointed, and 0 if it
89 	 * is resuming in a new domain.
90 	 */
91 	si->cancelled = HYPERVISOR_suspend(si->arg);
92 
93 	if (si->post)
94 		si->post(si->cancelled);
95 
96 	if (!si->cancelled) {
97 		xen_irq_resume();
98 		xen_console_resume();
99 		xen_timer_resume();
100 	}
101 
102 	syscore_resume();
103 
104 	return 0;
105 }
106 
107 static void do_suspend(void)
108 {
109 	int err;
110 	struct suspend_info si;
111 
112 	shutting_down = SHUTDOWN_SUSPEND;
113 
114 #ifdef CONFIG_PREEMPT
115 	/* If the kernel is preemptible, we need to freeze all the processes
116 	   to prevent them from being in the middle of a pagetable update
117 	   during suspend. */
118 	err = freeze_processes();
119 	if (err) {
120 		pr_err("%s: freeze failed %d\n", __func__, err);
121 		goto out;
122 	}
123 #endif
124 
125 	err = dpm_suspend_start(PMSG_FREEZE);
126 	if (err) {
127 		pr_err("%s: dpm_suspend_start %d\n", __func__, err);
128 		goto out_thaw;
129 	}
130 
131 	printk(KERN_DEBUG "suspending xenstore...\n");
132 	xs_suspend();
133 
134 	err = dpm_suspend_end(PMSG_FREEZE);
135 	if (err) {
136 		pr_err("dpm_suspend_end failed: %d\n", err);
137 		si.cancelled = 0;
138 		goto out_resume;
139 	}
140 
141 	si.cancelled = 1;
142 
143 	if (xen_hvm_domain()) {
144 		si.arg = 0UL;
145 		si.pre = NULL;
146 		si.post = &xen_hvm_post_suspend;
147 	} else {
148 		si.arg = virt_to_mfn(xen_start_info);
149 		si.pre = &xen_pre_suspend;
150 		si.post = &xen_post_suspend;
151 	}
152 
153 	err = stop_machine(xen_suspend, &si, cpumask_of(0));
154 
155 	dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
156 
157 	if (err) {
158 		pr_err("failed to start xen_suspend: %d\n", err);
159 		si.cancelled = 1;
160 	}
161 
162 out_resume:
163 	if (!si.cancelled) {
164 		xen_arch_resume();
165 		xs_resume();
166 	} else
167 		xs_suspend_cancel();
168 
169 	dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
170 
171 out_thaw:
172 #ifdef CONFIG_PREEMPT
173 	thaw_processes();
174 out:
175 #endif
176 	shutting_down = SHUTDOWN_INVALID;
177 }
178 #endif	/* CONFIG_HIBERNATE_CALLBACKS */
179 
180 struct shutdown_handler {
181 	const char *command;
182 	void (*cb)(void);
183 };
184 
185 static void do_poweroff(void)
186 {
187 	shutting_down = SHUTDOWN_POWEROFF;
188 	orderly_poweroff(false);
189 }
190 
191 static void do_reboot(void)
192 {
193 	shutting_down = SHUTDOWN_POWEROFF; /* ? */
194 	ctrl_alt_del();
195 }
196 
197 static void shutdown_handler(struct xenbus_watch *watch,
198 			     const char **vec, unsigned int len)
199 {
200 	char *str;
201 	struct xenbus_transaction xbt;
202 	int err;
203 	static struct shutdown_handler handlers[] = {
204 		{ "poweroff",	do_poweroff },
205 		{ "halt",	do_poweroff },
206 		{ "reboot",	do_reboot   },
207 #ifdef CONFIG_HIBERNATE_CALLBACKS
208 		{ "suspend",	do_suspend  },
209 #endif
210 		{NULL, NULL},
211 	};
212 	static struct shutdown_handler *handler;
213 
214 	if (shutting_down != SHUTDOWN_INVALID)
215 		return;
216 
217  again:
218 	err = xenbus_transaction_start(&xbt);
219 	if (err)
220 		return;
221 
222 	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
223 	/* Ignore read errors and empty reads. */
224 	if (XENBUS_IS_ERR_READ(str)) {
225 		xenbus_transaction_end(xbt, 1);
226 		return;
227 	}
228 
229 	for (handler = &handlers[0]; handler->command; handler++) {
230 		if (strcmp(str, handler->command) == 0)
231 			break;
232 	}
233 
234 	/* Only acknowledge commands which we are prepared to handle. */
235 	if (handler->cb)
236 		xenbus_write(xbt, "control", "shutdown", "");
237 
238 	err = xenbus_transaction_end(xbt, 0);
239 	if (err == -EAGAIN) {
240 		kfree(str);
241 		goto again;
242 	}
243 
244 	if (handler->cb) {
245 		handler->cb();
246 	} else {
247 		pr_info("Ignoring shutdown request: %s\n", str);
248 		shutting_down = SHUTDOWN_INVALID;
249 	}
250 
251 	kfree(str);
252 }
253 
254 #ifdef CONFIG_MAGIC_SYSRQ
255 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
256 			  unsigned int len)
257 {
258 	char sysrq_key = '\0';
259 	struct xenbus_transaction xbt;
260 	int err;
261 
262  again:
263 	err = xenbus_transaction_start(&xbt);
264 	if (err)
265 		return;
266 	if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
267 		pr_err("Unable to read sysrq code in control/sysrq\n");
268 		xenbus_transaction_end(xbt, 1);
269 		return;
270 	}
271 
272 	if (sysrq_key != '\0')
273 		xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
274 
275 	err = xenbus_transaction_end(xbt, 0);
276 	if (err == -EAGAIN)
277 		goto again;
278 
279 	if (sysrq_key != '\0')
280 		handle_sysrq(sysrq_key);
281 }
282 
283 static struct xenbus_watch sysrq_watch = {
284 	.node = "control/sysrq",
285 	.callback = sysrq_handler
286 };
287 #endif
288 
289 static struct xenbus_watch shutdown_watch = {
290 	.node = "control/shutdown",
291 	.callback = shutdown_handler
292 };
293 
294 static int setup_shutdown_watcher(void)
295 {
296 	int err;
297 
298 	err = register_xenbus_watch(&shutdown_watch);
299 	if (err) {
300 		pr_err("Failed to set shutdown watcher\n");
301 		return err;
302 	}
303 
304 #ifdef CONFIG_MAGIC_SYSRQ
305 	err = register_xenbus_watch(&sysrq_watch);
306 	if (err) {
307 		pr_err("Failed to set sysrq watcher\n");
308 		return err;
309 	}
310 #endif
311 
312 	return 0;
313 }
314 
315 static int shutdown_event(struct notifier_block *notifier,
316 			  unsigned long event,
317 			  void *data)
318 {
319 	setup_shutdown_watcher();
320 	return NOTIFY_DONE;
321 }
322 
323 int xen_setup_shutdown_event(void)
324 {
325 	static struct notifier_block xenstore_notifier = {
326 		.notifier_call = shutdown_event
327 	};
328 
329 	if (!xen_domain())
330 		return -ENODEV;
331 	register_xenstore_notifier(&xenstore_notifier);
332 
333 	return 0;
334 }
335 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
336 
337 subsys_initcall(xen_setup_shutdown_event);
338