xref: /netbsd-src/sys/arch/xen/xen/shutdown_xenbus.c (revision d7f8dc0d9ce24611a4c920389a1d1cd4fb1b7c0c)
1 /*	$Id: shutdown_xenbus.c,v 1.9 2020/05/13 22:13:49 jdolecek 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.9 2020/05/13 22:13:49 jdolecek Exp $");
60 
61 #include <sys/param.h>
62 
63 #include <dev/sysmon/sysmonvar.h>
64 
65 #include <xen/xenbus.h>
66 #include <xen/shutdown_xenbus.h>
67 
68 #define	SHUTDOWN_PATH	"control"
69 #define	SHUTDOWN_NAME	"shutdown"
70 
71 static struct sysmon_pswitch xenbus_power = {
72 	.smpsw_type = PSWITCH_TYPE_POWER,
73 	.smpsw_name = "xenbus",
74 };
75 static struct sysmon_pswitch xenbus_reset = {
76 	.smpsw_type = PSWITCH_TYPE_RESET,
77 	.smpsw_name = "xenbus",
78 };
79 static struct sysmon_pswitch xenbus_sleep = {
80 	.smpsw_type = PSWITCH_TYPE_SLEEP,
81 	.smpsw_name = "xenbus",
82 };
83 
84 static void
xenbus_shutdown_handler(struct xenbus_watch * watch,const char ** vec,unsigned int len)85 xenbus_shutdown_handler(struct xenbus_watch *watch, const char **vec,
86     unsigned int len)
87 {
88 
89 	struct xenbus_transaction *xbt;
90 	int error;
91 	char reqstr[32];
92 
93 again:
94 	xbt = xenbus_transaction_start();
95 	if (xbt == NULL) {
96 		return;
97 	}
98 	error = xenbus_read(xbt, SHUTDOWN_PATH, SHUTDOWN_NAME,
99 	    reqstr, sizeof(reqstr));
100 	/* Ignore if read error or empty value */
101 	if (error || reqstr[0] == '\0') {
102 		if (error && error != ENOENT) {
103 			printf("%s: xenbus_read %d\n", __func__, error);
104 		}
105 		error = xenbus_transaction_end(xbt, 1);
106 		if (error != 0) {
107 			printf("%s: xenbus_transaction_end 1 %d\n",
108 			    __func__, error);
109 		}
110 		return;
111 	}
112 
113 	/* Acknowledge the command */
114 	error = xenbus_write(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 		goto again;
121 	}
122 	if (error != 0) {
123 		printf("%s: xenbus_transaction_end 2 %d\n", __func__, error);
124 	}
125 	if (strcmp(reqstr, "poweroff") == 0) {
126 		sysmon_pswitch_event(&xenbus_power, PSWITCH_EVENT_PRESSED);
127 	} else if (strcmp(reqstr, "halt") == 0) { /* XXX eventually halt without -p */
128 		sysmon_pswitch_event(&xenbus_power, PSWITCH_EVENT_PRESSED);
129 	} else if (strcmp(reqstr, "reboot") == 0) {
130 		sysmon_pswitch_event(&xenbus_reset, PSWITCH_EVENT_PRESSED);
131 	} else if (strcmp(reqstr, "suspend") == 0) {
132 		xen_suspend_allow = true;
133 		sysmon_pswitch_event(&xenbus_sleep, PSWITCH_EVENT_PRESSED);
134 	} else {
135 		printf("ignore shutdown request: %s\n", reqstr);
136 	}
137 }
138 
139 static struct xenbus_watch xenbus_shutdown_watch = {
140 	.node = __UNCONST(SHUTDOWN_PATH "/" SHUTDOWN_NAME), /* XXX */
141 	.xbw_callback = xenbus_shutdown_handler,
142 };
143 
144 void
shutdown_xenbus_setup(void)145 shutdown_xenbus_setup(void)
146 {
147 	xen_suspend_allow = false;
148 
149 	if (sysmon_pswitch_register(&xenbus_power) != 0 ||
150 	    sysmon_pswitch_register(&xenbus_reset) != 0 ||
151 	    sysmon_pswitch_register(&xenbus_sleep) != 0) {
152 		aprint_error("%s: unable to register with sysmon\n", __func__);
153 		return;
154 	}
155 	if (register_xenbus_watch(&xenbus_shutdown_watch)) {
156 		aprint_error("%s: unable to watch control/shutdown\n", __func__);
157 	}
158 }
159