2 * Xen para-virtualization device
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"
22 #include "qemu/main-loop.h"
23 #include "hw/qdev-core.h"
24 #include "hw/xen/xen-legacy-backend.h"
25 #include "hw/xen/xen_pvdev.h"
32 QTAILQ_ENTRY(xs_dirs) list;
35 static QTAILQ_HEAD(, xs_dirs) xs_cleanup =
36 QTAILQ_HEAD_INITIALIZER(xs_cleanup);
38 static QTAILQ_HEAD(, XenLegacyDevice) xendevs =
39 QTAILQ_HEAD_INITIALIZER(xendevs);
41 /* ------------------------------------------------------------- */
43 static void xenstore_cleanup_dir(char *dir)
47 d = g_malloc(sizeof(*d));
49 QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
52 void xen_config_cleanup(void)
56 QTAILQ_FOREACH(d, &xs_cleanup, list) {
57 xs_rm(xenstore, 0, d->xs_dir);
61 int xenstore_mkdir(char *path, int p)
63 struct xs_permissions perms[2] = {
65 .id = 0, /* set owner: dom0 */
72 if (!xs_mkdir(xenstore, 0, path)) {
73 xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
76 xenstore_cleanup_dir(g_strdup(path));
78 if (!xs_set_permissions(xenstore, 0, path, perms, 2)) {
79 xen_pv_printf(NULL, 0, "xs_set_permissions %s: failed\n", path);
85 int xenstore_write_str(const char *base, const char *node, const char *val)
87 char abspath[XEN_BUFSIZE];
89 snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
90 if (!xs_write(xenstore, 0, abspath, val, strlen(val))) {
96 char *xenstore_read_str(const char *base, const char *node)
98 char abspath[XEN_BUFSIZE];
100 char *str, *ret = NULL;
102 snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
103 str = xs_read(xenstore, 0, abspath, &len);
105 /* move to qemu-allocated memory to make sure
106 * callers can savely g_free() stuff. */
113 int xenstore_write_int(const char *base, const char *node, int ival)
117 snprintf(val, sizeof(val), "%d", ival);
118 return xenstore_write_str(base, node, val);
121 int xenstore_write_int64(const char *base, const char *node, int64_t ival)
125 snprintf(val, sizeof(val), "%"PRId64, ival);
126 return xenstore_write_str(base, node, val);
129 int xenstore_read_int(const char *base, const char *node, int *ival)
134 val = xenstore_read_str(base, node);
135 if (val && 1 == sscanf(val, "%d", ival)) {
142 int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
147 val = xenstore_read_str(base, node);
148 if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
155 void xenstore_update(void *unused)
158 intptr_t type, ops, ptr;
159 unsigned int dom, count;
161 vec = xs_read_watch(xenstore, &count);
166 if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
167 &type, &dom, &ops) == 3) {
168 xenstore_update_be(vec[XS_WATCH_PATH], (void *)type, dom, (void*)ops);
170 if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
171 xenstore_update_fe(vec[XS_WATCH_PATH], (void *)ptr);
178 const char *xenbus_strstate(enum xenbus_state state)
180 static const char *const name[] = {
181 [XenbusStateUnknown] = "Unknown",
182 [XenbusStateInitialising] = "Initialising",
183 [XenbusStateInitWait] = "InitWait",
184 [XenbusStateInitialised] = "Initialised",
185 [XenbusStateConnected] = "Connected",
186 [XenbusStateClosing] = "Closing",
187 [XenbusStateClosed] = "Closed",
189 return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
194 * 0 == errors (stderr + logfile).
195 * 1 == informative debug messages (logfile only).
196 * 2 == noisy debug messages (logfile only).
197 * 3 == will flood your log (logfile only).
199 void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level,
200 const char *fmt, ...)
205 if (msg_level > xendev->debug) {
208 qemu_log("xen be: %s: ", xendev->name);
209 if (msg_level == 0) {
210 fprintf(stderr, "xen be: %s: ", xendev->name);
213 if (msg_level > debug) {
216 qemu_log("xen be core: ");
217 if (msg_level == 0) {
218 fprintf(stderr, "xen be core: ");
222 qemu_log_vprintf(fmt, args);
224 if (msg_level == 0) {
226 vfprintf(stderr, fmt, args);
232 void xen_pv_evtchn_event(void *opaque)
234 struct XenLegacyDevice *xendev = opaque;
237 port = xenevtchn_pending(xendev->evtchndev);
238 if (port != xendev->local_port) {
239 xen_pv_printf(xendev, 0,
240 "xenevtchn_pending returned %d (expected %d)\n",
241 port, xendev->local_port);
244 xenevtchn_unmask(xendev->evtchndev, port);
246 if (xendev->ops->event) {
247 xendev->ops->event(xendev);
251 void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev)
253 if (xendev->local_port == -1) {
256 qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
257 xenevtchn_unbind(xendev->evtchndev, xendev->local_port);
258 xen_pv_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
259 xendev->local_port = -1;
262 int xen_pv_send_notify(struct XenLegacyDevice *xendev)
264 return xenevtchn_notify(xendev->evtchndev, xendev->local_port);
267 /* ------------------------------------------------------------- */
269 struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev)
271 struct XenLegacyDevice *xendev;
273 QTAILQ_FOREACH(xendev, &xendevs, next) {
274 if (xendev->dom != dom) {
277 if (xendev->dev != dev) {
280 if (strcmp(xendev->type, type) != 0) {
289 * release xen backend device.
291 void xen_pv_del_xendev(struct XenLegacyDevice *xendev)
293 if (xendev->ops->free) {
294 xendev->ops->free(xendev);
298 char token[XEN_BUFSIZE];
299 snprintf(token, sizeof(token), "fe:%p", xendev);
300 xs_unwatch(xenstore, xendev->fe, token);
304 if (xendev->evtchndev != NULL) {
305 xenevtchn_close(xendev->evtchndev);
307 if (xendev->gnttabdev != NULL) {
308 xengnttab_close(xendev->gnttabdev);
311 QTAILQ_REMOVE(&xendevs, xendev, next);
313 qdev_unplug(&xendev->qdev, NULL);
316 void xen_pv_insert_xendev(struct XenLegacyDevice *xendev)
318 QTAILQ_INSERT_TAIL(&xendevs, xendev, next);