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).
199 static void xen_pv_output_msg(struct XenLegacyDevice
*xendev
,
200 FILE *f
, const char *fmt
, va_list args
)
203 fprintf(f
, "xen be: %s: ", xendev
->name
);
205 fprintf(f
, "xen be core: ");
207 vfprintf(f
, fmt
, args
);
210 void xen_pv_printf(struct XenLegacyDevice
*xendev
, int msg_level
,
211 const char *fmt
, ...)
216 if (msg_level
> (xendev
? xendev
->debug
: debug
)) {
220 logfile
= qemu_log_trylock();
223 xen_pv_output_msg(xendev
, logfile
, fmt
, args
);
225 qemu_log_unlock(logfile
);
228 if (msg_level
== 0) {
230 xen_pv_output_msg(xendev
, stderr
, fmt
, args
);
235 void xen_pv_evtchn_event(void *opaque
)
237 struct XenLegacyDevice
*xendev
= opaque
;
240 port
= xenevtchn_pending(xendev
->evtchndev
);
241 if (port
!= xendev
->local_port
) {
242 xen_pv_printf(xendev
, 0,
243 "xenevtchn_pending returned %d (expected %d)\n",
244 port
, xendev
->local_port
);
247 xenevtchn_unmask(xendev
->evtchndev
, port
);
249 if (xendev
->ops
->event
) {
250 xendev
->ops
->event(xendev
);
254 void xen_pv_unbind_evtchn(struct XenLegacyDevice
*xendev
)
256 if (xendev
->local_port
== -1) {
259 qemu_set_fd_handler(xenevtchn_fd(xendev
->evtchndev
), NULL
, NULL
, NULL
);
260 xenevtchn_unbind(xendev
->evtchndev
, xendev
->local_port
);
261 xen_pv_printf(xendev
, 2, "unbind evtchn port %d\n", xendev
->local_port
);
262 xendev
->local_port
= -1;
265 int xen_pv_send_notify(struct XenLegacyDevice
*xendev
)
267 return xenevtchn_notify(xendev
->evtchndev
, xendev
->local_port
);
270 /* ------------------------------------------------------------- */
272 struct XenLegacyDevice
*xen_pv_find_xendev(const char *type
, int dom
, int dev
)
274 struct XenLegacyDevice
*xendev
;
276 QTAILQ_FOREACH(xendev
, &xendevs
, next
) {
277 if (xendev
->dom
!= dom
) {
280 if (xendev
->dev
!= dev
) {
283 if (strcmp(xendev
->type
, type
) != 0) {
292 * release xen backend device.
294 void xen_pv_del_xendev(struct XenLegacyDevice
*xendev
)
296 if (xendev
->ops
->free
) {
297 xendev
->ops
->free(xendev
);
301 char token
[XEN_BUFSIZE
];
302 snprintf(token
, sizeof(token
), "fe:%p", xendev
);
303 xs_unwatch(xenstore
, xendev
->fe
, token
);
307 if (xendev
->evtchndev
!= NULL
) {
308 xenevtchn_close(xendev
->evtchndev
);
310 if (xendev
->gnttabdev
!= NULL
) {
311 xengnttab_close(xendev
->gnttabdev
);
314 QTAILQ_REMOVE(&xendevs
, xendev
, next
);
316 qdev_unplug(&xendev
->qdev
, NULL
);
319 void xen_pv_insert_xendev(struct XenLegacyDevice
*xendev
)
321 QTAILQ_INSERT_TAIL(&xendevs
, xendev
, next
);