diff mbox

[v8,2/7] Qemu-Xen-vTPM: Create a new file xen_pvdev.c

Message ID 1431840030-2797-4-git-send-email-quan.xu@intel.com
State New
Headers show

Commit Message

Xu, Quan May 17, 2015, 5:20 a.m. UTC
for some common part of xen frontend and backend, such as xendevs
queue and xenstore update functions.

Signed-off-by: Quan Xu <quan.xu@intel.com>
---
 hw/display/xenfb.c           |   4 +-
 hw/xen/Makefile.objs         |   2 +-
 hw/xen/xen_backend.c         | 353 -------------------------------
 hw/xen/xen_pvdev.c           | 481 +++++++++++++++++++++++++++++++++++++++++++
 include/hw/xen/xen_backend.h |  13 +-
 5 files changed, 496 insertions(+), 357 deletions(-)
 create mode 100644 hw/xen/xen_pvdev.c

Comments

Stefano Stabellini June 22, 2015, 4:37 p.m. UTC | #1
On Sun, 17 May 2015, Quan Xu wrote:
> for some common part of xen frontend and backend, such as xendevs
> queue and xenstore update functions.
> 
> Signed-off-by: Quan Xu <quan.xu@intel.com>

Hi Quan,

could you please separate out the code movement from any other changes?
This patch would become two patches: the first would only move code from
xen_backend.c to xen_pvdev.c, no other changes except for the ones
actually required to build the code (Makefile.objs).  The second patch
would rename xen_be_find_xendev to xen_find_xendev and any other changes
to the code that you making here.  That way I can very easily go and
look only at the things you actually modify.

Thanks,

Stefano


