manage.c revision c78277288e3d561d55fb48bc0fe8d6e2cf4d0880
13e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge/* 23e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge * Handle extern requests for shutdown, reboot and sysrq 33e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge */ 43e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge#include <linux/kernel.h> 53e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge#include <linux/err.h> 63e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge#include <linux/reboot.h> 73e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge#include <linux/sysrq.h> 80e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#include <linux/stop_machine.h> 90e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#include <linux/freezer.h> 103e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 113e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge#include <xen/xenbus.h> 120e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#include <xen/grant_table.h> 130e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#include <xen/events.h> 140e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#include <xen/hvc-console.h> 150e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#include <xen/xen-ops.h> 163e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 170e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#include <asm/xen/hypercall.h> 180e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#include <asm/xen/page.h> 190e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 200e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardingeenum shutdown_state { 210e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge SHUTDOWN_INVALID = -1, 220e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge SHUTDOWN_POWEROFF = 0, 230e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge SHUTDOWN_SUSPEND = 2, 240e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only 250e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge report a crash, not be instructed to crash! 260e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge HALT is the same as POWEROFF, as far as we're concerned. The tools use 270e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge the distinction when we return the reason code to them. */ 280e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge SHUTDOWN_HALT = 4, 290e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge}; 303e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 313e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge/* Ignore multiple shutdown requests. */ 320e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardingestatic enum shutdown_state shutting_down = SHUTDOWN_INVALID; 330e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 34c78277288e3d561d55fb48bc0fe8d6e2cf4d0880Jeremy Fitzhardinge#ifdef CONFIG_PM_SLEEP 350e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardingestatic int xen_suspend(void *data) 360e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge{ 370e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge int *cancelled = data; 38359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge int err; 390e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 400e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge BUG_ON(!irqs_disabled()); 410e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 420e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge load_cr3(swapper_pg_dir); 430e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 44359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge err = device_power_down(PMSG_SUSPEND); 45359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge if (err) { 46359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge printk(KERN_ERR "xen_suspend: device_power_down failed: %d\n", 47359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge err); 48359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge return err; 49359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge } 50359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge 510e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge xen_mm_pin_all(); 520e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge gnttab_suspend(); 530e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge xen_pre_suspend(); 540e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 550e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge /* 560e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge * This hypercall returns 1 if suspend was cancelled 570e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge * or the domain was merely checkpointed, and 0 if it 580e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge * is resuming in a new domain. 590e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge */ 600e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge *cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); 610e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 620e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge xen_post_suspend(*cancelled); 630e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge gnttab_resume(); 640e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge xen_mm_unpin_all(); 650e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 66359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge device_power_up(); 67359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge 680e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge if (!*cancelled) { 690e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge xen_irq_resume(); 700e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge xen_console_resume(); 710e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge } 720e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 730e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge return 0; 740e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge} 750e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 760e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardingestatic void do_suspend(void) 770e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge{ 780e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge int err; 790e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge int cancelled = 1; 800e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 810e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge shutting_down = SHUTDOWN_SUSPEND; 820e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 830e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#ifdef CONFIG_PREEMPT 840e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge /* If the kernel is preemptible, we need to freeze all the processes 850e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge to prevent them from being in the middle of a pagetable update 860e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge during suspend. */ 870e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge err = freeze_processes(); 880e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge if (err) { 890e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge printk(KERN_ERR "xen suspend: freeze failed %d\n", err); 900e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge return; 910e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge } 920e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#endif 930e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 940e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge err = device_suspend(PMSG_SUSPEND); 950e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge if (err) { 960e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge printk(KERN_ERR "xen suspend: device_suspend %d\n", err); 970e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge goto out; 980e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge } 990e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 1000e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge printk("suspending xenbus...\n"); 1010e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge /* XXX use normal device tree? */ 1020e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge xenbus_suspend(); 1030e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 1040e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge err = stop_machine_run(xen_suspend, &cancelled, 0); 1050e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge if (err) { 1060e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge printk(KERN_ERR "failed to start xen_suspend: %d\n", err); 1070e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge goto out; 1080e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge } 1090e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 1100e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge if (!cancelled) 1110e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge xenbus_resume(); 1120e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge else 1130e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge xenbus_suspend_cancel(); 1140e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 1150e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge device_resume(); 1160e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge 117359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge /* Make sure timer events get retriggered on all CPUs */ 118359cdd3f866b6219a6729e313faf2221397f3278Jeremy Fitzhardinge clock_was_set(); 1190e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardingeout: 1200e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#ifdef CONFIG_PREEMPT 1210e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge thaw_processes(); 1220e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#endif 1230e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge shutting_down = SHUTDOWN_INVALID; 1240e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge} 125c78277288e3d561d55fb48bc0fe8d6e2cf4d0880Jeremy Fitzhardinge#endif /* CONFIG_PM_SLEEP */ 1263e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1273e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardingestatic void shutdown_handler(struct xenbus_watch *watch, 1283e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge const char **vec, unsigned int len) 1293e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge{ 1303e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge char *str; 1313e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge struct xenbus_transaction xbt; 1323e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge int err; 1333e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1343e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (shutting_down != SHUTDOWN_INVALID) 1353e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge return; 1363e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1373e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge again: 1383e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge err = xenbus_transaction_start(&xbt); 1393e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (err) 1403e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge return; 1413e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1423e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge str = (char *)xenbus_read(xbt, "control", "shutdown", NULL); 1433e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge /* Ignore read errors and empty reads. */ 1443e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (XENBUS_IS_ERR_READ(str)) { 1453e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge xenbus_transaction_end(xbt, 1); 1463e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge return; 1473e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge } 1483e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1493e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge xenbus_write(xbt, "control", "shutdown", ""); 1503e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1513e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge err = xenbus_transaction_end(xbt, 0); 1523e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (err == -EAGAIN) { 1533e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge kfree(str); 1543e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge goto again; 1553e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge } 1563e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1573e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (strcmp(str, "poweroff") == 0 || 1580e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge strcmp(str, "halt") == 0) { 1590e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge shutting_down = SHUTDOWN_POWEROFF; 1603e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge orderly_poweroff(false); 1610e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge } else if (strcmp(str, "reboot") == 0) { 1620e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge shutting_down = SHUTDOWN_POWEROFF; /* ? */ 1633e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge ctrl_alt_del(); 1640e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#ifdef CONFIG_PM_SLEEP 1650e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge } else if (strcmp(str, "suspend") == 0) { 1660e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge do_suspend(); 1670e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge#endif 1680e91398f2a5d4eb6b07df8115917d0d1cf3e9b58Jeremy Fitzhardinge } else { 1693e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge printk(KERN_INFO "Ignoring shutdown request: %s\n", str); 1703e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge shutting_down = SHUTDOWN_INVALID; 1713e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge } 1723e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1733e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge kfree(str); 1743e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge} 1753e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1763e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardingestatic void sysrq_handler(struct xenbus_watch *watch, const char **vec, 1773e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge unsigned int len) 1783e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge{ 1793e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge char sysrq_key = '\0'; 1803e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge struct xenbus_transaction xbt; 1813e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge int err; 1823e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1833e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge again: 1843e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge err = xenbus_transaction_start(&xbt); 1853e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (err) 1863e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge return; 1873e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) { 1883e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge printk(KERN_ERR "Unable to read sysrq code in " 1893e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge "control/sysrq\n"); 1903e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge xenbus_transaction_end(xbt, 1); 1913e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge return; 1923e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge } 1933e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1943e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (sysrq_key != '\0') 1953e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge xenbus_printf(xbt, "control", "sysrq", "%c", '\0'); 1963e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 1973e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge err = xenbus_transaction_end(xbt, 0); 1983e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (err == -EAGAIN) 1993e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge goto again; 2003e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2013e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (sysrq_key != '\0') 2023e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge handle_sysrq(sysrq_key, NULL); 2033e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge} 2043e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2053e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardingestatic struct xenbus_watch shutdown_watch = { 2063e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge .node = "control/shutdown", 2073e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge .callback = shutdown_handler 2083e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge}; 2093e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2103e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardingestatic struct xenbus_watch sysrq_watch = { 2113e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge .node = "control/sysrq", 2123e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge .callback = sysrq_handler 2133e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge}; 2143e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2153e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardingestatic int setup_shutdown_watcher(void) 2163e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge{ 2173e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge int err; 2183e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2193e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge err = register_xenbus_watch(&shutdown_watch); 2203e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (err) { 2213e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge printk(KERN_ERR "Failed to set shutdown watcher\n"); 2223e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge return err; 2233e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge } 2243e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2253e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge err = register_xenbus_watch(&sysrq_watch); 2263e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge if (err) { 2273e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge printk(KERN_ERR "Failed to set sysrq watcher\n"); 2283e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge return err; 2293e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge } 2303e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2313e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge return 0; 2323e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge} 2333e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2343e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardingestatic int shutdown_event(struct notifier_block *notifier, 2353e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge unsigned long event, 2363e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge void *data) 2373e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge{ 2383e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge setup_shutdown_watcher(); 2393e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge return NOTIFY_DONE; 2403e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge} 2413e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2423e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardingestatic int __init setup_shutdown_event(void) 2433e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge{ 2443e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge static struct notifier_block xenstore_notifier = { 2453e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge .notifier_call = shutdown_event 2463e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge }; 2473e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge register_xenstore_notifier(&xenstore_notifier); 2483e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2493e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge return 0; 2503e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge} 2513e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardinge 2523e2b8fbeec8f005672f2a2e862fb9c26a0bafedcJeremy Fitzhardingesubsys_initcall(setup_shutdown_event); 253