*/
#include "qemu/osdep.h"
-
+#include "qemu/log.h"
+#include "hw/qdev-core.h"
#include "hw/xen/xen_backend.h"
#include "hw/xen/xen_pvdev.h"
+/* private */
static int debug;
+
+struct xs_dirs {
+ char *xs_dir;
+ QTAILQ_ENTRY(xs_dirs) list;
+};
+
+static QTAILQ_HEAD(xs_dirs_head, xs_dirs) xs_cleanup =
+ QTAILQ_HEAD_INITIALIZER(xs_cleanup);
+
+static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs =
+ QTAILQ_HEAD_INITIALIZER(xendevs);
+
/* ------------------------------------------------------------- */
+static void xenstore_cleanup_dir(char *dir)
+{
+ struct xs_dirs *d;
+
+ d = g_malloc(sizeof(*d));
+ d->xs_dir = dir;
+ QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
+}
+
+void xen_config_cleanup(void)
+{
+ struct xs_dirs *d;
+
+ QTAILQ_FOREACH(d, &xs_cleanup, list) {
+ xs_rm(xenstore, 0, d->xs_dir);
+ }
+}
+
+int xenstore_mkdir(char *path, int p)
+{
+ struct xs_permissions perms[2] = {
+ {
+ .id = 0, /* set owner: dom0 */
+ }, {
+ .id = xen_domid,
+ .perms = p,
+ }
+ };
+
+ if (!xs_mkdir(xenstore, 0, path)) {
+ xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
+ return -1;
+ }
+ xenstore_cleanup_dir(g_strdup(path));
+
+ if (!xs_set_permissions(xenstore, 0, path, perms, 2)) {
+ xen_pv_printf(NULL, 0, "xs_set_permissions %s: failed\n", path);
+ return -1;
+ }
+ return 0;
+}
+
int xenstore_write_str(const char *base, const char *node, const char *val)
{
char abspath[XEN_BUFSIZE];
* 2 == noisy debug messages (logfile only).
* 3 == will flood your log (logfile only).
*/
-void xen_be_printf(struct XenDevice *xendev, int msg_level,
+void xen_pv_printf(struct XenDevice *xendev, int msg_level,
const char *fmt, ...)
{
va_list args;
qemu_log_flush();
}
-void xen_be_evtchn_event(void *opaque)
+void xen_pv_evtchn_event(void *opaque)
{
struct XenDevice *xendev = opaque;
evtchn_port_t port;
port = xenevtchn_pending(xendev->evtchndev);
if (port != xendev->local_port) {
- xen_be_printf(xendev, 0,
+ xen_pv_printf(xendev, 0,
"xenevtchn_pending returned %d (expected %d)\n",
port, xendev->local_port);
return;
}
}
-void xen_be_unbind_evtchn(struct XenDevice *xendev)
+void xen_pv_unbind_evtchn(struct XenDevice *xendev)
{
if (xendev->local_port == -1) {
return;
}
qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
xenevtchn_unbind(xendev->evtchndev, xendev->local_port);
- xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
+ xen_pv_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
xendev->local_port = -1;
}
-int xen_be_send_notify(struct XenDevice *xendev)
+int xen_pv_send_notify(struct XenDevice *xendev)
{
return xenevtchn_notify(xendev->evtchndev, xendev->local_port);
}
+
+/* ------------------------------------------------------------- */
+
+struct XenDevice *xen_pv_find_xendev(const char *type, int dom, int dev)
+{
+ struct XenDevice *xendev;
+
+ QTAILQ_FOREACH(xendev, &xendevs, next) {
+ if (xendev->dom != dom) {
+ continue;
+ }
+ if (xendev->dev != dev) {
+ continue;
+ }
+ if (strcmp(xendev->type, type) != 0) {
+ continue;
+ }
+ return xendev;
+ }
+ return NULL;
+}
+
+/*
+ * release xen backend device.
+ */
+void xen_pv_del_xendev(struct XenDevice *xendev)
+{
+ if (xendev->ops->free) {
+ xendev->ops->free(xendev);
+ }
+
+ if (xendev->fe) {
+ char token[XEN_BUFSIZE];
+ snprintf(token, sizeof(token), "fe:%p", xendev);
+ xs_unwatch(xenstore, xendev->fe, token);
+ g_free(xendev->fe);
+ }
+
+ if (xendev->evtchndev != NULL) {
+ xenevtchn_close(xendev->evtchndev);
+ }
+ if (xendev->gnttabdev != NULL) {
+ xengnttab_close(xendev->gnttabdev);
+ }
+
+ QTAILQ_REMOVE(&xendevs, xendev, next);
+
+ qdev_unplug(&xendev->qdev, NULL);
+}
+
+void xen_pv_insert_xendev(struct XenDevice *xendev)
+{
+ QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
+}