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