Home | History | Annotate | Line # | Download | only in xen
      1 /*	$Id: shutdown_xenbus.c,v 1.7 2011/09/20 00:12:24 jym Exp $	*/
      2 
      3 /*-
      4  * Copyright (c)2006 YAMAMOTO Takashi,
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 /*
     30  * Copyright (c) 2005 Manuel Bouyer.
     31  *
     32  * Redistribution and use in source and binary forms, with or without
     33  * modification, are permitted provided that the following conditions
     34  * are met:
     35  * 1. Redistributions of source code must retain the above copyright
     36  *    notice, this list of conditions and the following disclaimer.
     37  * 2. Redistributions in binary form must reproduce the above copyright
     38  *    notice, this list of conditions and the following disclaimer in the
     39  *    documentation and/or other materials provided with the distribution.
     40  *
     41  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     42  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     44  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     45  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     47  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     48  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     49  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     50  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     51  *
     52  */
     53 
     54 /*
     55  * watch "control/shutdown" and generate sysmon events.
     56  */
     57 
     58 #include <sys/cdefs.h>
     59 __KERNEL_RCSID(0, "$NetBSD: shutdown_xenbus.c,v 1.6 2009/10/19 18:41:11 bouyer Exp $");
     60 
     61 #include <sys/param.h>
     62 #include <sys/malloc.h>
     63 
     64 #include <dev/sysmon/sysmonvar.h>
     65 
     66 #include <xen/xenbus.h>
     67 #include <xen/shutdown_xenbus.h>
     68 
     69 #define	SHUTDOWN_PATH	"control"
     70 #define	SHUTDOWN_NAME	"shutdown"
     71 
     72 static struct sysmon_pswitch xenbus_power = {
     73 	.smpsw_type = PSWITCH_TYPE_POWER,
     74 	.smpsw_name = "xenbus",
     75 };
     76 static struct sysmon_pswitch xenbus_reset = {
     77 	.smpsw_type = PSWITCH_TYPE_RESET,
     78 	.smpsw_name = "xenbus",
     79 };
     80 static struct sysmon_pswitch xenbus_sleep = {
     81 	.smpsw_type = PSWITCH_TYPE_SLEEP,
     82 	.smpsw_name = "xenbus",
     83 };
     84 
     85 static void
     86 xenbus_shutdown_handler(struct xenbus_watch *watch, const char **vec,
     87     unsigned int len)
     88 {
     89 
     90 	struct xenbus_transaction *xbt;
     91 	int error;
     92 	char *reqstr;
     93 	unsigned int reqstrlen;
     94 
     95 again:
     96 	xbt = xenbus_transaction_start();
     97 	if (xbt == NULL) {
     98 		return;
     99 	}
    100 	error = xenbus_read(xbt, SHUTDOWN_PATH, SHUTDOWN_NAME,
    101 	    &reqstrlen, &reqstr);
    102 	if (error) {
    103 		if (error != ENOENT) {
    104 			printf("%s: xenbus_read %d\n", __func__, error);
    105 		}
    106 		error = xenbus_transaction_end(xbt, 1);
    107 		if (error != 0) {
    108 			printf("%s: xenbus_transaction_end 1 %d\n",
    109 			    __func__, error);
    110 		}
    111 		return;
    112 	}
    113 	KASSERT(strlen(reqstr) == reqstrlen);
    114 	error = xenbus_rm(xbt, SHUTDOWN_PATH, SHUTDOWN_NAME);
    115 	if (error) {
    116 		printf("%s: xenbus_rm %d\n", __func__, error);
    117 	}
    118 	error = xenbus_transaction_end(xbt, 0);
    119 	if (error == EAGAIN) {
    120 		free(reqstr, M_DEVBUF);
    121 		goto again;
    122 	}
    123 	if (error != 0) {
    124 		printf("%s: xenbus_transaction_end 2 %d\n", __func__, error);
    125 	}
    126 	if (strcmp(reqstr, "poweroff") == 0) {
    127 		sysmon_pswitch_event(&xenbus_power, PSWITCH_EVENT_PRESSED);
    128 	} else if (strcmp(reqstr, "halt") == 0) { /* XXX eventually halt without -p */
    129 		sysmon_pswitch_event(&xenbus_power, PSWITCH_EVENT_PRESSED);
    130 	} else if (strcmp(reqstr, "reboot") == 0) {
    131 		sysmon_pswitch_event(&xenbus_reset, PSWITCH_EVENT_PRESSED);
    132 	} else if (strcmp(reqstr, "suspend") == 0) {
    133 		xen_suspend_allow = true;
    134 		sysmon_pswitch_event(&xenbus_sleep, PSWITCH_EVENT_PRESSED);
    135 	} else {
    136 		printf("ignore shutdown request: %s\n", reqstr);
    137 	}
    138 	free(reqstr, M_DEVBUF);
    139 }
    140 
    141 static struct xenbus_watch xenbus_shutdown_watch = {
    142 	.node = __UNCONST(SHUTDOWN_PATH "/" SHUTDOWN_NAME), /* XXX */
    143 	.xbw_callback = xenbus_shutdown_handler,
    144 };
    145 
    146 void
    147 shutdown_xenbus_setup(void)
    148 {
    149 	xen_suspend_allow = false;
    150 
    151 	if (sysmon_pswitch_register(&xenbus_power) != 0 ||
    152 	    sysmon_pswitch_register(&xenbus_reset) != 0 ||
    153 	    sysmon_pswitch_register(&xenbus_sleep) != 0) {
    154 		aprint_error("%s: unable to register with sysmon\n", __func__);
    155 		return;
    156 	}
    157 	if (register_xenbus_watch(&xenbus_shutdown_watch)) {
    158 		aprint_error("%s: unable to watch control/shutdown\n", __func__);
    159 	}
    160 }
    161