>  hw/display/xenfb.c           |   4 +-
>  hw/xen/Makefile.objs         |   2 +-
>  hw/xen/xen_backend.c         | 353 -------------------------------
>  hw/xen/xen_pvdev.c           | 481 +++++++++++++++++++++++++++++++++++++++++++
>  include/hw/xen/xen_backend.h |  13 +-
>  5 files changed, 496 insertions(+), 357 deletions(-)
>  create mode 100644 hw/xen/xen_pvdev.c
> 
> diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
> index 5e324ef..10751df 100644
> --- a/hw/display/xenfb.c
> +++ b/hw/display/xenfb.c
> @@ -988,8 +988,8 @@ void xen_init_display(int domid)
>  wait_more:
>      i++;
>      main_loop_wait(true);
> -    xfb = xen_be_find_xendev("vfb", domid, 0);
> -    xin = xen_be_find_xendev("vkbd", domid, 0);
> +    xfb = xen_find_xendev("vfb", domid, 0);
> +    xin = xen_find_xendev("vkbd", domid, 0);
>      if (!xfb || !xin) {
>          if (i < 256) {
>              usleep(10000);
> diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs
> index a0ca0aa..9ac9f7c 100644
> --- a/hw/xen/Makefile.objs
> +++ b/hw/xen/Makefile.objs
> @@ -1,5 +1,5 @@
>  # xen backend driver support
> -common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
> +common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o xen_pvdev.o
>  
>  obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
>  obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
> diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
> index b2cb22b..844f918 100644
> --- a/hw/xen/xen_backend.c
> +++ b/hw/xen/xen_backend.c
> @@ -44,86 +44,11 @@
>  /* ------------------------------------------------------------- */
>  
>  /* public */
> -XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
> -struct xs_handle *xenstore = NULL;
>  const char *xen_protocol;
>  
>  /* private */
> -static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs = QTAILQ_HEAD_INITIALIZER(xendevs);
>  static int debug = 0;
>  
> -/* ------------------------------------------------------------- */
> -
> -int xenstore_write_str(const char *base, const char *node, const char *val)
> -{
> -    char abspath[XEN_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[XEN_BUFSIZE];
> -    unsigned int len;
> -    char *str, *ret = NULL;
> -
> -    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
> -    str = xs_read(xenstore, 0, abspath, &len);
> -    if (str != NULL) {
> -        /* move to qemu-allocated memory to make sure
> -         * callers can savely g_free() stuff. */
> -        ret = g_strdup(str);
> -        free(str);
> -    }
> -    return ret;
> -}
> -
> -int xenstore_write_int(const char *base, const char *node, int ival)
> -{
> -    char val[12];
> -
> -    snprintf(val, sizeof(val), "%d", ival);
> -    return xenstore_write_str(base, node, val);
> -}
> -
> -int xenstore_write_int64(const char *base, const char *node, int64_t ival)
> -{
> -    char val[21];
> -
> -    snprintf(val, sizeof(val), "%"PRId64, 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;
> -    }
> -    g_free(val);
> -    return rc;
> -}
> -
> -int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
> -{
> -    char *val;
> -    int rc = -1;
> -
> -    val = xenstore_read_str(base, node);
> -    if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
> -        rc = 0;
> -    }
> -    g_free(val);
> -    return rc;
> -}
> -
>  int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val)
>  {
>      return xenstore_write_str(xendev->be, node, val);
> @@ -195,183 +120,6 @@ int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
>  }
>  
>  /* ------------------------------------------------------------- */
> -
> -struct XenDevice *xen_be_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;
> -}
> -
> -/*
> - * get xen backend device, allocate a new one if it doesn't exist.
> - */
> -static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
> -                                           struct XenDevOps *ops)
> -{
> -    struct XenDevice *xendev;
> -
> -    xendev = xen_be_find_xendev(type, dom, dev);
> -    if (xendev) {
> -        return xendev;
> -    }
> -
> -    /* init new xendev */
> -    xendev = g_malloc0(ops->size);
> -    xendev->type  = type;
> -    xendev->dom   = dom;
> -    xendev->dev   = dev;
> -    xendev->ops   = ops;
> -
> -    snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
> -             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 = xen_xc_evtchn_open(NULL, 0);
> -    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
> -        xen_be_printf(NULL, 0, "can't open evtchn device\n");
> -        g_free(xendev);
> -        return NULL;
> -    }
> -    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
> -
> -    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
> -        xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
> -        if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
> -            xen_be_printf(NULL, 0, "can't open gnttab device\n");
> -            xc_evtchn_close(xendev->evtchndev);
> -            g_free(xendev);
> -            return NULL;
> -        }
> -    } else {
> -        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
> -    }
> -
> -    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
> -
> -    if (xendev->ops->alloc) {
> -        xendev->ops->alloc(xendev);
> -    }
> -
> -    return xendev;
> -}
> -
> -/*
> - * release xen backend device.
> - */
> -static struct XenDevice *xen_be_del_xendev(int dom, int dev)
> -{
> -    struct XenDevice *xendev, *xnext;
> -
> -    /*
> -     * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next) but
> -     * we save the next pointer in xnext because we might free xendev.
> -     */
> -    xnext = xendevs.tqh_first;
> -    while (xnext) {
> -        xendev = xnext;
> -        xnext = xendev->next.tqe_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[XEN_BUFSIZE];
> -            snprintf(token, sizeof(token), "fe:%p", xendev);
> -            xs_unwatch(xenstore, xendev->fe, token);
> -            g_free(xendev->fe);
> -        }
> -
> -        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
> -            xc_evtchn_close(xendev->evtchndev);
> -        }
> -        if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
> -            xc_gnttab_close(xendev->gnttabdev);
> -        }
> -
> -        QTAILQ_REMOVE(&xendevs, xendev, next);
> -        g_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 XenDevice *xendev, const char *node)
> -{
> -    if (node == NULL  ||  strcmp(node, "online") == 0) {
> -        if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
> -            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 XenDevice *xendev, const char *node)
> -{
> -    int fe_state;
> -
> -    if (node == NULL  ||  strcmp(node, "state") == 0) {
> -        if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
> -            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 (node == NULL  ||  strcmp(node, "protocol") == 0) {
> -        g_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.        */
>  
>  /*
> @@ -611,81 +359,6 @@ static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
>      return 0;
>  }
>  
> -static void xenstore_update_be(char *watch, char *type, int dom,
> -                               struct XenDevOps *ops)
> -{
> -    struct XenDevice *xendev;
> -    char path[XEN_BUFSIZE], *bepath;
> -    unsigned int len, dev;
> -
> -    len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
> -    if (strncmp(path, watch, len) != 0) {
> -        return;
> -    }
> -    if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
> -        strcpy(path, "");
> -        if (sscanf(watch+len, "/%u", &dev) != 1) {
> -            dev = -1;
> -        }
> -    }
> -    if (dev == -1) {
> -        return;
> -    }
> -
> -    xendev = xen_be_get_xendev(type, dom, dev, ops);
> -    if (xendev != NULL) {
> -        bepath = xs_read(xenstore, 0, xendev->be, &len);
> -        if (bepath == NULL) {
> -            xen_be_del_xendev(dom, dev);
> -        } else {
> -            free(bepath);
> -            xen_be_backend_changed(xendev, path);
> -            xen_be_check_state(xendev);
> -        }
> -    }
> -}
> -
> -static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
> -{
> -    char *node;
> -    unsigned int len;
> -
> -    len = strlen(xendev->fe);
> -    if (strncmp(xendev->fe, watch, len) != 0) {
> -        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 (vec == NULL) {
> -        goto cleanup;
> -    }
> -
> -    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
> -               &type, &dom, &ops) == 3) {
> -        xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
> -    }
> -    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
> -        xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
> -    }
> -
> -cleanup:
> -    free(vec);
> -}
> -
>  static void xen_be_evtchn_event(void *opaque)
>  {
>      struct XenDevice *xendev = opaque;
> @@ -706,32 +379,6 @@ static void xen_be_evtchn_event(void *opaque)
>  
>  /* -------------------------------------------------------------------- */
>  
> -int xen_be_init(void)
> -{
> -    xenstore = xs_daemon_open();
> -    if (!xenstore) {
> -        xen_be_printf(NULL, 0, "can't connect to xenstored\n");
> -        return -1;
> -    }
> -
> -    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0) {
> -        goto err;
> -    }
> -
> -    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
> -        /* Check if xen_init() have been called */
> -        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(const char *type, struct XenDevOps *ops)
>  {
>      return xenstore_scan(type, xen_domid, ops);
> diff --git a/hw/xen/xen_pvdev.c b/hw/xen/xen_pvdev.c
> new file mode 100644
> index 0000000..dac8639
> --- /dev/null
> +++ b/hw/xen/xen_pvdev.c
> @@ -0,0 +1,481 @@
> +/*
> + * Xen para-virtualization device
> + *
> + *  Copyright (c) 2015 Intel Corporation
> + *  Authors:
> + *    Quan Xu <quan.xu@intel.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library 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
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>
> + */
> +
> +#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 "hw/hw.h"
> +#include "sysemu/char.h"
> +#include "qemu/log.h"
> +#include "hw/xen/xen_backend.h"
> +
> +#include <xen/grant_table.h>
> +
> +static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs =
> +           QTAILQ_HEAD_INITIALIZER(xendevs);
> +static int debug;
> +
> +/* public */
> +XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
> +struct xs_handle *xenstore;
> +
> +/*
> + * find Xen device
> + */
> +struct XenDevice *xen_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;
> +}
> +
> +/*
> + * get xen backend device, allocate a new one if it doesn't exist.
> + */
> +struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
> +                                    struct XenDevOps *ops)
> +{
> +    struct XenDevice *xendev;
> +
> +    xendev = xen_find_xendev(type, dom, dev);
> +    if (xendev) {
> +        return xendev;
> +    }
> +
> +    /* init new xendev */
> +    xendev = g_malloc0(ops->size);
> +    xendev->type  = type;
> +    xendev->dom   = dom;
> +    xendev->dev   = dev;
> +    xendev->ops   = ops;
> +
> +    snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
> +             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 = xen_xc_evtchn_open(NULL, 0);
> +    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
> +        xen_be_printf(NULL, 0, "can't open evtchn device\n");
> +        g_free(xendev);
> +        return NULL;
> +    }
> +    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
> +
> +    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
> +        xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
> +        if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
> +            xen_be_printf(NULL, 0, "can't open gnttab device\n");
> +            xc_evtchn_close(xendev->evtchndev);
> +            g_free(xendev);
> +            return NULL;
> +        }
> +    } else {
> +        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
> +    }
> +
> +    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
> +
> +    if (xendev->ops->alloc) {
> +        xendev->ops->alloc(xendev);
> +    }
> +
> +    return xendev;
> +}
> +
> +/*
> + * get xen fe device, allocate a new one if it doesn't exist.
> + */
> +struct XenDevice *xen_fe_get_xendev(const char *type, int dom, int dev,
> +                                    char *backend, struct XenDevOps *ops)
> +{
> +    struct XenDevice *xendev;
> +
> +    xendev = xen_find_xendev(type, dom, dev);
> +    if (xendev) {
> +        return xendev;
> +    }
> +
> +    /* init new xendev */
> +    xendev = g_malloc0(ops->size);
> +    xendev->type  = type;
> +    xendev->dom   = dom;
> +    xendev->dev   = dev;
> +    xendev->ops   = ops;
> +
> +    /*return if the ops->flags is not DEVOPS_FLAG_FE*/
> +    if (!(ops->flags & DEVOPS_FLAG_FE)) {
> +        return NULL;
> +    }
> +
> +    snprintf(xendev->be, sizeof(xendev->be), "%s", backend);
> +    snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
> +             xendev->type, xendev->dev);
> +
> +    xendev->debug = debug;
> +    xendev->local_port = -1;
> +
> +    xendev->evtchndev = xen_xc_evtchn_open(NULL, 0);
> +    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
> +        xen_be_printf(NULL, 0, "can't open evtchn device\n");
> +        g_free(xendev);
> +        return NULL;
> +    }
> +    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
> +
> +    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
> +        xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
> +        if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
> +            xen_be_printf(NULL, 0, "can't open gnttab device\n");
> +            xc_evtchn_close(xendev->evtchndev);
> +            g_free(xendev);
> +            return NULL;
> +        }
> +    } else {
> +        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
> +    }
> +
> +    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
> +
> +    if (xendev->ops->alloc) {
> +        xendev->ops->alloc(xendev);
> +    }
> +
> +    return xendev;
> +}
> +
> +/*
> + * release xen device
> + */
> +
> +struct XenDevice *xen_del_xendev(int dom, int dev)
> +{
> +    struct XenDevice *xendev, *xnext;
> +
> +    /*
> +     * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next) but
> +     * we save the next pointer in xnext because we might free xendev.
> +     */
> +    xnext = xendevs.tqh_first;
> +    while (xnext) {
> +        xendev = xnext;
> +        xnext = xendev->next.tqe_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[XEN_BUFSIZE];
> +            snprintf(token, sizeof(token), "fe:%p", xendev);
> +            xs_unwatch(xenstore, xendev->fe, token);
> +            g_free(xendev->fe);
> +        }
> +
> +        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
> +            xc_evtchn_close(xendev->evtchndev);
> +        }
> +        if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
> +            xc_gnttab_close(xendev->gnttabdev);
> +        }
> +
> +        QTAILQ_REMOVE(&xendevs, xendev, next);
> +        g_free(xendev);
> +    }
> +    return NULL;
> +}
> +
> +/* ------------------------------------------------------------- */
> +
> +int xenstore_write_str(const char *base, const char *node, const char *val)
> +{
> +    char abspath[XEN_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[XEN_BUFSIZE];
> +    unsigned int len;
> +    char *str, *ret = NULL;
> +
> +    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
> +    str = xs_read(xenstore, 0, abspath, &len);
> +    if (str != NULL) {
> +        /* move to qemu-allocated memory to make sure
> +         * callers can savely g_free() stuff. */
> +        ret = g_strdup(str);
> +        free(str);
> +    }
> +    return ret;
> +}
> +
> +int xenstore_write_int(const char *base, const char *node, int ival)
> +{
> +    char val[12];
> +
> +    snprintf(val, sizeof(val), "%d", ival);
> +    return xenstore_write_str(base, node, val);
> +}
> +
> +int xenstore_write_int64(const char *base, const char *node, int64_t ival)
> +{
> +    char val[21];
> +
> +    snprintf(val, sizeof(val), "%"PRId64, 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;
> +    }
> +    g_free(val);
> +    return rc;
> +}
> +
> +int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
> +{
> +    char *val;
> +    int rc = -1;
> +
> +    val = xenstore_read_str(base, node);
> +    if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
> +        rc = 0;
> +    }
> +    g_free(val);
> +    return rc;
> +}
> +
> +char *xenstore_get_domain_name(uint32_t domid)
> +{
> +    char *dom_path, *str, *ret = NULL;;
> +
> +    dom_path = xs_get_domain_path(xenstore, domid);
> +    str = xenstore_read_str(dom_path, "name");
> +    free(dom_path);
> +    if (str != NULL) {
> +        ret = g_strdup(str);
> +        free(str);
> +    }
> +
> +    return ret;
> +}
> +
> +/*
> + * Sync internal data structures on xenstore updates.
> + * Node specifies the changed field.  node = NULL means
> + * update all fields (used for initialization).
> + */
> +void xen_be_backend_changed(struct XenDevice *xendev, const char *node)
> +{
> +    if (node == NULL  ||  strcmp(node, "online") == 0) {
> +        if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
> +            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);
> +        }
> +    }
> +}
> +
> +void xen_be_frontend_changed(struct XenDevice *xendev, const char *node)
> +{
> +    int fe_state;
> +
> +    if (node == NULL  ||  strcmp(node, "state") == 0) {
> +        if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
> +            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 (node == NULL  ||  strcmp(node, "protocol") == 0) {
> +        g_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);
> +        }
> +    }
> +}
> +
> +static void xenstore_update_be(char *watch, char *type, int dom,
> +                        struct XenDevOps *ops)
> +{
> +    struct XenDevice *xendev;
> +    char path[XEN_BUFSIZE], *bepath;
> +    unsigned int len, dev;
> +
> +    len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
> +
> +    if (strstr(watch, path) == NULL) {
> +        return;
> +    }
> +    if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
> +        strcpy(path, "");
> +        if (sscanf(watch+len, "/%u", &dev) != 1) {
> +            dev = -1;
> +        }
> +    }
> +    if (dev == -1) {
> +        return;
> +    }
> +
> +    xendev = xen_be_get_xendev(type, dom, dev, ops);
> +    if (xendev != NULL) {
> +        bepath = xs_read(xenstore, 0, xendev->be, &len);
> +        if (bepath == NULL) {
> +            xen_del_xendev(dom, dev);
> +        } else {
> +            free(bepath);
> +            xen_be_backend_changed(xendev, path);
> +            if (!(ops->flags & DEVOPS_FLAG_FE)) {
> +                xen_be_check_state(xendev);
> +            }
> +        }
> +    }
> +}
> +
> +static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
> +{
> +    char *node;
> +    unsigned int len;
> +
> +    len = strlen(xendev->fe);
> +    if (strncmp(xendev->fe, watch, len) != 0) {
> +        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 (vec == NULL) {
> +        goto cleanup;
> +    }
> +
> +    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
> +               &type, &dom, &ops) == 3) {
> +        xenstore_update_be(vec[XS_WATCH_PATH], (void *)type, dom, (void *)ops);
> +    }
> +    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
> +        xenstore_update_fe(vec[XS_WATCH_PATH], (void *)ptr);
> +    }
> +
> +cleanup:
> +    free(vec);
> +}
> +
> +int xen_be_init(void)
> +{
> +    xenstore = xs_daemon_open();
> +    if (!xenstore) {
> +        xen_be_printf(NULL, 0, "can't connect to xenstored\n");
> +        return -1;
> +    }
> +
> +    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update,
> +        NULL, NULL) < 0) {
> +        goto err;
> +    }
> +
> +    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
> +
> +        /* Check if xen_init() have been called */
> +        goto err;
> +    }
> +    return 0;
> +
> +err:
> +    qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
> +    xs_daemon_close(xenstore);
> +    xenstore = NULL;
> +
> +    return -1;
> +}
> diff --git a/include/hw/xen/xen_backend.h b/include/hw/xen/xen_backend.h
> index 3b4125e..65476bf 100644
> --- a/include/hw/xen/xen_backend.h
> +++ b/include/hw/xen/xen_backend.h
> @@ -15,6 +15,8 @@ struct XenDevice;
>  #define DEVOPS_FLAG_NEED_GNTDEV   1
>  /* don't expect frontend doing correct state transitions (aka console quirk) */
>  #define DEVOPS_FLAG_IGNORE_STATE  2
> +/*dev is frontend device*/
> +#define DEVOPS_FLAG_FE            4
>  
>  struct XenDevOps {
>      size_t    size;
> @@ -77,9 +79,18 @@ int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival);
>  int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval);
>  int xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node, uint64_t *uval);
>  
> +char *xenstore_get_domain_name(uint32_t domid);
> +
>  const char *xenbus_strstate(enum xenbus_state state);
> -struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev);
> +struct XenDevice *xen_find_xendev(const char *type, int dom, int dev);
> +struct XenDevice *xen_del_xendev(int dom, int dev);
> +struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
> +                                    struct XenDevOps *ops);
> +struct XenDevice *xen_fe_get_xendev(const char *type, int dom, int dev,
> +                                    char *backend, struct XenDevOps *ops);
>  void xen_be_check_state(struct XenDevice *xendev);
> +void xen_be_backend_changed(struct XenDevice *xendev, const char *node);
> +void xen_be_frontend_changed(struct XenDevice *xendev, const char *node);
>  
>  /* xen backend driver bits */
>  int xen_be_init(void);
> -- 
> 1.8.3.2
>
Xu, Quan June 23, 2015, 6:43 a.m. UTC | #2
> -----Original Message-----
> From: Stefano Stabellini [mailto:stefano.stabellini@eu.citrix.com]
> Sent: Tuesday, June 23, 2015 12:37 AM
> To: Xu, Quan
> Cc: stefano.stabellini@eu.citrix.com; qemu-devel@nongnu.org;
> stefanb@linux.vnet.ibm.com; eblake@redhat.com; wei.liu2@citrix.com;
> dgdegra@tycho.nsa.gov; xen-devel@lists.xen.org
> Subject: Re: [PATCH v8 2/7] Qemu-Xen-vTPM: Create a new file xen_pvdev.c
> 
> On Sun, 17 May 2015, Quan Xu wrote:
> > for some common part of xen frontend and backend, such as xendevs
> > queue and xenstore update functions.
> >
> > Signed-off-by: Quan Xu <quan.xu@intel.com>
> 
> Hi Quan,
> 
> could you please separate out the code movement from any other changes?
> This patch would become two patches: the first would only move code from
> xen_backend.c to xen_pvdev.c, no other changes except for the ones actually
> required to build the code (Makefile.objs).  The second patch would rename
> xen_be_find_xendev to xen_find_xendev and any other changes to the code
> that you making here.  That way I can very easily go and look only at the things
> you actually modify.
> 
> Thanks,
> 
> Stefano
> 
> 

