qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: qemu-devel@nongnu.org
Cc: xen-devel@lists.xensource.com, Gerd Hoffmann <kraxel@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 2/7] xen: backend driver core
Date: Mon, 28 Jul 2008 09:13:04 -0500	[thread overview]
Message-ID: <488DD3F0.9060007@codemonkey.ws> (raw)
In-Reply-To: <1217251078-6591-3-git-send-email-kraxel@redhat.com>

Gerd Hoffmann wrote:
> This patch adds infrastructure for xen backend drivers living in qemu,
> so drivers don't need to implement common stuff on their own.  It's
> mostly xenbus management stuff: some functions to access xentore,
> setting up xenstore watches, callbacks on device discovery and state
> changes, handle event channel, ...
>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  Makefile.target  |    2 +-
>  hw/list.h        |  169 ++++++++++++++
>  hw/xen-backend.c |  663 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/xen-backend.h |  116 ++++++++++
>  hw/xen-machine.c |    5 +-
>  5 files changed, 953 insertions(+), 2 deletions(-)
>  create mode 100644 hw/list.h
>  create mode 100644 hw/xen-backend.c
>  create mode 100644 hw/xen-backend.h
>
> diff --git a/Makefile.target b/Makefile.target
> index 4f42582..0451048 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -516,7 +516,7 @@ LIBS += $(CONFIG_VNC_TLS_LIBS)
>  endif
>  
>  # xen backend driver support
> -XEN_OBJS := xen-machine.o
> +XEN_OBJS := xen-machine.o xen-backend.o
>  ifeq ($(CONFIG_XEN), yes)
>    OBJS += $(XEN_OBJS)
>    LIBS += $(XEN_LIBS)
> diff --git a/hw/list.h b/hw/list.h
> new file mode 100644
> index 0000000..fa9f790
> --- /dev/null
> +++ b/hw/list.h
>   

There's already a list implementation in audio/sys-queue.h

> diff --git a/hw/xen-backend.c b/hw/xen-backend.c
> new file mode 100644
> index 0000000..4819624
> --- /dev/null
> +++ b/hw/xen-backend.c
> @@ -0,0 +1,663 @@
> +/*
> + *  xen backend driver infrastructure
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; under version 2 of the License.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with this program; if not, write to the Free Software
> + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdarg.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include <inttypes.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/mman.h>
> +#include <sys/signal.h>
> +
> +#include <xs.h>
> +#include <xenctrl.h>
> +#include <xen/grant_table.h>
> +
> +#include "hw.h"
> +#include "qemu-char.h"
> +#include "xen-backend.h"
> +
> +/* ------------------------------------------------------------- */
> +
> +/* public */
> +int xen_xc;
> +struct xs_handle *xenstore = NULL;
> +
> +/* private */
> +static LIST_HEAD(xendevs);
> +static const char *root = "/local/domain/0/backend";
> +static int debug = 0;
> +
> +/* ------------------------------------------------------------- */
>   

I think it would be good to provide some more commenting in this file.  
Just a high level description of XenStore and how all of this stuff fits 
together would be nice.

