xref: /openbmc/linux/drivers/xen/manage.c (revision 34f5c1c5)
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/xenbus.h>
13 #include <xen/grant_table.h>
14 #include <xen/events.h>
15 #include <xen/hvc-console.h>
16 #include <xen/xen-ops.h>
17 
18 #include <asm/xen/hypercall.h>
19 #include <asm/xen/page.h>
20 
21 enum shutdown_state {
22 	SHUTDOWN_INVALID = -1,
23 	SHUTDOWN_POWEROFF = 0,
24 	SHUTDOWN_SUSPEND = 2,
25 	/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
26 	   report a crash, not be instructed to crash!
27 	   HALT is the same as POWEROFF, as far as we're concerned.  The tools use
28 	   the distinction when we return the reason code to them.  */
29 	 SHUTDOWN_HALT = 4,
30 };
31 
32 /* Ignore multiple shutdown requests. */
33 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
34 
35 #ifdef CONFIG_PM_SLEEP
36 static int xen_suspend(void *data)
37 {
38 	int *cancelled = data;
39 	int err;
40 
41 	BUG_ON(!irqs_disabled());
42 
43 	err = sysdev_suspend(PMSG_SUSPEND);
44 	if (err) {
45 		printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
46 			err);
47 		return err;
48 	}
49 
50 	xen_mm_pin_all();
51 	gnttab_suspend();
52 	xen_pre_suspend();
53 
54 	/*
55 	 * This hypercall returns 1 if suspend was cancelled
56 	 * or the domain was merely checkpointed, and 0 if it
57 	 * is resuming in a new domain.
58 	 */
59 	*cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
60 
61 	xen_post_suspend(*cancelled);
62 	gnttab_resume();
63 	xen_mm_unpin_all();
64 
65 	if (!*cancelled) {
66 		xen_irq_resume();
67 		xen_console_resume();
68 		xen_timer_resume();
69 	}
70 
71 	sysdev_resume();
72 
73 	return 0;
74 }
75 
76 static void do_suspend(void)
77 {
78 	int err;
79 	int cancelled = 1;
80 
81 	shutting_down = SHUTDOWN_SUSPEND;
82 
83 #ifdef CONFIG_PREEMPT
84 	/* If the kernel is preemptible, we need to freeze all the processes
85 	   to prevent them from being in the middle of a pagetable update
86 	   during suspend. */
87 	err = freeze_processes();
88 	if (err) {
89 		printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
90 		goto out;
91 	}
92 #endif
93 
94 	err = dpm_suspend_start(PMSG_SUSPEND);
95 	if (err) {
96 		printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
97 		goto out_thaw;
98 	}
99 
100 	printk(KERN_DEBUG "suspending xenstore...\n");
101 	xs_suspend();
102 
103 	err = dpm_suspend_noirq(PMSG_SUSPEND);
104 	if (err) {
105 		printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
106 		goto out_resume;
107 	}
108 
109 	err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
110 
111 	dpm_resume_noirq(PMSG_RESUME);
112 
113 	if (err) {
114 		printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
115 		cancelled = 1;
116 	}
117 
118 out_resume:
119 	if (!cancelled) {
120 		xen_arch_resume();
121 		xs_resume();
122 	} else
123 		xs_suspend_cancel();
124 
125 	dpm_resume_end(PMSG_RESUME);
126 
127 	/* Make sure timer events get retriggered on all CPUs */
128 	clock_was_set();
129 
130 out_thaw:
131 #ifdef CONFIG_PREEMPT
132 	thaw_processes();
133 out:
134 #endif
135 	shutting_down = SHUTDOWN_INVALID;
136 }
137 #endif	/* CONFIG_PM_SLEEP */
138 
139 static void shutdown_handler(struct xenbus_watch *watch,
140 			     const char **vec, unsigned int len)
141 {
142 	char *str;
143 	struct xenbus_transaction xbt;
144 	int err;
145 
146 	if (shutting_down != SHUTDOWN_INVALID)
147 		return;
148 
149  again:
150 	err = xenbus_transaction_start(&xbt);
151 	if (err)
152 		return;
153 
154 	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
155 	/* Ignore read errors and empty reads. */
156 	if (XENBUS_IS_ERR_READ(str)) {
157 		xenbus_transaction_end(xbt, 1);
158 		return;
159 	}
160 
161 	xenbus_write(xbt, "control", "shutdown", "");
162 
163 	err = xenbus_transaction_end(xbt, 0);
164 	if (err == -EAGAIN) {
165 		kfree(str);
166 		goto again;
167 	}
168 
169 	if (strcmp(str, "poweroff") == 0 ||
170 	    strcmp(str, "halt") == 0) {
171 		shutting_down = SHUTDOWN_POWEROFF;
172 		orderly_poweroff(false);
173 	} else if (strcmp(str, "reboot") == 0) {
174 		shutting_down = SHUTDOWN_POWEROFF; /* ? */
175 		ctrl_alt_del();
176 #ifdef CONFIG_PM_SLEEP
177 	} else if (strcmp(str, "suspend") == 0) {
178 		do_suspend();
179 #endif
180 	} else {
181 		printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
182 		shutting_down = SHUTDOWN_INVALID;
183 	}
184 
185 	kfree(str);
186 }
187 
188 #ifdef CONFIG_MAGIC_SYSRQ
189 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
190 			  unsigned int len)
191 {
192 	char sysrq_key = '\0';
193 	struct xenbus_transaction xbt;
194 	int err;
195 
196  again:
197 	err = xenbus_transaction_start(&xbt);
198 	if (err)
199 		return;
200 	if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
201 		printk(KERN_ERR "Unable to read sysrq code in "
202 		       "control/sysrq\n");
203 		xenbus_transaction_end(xbt, 1);
204 		return;
205 	}
206 
207 	if (sysrq_key != '\0')
208 		xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
209 
210 	err = xenbus_transaction_end(xbt, 0);
211 	if (err == -EAGAIN)
212 		goto again;
213 
214 	if (sysrq_key != '\0')
215 		handle_sysrq(sysrq_key, NULL);
216 }
217 
218 static struct xenbus_watch sysrq_watch = {
219 	.node = "control/sysrq",
220 	.callback = sysrq_handler
221 };
222 #endif
223 
224 static struct xenbus_watch shutdown_watch = {
225 	.node = "control/shutdown",
226 	.callback = shutdown_handler
227 };
228 
229 static int setup_shutdown_watcher(void)
230 {
231 	int err;
232 
233 	err = register_xenbus_watch(&shutdown_watch);
234 	if (err) {
235 		printk(KERN_ERR "Failed to set shutdown watcher\n");
236 		return err;
237 	}
238 
239 #ifdef CONFIG_MAGIC_SYSRQ
240 	err = register_xenbus_watch(&sysrq_watch);
241 	if (err) {
242 		printk(KERN_ERR "Failed to set sysrq watcher\n");
243 		return err;
244 	}
245 #endif
246 
247 	return 0;
248 }
249 
250 static int shutdown_event(struct notifier_block *notifier,
251 			  unsigned long event,
252 			  void *data)
253 {
254 	setup_shutdown_watcher();
255 	return NOTIFY_DONE;
256 }
257 
258 static int __init setup_shutdown_event(void)
259 {
260 	static struct notifier_block xenstore_notifier = {
261 		.notifier_call = shutdown_event
262 	};
263 	register_xenstore_notifier(&xenstore_notifier);
264 
265 	return 0;
266 }
267 
268 subsys_initcall(setup_shutdown_event);
269