Stefano, thanks for your comment.
Now I am focusing on ' VT-d async invalidation for Device-TLB' feature as high priority. 
I will fix all of your comments when I send out v1 of ' VT-d async invalidation for Device-TLB' feature.


Quan
Stefano Stabellini June 23, 2015, 10:56 a.m. UTC | #3
On Tue, 23 Jun 2015, Xu, Quan wrote:
> > -----Original Message-----
> > From: Stefano Stabellini [mailto:stefano.stabellini@eu.citrix.com]
> > Sent: Tuesday, June 23, 2015 12:37 AM
> > To: Xu, Quan
> > Cc: stefano.stabellini@eu.citrix.com; qemu-devel@nongnu.org;
> > stefanb@linux.vnet.ibm.com; eblake@redhat.com; wei.liu2@citrix.com;
> > dgdegra@tycho.nsa.gov; xen-devel@lists.xen.org
> > Subject: Re: [PATCH v8 2/7] Qemu-Xen-vTPM: Create a new file xen_pvdev.c
> > 
> > On Sun, 17 May 2015, Quan Xu wrote:
> > > for some common part of xen frontend and backend, such as xendevs
> > > queue and xenstore update functions.
> > >
> > > Signed-off-by: Quan Xu <quan.xu@intel.com>
> > 
> > Hi Quan,
> > 
> > could you please separate out the code movement from any other changes?
> > This patch would become two patches: the first would only move code from
> > xen_backend.c to xen_pvdev.c, no other changes except for the ones actually
> > required to build the code (Makefile.objs).  The second patch would rename
> > xen_be_find_xendev to xen_find_xendev and any other changes to the code
> > that you making here.  That way I can very easily go and look only at the things
> > you actually modify.
> > 
> > Thanks,
> > 
> > Stefano
> > 
> > 
> 
> Stefano, thanks for your comment.
> Now I am focusing on ' VT-d async invalidation for Device-TLB' feature as high priority. 
> I will fix all of your comments when I send out v1 of ' VT-d async invalidation for Device-TLB' feature.

