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/xen/xen_backend.h"
23 #include "hw/xen/xen_pvdev.h"
30 QTAILQ_ENTRY(xs_dirs
) list
;
33 static QTAILQ_HEAD(xs_dirs_head
, xs_dirs
) xs_cleanup
=
34 QTAILQ_HEAD_INITIALIZER(xs_cleanup
);
36 static QTAILQ_HEAD(XenDeviceHead
, XenDevice
) xendevs
=
37 QTAILQ_HEAD_INITIALIZER(xendevs
);
39 /* ------------------------------------------------------------- */
41 static void xenstore_cleanup_dir(char *dir
)
45 d
= g_malloc(sizeof(*d
));
47 QTAILQ_INSERT_TAIL(&xs_cleanup
, d
, list
);
50 void xen_config_cleanup(void)
54 QTAILQ_FOREACH(d
, &xs_cleanup
, list
) {
55 xs_rm(xenstore
, 0, d
->xs_dir
);
59 int xenstore_mkdir(char *path
, int p
)
61 struct xs_permissions perms
[2] = {
63 .id
= 0, /* set owner: dom0 */
70 if (!xs_mkdir(xenstore
, 0, path
)) {
71 xen_pv_printf(NULL
, 0, "xs_mkdir %s: failed\n", path
);
74 xenstore_cleanup_dir(g_strdup(path
));
76 if (!xs_set_permissions(xenstore
, 0, path
, perms
, 2)) {
77 xen_pv_printf(NULL
, 0, "xs_set_permissions %s: failed\n", path
);
83 int xenstore_write_str(const char *base
, const char *node
, const char *val
)
85 char abspath
[XEN_BUFSIZE
];
87 snprintf(abspath
, sizeof(abspath
), "%s/%s", base
, node
);
88 if (!xs_write(xenstore
, 0, abspath
, val
, strlen(val
))) {
94 char *xenstore_read_str(const char *base
, const char *node
)
96 char abspath
[XEN_BUFSIZE
];
98 char *str
, *ret
= NULL
;
100 snprintf(abspath
, sizeof(abspath
), "%s/%s", base
, node
);
101 str
= xs_read(xenstore
, 0, abspath
, &len
);
103 /* move to qemu-allocated memory to make sure
104 * callers can savely g_free() stuff. */
111 int xenstore_write_int(const char *base
, const char *node
, int ival
)
115 snprintf(val
, sizeof(val
), "%d", ival
);
116 return xenstore_write_str(base
, node
, val
);
119 int xenstore_write_int64(const char *base
, const char *node
, int64_t ival
)
123 snprintf(val
, sizeof(val
), "%"PRId64
, ival
);
124 return xenstore_write_str(base
, node
, val
);
127 int xenstore_read_int(const char *base
, const char *node
, int *ival
)
132 val
= xenstore_read_str(base
, node
);
133 if (val
&& 1 == sscanf(val
, "%d", ival
)) {
140 int xenstore_read_uint64(const char *base
, const char *node
, uint64_t *uval
)
145 val
= xenstore_read_str(base
, node
);
146 if (val
&& 1 == sscanf(val
, "%"SCNu64
, uval
)) {
153 void xenstore_update(void *unused
)
156 intptr_t type
, ops
, ptr
;
157 unsigned int dom
, count
;
159 vec
= xs_read_watch(xenstore
, &count
);
164 if (sscanf(vec
[XS_WATCH_TOKEN
], "be:%" PRIxPTR
":%d:%" PRIxPTR
,
165 &type
, &dom
, &ops
) == 3) {
166 xenstore_update_be(vec
[XS_WATCH_PATH
], (void *)type
, dom
, (void*)ops
);
168 if (sscanf(vec
[XS_WATCH_TOKEN
], "fe:%" PRIxPTR
, &ptr
) == 1) {
169 xenstore_update_fe(vec
[XS_WATCH_PATH
], (void *)ptr
);
176 const char *xenbus_strstate(enum xenbus_state state
)
178 static const char *const name
[] = {
179 [XenbusStateUnknown
] = "Unknown",
180 [XenbusStateInitialising
] = "Initialising",
181 [XenbusStateInitWait
] = "InitWait",
182 [XenbusStateInitialised
] = "Initialised",
183 [XenbusStateConnected
] = "Connected",
184 [XenbusStateClosing
] = "Closing",
185 [XenbusStateClosed
] = "Closed",
187 return (state
< ARRAY_SIZE(name
)) ? name
[state
] : "INVALID";
192 * 0 == errors (stderr + logfile).
193 * 1 == informative debug messages (logfile only).
194 * 2 == noisy debug messages (logfile only).
195 * 3 == will flood your log (logfile only).
197 void xen_pv_printf(struct XenDevice
*xendev
, int msg_level
,
198 const char *fmt
, ...)
203 if (msg_level
> xendev
->debug
) {
206 qemu_log("xen be: %s: ", xendev
->name
);
207 if (msg_level
== 0) {
208 fprintf(stderr
, "xen be: %s: ", xendev
->name
);
211 if (msg_level
> debug
) {
214 qemu_log("xen be core: ");
215 if (msg_level
== 0) {
216 fprintf(stderr
, "xen be core: ");
220 qemu_log_vprintf(fmt
, args
);
222 if (msg_level
== 0) {
224 vfprintf(stderr
, fmt
, args
);
230 void xen_be_evtchn_event(void *opaque
)
232 struct XenDevice
*xendev
= opaque
;
235 port
= xenevtchn_pending(xendev
->evtchndev
);
236 if (port
!= xendev
->local_port
) {
237 xen_pv_printf(xendev
, 0,
238 "xenevtchn_pending returned %d (expected %d)\n",
239 port
, xendev
->local_port
);
242 xenevtchn_unmask(xendev
->evtchndev
, port
);
244 if (xendev
->ops
->event
) {
245 xendev
->ops
->event(xendev
);
249 void xen_pv_unbind_evtchn(struct XenDevice
*xendev
)
251 if (xendev
->local_port
== -1) {
254 qemu_set_fd_handler(xenevtchn_fd(xendev
->evtchndev
), NULL
, NULL
, NULL
);
255 xenevtchn_unbind(xendev
->evtchndev
, xendev
->local_port
);
256 xen_pv_printf(xendev
, 2, "unbind evtchn port %d\n", xendev
->local_port
);
257 xendev
->local_port
= -1;
260 int xen_pv_send_notify(struct XenDevice
*xendev
)
262 return xenevtchn_notify(xendev
->evtchndev
, xendev
->local_port
);
265 /* ------------------------------------------------------------- */
267 struct XenDevice
*xen_be_find_xendev(const char *type
, int dom
, int dev
)
269 struct XenDevice
*xendev
;
271 QTAILQ_FOREACH(xendev
, &xendevs
, next
) {
272 if (xendev
->dom
!= dom
) {
275 if (xendev
->dev
!= dev
) {
278 if (strcmp(xendev
->type
, type
) != 0) {
287 * release xen backend device.
289 void xen_be_del_xendev(struct XenDevice
*xendev
)
291 if (xendev
->ops
->free
) {
292 xendev
->ops
->free(xendev
);
296 char token
[XEN_BUFSIZE
];
297 snprintf(token
, sizeof(token
), "fe:%p", xendev
);
298 xs_unwatch(xenstore
, xendev
->fe
, token
);
302 if (xendev
->evtchndev
!= NULL
) {
303 xenevtchn_close(xendev
->evtchndev
);
305 if (xendev
->gnttabdev
!= NULL
) {
306 xengnttab_close(xendev
->gnttabdev
);
309 QTAILQ_REMOVE(&xendevs
, xendev
, next
);
313 void xen_pv_insert_xendev(struct XenDevice
*xendev
)
315 QTAILQ_INSERT_TAIL(&xendevs
, xendev
, next
);