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