Sure, no problem.
Xu, Quan Feb. 14, 2016, 5:55 a.m. UTC | #4
> On June 23, 2015 12:37 AM, <stefano.stabellini@eu.citrix.com>:
> Cc: stefano.stabellini@eu.citrix.com; qemu-devel@nongnu.org;
> stefanb@linux.vnet.ibm.com; eblake@redhat.com; wei.liu2@citrix.com;
> dgdegra@tycho.nsa.gov; xen-devel@lists.xen.org
> Subject: Re: [PATCH v8 2/7] Qemu-Xen-vTPM: Create a new file xen_pvdev.c
> 
> On Sun, 17 May 2015, Quan Xu wrote:
> > for some common part of xen frontend and backend, such as xendevs
> > queue and xenstore update functions.
> >
> > Signed-off-by: Quan Xu <quan.xu@intel.com>
> 
> Hi Quan,
> 
> could you please separate out the code movement from any other changes?
> This patch would become two patches: the first would only move code from
> xen_backend.c to xen_pvdev.c, no other changes except for the ones actually
> required to build the code (Makefile.objs).  The second patch would rename
> xen_be_find_xendev to xen_find_xendev and any other changes to the code
> that you making here.  That way I can very easily go and look only at the things
> you actually modify.

Sure, make sense.
I will modify it in next v9. I apologize for this late reply!

-Quan




