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 qemu_xen_xs_destroy(xenstore
, 0, d
->xs_dir
);
61 int xenstore_mkdir(char *path
, int p
)
63 if (!qemu_xen_xs_create(xenstore
, 0, 0, xen_domid
, p
, path
)) {
64 xen_pv_printf(NULL
, 0, "xs_mkdir %s: failed\n", path
);
67 xenstore_cleanup_dir(g_strdup(path
));
71 int xenstore_write_str(const char *base
, const char *node
, const char *val
)
73 char abspath
[XEN_BUFSIZE
];
75 snprintf(abspath
, sizeof(abspath
), "%s/%s", base
, node
);
76 if (!qemu_xen_xs_write(xenstore
, 0, abspath
, val
, strlen(val
))) {
82 char *xenstore_read_str(const char *base
, const char *node
)
84 char abspath
[XEN_BUFSIZE
];
86 char *str
, *ret
= NULL
;
88 snprintf(abspath
, sizeof(abspath
), "%s/%s", base
, node
);
89 str
= qemu_xen_xs_read(xenstore
, 0, abspath
, &len
);
91 /* move to qemu-allocated memory to make sure
92 * callers can safely g_free() stuff. */
99 int xenstore_write_int(const char *base
, const char *node
, int ival
)
103 snprintf(val
, sizeof(val
), "%d", ival
);
104 return xenstore_write_str(base
, node
, val
);
107 int xenstore_write_int64(const char *base
, const char *node
, int64_t ival
)
111 snprintf(val
, sizeof(val
), "%"PRId64
, ival
);
112 return xenstore_write_str(base
, node
, val
);
115 int xenstore_read_int(const char *base
, const char *node
, int *ival
)
120 val
= xenstore_read_str(base
, node
);
121 if (val
&& 1 == sscanf(val
, "%d", ival
)) {
128 int xenstore_read_uint64(const char *base
, const char *node
, uint64_t *uval
)
133 val
= xenstore_read_str(base
, node
);
134 if (val
&& 1 == sscanf(val
, "%"SCNu64
, uval
)) {
141 const char *xenbus_strstate(enum xenbus_state state
)
143 static const char *const name
[] = {
144 [XenbusStateUnknown
] = "Unknown",
145 [XenbusStateInitialising
] = "Initialising",
146 [XenbusStateInitWait
] = "InitWait",
147 [XenbusStateInitialised
] = "Initialised",
148 [XenbusStateConnected
] = "Connected",
149 [XenbusStateClosing
] = "Closing",
150 [XenbusStateClosed
] = "Closed",
152 return (state
< ARRAY_SIZE(name
)) ? name
[state
] : "INVALID";
157 * 0 == errors (stderr + logfile).
158 * 1 == informative debug messages (logfile only).
159 * 2 == noisy debug messages (logfile only).
160 * 3 == will flood your log (logfile only).
163 static void xen_pv_output_msg(struct XenLegacyDevice
*xendev
,
164 FILE *f
, const char *fmt
, va_list args
)
167 fprintf(f
, "xen be: %s: ", xendev
->name
);
169 fprintf(f
, "xen be core: ");
171 vfprintf(f
, fmt
, args
);
174 void xen_pv_printf(struct XenLegacyDevice
*xendev
, int msg_level
,
175 const char *fmt
, ...)
180 if (msg_level
> (xendev
? xendev
->debug
: debug
)) {
184 logfile
= qemu_log_trylock();
187 xen_pv_output_msg(xendev
, logfile
, fmt
, args
);
189 qemu_log_unlock(logfile
);
192 if (msg_level
== 0) {
194 xen_pv_output_msg(xendev
, stderr
, fmt
, args
);
199 void xen_pv_evtchn_event(void *opaque
)
201 struct XenLegacyDevice
*xendev
= opaque
;
204 port
= qemu_xen_evtchn_pending(xendev
->evtchndev
);
205 if (port
!= xendev
->local_port
) {
206 xen_pv_printf(xendev
, 0,
207 "xenevtchn_pending returned %d (expected %d)\n",
208 port
, xendev
->local_port
);
211 qemu_xen_evtchn_unmask(xendev
->evtchndev
, port
);
213 if (xendev
->ops
->event
) {
214 xendev
->ops
->event(xendev
);
218 void xen_pv_unbind_evtchn(struct XenLegacyDevice
*xendev
)
220 if (xendev
->local_port
== -1) {
223 qemu_set_fd_handler(qemu_xen_evtchn_fd(xendev
->evtchndev
), NULL
, NULL
, NULL
);
224 qemu_xen_evtchn_unbind(xendev
->evtchndev
, xendev
->local_port
);
225 xen_pv_printf(xendev
, 2, "unbind evtchn port %d\n", xendev
->local_port
);
226 xendev
->local_port
= -1;
229 int xen_pv_send_notify(struct XenLegacyDevice
*xendev
)
231 return qemu_xen_evtchn_notify(xendev
->evtchndev
, xendev
->local_port
);
234 /* ------------------------------------------------------------- */
236 struct XenLegacyDevice
*xen_pv_find_xendev(const char *type
, int dom
, int dev
)
238 struct XenLegacyDevice
*xendev
;
240 QTAILQ_FOREACH(xendev
, &xendevs
, next
) {
241 if (xendev
->dom
!= dom
) {
244 if (xendev
->dev
!= dev
) {
247 if (strcmp(xendev
->type
, type
) != 0) {
256 * release xen backend device.
258 void xen_pv_del_xendev(struct XenLegacyDevice
*xendev
)
260 if (xendev
->ops
->free
) {
261 xendev
->ops
->free(xendev
);
265 qemu_xen_xs_unwatch(xenstore
, xendev
->watch
);
269 if (xendev
->evtchndev
!= NULL
) {
270 qemu_xen_evtchn_close(xendev
->evtchndev
);
272 if (xendev
->gnttabdev
!= NULL
) {
273 qemu_xen_gnttab_close(xendev
->gnttabdev
);
276 QTAILQ_REMOVE(&xendevs
, xendev
, next
);
278 qdev_unplug(&xendev
->qdev
, NULL
);
281 void xen_pv_insert_xendev(struct XenLegacyDevice
*xendev
)
283 QTAILQ_INSERT_TAIL(&xendevs
, xendev
, next
);