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 = {
>
next prev parent 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).