> 
> 
> >  hw/display/xenfb.c           |   4 +-
> >  hw/xen/Makefile.objs         |   2 +-
> >  hw/xen/xen_backend.c         | 353 -------------------------------
> >  hw/xen/xen_pvdev.c           | 481
> +++++++++++++++++++++++++++++++++++++++++++
> >  include/hw/xen/xen_backend.h |  13 +-
> >  5 files changed, 496 insertions(+), 357 deletions(-)  create mode
> > 100644 hw/xen/xen_pvdev.c
> >
> > diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c index
> > 5e324ef..10751df 100644
> > --- a/hw/display/xenfb.c
> > +++ b/hw/display/xenfb.c
> > @@ -988,8 +988,8 @@ void xen_init_display(int domid)
> >  wait_more:
> >      i++;
> >      main_loop_wait(true);
> > -    xfb = xen_be_find_xendev("vfb", domid, 0);
> > -    xin = xen_be_find_xendev("vkbd", domid, 0);
> > +    xfb = xen_find_xendev("vfb", domid, 0);
> > +    xin = xen_find_xendev("vkbd", domid, 0);
> >      if (!xfb || !xin) {
> >          if (i < 256) {
> >              usleep(10000);
> > diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs index
> > a0ca0aa..9ac9f7c 100644
> > --- a/hw/xen/Makefile.objs
> > +++ b/hw/xen/Makefile.objs
> > @@ -1,5 +1,5 @@
> >  # xen backend driver support
> > -common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
> > +common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
> > +xen_pvdev.o
> >
> >  obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
> >  obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o
> > xen_pt_msi.o diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
> > index b2cb22b..844f918 100644
> > --- a/hw/xen/xen_backend.c
> > +++ b/hw/xen/xen_backend.c
> > @@ -44,86 +44,11 @@
> >  /* ------------------------------------------------------------- */
> >
> >  /* public */
> > -XenXC xen_xc = XC_HANDLER_INITIAL_VALUE; -struct xs_handle *xenstore
> > = NULL;  const char *xen_protocol;
> >
> >  /* private */
> > -static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs =
> > QTAILQ_HEAD_INITIALIZER(xendevs);  static int debug = 0;
> >
> > -/* ------------------------------------------------------------- */
> > -
> > -int xenstore_write_str(const char *base, const char *node, const char
> > *val) -{
> > -    char abspath[XEN_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[XEN_BUFSIZE];
> > -    unsigned int len;
> > -    char *str, *ret = NULL;
> > -
> > -    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
> > -    str = xs_read(xenstore, 0, abspath, &len);
> > -    if (str != NULL) {
> > -        /* move to qemu-allocated memory to make sure
> > -         * callers can savely g_free() stuff. */
> > -        ret = g_strdup(str);
> > -        free(str);
> > -    }
> > -    return ret;
> > -}
> > -
> > -int xenstore_write_int(const char *base, const char *node, int ival)
> > -{
> > -    char val[12];
> > -
> > -    snprintf(val, sizeof(val), "%d", ival);
> > -    return xenstore_write_str(base, node, val);
> > -}
> > -
> > -int xenstore_write_int64(const char *base, const char *node, int64_t
> > ival) -{
> > -    char val[21];
> > -
> > -    snprintf(val, sizeof(val), "%"PRId64, 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;
> > -    }
> > -    g_free(val);
> > -    return rc;
> > -}
> > -
> > -int xenstore_read_uint64(const char *base, const char *node, uint64_t
> > *uval) -{
> > -    char *val;
> > -    int rc = -1;
> > -
> > -    val = xenstore_read_str(base, node);
> > -    if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
> > -        rc = 0;
> > -    }
> > -    g_free(val);
> > -    return rc;
> > -}
> > -
> >  int xenstore_write_be_str(struct XenDevice *xendev, const char *node,
> > const char *val)  {
> >      return xenstore_write_str(xendev->be, node, val); @@ -195,183
> > +120,6 @@ int xen_be_set_state(struct XenDevice *xendev, enum
> > xenbus_state state)  }
> >
> >  /* ------------------------------------------------------------- */
> > -
> > -struct XenDevice *xen_be_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;
> > -}
> > -
> > -/*
> > - * get xen backend device, allocate a new one if it doesn't exist.
> > - */
> > -static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int
> dev,
> > -                                           struct XenDevOps *ops)
> > -{
> > -    struct XenDevice *xendev;
> > -
> > -    xendev = xen_be_find_xendev(type, dom, dev);
> > -    if (xendev) {
> > -        return xendev;
> > -    }
> > -
> > -    /* init new xendev */
> > -    xendev = g_malloc0(ops->size);
> > -    xendev->type  = type;
> > -    xendev->dom   = dom;
> > -    xendev->dev   = dev;
> > -    xendev->ops   = ops;
> > -
> > -    snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
> > -             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 = xen_xc_evtchn_open(NULL, 0);
> > -    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
> > -        xen_be_printf(NULL, 0, "can't open evtchn device\n");
> > -        g_free(xendev);
> > -        return NULL;
> > -    }
> > -    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
> > -
> > -    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
> > -        xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
> > -        if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
> > -            xen_be_printf(NULL, 0, "can't open gnttab device\n");
> > -            xc_evtchn_close(xendev->evtchndev);
> > -            g_free(xendev);
> > -            return NULL;
> > -        }
> > -    } else {
> > -        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
> > -    }
> > -
> > -    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
> > -
> > -    if (xendev->ops->alloc) {
> > -        xendev->ops->alloc(xendev);
> > -    }
> > -
> > -    return xendev;
> > -}
> > -
> > -/*
> > - * release xen backend device.
> > - */
> > -static struct XenDevice *xen_be_del_xendev(int dom, int dev) -{
> > -    struct XenDevice *xendev, *xnext;
> > -
> > -    /*
> > -     * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next)
> but
> > -     * we save the next pointer in xnext because we might free xendev.
> > -     */
> > -    xnext = xendevs.tqh_first;
> > -    while (xnext) {
> > -        xendev = xnext;
> > -        xnext = xendev->next.tqe_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[XEN_BUFSIZE];
> > -            snprintf(token, sizeof(token), "fe:%p", xendev);
> > -            xs_unwatch(xenstore, xendev->fe, token);
> > -            g_free(xendev->fe);
> > -        }
> > -
> > -        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
> > -            xc_evtchn_close(xendev->evtchndev);
> > -        }
> > -        if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
> > -            xc_gnttab_close(xendev->gnttabdev);
> > -        }
> > -
> > -        QTAILQ_REMOVE(&xendevs, xendev, next);
> > -        g_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 XenDevice *xendev, const
> > char *node) -{
> > -    if (node == NULL  ||  strcmp(node, "online") == 0) {
> > -        if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1)
> {
> > -            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 XenDevice *xendev, const
> > char *node) -{
> > -    int fe_state;
> > -
> > -    if (node == NULL  ||  strcmp(node, "state") == 0) {
> > -        if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
> > -            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 (node == NULL  ||  strcmp(node, "protocol") == 0) {
> > -        g_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.        */
> >
> >  /*
> > @@ -611,81 +359,6 @@ static int xenstore_scan(const char *type, int dom,
> struct XenDevOps *ops)
> >      return 0;
> >  }
> >
> > -static void xenstore_update_be(char *watch, char *type, int dom,
> > -                               struct XenDevOps *ops)
> > -{
> > -    struct XenDevice *xendev;
> > -    char path[XEN_BUFSIZE], *bepath;
> > -    unsigned int len, dev;
> > -
> > -    len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
> > -    if (strncmp(path, watch, len) != 0) {
> > -        return;
> > -    }
> > -    if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
> > -        strcpy(path, "");
> > -        if (sscanf(watch+len, "/%u", &dev) != 1) {
> > -            dev = -1;
> > -        }
> > -    }
> > -    if (dev == -1) {
> > -        return;
> > -    }
> > -
> > -    xendev = xen_be_get_xendev(type, dom, dev, ops);
> > -    if (xendev != NULL) {
> > -        bepath = xs_read(xenstore, 0, xendev->be, &len);
> > -        if (bepath == NULL) {
> > -            xen_be_del_xendev(dom, dev);
> > -        } else {
> > -            free(bepath);
> > -            xen_be_backend_changed(xendev, path);
> > -            xen_be_check_state(xendev);
> > -        }
> > -    }
> > -}
> > -
> > -static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
> > -{
> > -    char *node;
> > -    unsigned int len;
> > -
> > -    len = strlen(xendev->fe);
> > -    if (strncmp(xendev->fe, watch, len) != 0) {
> > -        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 (vec == NULL) {
> > -        goto cleanup;
> > -    }
> > -
> > -    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
> > -               &type, &dom, &ops) == 3) {
> > -        xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom,
> (void*)ops);
> > -    }
> > -    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
> > -        xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
> > -    }
> > -
> > -cleanup:
> > -    free(vec);
> > -}
> > -
> >  static void xen_be_evtchn_event(void *opaque)  {
> >      struct XenDevice *xendev = opaque; @@ -706,32 +379,6 @@ static
> > void xen_be_evtchn_event(void *opaque)
> >
> >  /*
> > --------------------------------------------------------------------
> > */
> >
> > -int xen_be_init(void)
> > -{
> > -    xenstore = xs_daemon_open();
> > -    if (!xenstore) {
> > -        xen_be_printf(NULL, 0, "can't connect to xenstored\n");
> > -        return -1;
> > -    }
> > -
> > -    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL,
> NULL) < 0) {
> > -        goto err;
> > -    }
> > -
> > -    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
> > -        /* Check if xen_init() have been called */
> > -        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(const char *type, struct XenDevOps *ops)  {
> >      return xenstore_scan(type, xen_domid, ops); diff --git
> > a/hw/xen/xen_pvdev.c b/hw/xen/xen_pvdev.c new file mode 100644 index
> > 0000000..dac8639
> > --- /dev/null
> > +++ b/hw/xen/xen_pvdev.c
> > @@ -0,0 +1,481 @@
> > +/*
> > + * Xen para-virtualization device
> > + *
> > + *  Copyright (c) 2015 Intel Corporation
> > + *  Authors:
> > + *    Quan Xu <quan.xu@intel.com>
> > + *
> > + * This library is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU Lesser General Public
> > + * License as published by the Free Software Foundation; either
> > + * version 2 of the License, or (at your option) any later version.
> > + *
> > + * This library 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
> > + * Lesser General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU Lesser General Public
> > + * License along with this library; if not, see
> > +<http://www.gnu.org/licenses/>  */
> > +
> > +#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 "hw/hw.h"
> > +#include "sysemu/char.h"
> > +#include "qemu/log.h"
> > +#include "hw/xen/xen_backend.h"
> > +
> > +#include <xen/grant_table.h>
> > +
> > +static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs =
> > +           QTAILQ_HEAD_INITIALIZER(xendevs); static int debug;
> > +
> > +/* public */
> > +XenXC xen_xc = XC_HANDLER_INITIAL_VALUE; struct xs_handle *xenstore;
> > +
> > +/*
> > + * find Xen device
> > + */
> > +struct XenDevice *xen_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;
> > +}
> > +
> > +/*
> > + * get xen backend device, allocate a new one if it doesn't exist.
> > + */
> > +struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
> > +                                    struct XenDevOps *ops) {
> > +    struct XenDevice *xendev;
> > +
> > +    xendev = xen_find_xendev(type, dom, dev);
> > +    if (xendev) {
> > +        return xendev;
> > +    }
> > +
> > +    /* init new xendev */
> > +    xendev = g_malloc0(ops->size);
> > +    xendev->type  = type;
> > +    xendev->dom   = dom;
> > +    xendev->dev   = dev;
> > +    xendev->ops   = ops;
> > +
> > +    snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
> > +             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 = xen_xc_evtchn_open(NULL, 0);
> > +    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
> > +        xen_be_printf(NULL, 0, "can't open evtchn device\n");
> > +        g_free(xendev);
> > +        return NULL;
> > +    }
> > +    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
> > +
> > +    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
> > +        xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
> > +        if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
> > +            xen_be_printf(NULL, 0, "can't open gnttab device\n");
> > +            xc_evtchn_close(xendev->evtchndev);
> > +            g_free(xendev);
> > +            return NULL;
> > +        }
> > +    } else {
> > +        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
> > +    }
> > +
> > +    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
> > +
> > +    if (xendev->ops->alloc) {
> > +        xendev->ops->alloc(xendev);
> > +    }
> > +
> > +    return xendev;
> > +}
> > +
> > +/*
> > + * get xen fe device, allocate a new one if it doesn't exist.
> > + */
> > +struct XenDevice *xen_fe_get_xendev(const char *type, int dom, int dev,
> > +                                    char *backend, struct
> XenDevOps
> > +*ops) {
> > +    struct XenDevice *xendev;
> > +
> > +    xendev = xen_find_xendev(type, dom, dev);
> > +    if (xendev) {
> > +        return xendev;
> > +    }
> > +
> > +    /* init new xendev */
> > +    xendev = g_malloc0(ops->size);
> > +    xendev->type  = type;
> > +    xendev->dom   = dom;
> > +    xendev->dev   = dev;
> > +    xendev->ops   = ops;
> > +
> > +    /*return if the ops->flags is not DEVOPS_FLAG_FE*/
> > +    if (!(ops->flags & DEVOPS_FLAG_FE)) {
> > +        return NULL;
> > +    }
> > +
> > +    snprintf(xendev->be, sizeof(xendev->be), "%s", backend);
> > +    snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
> > +             xendev->type, xendev->dev);
> > +
> > +    xendev->debug = debug;
> > +    xendev->local_port = -1;
> > +
> > +    xendev->evtchndev = xen_xc_evtchn_open(NULL, 0);
> > +    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
> > +        xen_be_printf(NULL, 0, "can't open evtchn device\n");
> > +        g_free(xendev);
> > +        return NULL;
> > +    }
> > +    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
> > +
> > +    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
> > +        xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
> > +        if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
> > +            xen_be_printf(NULL, 0, "can't open gnttab device\n");
> > +            xc_evtchn_close(xendev->evtchndev);
> > +            g_free(xendev);
> > +            return NULL;
> > +        }
> > +    } else {
> > +        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
> > +    }
> > +
> > +    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
> > +
> > +    if (xendev->ops->alloc) {
> > +        xendev->ops->alloc(xendev);
> > +    }
> > +
> > +    return xendev;
> > +}
> > +
> > +/*
> > + * release xen device
> > + */
> > +
> > +struct XenDevice *xen_del_xendev(int dom, int dev) {
> > +    struct XenDevice *xendev, *xnext;
> > +
> > +    /*
> > +     * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next)
> but
> > +     * we save the next pointer in xnext because we might free xendev.
> > +     */
> > +    xnext = xendevs.tqh_first;
> > +    while (xnext) {
> > +        xendev = xnext;
> > +        xnext = xendev->next.tqe_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[XEN_BUFSIZE];
> > +            snprintf(token, sizeof(token), "fe:%p", xendev);
> > +            xs_unwatch(xenstore, xendev->fe, token);
> > +            g_free(xendev->fe);
> > +        }
> > +
> > +        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
> > +            xc_evtchn_close(xendev->evtchndev);
> > +        }
> > +        if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
> > +            xc_gnttab_close(xendev->gnttabdev);
> > +        }
> > +
> > +        QTAILQ_REMOVE(&xendevs, xendev, next);
> > +        g_free(xendev);
> > +    }
> > +    return NULL;
> > +}
> > +
> > +/* ------------------------------------------------------------- */
> > +
> > +int xenstore_write_str(const char *base, const char *node, const char
> > +*val) {
> > +    char abspath[XEN_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[XEN_BUFSIZE];
> > +    unsigned int len;
> > +    char *str, *ret = NULL;
> > +
> > +    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
> > +    str = xs_read(xenstore, 0, abspath, &len);
> > +    if (str != NULL) {
> > +        /* move to qemu-allocated memory to make sure
> > +         * callers can savely g_free() stuff. */
> > +        ret = g_strdup(str);
> > +        free(str);
> > +    }
> > +    return ret;
> > +}
> > +
> > +int xenstore_write_int(const char *base, const char *node, int ival)
> > +{
> > +    char val[12];
> > +
> > +    snprintf(val, sizeof(val), "%d", ival);
> > +    return xenstore_write_str(base, node, val); }
> > +
> > +int xenstore_write_int64(const char *base, const char *node, int64_t
> > +ival) {
> > +    char val[21];
> > +
> > +    snprintf(val, sizeof(val), "%"PRId64, 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;
> > +    }
> > +    g_free(val);
> > +    return rc;
> > +}
> > +
> > +int xenstore_read_uint64(const char *base, const char *node, uint64_t
> > +*uval) {
> > +    char *val;
> > +    int rc = -1;
> > +
> > +    val = xenstore_read_str(base, node);
> > +    if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
> > +        rc = 0;
> > +    }
> > +    g_free(val);
> > +    return rc;
> > +}
> > +
> > +char *xenstore_get_domain_name(uint32_t domid) {
> > +    char *dom_path, *str, *ret = NULL;;
> > +
> > +    dom_path = xs_get_domain_path(xenstore, domid);
> > +    str = xenstore_read_str(dom_path, "name");
> > +    free(dom_path);
> > +    if (str != NULL) {
> > +        ret = g_strdup(str);
> > +        free(str);
> > +    }
> > +
> > +    return ret;
> > +}
> > +
> > +/*
> > + * Sync internal data structures on xenstore updates.
> > + * Node specifies the changed field.  node = NULL means
> > + * update all fields (used for initialization).
> > + */
> > +void xen_be_backend_changed(struct XenDevice *xendev, const char
> > +*node) {
> > +    if (node == NULL  ||  strcmp(node, "online") == 0) {
> > +        if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1)
> {
> > +            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);
> > +        }
> > +    }
> > +}
> > +
> > +void xen_be_frontend_changed(struct XenDevice *xendev, const char
> > +*node) {
> > +    int fe_state;
> > +
> > +    if (node == NULL  ||  strcmp(node, "state") == 0) {
> > +        if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
> > +            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 (node == NULL  ||  strcmp(node, "protocol") == 0) {
> > +        g_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);
> > +        }
> > +    }
> > +}
> > +
> > +static void xenstore_update_be(char *watch, char *type, int dom,
> > +                        struct XenDevOps *ops) {
> > +    struct XenDevice *xendev;
> > +    char path[XEN_BUFSIZE], *bepath;
> > +    unsigned int len, dev;
> > +
> > +    len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
> > +
> > +    if (strstr(watch, path) == NULL) {
> > +        return;
> > +    }
> > +    if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
> > +        strcpy(path, "");
> > +        if (sscanf(watch+len, "/%u", &dev) != 1) {
> > +            dev = -1;
> > +        }
> > +    }
> > +    if (dev == -1) {
> > +        return;
> > +    }
> > +
> > +    xendev = xen_be_get_xendev(type, dom, dev, ops);
> > +    if (xendev != NULL) {
> > +        bepath = xs_read(xenstore, 0, xendev->be, &len);
> > +        if (bepath == NULL) {
> > +            xen_del_xendev(dom, dev);
> > +        } else {
> > +            free(bepath);
> > +            xen_be_backend_changed(xendev, path);
> > +            if (!(ops->flags & DEVOPS_FLAG_FE)) {
> > +                xen_be_check_state(xendev);
> > +            }
> > +        }
> > +    }
> > +}
> > +
> > +static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
> > +{
> > +    char *node;
> > +    unsigned int len;
> > +
> > +    len = strlen(xendev->fe);
> > +    if (strncmp(xendev->fe, watch, len) != 0) {
> > +        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 (vec == NULL) {
> > +        goto cleanup;
> > +    }
> > +
> > +    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
> > +               &type, &dom, &ops) == 3) {
> > +        xenstore_update_be(vec[XS_WATCH_PATH], (void *)type, dom,
> (void *)ops);
> > +    }
> > +    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
> > +        xenstore_update_fe(vec[XS_WATCH_PATH], (void *)ptr);
> > +    }
> > +
> > +cleanup:
> > +    free(vec);
> > +}
> > +
> > +int xen_be_init(void)
> > +{
> > +    xenstore = xs_daemon_open();
> > +    if (!xenstore) {
> > +        xen_be_printf(NULL, 0, "can't connect to xenstored\n");
> > +        return -1;
> > +    }
> > +
> > +    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update,
> > +        NULL, NULL) < 0) {
> > +        goto err;
> > +    }
> > +
> > +    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
> > +
> > +        /* Check if xen_init() have been called */
> > +        goto err;
> > +    }
> > +    return 0;
> > +
> > +err:
> > +    qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
> > +    xs_daemon_close(xenstore);
> > +    xenstore = NULL;
> > +
> > +    return -1;
> > +}
> > diff --git a/include/hw/xen/xen_backend.h
> > b/include/hw/xen/xen_backend.h index 3b4125e..65476bf 100644
> > --- a/include/hw/xen/xen_backend.h
> > +++ b/include/hw/xen/xen_backend.h
> > @@ -15,6 +15,8 @@ struct XenDevice;
> >  #define DEVOPS_FLAG_NEED_GNTDEV   1
> >  /* don't expect frontend doing correct state transitions (aka console
> > quirk) */  #define DEVOPS_FLAG_IGNORE_STATE  2
> > +/*dev is frontend device*/
> > +#define DEVOPS_FLAG_FE            4
> >
> >  struct XenDevOps {
> >      size_t    size;
> > @@ -77,9 +79,18 @@ int xenstore_read_fe_int(struct XenDevice *xendev,
> > const char *node, int *ival);  int xenstore_read_uint64(const char
> > *base, const char *node, uint64_t *uval);  int
> > xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node,
> > uint64_t *uval);
> >
> > +char *xenstore_get_domain_name(uint32_t domid);
> > +
> >  const char *xenbus_strstate(enum xenbus_state state); -struct
> > XenDevice *xen_be_find_xendev(const char *type, int dom, int dev);
> > +struct XenDevice *xen_find_xendev(const char *type, int dom, int
> > +dev); struct XenDevice *xen_del_xendev(int dom, int dev); struct
> > +XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
> > +                                    struct XenDevOps *ops); struct
> > +XenDevice *xen_fe_get_xendev(const char *type, int dom, int dev,
> > +                                    char *backend, struct
> XenDevOps
> > +*ops);
> >  void xen_be_check_state(struct XenDevice *xendev);
> > +void xen_be_backend_changed(struct XenDevice *xendev, const char
> > +*node); void xen_be_frontend_changed(struct XenDevice *xendev, const
> > +char *node);
> >
> >  /* xen backend driver bits */
> >  int xen_be_init(void);
> > --
> > 1.8.3.2
> >
diff mbox

