nvme: simplify plug/unplug
[qemu/ar7.git] / hw / xen / xen_pvdev.c
blobaed783e844ea8b3ef1359d9c93cbdc596cba95f4
1 /*
2 * Xen para-virtualization device
4 * (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>
20 #include "qemu/osdep.h"
21 #include "qemu/log.h"
22 #include "hw/qdev-core.h"
23 #include "hw/xen/xen_backend.h"
24 #include "hw/xen/xen_pvdev.h"
26 /* private */
27 static int debug;
29 struct xs_dirs {
30 char *xs_dir;
31 QTAILQ_ENTRY(xs_dirs) list;
34 static QTAILQ_HEAD(xs_dirs_head, xs_dirs) xs_cleanup =
35 QTAILQ_HEAD_INITIALIZER(xs_cleanup);
37 static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs =
38 QTAILQ_HEAD_INITIALIZER(xendevs);
40 /* ------------------------------------------------------------- */
42 static void xenstore_cleanup_dir(char *dir)
44 struct xs_dirs *d;
46 d = g_malloc(sizeof(*d));
47 d->xs_dir = dir;
48 QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
51 void xen_config_cleanup(void)
53 struct xs_dirs *d;
55 QTAILQ_FOREACH(d, &xs_cleanup, list) {
56 xs_rm(xenstore, 0, d->xs_dir);
60 int xenstore_mkdir(char *path, int p)
62 struct xs_permissions perms[2] = {
64 .id = 0, /* set owner: dom0 */
65 }, {
66 .id = xen_domid,
67 .perms = p,
71 if (!xs_mkdir(xenstore, 0, path)) {
72 xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
73 return -1;
75 xenstore_cleanup_dir(g_strdup(path));
77 if (!xs_set_permissions(xenstore, 0, path, perms, 2)) {
78 xen_pv_printf(NULL, 0, "xs_set_permissions %s: failed\n", path);
79 return -1;
81 return 0;
84 int xenstore_write_str(const char *base, const char *node, const char *val)
86 char abspath[XEN_BUFSIZE];
88 snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
89 if (!xs_write(xenstore, 0, abspath, val, strlen(val))) {
90 return -1;
92 return 0;
95 char *xenstore_read_str(const char *base, const char *node)
97 char abspath[XEN_BUFSIZE];
98 unsigned int len;
99 char *str, *ret = NULL;
101 snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
102 str = xs_read(xenstore, 0, abspath, &len);
103 if (str != NULL) {
104 /* move to qemu-allocated memory to make sure
105 * callers can savely g_free() stuff. */
106 ret = g_strdup(str);
107 free(str);
109 return ret;
112 int xenstore_write_int(const char *base, const char *node, int ival)
114 char val[12];
116 snprintf(val, sizeof(val), "%d", ival);
117 return xenstore_write_str(base, node, val);
120 int xenstore_write_int64(const char *base, const char *node, int64_t ival)
122 char val[21];
124 snprintf(val, sizeof(val), "%"PRId64, ival);
125 return xenstore_write_str(base, node, val);
128 int xenstore_read_int(const char *base, const char *node, int *ival)
130 char *val;
131 int rc = -1;
133 val = xenstore_read_str(base, node);
134 if (val && 1 == sscanf(val, "%d", ival)) {
135 rc = 0;
137 g_free(val);
138 return rc;
141 int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
143 char *val;
144 int rc = -1;
146 val = xenstore_read_str(base, node);
147 if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
148 rc = 0;
150 g_free(val);
151 return rc;
154 void xenstore_update(void *unused)
156 char **vec = NULL;
157 intptr_t type, ops, ptr;
158 unsigned int dom, count;
160 vec = xs_read_watch(xenstore, &count);
161 if (vec == NULL) {
162 goto cleanup;
165 if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
166 &type, &dom, &ops) == 3) {
167 xenstore_update_be(vec[XS_WATCH_PATH], (void *)type, dom, (void*)ops);
169 if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
170 xenstore_update_fe(vec[XS_WATCH_PATH], (void *)ptr);
173 cleanup:
174 free(vec);
177 const char *xenbus_strstate(enum xenbus_state state)
179 static const char *const name[] = {
180 [XenbusStateUnknown] = "Unknown",
181 [XenbusStateInitialising] = "Initialising",
182 [XenbusStateInitWait] = "InitWait",
183 [XenbusStateInitialised] = "Initialised",
184 [XenbusStateConnected] = "Connected",
185 [XenbusStateClosing] = "Closing",
186 [XenbusStateClosed] = "Closed",
188 return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
192 * msg_level:
193 * 0 == errors (stderr + logfile).
194 * 1 == informative debug messages (logfile only).
195 * 2 == noisy debug messages (logfile only).
196 * 3 == will flood your log (logfile only).
198 void xen_pv_printf(struct XenDevice *xendev, int msg_level,
199 const char *fmt, ...)
201 va_list args;
203 if (xendev) {
204 if (msg_level > xendev->debug) {
205 return;
207 qemu_log("xen be: %s: ", xendev->name);
208 if (msg_level == 0) {
209 fprintf(stderr, "xen be: %s: ", xendev->name);
211 } else {
212 if (msg_level > debug) {
213 return;
215 qemu_log("xen be core: ");
216 if (msg_level == 0) {
217 fprintf(stderr, "xen be core: ");
220 va_start(args, fmt);
221 qemu_log_vprintf(fmt, args);
222 va_end(args);
223 if (msg_level == 0) {
224 va_start(args, fmt);
225 vfprintf(stderr, fmt, args);
226 va_end(args);
228 qemu_log_flush();
231 void xen_pv_evtchn_event(void *opaque)
233 struct XenDevice *xendev = opaque;
234 evtchn_port_t port;
236 port = xenevtchn_pending(xendev->evtchndev);
237 if (port != xendev->local_port) {
238 xen_pv_printf(xendev, 0,
239 "xenevtchn_pending returned %d (expected %d)\n",
240 port, xendev->local_port);
241 return;
243 xenevtchn_unmask(xendev->evtchndev, port);
245 if (xendev->ops->event) {
246 xendev->ops->event(xendev);
250 void xen_pv_unbind_evtchn(struct XenDevice *xendev)
252 if (xendev->local_port == -1) {
253 return;
255 qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
256 xenevtchn_unbind(xendev->evtchndev, xendev->local_port);
257 xen_pv_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
258 xendev->local_port = -1;
261 int xen_pv_send_notify(struct XenDevice *xendev)
263 return xenevtchn_notify(xendev->evtchndev, xendev->local_port);
266 /* ------------------------------------------------------------- */
268 struct XenDevice *xen_pv_find_xendev(const char *type, int dom, int dev)
270 struct XenDevice *xendev;
272 QTAILQ_FOREACH(xendev, &xendevs, next) {
273 if (xendev->dom != dom) {
274 continue;
276 if (xendev->dev != dev) {
277 continue;
279 if (strcmp(xendev->type, type) != 0) {
280 continue;
282 return xendev;
284 return NULL;
288 * release xen backend device.
290 void xen_pv_del_xendev(struct XenDevice *xendev)
292 if (xendev->ops->free) {
293 xendev->ops->free(xendev);
296 if (xendev->fe) {
297 char token[XEN_BUFSIZE];
298 snprintf(token, sizeof(token), "fe:%p", xendev);
299 xs_unwatch(xenstore, xendev->fe, token);
300 g_free(xendev->fe);
303 if (xendev->evtchndev != NULL) {
304 xenevtchn_close(xendev->evtchndev);
306 if (xendev->gnttabdev != NULL) {
307 xengnttab_close(xendev->gnttabdev);
310 QTAILQ_REMOVE(&xendevs, xendev, next);
312 qdev_unplug(&xendev->qdev, NULL);
315 void xen_pv_insert_xendev(struct XenDevice *xendev)
317 QTAILQ_INSERT_TAIL(&xendevs, xendev, next);