xref: /linux/drivers/xen/manage.c (revision b8bb76713ec50df2f11efee386e16f93d51e1076)
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 	sysdev_resume();
66 
67 	if (!*cancelled) {
68 		xen_irq_resume();
69 		xen_console_resume();
70 		xen_timer_resume();
71 	}
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 		return;
91 	}
92 #endif
93 
94 	err = device_suspend(PMSG_SUSPEND);
95 	if (err) {
96 		printk(KERN_ERR "xen suspend: device_suspend %d\n", err);
97 		goto out;
98 	}
99 
100 	printk("suspending xenbus...\n");
101 	/* XXX use normal device tree? */
102 	xenbus_suspend();
103 
104 	err = device_power_down(PMSG_SUSPEND);
105 	if (err) {
106 		printk(KERN_ERR "device_power_down failed: %d\n", err);
107 		goto resume_devices;
108 	}
109 
110 	err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
111 	if (err) {
112 		printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
113 		goto out;
114 	}
115 
116 	if (!cancelled) {
117 		xen_arch_resume();
118 		xenbus_resume();
119 	} else
120 		xenbus_suspend_cancel();
121 
122 	device_power_up(PMSG_RESUME);
123 
124 resume_devices:
125 	device_resume(PMSG_RESUME);
126 
127 	/* Make sure timer events get retriggered on all CPUs */
128 	clock_was_set();
129 out:
130 #ifdef CONFIG_PREEMPT
131 	thaw_processes();
132 #endif
133 	shutting_down = SHUTDOWN_INVALID;
134 }
135 #endif	/* CONFIG_PM_SLEEP */
136 
137 static void shutdown_handler(struct xenbus_watch *watch,
138 			     const char **vec, unsigned int len)
139 {
140 	char *str;
141 	struct xenbus_transaction xbt;
142 	int err;
143 
144 	if (shutting_down != SHUTDOWN_INVALID)
145 		return;
146 
147  again:
148 	err = xenbus_transaction_start(&xbt);
149 	if (err)
150 		return;
151 
152 	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
153 	/* Ignore read errors and empty reads. */
154 	if (XENBUS_IS_ERR_READ(str)) {
155 		xenbus_transaction_end(xbt, 1);
156 		return;
157 	}
158 
159 	xenbus_write(xbt, "control", "shutdown", "");
160 
161 	err = xenbus_transaction_end(xbt, 0);
162 	if (err == -EAGAIN) {
163 		kfree(str);
164 		goto again;
165 	}
166 
167 	if (strcmp(str, "poweroff") == 0 ||
168 	    strcmp(str, "halt") == 0) {
169 		shutting_down = SHUTDOWN_POWEROFF;
170 		orderly_poweroff(false);
171 	} else if (strcmp(str, "reboot") == 0) {
172 		shutting_down = SHUTDOWN_POWEROFF; /* ? */
173 		ctrl_alt_del();
174 #ifdef CONFIG_PM_SLEEP
175 	} else if (strcmp(str, "suspend") == 0) {
176 		do_suspend();
177 #endif
178 	} else {
179 		printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
180 		shutting_down = SHUTDOWN_INVALID;
181 	}
182 
183 	kfree(str);
184 }
185 
186 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
187 			  unsigned int len)
188 {
189 	char sysrq_key = '\0';
190 	struct xenbus_transaction xbt;
191 	int err;
192 
193  again:
194 	err = xenbus_transaction_start(&xbt);
195 	if (err)
196 		return;
197 	if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
198 		printk(KERN_ERR "Unable to read sysrq code in "
199 		       "control/sysrq\n");
200 		xenbus_transaction_end(xbt, 1);
201 		return;
202 	}
203 
204 	if (sysrq_key != '\0')
205 		xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
206 
207 	err = xenbus_transaction_end(xbt, 0);
208 	if (err == -EAGAIN)
209 		goto again;
210 
211 	if (sysrq_key != '\0')
212 		handle_sysrq(sysrq_key, NULL);
213 }
214 
215 static struct xenbus_watch shutdown_watch = {
216 	.node = "control/shutdown",
217 	.callback = shutdown_handler
218 };
219 
220 static struct xenbus_watch sysrq_watch = {
221 	.node = "control/sysrq",
222 	.callback = sysrq_handler
223 };
224 
225 static int setup_shutdown_watcher(void)
226 {
227 	int err;
228 
229 	err = register_xenbus_watch(&shutdown_watch);
230 	if (err) {
231 		printk(KERN_ERR "Failed to set shutdown watcher\n");
232 		return err;
233 	}
234 
235 	err = register_xenbus_watch(&sysrq_watch);
236 	if (err) {
237 		printk(KERN_ERR "Failed to set sysrq watcher\n");
238 		return err;
239 	}
240 
241 	return 0;
242 }
243 
244 static int shutdown_event(struct notifier_block *notifier,
245 			  unsigned long event,
246 			  void *data)
247 {
248 	setup_shutdown_watcher();
249 	return NOTIFY_DONE;
250 }
251 
252 static int __init setup_shutdown_event(void)
253 {
254 	static struct notifier_block xenstore_notifier = {
255 		.notifier_call = shutdown_event
256 	};
257 	register_xenstore_notifier(&xenstore_notifier);
258 
259 	return 0;
260 }
261 
262 subsys_initcall(setup_shutdown_event);
263