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"
22 #include "hw/qdev-core.h"
23 #include "hw/xen/xen-legacy-backend.h"
24 #include "hw/xen/xen_pvdev.h"
31 QTAILQ_ENTRY(xs_dirs
) list
;
34 static QTAILQ_HEAD(, xs_dirs
) xs_cleanup
=
35 QTAILQ_HEAD_INITIALIZER(xs_cleanup
);
37 static QTAILQ_HEAD(, XenLegacyDevice
) xendevs
=
38 QTAILQ_HEAD_INITIALIZER(xendevs
);
40 /* ------------------------------------------------------------- */
42 static void xenstore_cleanup_dir(char *dir
)
46 d
= g_malloc(sizeof(*d
));
48 QTAILQ_INSERT_TAIL(&xs_cleanup
, d
, list
);
51 void xen_config_cleanup(void)
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 */
71 if (!xs_mkdir(xenstore
, 0, path
)) {
72 xen_pv_printf(NULL
, 0, "xs_mkdir %s: failed\n", path
);
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
);
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
))) {
95 char *xenstore_read_str(const char *base
, const char *node
)
97 char abspath
[XEN_BUFSIZE
];
99 char *str
, *ret
= NULL
;
101 snprintf(abspath
, sizeof(abspath
), "%s/%s", base
, node
);
102 str
= xs_read(xenstore
, 0, abspath
, &len
);
104 /* move to qemu-allocated memory to make sure
105 * callers can savely g_free() stuff. */
112 int xenstore_write_int(const char *base
, const char *node
, int ival
)
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
)
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
)
133 val
= xenstore_read_str(base
, node
);
134 if (val
&& 1 == sscanf(val
, "%d", ival
)) {
141 int xenstore_read_uint64(const char *base
, const char *node
, uint64_t *uval
)
146 val
= xenstore_read_str(base
, node
);
147 if (val
&& 1 == sscanf(val
, "%"SCNu64
, uval
)) {
154 void xenstore_update(void *unused
)
157 intptr_t type
, ops
, ptr
;
158 unsigned int dom
, count
;
160 vec
= xs_read_watch(xenstore
, &count
);
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
);
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";
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 XenLegacyDevice
*xendev
, int msg_level
,
199 const char *fmt
, ...)
204 if (msg_level
> xendev
->debug
) {
207 qemu_log("xen be: %s: ", xendev
->name
);
208 if (msg_level
== 0) {
209 fprintf(stderr
, "xen be: %s: ", xendev
->name
);
212 if (msg_level
> debug
) {
215 qemu_log("xen be core: ");
216 if (msg_level
== 0) {
217 fprintf(stderr
, "xen be core: ");
221 qemu_log_vprintf(fmt
, args
);
223 if (msg_level
== 0) {
225 vfprintf(stderr
, fmt
, args
);
231 void xen_pv_evtchn_event(void *opaque
)
233 struct XenLegacyDevice
*xendev
= opaque
;
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
);
243 xenevtchn_unmask(xendev
->evtchndev
, port
);
245 if (xendev
->ops
->event
) {
246 xendev
->ops
->event(xendev
);
250 void xen_pv_unbind_evtchn(struct XenLegacyDevice
*xendev
)
252 if (xendev
->local_port
== -1) {
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 XenLegacyDevice
*xendev
)
263 return xenevtchn_notify(xendev
->evtchndev
, xendev
->local_port
);
266 /* ------------------------------------------------------------- */
268 struct XenLegacyDevice
*xen_pv_find_xendev(const char *type
, int dom
, int dev
)
270 struct XenLegacyDevice
*xendev
;
272 QTAILQ_FOREACH(xendev
, &xendevs
, next
) {
273 if (xendev
->dom
!= dom
) {
276 if (xendev
->dev
!= dev
) {
279 if (strcmp(xendev
->type
, type
) != 0) {
288 * release xen backend device.
290 void xen_pv_del_xendev(struct XenLegacyDevice
*xendev
)
292 if (xendev
->ops
->free
) {
293 xendev
->ops
->free(xendev
);
297 char token
[XEN_BUFSIZE
];
298 snprintf(token
, sizeof(token
), "fe:%p", xendev
);
299 xs_unwatch(xenstore
, xendev
->fe
, token
);
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 XenLegacyDevice
*xendev
)
317 QTAILQ_INSERT_TAIL(&xendevs
, xendev
, next
);