Patch

diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 5e324ef..10751df 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -988,8 +988,8 @@  void xen_init_display(int domid)
 wait_more:
     i++;
     main_loop_wait(true);
-    xfb = xen_be_find_xendev("vfb", domid, 0);
-    xin = xen_be_find_xendev("vkbd", domid, 0);
+    xfb = xen_find_xendev("vfb", domid, 0);
+    xin = xen_find_xendev("vkbd", domid, 0);
     if (!xfb || !xin) {
         if (i < 256) {
             usleep(10000);
diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs
index a0ca0aa..9ac9f7c 100644
--- a/hw/xen/Makefile.objs
+++ b/hw/xen/Makefile.objs
@@ -1,5 +1,5 @@ 
 # xen backend driver support
-common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
+common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o xen_pvdev.o
 
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index b2cb22b..844f918 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -44,86 +44,11 @@ 
 /* ------------------------------------------------------------- */
 
 /* public */
-XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
-struct xs_handle *xenstore = NULL;
 const char *xen_protocol;
 
 /* private */
-static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs = QTAILQ_HEAD_INITIALIZER(xendevs);
 static int debug = 0;
 
-/* ------------------------------------------------------------- */
-
-int xenstore_write_str(const char *base, const char *node, const char *val)
-{
-    char abspath[XEN_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[XEN_BUFSIZE];
-    unsigned int len;
-    char *str, *ret = NULL;
-
-    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
-    str = xs_read(xenstore, 0, abspath, &len);
-    if (str != NULL) {
-        /* move to qemu-allocated memory to make sure
-         * callers can savely g_free() stuff. */
-        ret = g_strdup(str);
-        free(str);
-    }
-    return ret;
-}
-
-int xenstore_write_int(const char *base, const char *node, int ival)
-{
-    char val[12];
-
-    snprintf(val, sizeof(val), "%d", ival);
-    return xenstore_write_str(base, node, val);
-}
-
-int xenstore_write_int64(const char *base, const char *node, int64_t ival)
-{
-    char val[21];
-
-    snprintf(val, sizeof(val), "%"PRId64, 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;
-    }
-    g_free(val);
-    return rc;
-}
-
-int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
-{
-    char *val;
-    int rc = -1;
-
-    val = xenstore_read_str(base, node);
-    if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
-        rc = 0;
-    }
-    g_free(val);
-    return rc;
-}
-
 int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val)
 {
     return xenstore_write_str(xendev->be, node, val);
@@ -195,183 +120,6 @@  int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
 }
 
 /* ------------------------------------------------------------- */
-
-struct XenDevice *xen_be_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;
-}
-
-/*
- * get xen backend device, allocate a new one if it doesn't exist.
- */
-static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
-                                           struct XenDevOps *ops)
-{
-    struct XenDevice *xendev;
-
-    xendev = xen_be_find_xendev(type, dom, dev);
-    if (xendev) {
-        return xendev;
-    }
-
-    /* init new xendev */
-    xendev = g_malloc0(ops->size);
-    xendev->type  = type;
-    xendev->dom   = dom;
-    xendev->dev   = dev;
-    xendev->ops   = ops;
-
-    snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
-             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 = xen_xc_evtchn_open(NULL, 0);
-    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
-        xen_be_printf(NULL, 0, "can't open evtchn device\n");
-        g_free(xendev);
-        return NULL;
-    }
-    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
-
-    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
-        xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
-        if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
-            xen_be_printf(NULL, 0, "can't open gnttab device\n");
-            xc_evtchn_close(xendev->evtchndev);
-            g_free(xendev);
-            return NULL;
-        }
-    } else {
-        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
-    }
-
-    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
-
-    if (xendev->ops->alloc) {
-        xendev->ops->alloc(xendev);
-    }
-
-    return xendev;
-}
-
-/*
- * release xen backend device.
- */
-static struct XenDevice *xen_be_del_xendev(int dom, int dev)
-{
-    struct XenDevice *xendev, *xnext;
-
-    /*
-     * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next) but
-     * we save the next pointer in xnext because we might free xendev.
-     */
-    xnext = xendevs.tqh_first;
-    while (xnext) {
-        xendev = xnext;
-        xnext = xendev->next.tqe_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[XEN_BUFSIZE];
-            snprintf(token, sizeof(token), "fe:%p", xendev);
-            xs_unwatch(xenstore, xendev->fe, token);
-            g_free(xendev->fe);
-        }
-
-        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
-            xc_evtchn_close(xendev->evtchndev);
-        }
-        if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
-            xc_gnttab_close(xendev->gnttabdev);
-        }
-
-        QTAILQ_REMOVE(&xendevs, xendev, next);
-        g_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 XenDevice *xendev, const char *node)
-{
-    if (node == NULL  ||  strcmp(node, "online") == 0) {
-        if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
-            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 XenDevice *xendev, const char *node)
-{
-    int fe_state;
-
-    if (node == NULL  ||  strcmp(node, "state") == 0) {
-        if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
-            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 (node == NULL  ||  strcmp(node, "protocol") == 0) {
-        g_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.        */
 
 /*
@@ -611,81 +359,6 @@  static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
     return 0;
 }
 
-static void xenstore_update_be(char *watch, char *type, int dom,
-                               struct XenDevOps *ops)
-{
-    struct XenDevice *xendev;
-    char path[XEN_BUFSIZE], *bepath;
-    unsigned int len, dev;
-
-    len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
-    if (strncmp(path, watch, len) != 0) {
-        return;
-    }
-    if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
-        strcpy(path, "");
-        if (sscanf(watch+len, "/%u", &dev) != 1) {
-            dev = -1;
-        }
-    }
-    if (dev == -1) {
-        return;
-    }
-
-    xendev = xen_be_get_xendev(type, dom, dev, ops);
-    if (xendev != NULL) {
-        bepath = xs_read(xenstore, 0, xendev->be, &len);
-        if (bepath == NULL) {
-            xen_be_del_xendev(dom, dev);
-        } else {
-            free(bepath);
-            xen_be_backend_changed(xendev, path);
-            xen_be_check_state(xendev);
-        }
-    }
-}
-
-static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
-{
-    char *node;
-    unsigned int len;
-
-    len = strlen(xendev->fe);
-    if (strncmp(xendev->fe, watch, len) != 0) {
-        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 (vec == NULL) {
-        goto cleanup;
-    }
-
-    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
-               &type, &dom, &ops) == 3) {
-        xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
-    }
-    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
-        xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
-    }
-
-cleanup:
-    free(vec);
-}
-
 static void xen_be_evtchn_event(void *opaque)
 {
     struct XenDevice *xendev = opaque;
@@ -706,32 +379,6 @@  static void xen_be_evtchn_event(void *opaque)
 
 /* -------------------------------------------------------------------- */
 
-int xen_be_init(void)
-{
-    xenstore = xs_daemon_open();
-    if (!xenstore) {
-        xen_be_printf(NULL, 0, "can't connect to xenstored\n");
-        return -1;
-    }
-
-    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0) {
-        goto err;
-    }
-
-    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
-        /* Check if xen_init() have been called */
-        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(const char *type, struct XenDevOps *ops)
 {
     return xenstore_scan(type, xen_domid, ops);
diff --git a/hw/xen/xen_pvdev.c b/hw/xen/xen_pvdev.c
new file mode 100644
index 0000000..dac8639
--- /dev/null
+++ b/hw/xen/xen_pvdev.c
@@ -0,0 +1,481 @@ 
+/*
+ * Xen para-virtualization device
+ *
+ *  Copyright (c) 2015 Intel Corporation
+ *  Authors:
+ *    Quan Xu <quan.xu@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#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 "hw/hw.h"
+#include "sysemu/char.h"
+#include "qemu/log.h"
+#include "hw/xen/xen_backend.h"
+
+#include <xen/grant_table.h>
+
+static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs =
+           QTAILQ_HEAD_INITIALIZER(xendevs);
+static int debug;
+
+/* public */
+XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
+struct xs_handle *xenstore;
+
+/*
+ * find Xen device
+ */
+struct XenDevice *xen_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;
+}
+
+/*
+ * get xen backend device, allocate a new one if it doesn't exist.
+ */
+struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
+                                    struct XenDevOps *ops)
+{
+    struct XenDevice *xendev;
+
+    xendev = xen_find_xendev(type, dom, dev);
+    if (xendev) {
+        return xendev;
+    }
+
+    /* init new xendev */
+    xendev = g_malloc0(ops->size);
+    xendev->type  = type;
+    xendev->dom   = dom;
+    xendev->dev   = dev;
+    xendev->ops   = ops;
+
+    snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
+             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 = xen_xc_evtchn_open(NULL, 0);
+    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
+        xen_be_printf(NULL, 0, "can't open evtchn device\n");
+        g_free(xendev);
+        return NULL;
+    }
+    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
+
+    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
+        xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
+        if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
+            xen_be_printf(NULL, 0, "can't open gnttab device\n");
+            xc_evtchn_close(xendev->evtchndev);
+            g_free(xendev);
+            return NULL;
+        }
+    } else {
+        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
+    }
+
+    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
+
+    if (xendev->ops->alloc) {
+        xendev->ops->alloc(xendev);
+    }
+
+    return xendev;
+}
+
+/*
+ * get xen fe device, allocate a new one if it doesn't exist.
+ */
+struct XenDevice *xen_fe_get_xendev(const char *type, int dom, int dev,
+                                    char *backend, struct XenDevOps *ops)
+{
+    struct XenDevice *xendev;
+
+    xendev = xen_find_xendev(type, dom, dev);
+    if (xendev) {
+        return xendev;
+    }
+
+    /* init new xendev */
+    xendev = g_malloc0(ops->size);
+    xendev->type  = type;
+    xendev->dom   = dom;
+    xendev->dev   = dev;
+    xendev->ops   = ops;
+
+    /*return if the ops->flags is not DEVOPS_FLAG_FE*/
+    if (!(ops->flags & DEVOPS_FLAG_FE)) {
+        return NULL;
+    }
+
+    snprintf(xendev->be, sizeof(xendev->be), "%s", backend);
+    snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
+             xendev->type, xendev->dev);
+
+    xendev->debug = debug;
+    xendev->local_port = -1;
+
+    xendev->evtchndev = xen_xc_evtchn_open(NULL, 0);
+    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
+        xen_be_printf(NULL, 0, "can't open evtchn device\n");
+        g_free(xendev);
+        return NULL;
+    }
+    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
+
+    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
+        xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
+        if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
+            xen_be_printf(NULL, 0, "can't open gnttab device\n");
+            xc_evtchn_close(xendev->evtchndev);
+            g_free(xendev);
+            return NULL;
+        }
+    } else {
+        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
+    }
+
+    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
+
+    if (xendev->ops->alloc) {
+        xendev->ops->alloc(xendev);
+    }
+
+    return xendev;
+}
+
+/*
+ * release xen device
+ */
+
+struct XenDevice *xen_del_xendev(int dom, int dev)
+{
+    struct XenDevice *xendev, *xnext;
+
+    /*
+     * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next) but
+     * we save the next pointer in xnext because we might free xendev.
+     */
+    xnext = xendevs.tqh_first;
+    while (xnext) {
+        xendev = xnext;
+        xnext = xendev->next.tqe_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[XEN_BUFSIZE];
+            snprintf(token, sizeof(token), "fe:%p", xendev);
+            xs_unwatch(xenstore, xendev->fe, token);
+            g_free(xendev->fe);
+        }
+
+        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
+            xc_evtchn_close(xendev->evtchndev);
+        }
+        if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
+            xc_gnttab_close(xendev->gnttabdev);
+        }
+
+        QTAILQ_REMOVE(&xendevs, xendev, next);
+        g_free(xendev);
+    }
+    return NULL;
+}
+
+/* ------------------------------------------------------------- */
+
+int xenstore_write_str(const char *base, const char *node, const char *val)
+{
+    char abspath[XEN_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[XEN_BUFSIZE];
+    unsigned int len;
+    char *str, *ret = NULL;
+
+    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
+    str = xs_read(xenstore, 0, abspath, &len);
+    if (str != NULL) {
+        /* move to qemu-allocated memory to make sure
+         * callers can savely g_free() stuff. */
+        ret = g_strdup(str);
+        free(str);
+    }
+    return ret;
+}
+
+int xenstore_write_int(const char *base, const char *node, int ival)
+{
+    char val[12];
+
+    snprintf(val, sizeof(val), "%d", ival);
+    return xenstore_write_str(base, node, val);
+}
+
+int xenstore_write_int64(const char *base, const char *node, int64_t ival)
+{
+    char val[21];
+
+    snprintf(val, sizeof(val), "%"PRId64, 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;
+    }
+    g_free(val);
+    return rc;
+}
+
+int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
+{
+    char *val;
+    int rc = -1;
+
+    val = xenstore_read_str(base, node);
+    if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
+        rc = 0;
+    }
+    g_free(val);
+    return rc;
+}
+
+char *xenstore_get_domain_name(uint32_t domid)
+{
+    char *dom_path, *str, *ret = NULL;;
+
+    dom_path = xs_get_domain_path(xenstore, domid);
+    str = xenstore_read_str(dom_path, "name");
+    free(dom_path);
+    if (str != NULL) {
+        ret = g_strdup(str);
+        free(str);
+    }
+
+    return ret;
+}
+
+/*
+ * Sync internal data structures on xenstore updates.
+ * Node specifies the changed field.  node = NULL means
+ * update all fields (used for initialization).
+ */
+void xen_be_backend_changed(struct XenDevice *xendev, const char *node)
+{
+    if (node == NULL  ||  strcmp(node, "online") == 0) {
+        if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
+            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);
+        }
+    }
+}
+
+void xen_be_frontend_changed(struct XenDevice *xendev, const char *node)
+{
+    int fe_state;
+
+    if (node == NULL  ||  strcmp(node, "state") == 0) {
+        if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
+            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 (node == NULL  ||  strcmp(node, "protocol") == 0) {
+        g_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);
+        }
+    }
+}
+
+static void xenstore_update_be(char *watch, char *type, int dom,
+                        struct XenDevOps *ops)
+{
+    struct XenDevice *xendev;
+    char path[XEN_BUFSIZE], *bepath;
+    unsigned int len, dev;
+
+    len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
+
+    if (strstr(watch, path) == NULL) {
+        return;
+    }
+    if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
+        strcpy(path, "");
+        if (sscanf(watch+len, "/%u", &dev) != 1) {
+            dev = -1;
+        }
+    }
+    if (dev == -1) {
+        return;
+    }
+
+    xendev = xen_be_get_xendev(type, dom, dev, ops);
+    if (xendev != NULL) {
+        bepath = xs_read(xenstore, 0, xendev->be, &len);
+        if (bepath == NULL) {
+            xen_del_xendev(dom, dev);
+        } else {
+            free(bepath);
+            xen_be_backend_changed(xendev, path);
+            if (!(ops->flags & DEVOPS_FLAG_FE)) {
+                xen_be_check_state(xendev);
+            }
+        }
+    }
+}
+
+static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
+{
+    char *node;
+    unsigned int len;
+
+    len = strlen(xendev->fe);
+    if (strncmp(xendev->fe, watch, len) != 0) {
+        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 (vec == NULL) {
+        goto cleanup;
+    }
+
+    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
+               &type, &dom, &ops) == 3) {
+        xenstore_update_be(vec[XS_WATCH_PATH], (void *)type, dom, (void *)ops);
+    }
+    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
+        xenstore_update_fe(vec[XS_WATCH_PATH], (void *)ptr);
+    }
+
+cleanup:
+    free(vec);
+}
+
+int xen_be_init(void)
+{
+    xenstore = xs_daemon_open();
+    if (!xenstore) {
+        xen_be_printf(NULL, 0, "can't connect to xenstored\n");
+        return -1;
+    }
+
+    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update,
+        NULL, NULL) < 0) {
+        goto err;
+    }
+
+    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
+
+        /* Check if xen_init() have been called */
+        goto err;
+    }
+    return 0;
+
+err:
+    qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
+    xs_daemon_close(xenstore);
+    xenstore = NULL;
+
+    return -1;
+}
diff --git a/include/hw/xen/xen_backend.h b/include/hw/xen/xen_backend.h
index 3b4125e..65476bf 100644
--- a/include/hw/xen/xen_backend.h
+++ b/include/hw/xen/xen_backend.h
@@ -15,6 +15,8 @@  struct XenDevice;
 #define DEVOPS_FLAG_NEED_GNTDEV   1
 /* don't expect frontend doing correct state transitions (aka console quirk) */
 #define DEVOPS_FLAG_IGNORE_STATE  2
+/*dev is frontend device*/
+#define DEVOPS_FLAG_FE            4
 
 struct XenDevOps {
     size_t    size;
@@ -77,9 +79,18 @@  int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival);
 int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval);
 int xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node, uint64_t *uval);
 
+char *xenstore_get_domain_name(uint32_t domid);
+
 const char *xenbus_strstate(enum xenbus_state state);
-struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev);
+struct XenDevice *xen_find_xendev(const char *type, int dom, int dev);
+struct XenDevice *xen_del_xendev(int dom, int dev);
+struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
+                                    struct XenDevOps *ops);
+struct XenDevice *xen_fe_get_xendev(const char *type, int dom, int dev,
+                                    char *backend, struct XenDevOps *ops);
 void xen_be_check_state(struct XenDevice *xendev);
+void xen_be_backend_changed(struct XenDevice *xendev, const char *node);
+void xen_be_frontend_changed(struct XenDevice *xendev, const char *node);
 
 /* xen backend driver bits */
 int xen_be_init(void);