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