> +int xenstore_write_str(const char *base, const char *node, const char *val)
> +{
> +    char abspath[BUFSIZE];
> +
> +    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
> +    if (!xs_write(xenstore, 0, abspath, val, strlen(val)))
> +	return -1;
> +    return 0;
> +}
> +
> +char *xenstore_read_str(const char *base, const char *node)
> +{
> +    char abspath[BUFSIZE];
> +    unsigned int len;
> +
> +    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
> +    return xs_read(xenstore, 0, abspath, &len);
> +}
> +
> +int xenstore_write_int(const char *base, const char *node, int ival)
> +{
> +    char val[32];
> +
> +    snprintf(val, sizeof(val), "%d", ival);
> +    return xenstore_write_str(base, node, val);
> +}
> +
> +int xenstore_read_int(const char *base, const char *node, int *ival)
> +{
> +    char *val;
> +    int rc = -1;
> +
> +    val = xenstore_read_str(base, node);
> +    if (val && 1 == sscanf(val, "%d", ival))
> +	rc = 0;
> +    free(val);
> +    return rc;
> +}
> +
> +int xenstore_write_be_str(struct xendev *xendev, const char *node, const char *val)
> +{
> +    return xenstore_write_str(xendev->be, node, val);
> +}
> +
> +int xenstore_write_be_int(struct xendev *xendev, const char *node, int ival)
> +{
> +    return xenstore_write_int(xendev->be, node, ival);
> +}
> +
> +char *xenstore_read_be_str(struct xendev *xendev, const char *node)
> +{
> +    return xenstore_read_str(xendev->be, node);
> +}
> +
> +int xenstore_read_be_int(struct xendev *xendev, const char *node, int *ival)
> +{
> +    return xenstore_read_int(xendev->be, node, ival);
> +}
> +
> +char *xenstore_read_fe_str(struct xendev *xendev, const char *node)
> +{
> +    return xenstore_read_str(xendev->fe, node);
> +}
> +
> +int xenstore_read_fe_int(struct xendev *xendev, const char *node, int *ival)
> +{
> +    return xenstore_read_int(xendev->fe, node, ival);
> +}
> +
> +/* ------------------------------------------------------------- */
> +
> +const char *xenbus_strstate(enum xenbus_state state)
> +{
> +	static const char *const name[] = {
> +		[ XenbusStateUnknown      ] = "Unknown",
> +		[ XenbusStateInitialising ] = "Initialising",
> +		[ XenbusStateInitWait     ] = "InitWait",
> +		[ XenbusStateInitialised  ] = "Initialised",
> +		[ XenbusStateConnected    ] = "Connected",
> +		[ XenbusStateClosing      ] = "Closing",
> +		[ XenbusStateClosed	  ] = "Closed",
> +	};
> +	return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
> +}
> +
> +int xen_be_set_state(struct xendev *xendev, enum xenbus_state state)
> +{
> +    int rc;
> +
> +    rc = xenstore_write_be_int(xendev, "state", state);
> +    if (0 != rc)
>   

It's a nit, but try to avoid the defensive ifs.

> +	return rc;
> +    xen_be_printf(xendev, 1, "backend state: %s -> %s\n",
> +		  xenbus_strstate(xendev->be_state), xenbus_strstate(state));
> +    xendev->be_state = state;
> +    return 0;
> +}
> +
> +/* ------------------------------------------------------------- */
> +
> +struct xendev *xen_be_find_xendev(char *type, int dom, int dev)
> +{
> +    struct xendev *xendev;
> +    struct list_head *item;
> +
> +    list_for_each(item, &xendevs) {
> +	xendev = list_entry(item, struct xendev, next);
> +	if (xendev->dom != dom)
> +	    continue;
> +	if (xendev->dev != dev)
> +	    continue;
> +	if (0 != strcmp(xendev->type, type))
> +	    continue;
> +	return xendev;
> +    }
> +    return NULL;
> +}
> +
> +/*
> + * get xen backend device, allocate a new one if it doesn't exist.
> + */
> +static struct xendev *xen_be_get_xendev(char *type, int dom, int dev,
> +					struct devops *ops)
> +{
> +    struct xendev *xendev;
> +
> +    xendev = xen_be_find_xendev(type, dom, dev);
> +    if (xendev)
> +	return xendev;
> +
> +    /* init new xendev */
> +    xendev = malloc(ops->size);
> +    memset(xendev,0,ops->size);
>   

qemu_mallocz()

> +    xendev->type  = type;
> +    xendev->dom   = dom;
> +    xendev->dev   = dev;
> +    xendev->ops   = ops;
> +    snprintf(xendev->be, sizeof(xendev->be), "%s/%s/%d/%d",
> +	     root, xendev->type, xendev->dom, xendev->dev);
> +    snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
> +	     xendev->type, xendev->dev);
> +
> +    xendev->debug      = debug;
> +    xendev->local_port = -1;
> +
> +    xendev->evtchndev = xc_evtchn_open();
> +    if (xendev->evtchndev < 0) {
> +	fprintf(stderr, "can't open evtchn device\n");
> +	free(xendev);
>   

qemu_free()

Considering all you're doing, the patch looks pretty nice.

Regards,

Anthony Liguori

> +	return NULL;
> +    }
> +    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
> +
> +    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
> +	xendev->gnttabdev = xc_gnttab_open();
> +	if (xendev->gnttabdev < 0) {
> +	    fprintf(stderr, "can't open gnttab device\n");
> +	    xc_evtchn_close(xendev->evtchndev);
> +	    free(xendev);
> +	    return NULL;
> +	}
> +    } else {
> +	xendev->gnttabdev = -1;
> +    }
> +
> +    list_add_tail(&xendev->next, &xendevs);
> +
> +    if (xendev->ops->alloc)
> +	xendev->ops->alloc(xendev);
> +
> +    return xendev;
> +}
> +
> +/*
> + * release xen backend device.
> + */
> +static struct xendev *xen_be_del_xendev(int dom, int dev)
> +{
> +    struct xendev *xendev;
> +    struct list_head *item, *tmp;
> +
> +    list_for_each_safe(item, tmp, &xendevs) {
> +	xendev = list_entry(item, struct xendev, next);
> +	if (xendev->dom != dom)
> +	    continue;
> +	if (xendev->dev != dev && dev != -1)
> +	    continue;
> +
> +	if (xendev->ops->free)
> +	    xendev->ops->free(xendev);
> +
> +	if (xendev->fe) {
> +	    char token[BUFSIZE];
> +	    snprintf(token, sizeof(token), "fe:%p", xendev);
> +	    xs_unwatch(xenstore, xendev->fe, token);
> +	    free(xendev->fe);
> +	}
> +
> +	if (xendev->evtchndev >= 0)
> +	    xc_evtchn_close(xendev->evtchndev);
> +	if (xendev->gnttabdev >= 0)
> +	    xc_gnttab_close(xendev->gnttabdev);
> +
> +	list_del(&xendev->next);
> +	free(xendev);
> +    }
> +    return NULL;
> +}
> +
> +/*
> + * Sync internal data structures on xenstore updates.
> + * Node specifies the changed field.  node = NULL means
> + * update all fields (used for initialization).
> + */
> +static void xen_be_backend_changed(struct xendev *xendev, const char *node)
> +{
> +    if (NULL == node  ||  0 == strcmp(node, "online")) {
> +	if (-1 == xenstore_read_be_int(xendev, "online", &xendev->online))
> +	    xendev->online = 0;
> +    }
> +
> +    if (node) {
> +	xen_be_printf(xendev, 2, "backend update: %s\n", node);
> +	if (xendev->ops->backend_changed)
> +	    xendev->ops->backend_changed(xendev, node);
> +    }
> +}
> +
> +static void xen_be_frontend_changed(struct xendev *xendev, const char *node)
> +{
> +    int fe_state;
> +
> +    if (NULL == node  ||  0 == strcmp(node, "state")) {
> +	if (-1 == xenstore_read_fe_int(xendev, "state", &fe_state))
> +	    fe_state = XenbusStateUnknown;
> +	if (xendev->fe_state != fe_state)
> +	    xen_be_printf(xendev, 1, "frontend state: %s -> %s\n",
> +			  xenbus_strstate(xendev->fe_state),
> +			  xenbus_strstate(fe_state));
> +	xendev->fe_state = fe_state;
> +    }
> +    if (NULL == node  ||  0 == strcmp(node, "protocol")) {
> +	free(xendev->protocol);
> +	xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
> +	if (xendev->protocol)
> +	    xen_be_printf(xendev, 1, "frontend protocol: %s\n", xendev->protocol);
> +    }
> +
> +    if (node) {
> +	xen_be_printf(xendev, 2, "frontend update: %s\n", node);
> +	if (xendev->ops->frontend_changed)
> +	    xendev->ops->frontend_changed(xendev, node);
> +    }
> +}
> +
> +/* ------------------------------------------------------------- */
> +/* Check for possible state transitions and perform them.        */
> +
> +/*
> + * Initial xendev setup.  Read frontend path, register watch for it.
> + * Should succeed once xend finished setting up the backend device.
> + *
> + * Also sets initial state (-> Initializing) when done.  Which
> + * only affects the xendev->be_state variable as xenbus should
> + * already be put into that state by xend.
> + */
> +static int xen_be_try_setup(struct xendev *xendev)
> +{
> +    char token[BUFSIZE];
> +    int be_state;
> +
> +    if (-1 == xenstore_read_be_int(xendev, "state", &be_state)) {
> +	xen_be_printf(xendev, 0, "reading backend state failed\n");
> +	return -1;
> +    }
> +
> +    if (be_state != XenbusStateInitialising) {
> +	xen_be_printf(xendev, 0, "initial backend state is wrong (%s)\n",
> +		      xenbus_strstate(be_state));
> +	return -1;
> +    }
> +
> +    xendev->fe = xenstore_read_be_str(xendev, "frontend");
> +    if (NULL == xendev->fe) {
> +	xen_be_printf(xendev, 0, "reading frontend path failed\n");
> +	return -1;
> +    }
> +
> +    /* setup frontend watch */
> +    snprintf(token, sizeof(token), "fe:%p", xendev);
> +    if (!xs_watch(xenstore, xendev->fe, token)) {
> +	xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
> +		      xendev->fe);
> +	return -1;
> +    }
> +    xen_be_set_state(xendev, XenbusStateInitialising);
> +
> +    xen_be_backend_changed(xendev, NULL);
> +    xen_be_frontend_changed(xendev, NULL);
> +    return 0;
> +}
> +
> +/*
> + * Try initialize xendev.  Prepare everything the backend can do
> + * without synchronizing with the frontend.  Fakes hotplug-status.  No
> + * hotplug involved here because this is about userspace drivers, thus
> + * there are kernel backend devices which could invoke hotplug.
> + *
> + * Goes to InitWait on success.
> + */
> +static int xen_be_try_init(struct xendev *xendev)
> +{
> +    int rc = 0;
> +
> +    if (!xendev->online) {
> +	xen_be_printf(xendev, 1, "not online\n");
> +	return -1;
> +    }
> +
> +    if (xendev->ops->init)
> +	rc = xendev->ops->init(xendev);
> +    if (0 != rc) {
> +	xen_be_printf(xendev, 1, "init() failed\n");
> +	return rc;
> +    }
> +
> +    xenstore_write_be_str(xendev, "hotplug-status", "connected");
> +    xen_be_set_state(xendev, XenbusStateInitWait);
> +    return 0;
> +}
> +
> +/*
> + * Try to connect xendev.  Depends on the frontend being ready
> + * for it (shared ring and evtchn info in xenstore, state being
> + * Initialised or Connected).
> + *
> + * Goes to Connected on success.
> + */
> +static int xen_be_try_connect(struct xendev *xendev)
> +{
> +    int rc = 0;
> +
> +    if (xendev->fe_state != XenbusStateInitialised  &&
> +	xendev->fe_state != XenbusStateConnected) {
> +	if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
> +	    xen_be_printf(xendev, 2, "frontend not ready, ignoring\n");
> +	} else {
> +	    xen_be_printf(xendev, 2, "frontend not ready (yet)\n");
> +	    return -1;
> +	}
> +    }
> +
> +    if (xendev->ops->connect)
> +	rc = xendev->ops->connect(xendev);
> +    if (0 != rc) {
> +	xen_be_printf(xendev, 0, "connect() failed\n");
> +	return rc;
> +    }
> +
> +    xen_be_set_state(xendev, XenbusStateConnected);
> +
> +#if 0
> +    if (xendev->ops->event)
> +	xendev->ops->event(xendev);
> +#endif
> +    return 0;
> +}
> +
> +/*
> + * Teardown connection.
> + *
> + * Goes to Closed when done.
> + */
> +static void xen_be_disconnect(struct xendev *xendev)
> +{
> +    if (xendev->be_state == XenbusStateClosed)
> +	return;
> +    if (xendev->ops->disconnect)
> +	xendev->ops->disconnect(xendev);
> +    xen_be_set_state(xendev, XenbusStateClosed);
> +}
> +
> +/*
> + * state change dispatcher function
> + */
> +void xen_be_check_state(struct xendev *xendev)
> +{
> +    int rc = 0;
> +
> +    /* frontend may request shutdown from almost anywhere */
> +    if (xendev->fe_state == XenbusStateClosing ||
> +	xendev->fe_state == XenbusStateClosed) {
> +	xen_be_disconnect(xendev);
> +	return;
> +    }
> +
> +    /* check for possible backend state transitions */
> +    for (;;) {
> +	switch (xendev->be_state) {
> +	case XenbusStateUnknown:
> +	    rc = xen_be_try_setup(xendev);
> +	    break;
> +	case XenbusStateInitialising:
> +	    rc = xen_be_try_init(xendev);
> +	    break;
> +	case XenbusStateInitWait:
> +	    rc = xen_be_try_connect(xendev);
> +	    break;
> +	default:
> +	    rc = -1;
> +	}
> +	if (0 != rc)
> +	    break;
> +    }
> +}
> +
> +/* ------------------------------------------------------------- */
> +
> +static int xenstore_scan(char *type, int dom, struct devops *ops)
> +{
> +    struct xendev *xendev;
> +    char path[BUFSIZE], token[BUFSIZE];
> +    char **dev = NULL;
> +    unsigned int cdev, j;
> +
> +    /* setup watch */
> +    snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
> +    snprintf(path, sizeof(path), "%s/%s/%d", root, type, dom);
> +    if (!xs_watch(xenstore, path, token)) {
> +	fprintf(stderr, "xen be: watching backend path (%s) failed\n", path);
> +	return -1;
> +    }
> +
> +    /* look for backends */
> +    dev = xs_directory(xenstore, 0, path, &cdev);
> +    if (!dev)
> +	return 0;
> +    for (j = 0; j < cdev; j++) {
> +	xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
> +	if (NULL == xendev)
> +	    continue;
> +	xen_be_check_state(xendev);
> +    }
> +    free(dev);
> +    return 0;
> +}
> +
> +static void xenstore_update_be(char *watch, char *type, int dom,
> +			       struct devops *ops)
> +{
> +    struct xendev *xendev;
> +    char path[BUFSIZE];
> +    unsigned int len, dev;
> +
> +    len = snprintf(path, sizeof(path), "%s/%s/%d", root, type, dom);
> +    if (0 != strncmp(path, watch, len))
> +	return;
> +    if (2 != sscanf(watch+len, "/%u/%255s", &dev, path)) {
> +	strcpy(path, "");
> +	if (1 != sscanf(watch+len, "/%u", &dev))
> +	    dev = -1;
> +    }
> +    if (-1 == dev)
> +	return;
> +
> +    if (0) {
> +	/* FIXME: detect devices being deleted from xenstore ... */
> +	xen_be_del_xendev(dom, dev);
> +    }
> +
> +    xendev = xen_be_get_xendev(type, dom, dev, ops);
> +    if (NULL != xendev) {
> +	xen_be_backend_changed(xendev, path);
> +	xen_be_check_state(xendev);
> +    }
> +}
> +
> +static void xenstore_update_fe(char *watch, struct xendev *xendev)
> +{
> +    char *node;
> +    unsigned int len;
> +
> +    len = strlen(xendev->fe);
> +    if (0 != strncmp(xendev->fe, watch, len))
> +	return;
> +    if (watch[len] != '/')
> +	return;
> +    node = watch + len + 1;
> +
> +    xen_be_frontend_changed(xendev, node);
> +    xen_be_check_state(xendev);
> +}
> +
> +static void xenstore_update(void *unused)
> +{
> +    char **vec = NULL;
> +    intptr_t type, ops, ptr;
> +    unsigned int dom, count;
> +
> +    vec = xs_read_watch(xenstore, &count);
> +    if (NULL == vec)
> +	goto cleanup;
> +
> +    if (3 == sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
> +		    &type, &dom, &ops))
> +	xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
> +    if (1 == sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr))
> +	xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
> +
> +cleanup:
> +    free(vec);
> +}
> +
> +static void xen_be_evtchn_event(void *opaque)
> +{
> +    struct xendev *xendev = opaque;
> +    evtchn_port_t port;
> +
> +    port = xc_evtchn_pending(xendev->evtchndev);
> +    if (port != xendev->local_port) {
> +	xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
> +		      port, xendev->local_port);
> +	return;
> +    }
> +    xc_evtchn_unmask(xendev->evtchndev, port);
> +
> +    if (xendev->ops->event)
> +	xendev->ops->event(xendev);
> +}
> +
> +/* -------------------------------------------------------------------- */
> +
> +int xen_be_init(void)
> +{
> +    xenstore = xs_daemon_open();
> +    if (!xenstore) {
> +	fprintf(stderr, "can't connect to xenstored\n");
> +	return -1;
> +    }
> +
> +    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0)
> +	goto err;
> +
> +    xen_xc = xc_interface_open();
> +    if (-1 == xen_xc) {
> +	fprintf(stderr, "can't open xen interface\n");
> +	goto err;
> +    }
> +    return 0;
> +
> +err:
> +    qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
> +    xs_daemon_close(xenstore);
> +    xenstore = NULL;
> +    
> +    return -1;
> +}
> +
> +int xen_be_register(char *type, struct devops *ops)
> +{
> +    return xenstore_scan(type, xen_domid, ops);
> +}
> +
> +int xen_be_bind_evtchn(struct xendev *xendev)
> +{
> +    if (xendev->local_port != -1)
> +	return 0;
> +    xendev->local_port = xc_evtchn_bind_interdomain
> +	(xendev->evtchndev, xendev->dom, xendev->remote_port);
> +    if (-1 == xendev->local_port) {
> +	xendev->local_port = 0;
> +	return -1;
> +    }
> +    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
> +			xen_be_evtchn_event, NULL, xendev);
> +#if 0
> +    xc_evtchn_unmask(xendev->evtchndev, xendev->local_port);
> +#endif
> +    return 0;
> +}
> +
> +void xen_be_unbind_evtchn(struct xendev *xendev)
> +{
> +    if (xendev->local_port == -1)
> +	return;
> +    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
> +    xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
> +    xendev->local_port = -1;
> +}
> +
> +int xen_be_send_notify(struct xendev *xendev)
> +{
> +    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
> +}
> +
> +/*
> + * msg_level:
> + *  0 == errors.
> + *  1 == informative debug messages.
> + *  2 == noisy debug messages.
> + *  3 == will flood your log.
> + */
> +void xen_be_printf(struct xendev *xendev, int msg_level, const char *fmt, ...)
> +{
> +    va_list args;
> +
> +    if (msg_level > xendev->debug)
> +	return;
> +    fprintf(stderr, "xen be: %s: ", xendev->name);
> +    va_start(args, fmt);
> +    vfprintf(stderr, fmt, args);
> +    va_end(args);
> +}
> diff --git a/hw/xen-backend.h b/hw/xen-backend.h
> new file mode 100644
> index 0000000..db36ae7
> --- /dev/null
> +++ b/hw/xen-backend.h
> @@ -0,0 +1,116 @@
> +#include <stddef.h>
> +#include <xs.h>
> +#include <xenctrl.h>
> +#include <xen/elfnote.h>
> +#include <xen/elfstructs.h>
> +
> +#include <xen/io/xenbus.h>
> +
> +#include "list.h"
> +
> +#include "hw.h"
> +#include "xen.h"
> +
> +/*
> + * tweaks needed to build with different xen versions
> + *  0x00030205 -> 3.1.0
> + *  0x00030207 -> 3.2.0
> + *  0x00030208 -> unstable
> + */
> +#include <xen/xen-compat.h>
> +#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00030207
> +# define xc_map_foreign_pages xc_map_foreign_batch
> +#endif
> +#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00030208
> +# define xen_mb()  mb()
> +# define xen_rmb() rmb()
> +# define xen_wmb() wmb()
> +#endif
> +
> +/* ------------------------------------------------------------- */
> +
> +#define container_of(ptr, type, member) ({                      \
> +        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
> +        (type *)( (char *)__mptr - offsetof(type,member) );})
> +
> +/* ------------------------------------------------------------- */
> +
> +#define BUFSIZE 1024
> +
> +struct xendev;
> +
> +/* driver uses grant tables  ->  open gntdev device (xendev->gnttabdev) */
> +#define DEVOPS_FLAG_NEED_GNTDEV   1
> +/* don't expect frontend doing correct state transitions (aka console quirk) */
> +#define DEVOPS_FLAG_IGNORE_STATE  2  
> +
> +struct devops {
> +    size_t    size;
> +    uint32_t  flags;
> +    void      (*alloc)(struct xendev *xendev);
> +    int       (*init)(struct xendev *xendev);
> +    int       (*connect)(struct xendev *xendev);
> +    void      (*event)(struct xendev *xendev);
> +    void      (*disconnect)(struct xendev *xendev);
> +    int       (*free)(struct xendev *xendev);
> +    void      (*backend_changed)(struct xendev *xendev, const char *node);
> +    void      (*frontend_changed)(struct xendev *xendev, const char *node);
> +};
> +
> +struct xendev {
> +    char               *type;
> +    int                dom;
> +    int                dev;
> +    char               name[64];
> +    int                debug;
> +
> +    enum xenbus_state  be_state;
> +    enum xenbus_state  fe_state;
> +    int                online;
> +    char               be[BUFSIZE];
> +    char               *fe;
> +    char               *protocol;
> +    int                remote_port;
> +    int                local_port;
> +
> +    int                evtchndev;
> +    int                gnttabdev;
> +
> +    struct devops      *ops;
> +    struct list_head   next;
> +};
> +
> +/* ------------------------------------------------------------- */
> +
> +/* variables */
> +extern int xen_domid; /* set by cmd line option, in vl.c */
> +extern int xen_xc;
> +extern struct xs_handle *xenstore;
> +
> +/* xenstore helper functions */
> +int xenstore_write_str(const char *base, const char *node, const char *val);
> +int xenstore_write_int(const char *base, const char *node, int ival);
> +char *xenstore_read_str(const char *base, const char *node);
> +int xenstore_read_int(const char *base, const char *node, int *ival);
> +
> +int xenstore_write_be_str(struct xendev *xendev, const char *node, const char *val);
> +int xenstore_write_be_int(struct xendev *xendev, const char *node, int ival);
> +char *xenstore_read_be_str(struct xendev *xendev, const char *node);
> +int xenstore_read_be_int(struct xendev *xendev, const char *node, int *ival);
> +char *xenstore_read_fe_str(struct xendev *xendev, const char *node);
> +int xenstore_read_fe_int(struct xendev *xendev, const char *node, int *ival);
> +
> +const char *xenbus_strstate(enum xenbus_state state);
> +struct xendev *xen_be_find_xendev(char *type, int dom, int dev);
> +void xen_be_check_state(struct xendev *xendev);
> +
> +/* xen backend driver bits */
> +int xen_be_init(void);
> +int xen_be_register(char *type, struct devops *ops);
> +int xen_be_set_state(struct xendev *xendev, enum xenbus_state state);
> +int xen_be_bind_evtchn(struct xendev *xendev);
> +void xen_be_unbind_evtchn(struct xendev *xendev);
> +int xen_be_send_notify(struct xendev *xendev);
> +void xen_be_printf(struct xendev *xendev, int msg_level, const char *fmt, ...)
> +    __attribute__ ((format(printf, 3, 4)));
> +
> diff --git a/hw/xen-machine.c b/hw/xen-machine.c
> index 88f0f6e..798c0a7 100644
> --- a/hw/xen-machine.c
> +++ b/hw/xen-machine.c
> @@ -25,7 +25,7 @@
>  #include "hw.h"
>  #include "boards.h"
>  
> -#include "xen.h"
> +#include "xen-backend.h"
>  
>  /* -------------------------------------------------------------------- */
>  /* variables                                                            */
> @@ -54,6 +54,9 @@ static void xenpv_init(ram_addr_t ram_size, int vga_ram_size,
>      }
>      env = cpu_init(cpu_model);
>      env->halted = 1;
> +
> +    /* setup xen backend handlers */
> +    xen_be_init();
>  }
>  
>  QEMUMachine xenpv_machine = {
>   

  reply	other threads:[~2008-07-28 14:13 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-28 13:17 [Qemu-devel] [PATCH 0/7] merge some xen bits into qemu Gerd Hoffmann
2008-07-28 13:17 ` [Qemu-devel] [PATCH 1/7] xen: groundwork for xen support Gerd Hoffmann
2008-07-28 14:04   ` Anthony Liguori
2008-07-28 14:52     ` Gerd Hoffmann
2008-07-29  8:10       ` [Xen-devel] " Daniel P. Berrange
2008-07-29 13:32         ` Anthony Liguori
2008-07-29 14:24           ` Daniel P. Berrange
2008-07-29 19:11             ` Anthony Liguori
2008-07-29 21:36               ` Gerd Hoffmann
2008-07-29 21:48                 ` Anthony Liguori
2008-07-29 14:32           ` Gerd Hoffmann
2008-07-28 23:14     ` Samuel Thibault
2008-07-29  7:38       ` Gerd Hoffmann
2008-07-29  8:12         ` Daniel P. Berrange
2008-07-29  8:55           ` Gerd Hoffmann
2008-07-28 13:17 ` [Qemu-devel] [PATCH 2/7] xen: backend driver core Gerd Hoffmann
2008-07-28 14:13   ` Anthony Liguori [this message]
2008-07-28 15:51     ` Gerd Hoffmann
2008-07-28 13:17 ` [Qemu-devel] [PATCH 3/7] xen: add console backend driver Gerd Hoffmann
2008-07-28 14:17   ` Anthony Liguori
2008-07-28 15:43     ` Gerd Hoffmann
2008-07-28 19:04       ` Anthony Liguori
2008-07-28 13:17 ` [Qemu-devel] [PATCH 4/7] xen: add framebuffer " Gerd Hoffmann
2008-07-28 14:22   ` Anthony Liguori
2008-07-28 14:41     ` Andreas Färber
2008-07-30  9:59       ` Gerd Hoffmann
2008-08-01 14:57         ` Anthony Liguori
2008-07-30  9:20     ` Gerd Hoffmann
2008-07-30 16:31       ` Markus Armbruster
2008-08-01 15:05         ` Anthony Liguori
2008-07-28 13:17 ` [Qemu-devel] [PATCH 5/7] xen: add block device " Gerd Hoffmann
2008-07-28 14:25   ` Anthony Liguori
2008-07-28 13:17 ` [Qemu-devel] [PATCH 6/7] xen: add net " Gerd Hoffmann
2008-07-28 14:27   ` Anthony Liguori
2008-07-28 15:45     ` Gerd Hoffmann
2008-07-28 13:17 ` [Qemu-devel] [PATCH 7/7] xen: blk & nic configuration via cmd line Gerd Hoffmann
  -- strict thread matches above, loose matches on Subject: below --
2008-08-04 15:50 [Qemu-devel] [PATCH 0/7] merge some xen bits into qemu Gerd Hoffmann
2008-08-04 15:50 ` [Qemu-devel] [PATCH 2/7] xen: backend driver core Gerd Hoffmann
2008-10-28 12:23 [Qemu-devel] [PATCH 0/7] merge some xen bits into qemu Gerd Hoffmann
2008-10-28 12:23 ` [Qemu-devel] [PATCH 2/7] xen: backend driver core Gerd Hoffmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=488DD3F0.9060007@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).