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.1 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).
200 static void xen_pv_output_msg(struct XenLegacyDevice
*xendev
,
201 FILE *f
, const char *fmt
, va_list args
)
204 fprintf(f
, "xen be: %s: ", xendev
->name
);
206 fprintf(f
, "xen be core: ");
208 vfprintf(f
, fmt
, args
);
211 void xen_pv_printf(struct XenLegacyDevice
*xendev
, int msg_level
,
212 const char *fmt
, ...)
217 if (msg_level
> (xendev
? xendev
->debug
: debug
)) {
221 logfile
= qemu_log_trylock();
224 xen_pv_output_msg(xendev
, logfile
, fmt
, args
);
226 qemu_log_unlock(logfile
);
229 if (msg_level
== 0) {
231 xen_pv_output_msg(xendev
, stderr
, fmt
, args
);
236 void xen_pv_evtchn_event(void *opaque
)
238 struct XenLegacyDevice
*xendev
= opaque
;
241 port
= xenevtchn_pending(xendev
->evtchndev
);
242 if (port
!= xendev
->local_port
) {
243 xen_pv_printf(xendev
, 0,
244 "xenevtchn_pending returned %d (expected %d)\n",
245 port
, xendev
->local_port
);
248 xenevtchn_unmask(xendev
->evtchndev
, port
);
250 if (xendev
->ops
->event
) {
251 xendev
->ops
->event(xendev
);
255 void xen_pv_unbind_evtchn(struct XenLegacyDevice
*xendev
)
257 if (xendev
->local_port
== -1) {
260 qemu_set_fd_handler(xenevtchn_fd(xendev
->evtchndev
), NULL
, NULL
, NULL
);
261 xenevtchn_unbind(xendev
->evtchndev
, xendev
->local_port
);
262 xen_pv_printf(xendev
, 2, "unbind evtchn port %d\n", xendev
->local_port
);
263 xendev
->local_port
= -1;
266 int xen_pv_send_notify(struct XenLegacyDevice
*xendev
)
268 return xenevtchn_notify(xendev
->evtchndev
, xendev
->local_port
);
271 /* ------------------------------------------------------------- */
273 struct XenLegacyDevice
*xen_pv_find_xendev(const char *type
, int dom
, int dev
)
275 struct XenLegacyDevice
*xendev
;
277 QTAILQ_FOREACH(xendev
, &xendevs
, next
) {
278 if (xendev
->dom
!= dom
) {
281 if (xendev
->dev
!= dev
) {
284 if (strcmp(xendev
->type
, type
) != 0) {
293 * release xen backend device.
295 void xen_pv_del_xendev(struct XenLegacyDevice
*xendev
)
297 if (xendev
->ops
->free
) {
298 xendev
->ops
->free(xendev
);
302 char token
[XEN_BUFSIZE
];
303 snprintf(token
, sizeof(token
), "fe:%p", xendev
);
304 xs_unwatch(xenstore
, xendev
->fe
, token
);
308 if (xendev
->evtchndev
!= NULL
) {
309 xenevtchn_close(xendev
->evtchndev
);
311 if (xendev
->gnttabdev
!= NULL
) {
312 xengnttab_close(xendev
->gnttabdev
);
315 QTAILQ_REMOVE(&xendevs
, xendev
, next
);
317 qdev_unplug(&xendev
->qdev
, NULL
);
320 void xen_pv_insert_xendev(struct XenLegacyDevice
*xendev
)
322 QTAILQ_INSERT_TAIL(&xendevs
, xendev
, next
);