Patchwork [V10,03/15] xen: Support new libxc calls from xen unstable.

login
register
mail settings
Submitter Anthony PERARD
Date Feb. 2, 2011, 2:49 p.m.
Message ID <1296658172-16609-4-git-send-email-anthony.perard@citrix.com>
Download mbox | patch
Permalink /patch/81508/
State New
Headers show

Comments

Anthony PERARD - Feb. 2, 2011, 2:49 p.m.
From: Anthony PERARD <anthony.perard@citrix.com>

This patch adds a generic layer for xc calls, allowing us to choose between the
xenner and xen implementations at runtime.

It also update the libxenctrl calls in Qemu to use the new interface,
otherwise Qemu wouldn't be able to build against new versions of the
library.

We check libxenctrl version in configure, from Xen 3.3.0 to Xen
unstable.

Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Alexander Graf <agraf@suse.de>
---
 Makefile.target      |    3 +
 configure            |   62 +++++++++++++++-
 hw/xen_backend.c     |   74 ++++++++++---------
 hw/xen_backend.h     |    7 +-
 hw/xen_common.h      |   38 ++++++----
 hw/xen_console.c     |   10 +-
 hw/xen_devconfig.c   |   10 +-
 hw/xen_disk.c        |   28 ++++---
 hw/xen_domainbuild.c |   29 ++++----
 hw/xen_interfaces.c  |  191 ++++++++++++++++++++++++++++++++++++++++++++++++
 hw/xen_interfaces.h  |  198 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/xen_nic.c         |   36 +++++-----
 hw/xenfb.c           |   14 ++--
 13 files changed, 584 insertions(+), 116 deletions(-)
 create mode 100644 hw/xen_interfaces.c
 create mode 100644 hw/xen_interfaces.h
Anthony Liguori - Feb. 24, 2011, 5:29 p.m.
On 02/02/2011 08:49 AM, anthony.perard@citrix.com wrote:
> From: Anthony PERARD<anthony.perard@citrix.com>
>
> This patch adds a generic layer for xc calls, allowing us to choose between the
> xenner and xen implementations at runtime.
>
> It also update the libxenctrl calls in Qemu to use the new interface,
> otherwise Qemu wouldn't be able to build against new versions of the
> library.
>
> We check libxenctrl version in configure, from Xen 3.3.0 to Xen
> unstable.
>
> Signed-off-by: Anthony PERARD<anthony.perard@citrix.com>
> Signed-off-by: Stefano Stabellini<stefano.stabellini@eu.citrix.com>
> Acked-by: Alexander Graf<agraf@suse.de>
> ---
>   Makefile.target      |    3 +
>   configure            |   62 +++++++++++++++-
>   hw/xen_backend.c     |   74 ++++++++++---------
>   hw/xen_backend.h     |    7 +-
>   hw/xen_common.h      |   38 ++++++----
>   hw/xen_console.c     |   10 +-
>   hw/xen_devconfig.c   |   10 +-
>   hw/xen_disk.c        |   28 ++++---
>   hw/xen_domainbuild.c |   29 ++++----
>   hw/xen_interfaces.c  |  191 ++++++++++++++++++++++++++++++++++++++++++++++++
>   hw/xen_interfaces.h  |  198 ++++++++++++++++++++++++++++++++++++++++++++++++++
>   hw/xen_nic.c         |   36 +++++-----
>   hw/xenfb.c           |   14 ++--
>   13 files changed, 584 insertions(+), 116 deletions(-)
>   create mode 100644 hw/xen_interfaces.c
>   create mode 100644 hw/xen_interfaces.h
>
> diff --git a/Makefile.target b/Makefile.target
> index db29e96..d09719f 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -205,6 +205,9 @@ QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
>   QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
>   QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
>
> +# xen support
> +obj-$(CONFIG_XEN) += xen_interfaces.o
> +
>   # xen backend driver support
>   obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o
>   obj-$(CONFIG_XEN) += xen_console.o xenfb.o xen_disk.o xen_nic.o
> diff --git a/configure b/configure
> index 5a9121d..fde9bad 100755
> --- a/configure
> +++ b/configure
> @@ -126,6 +126,7 @@ vnc_jpeg=""
>   vnc_png=""
>   vnc_thread="no"
>   xen=""
> +xen_ctrl_version=""
>   linux_aio=""
>   attr=""
>   vhost_net=""
> @@ -1144,13 +1145,71 @@ fi
>
>   if test "$xen" != "no" ; then
>     xen_libs="-lxenstore -lxenctrl -lxenguest"
> +
> +  # Xen unstable
>     cat>  $TMPC<<EOF
>   #include<xenctrl.h>
>   #include<xs.h>
> -int main(void) { xs_daemon_open(); xc_interface_open(); return 0; }
> +#include<stdint.h>
> +#include<xen/hvm/hvm_info_table.h>
> +#if !defined(HVM_MAX_VCPUS)
> +# error HVM_MAX_VCPUS not defined
> +#endif
> +int main(void) {
> +  xc_interface *xc;
> +  xs_daemon_open();
> +  xc = xc_interface_open(0, 0, 0);
> +  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
> +  xc_gnttab_open(NULL, 0);
> +  return 0;
> +}
>   EOF
>     if compile_prog "" "$xen_libs" ; then
> +    xen_ctrl_version=410
> +    xen=yes
> +
> +  # Xen 4.0.0
> +  elif (
> +      cat>  $TMPC<<EOF
> +#include<xenctrl.h>
> +#include<xs.h>
> +#include<stdint.h>
> +#include<xen/hvm/hvm_info_table.h>
> +#if !defined(HVM_MAX_VCPUS)
> +# error HVM_MAX_VCPUS not defined
> +#endif
> +int main(void) {
> +  xs_daemon_open();
> +  xc_interface_open();
> +  xc_gnttab_open();
> +  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
> +  return 0;
> +}
> +EOF
> +      compile_prog "" "$xen_libs"
> +    ) ; then
> +    xen_ctrl_version=400
> +    xen=yes
> +
> +  # Xen 3.3.0, 3.4.0
> +  elif (
> +      cat>  $TMPC<<EOF
> +#include<xenctrl.h>
> +#include<xs.h>
> +int main(void) {
> +  xs_daemon_open();
> +  xc_interface_open();
> +  xc_gnttab_open();
> +  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
> +  return 0;
> +}
> +EOF
> +      compile_prog "" "$xen_libs"
> +    ) ; then
> +    xen_ctrl_version=330
>       xen=yes
> +
> +  # Xen not found or unsupported
>     else
>       if test "$xen" = "yes" ; then
>         feature_not_found "xen"
> @@ -3009,6 +3068,7 @@ case "$target_arch2" in
>       if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
>         echo "CONFIG_XEN=y">>  $config_target_mak
>         echo "LIBS+=$xen_libs">>  $config_target_mak
> +      echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version">>  $config_target_mak
>       fi
>   esac
>   case "$target_arch2" in
> diff --git a/hw/xen_backend.c b/hw/xen_backend.c
> index 860b038..cf081e1 100644
> --- a/hw/xen_backend.c
> +++ b/hw/xen_backend.c
> @@ -43,7 +43,8 @@
>   /* ------------------------------------------------------------- */
>
>   /* public */
> -int xen_xc;
> +XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
> +XenGnttab xen_xcg = XC_HANDLER_INITIAL_VALUE;
>   struct xs_handle *xenstore = NULL;
>   const char *xen_protocol;
>
> @@ -58,7 +59,7 @@ 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)))
> +    if (!xs_ops.write(xenstore, 0, abspath, val, strlen(val)))
>           return -1;
>       return 0;
>   }
> @@ -70,7 +71,7 @@ char *xenstore_read_str(const char *base, const char *node)
>       char *str, *ret = NULL;
>
>       snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
> -    str = xs_read(xenstore, 0, abspath,&len);
> +    str = xs_ops.read(xenstore, 0, abspath,&len);
>    

I think I gave this feedback before but I'd really like to see static 
inlines here.

It's very likely that you'll either want to have tracing or some 
commands can have a NULL function pointer in which case having a central 
location to do this is very useful.

Plus, it's more natural to read code that's making a function call 
instead of going through a function pointer in a structure redirection.

Can probably do this with just a sed over the current patch.

Regards,

Anthony Liguori

>       if (str != NULL) {
>           /* move to qemu-allocated memory to make sure
>            * callers can savely qemu_free() stuff. */
> @@ -197,7 +198,7 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
>       xendev->dev   = dev;
>       xendev->ops   = ops;
>
> -    dom0 = xs_get_domain_path(xenstore, 0);
> +    dom0 = xs_ops.get_domain_path(xenstore, 0);
>       snprintf(xendev->be, sizeof(xendev->be), "%s/backend/%s/%d/%d",
>                dom0, xendev->type, xendev->dom, xendev->dev);
>       snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
> @@ -207,24 +208,24 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
>       xendev->debug      = debug;
>       xendev->local_port = -1;
>
> -    xendev->evtchndev = xc_evtchn_open();
> -    if (xendev->evtchndev<  0) {
> +    xendev->evtchndev = xc_evtchn_ops.open(NULL, 0);
> +    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
>           xen_be_printf(NULL, 0, "can't open evtchn device\n");
>           qemu_free(xendev);
>           return NULL;
>       }
> -    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
> +    fcntl(xc_evtchn_ops.fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
>
>       if (ops->flags&  DEVOPS_FLAG_NEED_GNTDEV) {
> -        xendev->gnttabdev = xc_gnttab_open();
> -        if (xendev->gnttabdev<  0) {
> +        xendev->gnttabdev = xc_gnttab_ops.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);
> +            xc_evtchn_ops.close(xendev->evtchndev);
>               qemu_free(xendev);
>               return NULL;
>           }
>       } else {
> -        xendev->gnttabdev = -1;
> +        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
>       }
>
>       QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
> @@ -262,14 +263,16 @@ static struct XenDevice *xen_be_del_xendev(int dom, int dev)
>           if (xendev->fe) {
>               char token[XEN_BUFSIZE];
>               snprintf(token, sizeof(token), "fe:%p", xendev);
> -            xs_unwatch(xenstore, xendev->fe, token);
> +            xs_ops.unwatch(xenstore, xendev->fe, token);
>               qemu_free(xendev->fe);
>           }
>
> -        if (xendev->evtchndev>= 0)
> -            xc_evtchn_close(xendev->evtchndev);
> -        if (xendev->gnttabdev>= 0)
> -            xc_gnttab_close(xendev->gnttabdev);
> +        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
> +            xc_evtchn_ops.close(xendev->evtchndev);
> +        }
> +        if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
> +            xc_gnttab_ops.close(xendev->gnttabdev);
> +        }
>
>           QTAILQ_REMOVE(&xendevs, xendev, next);
>           qemu_free(xendev);
> @@ -358,7 +361,7 @@ static int xen_be_try_setup(struct XenDevice *xendev)
>
>       /* setup frontend watch */
>       snprintf(token, sizeof(token), "fe:%p", xendev);
> -    if (!xs_watch(xenstore, xendev->fe, token)) {
> +    if (!xs_ops.watch(xenstore, xendev->fe, token)) {
>           xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
>                         xendev->fe);
>           return -1;
> @@ -506,17 +509,17 @@ static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
>       unsigned int cdev, j;
>
>       /* setup watch */
> -    dom0 = xs_get_domain_path(xenstore, 0);
> +    dom0 = xs_ops.get_domain_path(xenstore, 0);
>       snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
>       snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
>       free(dom0);
> -    if (!xs_watch(xenstore, path, token)) {
> +    if (!xs_ops.watch(xenstore, path, token)) {
>           xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
>           return -1;
>       }
>
>       /* look for backends */
> -    dev = xs_directory(xenstore, 0, path,&cdev);
> +    dev = xs_ops.directory(xenstore, 0, path,&cdev);
>       if (!dev)
>           return 0;
>       for (j = 0; j<  cdev; j++) {
> @@ -536,7 +539,7 @@ static void xenstore_update_be(char *watch, char *type, int dom,
>       char path[XEN_BUFSIZE], *dom0;
>       unsigned int len, dev;
>
> -    dom0 = xs_get_domain_path(xenstore, 0);
> +    dom0 = xs_ops.get_domain_path(xenstore, 0);
>       len = snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
>       free(dom0);
>       if (strncmp(path, watch, len) != 0)
> @@ -583,7 +586,7 @@ static void xenstore_update(void *unused)
>       intptr_t type, ops, ptr;
>       unsigned int dom, count;
>
> -    vec = xs_read_watch(xenstore,&count);
> +    vec = xs_ops.read_watch(xenstore,&count);
>       if (vec == NULL)
>           goto cleanup;
>
> @@ -602,13 +605,13 @@ static void xen_be_evtchn_event(void *opaque)
>       struct XenDevice *xendev = opaque;
>       evtchn_port_t port;
>
> -    port = xc_evtchn_pending(xendev->evtchndev);
> +    port = xc_evtchn_ops.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);
> +    xc_evtchn_ops.unmask(xendev->evtchndev, port);
>
>       if (xendev->ops->event)
>           xendev->ops->event(xendev);
> @@ -618,25 +621,26 @@ static void xen_be_evtchn_event(void *opaque)
>
>   int xen_be_init(void)
>   {
> -    xenstore = xs_daemon_open();
> +    xenstore = xs_ops.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)
> +    if (qemu_set_fd_handler(xs_ops.fileno(xenstore), xenstore_update, NULL, NULL)<  0) {
>           goto err;
> +    }
>
> -    xen_xc = xc_interface_open();
> -    if (xen_xc == -1) {
> +    xen_xc = xc_ops.interface_open(0, 0, 0);
> +    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
>           xen_be_printf(NULL, 0, "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);
> +    qemu_set_fd_handler(xs_ops.fileno(xenstore), NULL, NULL, NULL);
> +    xs_ops.daemon_close(xenstore);
>       xenstore = NULL;
>
>       return -1;
> @@ -651,14 +655,14 @@ int xen_be_bind_evtchn(struct XenDevice *xendev)
>   {
>       if (xendev->local_port != -1)
>           return 0;
> -    xendev->local_port = xc_evtchn_bind_interdomain
> +    xendev->local_port = xc_evtchn_ops.bind_interdomain
>           (xendev->evtchndev, xendev->dom, xendev->remote_port);
>       if (xendev->local_port == -1) {
>           xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
>           return -1;
>       }
>       xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
> -    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
> +    qemu_set_fd_handler(xc_evtchn_ops.fd(xendev->evtchndev),
>                           xen_be_evtchn_event, NULL, xendev);
>       return 0;
>   }
> @@ -667,15 +671,15 @@ void xen_be_unbind_evtchn(struct XenDevice *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);
> +    qemu_set_fd_handler(xc_evtchn_ops.fd(xendev->evtchndev), NULL, NULL, NULL);
> +    xc_evtchn_ops.unbind(xendev->evtchndev, xendev->local_port);
>       xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
>       xendev->local_port = -1;
>   }
>
>   int xen_be_send_notify(struct XenDevice *xendev)
>   {
> -    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
> +    return xc_evtchn_ops.notify(xendev->evtchndev, xendev->local_port);
>   }
>
>   /*
> diff --git a/hw/xen_backend.h b/hw/xen_backend.h
> index 1b428e3..5af09b8 100644
> --- a/hw/xen_backend.h
> +++ b/hw/xen_backend.h
> @@ -2,6 +2,7 @@
>   #define QEMU_HW_XEN_BACKEND_H 1
>
>   #include "xen_common.h"
> +#include "xen_interfaces.h"
>   #include "sysemu.h"
>   #include "net.h"
>
> @@ -45,8 +46,8 @@ struct XenDevice {
>       int                remote_port;
>       int                local_port;
>
> -    int                evtchndev;
> -    int                gnttabdev;
> +    XenEvtchn          evtchndev;
> +    XenGnttab          gnttabdev;
>
>       struct XenDevOps   *ops;
>       QTAILQ_ENTRY(XenDevice) next;
> @@ -55,7 +56,7 @@ struct XenDevice {
>   /* ------------------------------------------------------------- */
>
>   /* variables */
> -extern int xen_xc;
> +extern XenXC xen_xc;
>   extern struct xs_handle *xenstore;
>   extern const char *xen_protocol;
>
> diff --git a/hw/xen_common.h b/hw/xen_common.h
> index 8a55b44..3a08f6a 100644
> --- a/hw/xen_common.h
> +++ b/hw/xen_common.h
> @@ -1,6 +1,8 @@
>   #ifndef QEMU_HW_XEN_COMMON_H
>   #define QEMU_HW_XEN_COMMON_H 1
>
> +#include "config-target.h"
> +
>   #include<stddef.h>
>   #include<inttypes.h>
>
> @@ -13,22 +15,28 @@
>   #include "qemu-queue.h"
>
>   /*
> - * tweaks needed to build with different xen versions
> - *  0x00030205 ->  3.1.0
> - *  0x00030207 ->  3.2.0
> - *  0x00030208 ->  unstable
> + * We don't support Xen prior to 3.3.0.
>    */
> -#include<xen/xen-compat.h>
> -#if __XEN_LATEST_INTERFACE_VERSION__<  0x00030205
> -# define evtchn_port_or_error_t int
> -#endif
> -#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()
> +
> +/* Xen unstable */
> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION<  410
> +typedef int XenXC;
> +#  define XC_INTERFACE_FMT "%i"
> +#  define XC_HANDLER_INITIAL_VALUE    -1
> +static inline int xc_fd(int xen_xc)
> +{
> +    return xen_xc;
> +}
> +#else
> +typedef xc_interface *XenXC;
> +#  define XC_INTERFACE_FMT "%p"
> +#  define XC_HANDLER_INITIAL_VALUE    NULL
> +/* FIXME The fd of xen_xc is now xen_xc->fd */
> +/* fd is the first field, so this works */
> +static inline int xc_fd(xc_interface *xen_xc)
> +{
> +    return *(int*)xen_xc;
> +}
>   #endif
>
>   #endif /* QEMU_HW_XEN_COMMON_H */
> diff --git a/hw/xen_console.c b/hw/xen_console.c
> index d2261f4..7f79df9 100644
> --- a/hw/xen_console.c
> +++ b/hw/xen_console.c
> @@ -183,7 +183,7 @@ static int con_init(struct XenDevice *xendev)
>       char *type, *dom;
>
>       /* setup */
> -    dom = xs_get_domain_path(xenstore, con->xendev.dom);
> +    dom = xs_ops.get_domain_path(xenstore, con->xendev.dom);
>       snprintf(con->console, sizeof(con->console), "%s/console", dom);
>       free(dom);
>
> @@ -214,10 +214,10 @@ static int con_connect(struct XenDevice *xendev)
>       if (xenstore_read_int(con->console, "limit",&limit) == 0)
>   	con->buffer.max_capacity = limit;
>
> -    con->sring = xc_map_foreign_range(xen_xc, con->xendev.dom,
> -				      XC_PAGE_SIZE,
> -				      PROT_READ|PROT_WRITE,
> -				      con->ring_ref);
> +    con->sring = xc_ops.map_foreign_range(xen_xc, con->xendev.dom,
> +                                          XC_PAGE_SIZE,
> +                                          PROT_READ|PROT_WRITE,
> +                                          con->ring_ref);
>       if (!con->sring)
>   	return -1;
>
> diff --git a/hw/xen_devconfig.c b/hw/xen_devconfig.c
> index 8d50216..b79c444 100644
> --- a/hw/xen_devconfig.c
> +++ b/hw/xen_devconfig.c
> @@ -24,7 +24,7 @@ void xen_config_cleanup(void)
>       struct xs_dirs *d;
>
>       QTAILQ_FOREACH(d,&xs_cleanup, list) {
> -	xs_rm(xenstore, 0, d->xs_dir);
> +	xs_ops.rm(xenstore, 0, d->xs_dir);
>       }
>   }
>
> @@ -39,13 +39,13 @@ static int xen_config_dev_mkdir(char *dev, int p)
>               .perms = p,
>           }};
>
> -    if (!xs_mkdir(xenstore, 0, dev)) {
> +    if (!xs_ops.mkdir(xenstore, 0, dev)) {
>   	xen_be_printf(NULL, 0, "xs_mkdir %s: failed\n", dev);
>   	return -1;
>       }
>       xen_config_cleanup_dir(qemu_strdup(dev));
>
> -    if (!xs_set_permissions(xenstore, 0, dev, perms, 2)) {
> +    if (!xs_ops.set_permissions(xenstore, 0, dev, perms, 2)) {
>   	xen_be_printf(NULL, 0, "xs_set_permissions %s: failed\n", dev);
>   	return -1;
>       }
> @@ -57,11 +57,11 @@ static int xen_config_dev_dirs(const char *ftype, const char *btype, int vdev,
>   {
>       char *dom;
>
> -    dom = xs_get_domain_path(xenstore, xen_domid);
> +    dom = xs_ops.get_domain_path(xenstore, xen_domid);
>       snprintf(fe, len, "%s/device/%s/%d", dom, ftype, vdev);
>       free(dom);
>
> -    dom = xs_get_domain_path(xenstore, 0);
> +    dom = xs_ops.get_domain_path(xenstore, 0);
>       snprintf(be, len, "%s/backend/%s/%d/%d", dom, btype, xen_domid, vdev);
>       free(dom);
>
> diff --git a/hw/xen_disk.c b/hw/xen_disk.c
> index 7f6aaca..7fe7d56 100644
> --- a/hw/xen_disk.c
> +++ b/hw/xen_disk.c
> @@ -239,7 +239,7 @@ err:
>
>   static void ioreq_unmap(struct ioreq *ioreq)
>   {
> -    int gnt = ioreq->blkdev->xendev.gnttabdev;
> +    XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
>       int i;
>
>       if (ioreq->v.niov == 0)
> @@ -247,18 +247,20 @@ static void ioreq_unmap(struct ioreq *ioreq)
>       if (batch_maps) {
>           if (!ioreq->pages)
>               return;
> -        if (xc_gnttab_munmap(gnt, ioreq->pages, ioreq->v.niov) != 0)
> -            xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
> +        if (xc_gnttab_ops.munmap(gnt, ioreq->pages, ioreq->v.niov) != 0) {
> +            xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_ops.munmap failed: %s\n",
>                             strerror(errno));
> +        }
>           ioreq->blkdev->cnt_map -= ioreq->v.niov;
>           ioreq->pages = NULL;
>       } else {
>           for (i = 0; i<  ioreq->v.niov; i++) {
>               if (!ioreq->page[i])
>                   continue;
> -            if (xc_gnttab_munmap(gnt, ioreq->page[i], 1) != 0)
> -                xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
> +            if (xc_gnttab_ops.munmap(gnt, ioreq->page[i], 1) != 0) {
> +                xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_ops.munmap failed: %s\n",
>                                 strerror(errno));
> +            }
>               ioreq->blkdev->cnt_map--;
>               ioreq->page[i] = NULL;
>           }
> @@ -267,13 +269,13 @@ static void ioreq_unmap(struct ioreq *ioreq)
>
>   static int ioreq_map(struct ioreq *ioreq)
>   {
> -    int gnt = ioreq->blkdev->xendev.gnttabdev;
> +    XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
>       int i;
>
>       if (ioreq->v.niov == 0)
>           return 0;
>       if (batch_maps) {
> -        ioreq->pages = xc_gnttab_map_grant_refs
> +        ioreq->pages = xc_gnttab_ops.map_grant_refs
>               (gnt, ioreq->v.niov, ioreq->domids, ioreq->refs, ioreq->prot);
>           if (ioreq->pages == NULL) {
>               xen_be_printf(&ioreq->blkdev->xendev, 0,
> @@ -287,7 +289,7 @@ static int ioreq_map(struct ioreq *ioreq)
>           ioreq->blkdev->cnt_map += ioreq->v.niov;
>       } else  {
>           for (i = 0; i<  ioreq->v.niov; i++) {
> -            ioreq->page[i] = xc_gnttab_map_grant_ref
> +            ioreq->page[i] = xc_gnttab_ops.map_grant_ref
>                   (gnt, ioreq->domids[i], ioreq->refs[i], ioreq->prot);
>               if (ioreq->page[i] == NULL) {
>                   xen_be_printf(&ioreq->blkdev->xendev, 0,
> @@ -687,10 +689,10 @@ static int blk_connect(struct XenDevice *xendev)
>               blkdev->protocol = BLKIF_PROTOCOL_X86_64;
>       }
>
> -    blkdev->sring = xc_gnttab_map_grant_ref(blkdev->xendev.gnttabdev,
> -                                            blkdev->xendev.dom,
> -                                            blkdev->ring_ref,
> -                                            PROT_READ | PROT_WRITE);
> +    blkdev->sring = xc_gnttab_ops.map_grant_ref(blkdev->xendev.gnttabdev,
> +                                                blkdev->xendev.dom,
> +                                                blkdev->ring_ref,
> +                                                PROT_READ | PROT_WRITE);
>       if (!blkdev->sring)
>           return -1;
>       blkdev->cnt_map++;
> @@ -742,7 +744,7 @@ static void blk_disconnect(struct XenDevice *xendev)
>       xen_be_unbind_evtchn(&blkdev->xendev);
>
>       if (blkdev->sring) {
> -        xc_gnttab_munmap(blkdev->xendev.gnttabdev, blkdev->sring, 1);
> +        xc_gnttab_ops.munmap(blkdev->xendev.gnttabdev, blkdev->sring, 1);
>           blkdev->cnt_map--;
>           blkdev->sring = NULL;
>       }
> diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
> index 7f1fd66..ae241fa 100644
> --- a/hw/xen_domainbuild.c
> +++ b/hw/xen_domainbuild.c
> @@ -25,22 +25,22 @@ static int xenstore_domain_mkdir(char *path)
>       char subpath[256];
>       int i;
>
> -    if (!xs_mkdir(xenstore, 0, path)) {
> +    if (!xs_ops.mkdir(xenstore, 0, path)) {
>           fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
>   	return -1;
>       }
> -    if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
> +    if (!xs_ops.set_permissions(xenstore, 0, path, perms_ro, 2)) {
>           fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
>   	return -1;
>       }
>
>       for (i = 0; writable[i]; i++) {
>           snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
> -        if (!xs_mkdir(xenstore, 0, subpath)) {
> +        if (!xs_ops.mkdir(xenstore, 0, subpath)) {
>               fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
>               return -1;
>           }
> -        if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
> +        if (!xs_ops.set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
>               fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
>               return -1;
>           }
> @@ -59,7 +59,7 @@ int xenstore_domain_init1(const char *kernel, const char *ramdisk,
>                qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
>                qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
>                qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
> -    dom = xs_get_domain_path(xenstore, xen_domid);
> +    dom = xs_ops.get_domain_path(xenstore, xen_domid);
>       snprintf(vm,  sizeof(vm),  "/vm/%s", uuid_string);
>
>       xenstore_domain_mkdir(dom);
> @@ -104,13 +104,13 @@ int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
>   {
>       char *dom;
>
> -    dom = xs_get_domain_path(xenstore, xen_domid);
> +    dom = xs_ops.get_domain_path(xenstore, xen_domid);
>
>       /* signal new domain */
> -    xs_introduce_domain(xenstore,
> -                        xen_domid,
> -                        xenstore_mfn,
> -                        xenstore_port);
> +    xs_ops.introduce_domain(xenstore,
> +                            xen_domid,
> +                            xenstore_mfn,
> +                            xenstore_port);
>
>       /* xenstore */
>       xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
> @@ -176,8 +176,9 @@ static int xen_domain_watcher(void)
>       for (i = 3; i<  n; i++) {
>           if (i == fd[0])
>               continue;
> -        if (i == xen_xc)
> +        if (i == xc_fd(xen_xc)) {
>               continue;
> +        }
>           close(i);
>       }
>
> @@ -216,12 +217,12 @@ static void xen_domain_cleanup(void)
>   {
>       char *dom;
>
> -    dom = xs_get_domain_path(xenstore, xen_domid);
> +    dom = xs_ops.get_domain_path(xenstore, xen_domid);
>       if (dom) {
> -        xs_rm(xenstore, 0, dom);
> +        xs_ops.rm(xenstore, 0, dom);
>           free(dom);
>       }
> -    xs_release_domain(xenstore, xen_domid);
> +    xs_ops.release_domain(xenstore, xen_domid);
>   }
>
>   int xen_domain_build_pv(const char *kernel, const char *ramdisk,
> diff --git a/hw/xen_interfaces.c b/hw/xen_interfaces.c
> new file mode 100644
> index 0000000..96f33fe
> --- /dev/null
> +++ b/hw/xen_interfaces.c
> @@ -0,0 +1,191 @@
> +/*
> + * Copyright (C) 2011       Citrix Ltd.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2.  See
> + * the COPYING file in the top-level directory.
> + *
> + */
> +
> +#include "config-host.h"
> +
> +#include<xenctrl.h>
> +#include<xs.h>
> +
> +#include "hw.h"
> +#include "xen.h"
> +#include "xen_common.h"
> +#include "xen_interfaces.h"
> +
> +#ifdef CONFIG_XEN
> +
> +#  if CONFIG_XEN_CTRL_INTERFACE_VERSION<  410
> +static int evtchn_open(xentoollog_logger *logger, unsigned open_flags)
> +{
> +    return xc_evtchn_open();
> +}
> +
> +static XenEvtOps xc_evtchn_xen = {
> +    .open               = evtchn_open,
> +    .close              = xc_evtchn_close,
> +    .fd                 = xc_evtchn_fd,
> +    .notify             = xc_evtchn_notify,
> +    .bind_unbound_port  = xc_evtchn_bind_unbound_port,
> +    .bind_interdomain   = xc_evtchn_bind_interdomain,
> +    .bind_virq          = xc_evtchn_bind_virq,
> +    .unbind             = xc_evtchn_unbind,
> +    .pending            = xc_evtchn_pending,
> +    .unmask             = xc_evtchn_unmask,
> +};
> +
> +#  else /* CONFIG_XEN_CTRL_INTERFACE_VERSION>= 410 */
> +static XenEvtOps xc_evtchn_xen = {
> +    .open               = xc_evtchn_open,
> +    .close              = xc_evtchn_close,
> +    .fd                 = xc_evtchn_fd,
> +    .notify             = xc_evtchn_notify,
> +    .bind_unbound_port  = xc_evtchn_bind_unbound_port,
> +    .bind_interdomain   = xc_evtchn_bind_interdomain,
> +    .bind_virq          = xc_evtchn_bind_virq,
> +    .unbind             = xc_evtchn_unbind,
> +    .pending            = xc_evtchn_pending,
> +    .unmask             = xc_evtchn_unmask,
> +};
> +#  endif
> +
> +static int xs_domid(struct xs_handle *h, int domid)
> +{
> +    return -1;
> +}
> +
> +static XenStoreOps xs_xen = {
> +    .daemon_open           = xs_daemon_open,
> +    .domain_open           = xs_domain_open,
> +    .daemon_open_readonly  = xs_daemon_open_readonly,
> +    .domid                 = xs_domid,
> +    .daemon_close          = xs_daemon_close,
> +    .directory             = xs_directory,
> +    .read                  = xs_read,
> +    .write                 = xs_write,
> +    .mkdir                 = xs_mkdir,
> +    .rm                    = xs_rm,
> +    .get_permissions       = xs_get_permissions,
> +    .set_permissions       = xs_set_permissions,
> +    .watch                 = xs_watch,
> +    .fileno                = xs_fileno,
> +    .read_watch            = xs_read_watch,
> +    .unwatch               = xs_unwatch,
> +    .transaction_start     = xs_transaction_start,
> +    .transaction_end       = xs_transaction_end,
> +    .introduce_domain      = xs_introduce_domain,
> +    .resume_domain         = xs_resume_domain,
> +    .release_domain        = xs_release_domain,
> +    .get_domain_path       = xs_get_domain_path,
> +    .is_domain_introduced  = xs_is_domain_introduced,
> +};
> +
> +/* ------------------------------------------------------------- */
> +/* xen grant table interface                                     */
> +
> +#  if CONFIG_XEN_CTRL_INTERFACE_VERSION<  410
> +static int gnttab_open(xentoollog_logger *logger, unsigned open_flags)
> +{
> +    return xc_gnttab_open();
> +}
> +
> +static XenGnttabOps xc_gnttab_xen = {
> +    .open            = gnttab_open,
> +    .close           = xc_gnttab_close,
> +    .map_grant_ref   = xc_gnttab_map_grant_ref,
> +    .map_grant_refs  = xc_gnttab_map_grant_refs,
> +    .munmap          = xc_gnttab_munmap,
> +};
> +
> +#  else /* CONFIG_XEN_CTRL_INTERFACE_VERSION>= 410 */
> +static XenGnttabOps xc_gnttab_xen = {
> +    .open            = xc_gnttab_open,
> +    .close           = xc_gnttab_close,
> +    .map_grant_ref   = xc_gnttab_map_grant_ref,
> +    .map_grant_refs  = xc_gnttab_map_grant_refs,
> +    .munmap          = xc_gnttab_munmap,
> +};
> +#  endif
> +
> +/* ------------------------------------------------------------- */
> +/* xen hypercall interface                                       */
> +
> +#  if CONFIG_XEN_CTRL_INTERFACE_VERSION<  400
> +static XenXC interface_open(xentoollog_logger *logger,
> +                            xentoollog_logger *dombuild_logger,
> +                            unsigned open_flags)
> +{
> +    return xc_interface_open();
> +}
> +
> +static void *map_foreign_batch(int xc_handle, uint32_t dom, int prot,
> +                               const xen_pfn_t *arr, int *err, unsigned int num)
> +{
> +    return xc_map_foreign_batch(xc_handle, dom, prot, (xen_pfn_t*)arr, num);
> +}
> +
> +struct XenIfOps xc_xen = {
> +    .interface_open                 = interface_open,
> +    .interface_close                = xc_interface_close,
> +    .map_foreign_range              = xc_map_foreign_range,
> +    .map_foreign_pages              = xc_map_foreign_pages,
> +    .map_foreign_bulk               = map_foreign_batch,
> +    .domain_populate_physmap_exact  = xc_domain_memory_populate_physmap,
> +};
> +
> +#  elif CONFIG_XEN_CTRL_INTERFACE_VERSION<  410
> +static XenXC interface_open(xentoollog_logger *logger,
> +                            xentoollog_logger *dombuild_logger,
> +                            unsigned open_flags)
> +{
> +    return xc_interface_open();
> +}
> +
> +struct XenIfOps xc_xen = {
> +    .interface_open                 = interface_open,
> +    .interface_close                = xc_interface_close,
> +    .map_foreign_range              = xc_map_foreign_range,
> +    .map_foreign_pages              = xc_map_foreign_pages,
> +    .map_foreign_bulk               = xc_map_foreign_bulk,
> +    .domain_populate_physmap_exact  = xc_domain_memory_populate_physmap,
> +};
> +
> +#  else /* CONFIG_XEN_CTRL_INTERFACE_VERSION>= 410 */
> +struct XenIfOps xc_xen = {
> +    .interface_open                 = xc_interface_open,
> +    .interface_close                = xc_interface_close,
> +    .map_foreign_range              = xc_map_foreign_range,
> +    .map_foreign_pages              = xc_map_foreign_pages,
> +    .map_foreign_bulk               = xc_map_foreign_bulk,
> +    .domain_populate_physmap_exact  = xc_domain_populate_physmap_exact,
> +};
> +#  endif
> +
> +#endif /* CONFIG_XEN */
> +
> +XenEvtOps xc_evtchn_ops;
> +XenGnttabOps xc_gnttab_ops;
> +XenIfOps xc_ops;
> +XenStoreOps xs_ops;
> +
> +void xen_interfaces_init(void)
> +{
> +    switch (xen_mode) {
> +#ifdef CONFIG_XEN
> +    case XEN_ATTACH:
> +    case XEN_CREATE:
> +        xc_evtchn_ops = xc_evtchn_xen;
> +        xc_gnttab_ops = xc_gnttab_xen;
> +        xc_ops        = xc_xen;
> +        xs_ops        = xs_xen;
> +        break;
> +#endif
> +    default:
> +        fprintf(stderr, "ERROR: Compiled without %s support, sorry.\n",
> +                xen_mode == XEN_EMULATE ? "xenner" : "Xen");
> +        exit(1);
> +    }
> +}
> diff --git a/hw/xen_interfaces.h b/hw/xen_interfaces.h
> new file mode 100644
> index 0000000..ec0ab68
> --- /dev/null
> +++ b/hw/xen_interfaces.h
> @@ -0,0 +1,198 @@
> +/*
> + * Copyright (C) 2011       Citrix Ltd.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2.  See
> + * the COPYING file in the top-level directory.
> + *
> + */
> +
> +#ifndef QEMU_HW_XEN_INTERFACES_H
> +#define QEMU_HW_XEN_INTERFACES_H 1
> +
> +#include<xenctrl.h>
> +#include<xs.h>
> +
> +#include "hw/xen_common.h"
> +
> +
> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION<  410
> +typedef struct xentoollog_logger xentoollog_logger;
> +#endif
> +
> +/* ------------------------------------------------------------- */
> +/* xen event channel interface                                   */
> +
> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION<  410
> +typedef int XenEvtchn;
> +#else
> +typedef xc_evtchn *XenEvtchn;
> +#endif
> +
> +typedef XenEvtchn (*xc_evtchn_open_fn)
> +    (xentoollog_logger *logger, unsigned open_flags);
> +typedef int (*xc_evtchn_close_fn)(XenEvtchn xce);
> +typedef int (*xc_evtchn_fd_fn)(XenEvtchn xce);
> +typedef int (*xc_evtchn_notify_fn)(XenEvtchn xce, evtchn_port_t port);
> +typedef evtchn_port_or_error_t (*xc_evtchn_bind_unbound_port_fn)
> +    (XenEvtchn xce, int domid);
> +typedef evtchn_port_or_error_t (*xc_evtchn_bind_interdomain_fn)
> +    (XenEvtchn xce, int domid, evtchn_port_t remote_port);
> +typedef evtchn_port_or_error_t (*xc_evtchn_bind_virq_fn)
> +    (XenEvtchn xce, unsigned int virq);
> +typedef int (*xc_evtchn_unbind_fn) (XenEvtchn xce, evtchn_port_t port);
> +typedef evtchn_port_or_error_t (*xc_evtchn_pending_fn)(XenEvtchn xce);
> +typedef int (*xc_evtchn_unmask_fn)(XenEvtchn xce, evtchn_port_t port);
> +
> +struct XenEvtOps {
> +    xc_evtchn_open_fn               open;
> +    xc_evtchn_close_fn              close;
> +    xc_evtchn_fd_fn                 fd;
> +    xc_evtchn_notify_fn             notify;
> +    xc_evtchn_bind_unbound_port_fn  bind_unbound_port;
> +    xc_evtchn_bind_interdomain_fn   bind_interdomain;
> +    xc_evtchn_bind_virq_fn          bind_virq;
> +    xc_evtchn_unbind_fn             unbind;
> +    xc_evtchn_pending_fn            pending;
> +    xc_evtchn_unmask_fn             unmask;
> +};
> +typedef struct XenEvtOps XenEvtOps;
> +extern XenEvtOps xc_evtchn_ops;
> +
> +/* ------------------------------------------------------------- */
> +/* xenstore interface                                            */
> +
> +struct xs_handle;
> +
> +typedef struct xs_handle *(*xenstore_daemon_open_fn)(void);
> +typedef struct xs_handle *(*xenstore_domain_open_fn)(void);
> +typedef struct xs_handle *(*xenstore_daemon_open_readonly_fn)(void);
> +typedef int (*xenstore_domid_fn)(struct xs_handle *h, int domid);
> +typedef void (*xenstore_daemon_close_fn)(struct xs_handle *);
> +typedef char **(*xenstore_directory_fn)
> +    (struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *num);
> +typedef void *(*xenstore_read_fn)
> +    (struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *len);
> +typedef bool (*xenstore_write_fn)
> +    (struct xs_handle *h, xs_transaction_t t, const char *path,
> +     const void *data, unsigned int len);
> +typedef bool (*xenstore_mkdir_fn)
> +    (struct xs_handle *h, xs_transaction_t t, const char *path);
> +typedef bool (*xenstore_rm_fn)
> +    (struct xs_handle *h, xs_transaction_t t, const char *path);
> +typedef struct xs_permissions *(*xenstore_get_permissions_fn)
> +    (struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *num);
> +typedef bool (*xenstore_set_permissions_fn)
> +    (struct xs_handle *h, xs_transaction_t t, const char *path,
> +     struct xs_permissions *perms, unsigned int num_perms);
> +typedef bool (*xenstore_watch_fn)
> +    (struct xs_handle *h, const char *path, const char *token);
> +typedef int (*xenstore_fileno_fn)(struct xs_handle *h);
> +typedef char **(*xenstore_read_watch_fn)(struct xs_handle *h, unsigned int *num);
> +typedef bool (*xenstore_unwatch_fn)
> +    (struct xs_handle *h, const char *path, const char *token);
> +typedef xs_transaction_t (*xenstore_transaction_start_fn)(struct xs_handle *h);
> +typedef bool (*xenstore_transaction_end_fn)
> +    (struct xs_handle *h, xs_transaction_t t, bool abort);
> +typedef bool (*xenstore_introduce_domain_fn)
> +    (struct xs_handle *h, unsigned int domid, unsigned long mfn,
> +     unsigned int eventchn);
> +typedef bool (*xenstore_resume_domain_fn)
> +    (struct xs_handle *h, unsigned int domid);
> +typedef bool (*xenstore_release_domain_fn)
> +    (struct xs_handle *h, unsigned int domid);
> +typedef char *(*xenstore_get_domain_path_fn)
> +    (struct xs_handle *h, unsigned int domid);
> +typedef bool (*xenstore_is_domain_introduced_fn)
> +    (struct xs_handle *h, unsigned int domid);
> +
> +struct XenStoreOps {
> +    xenstore_daemon_open_fn daemon_open;
> +    xenstore_domain_open_fn domain_open;
> +    xenstore_daemon_open_readonly_fn daemon_open_readonly;
> +    xenstore_domid_fn domid;
> +    xenstore_daemon_close_fn daemon_close;
> +    xenstore_directory_fn directory;
> +    xenstore_read_fn read;
> +    xenstore_write_fn write;
> +    xenstore_mkdir_fn mkdir;
> +    xenstore_rm_fn rm;
> +    xenstore_get_permissions_fn get_permissions;
> +    xenstore_set_permissions_fn set_permissions;
> +    xenstore_watch_fn watch;
> +    xenstore_fileno_fn fileno;
> +    xenstore_read_watch_fn read_watch;
> +    xenstore_unwatch_fn unwatch;
> +    xenstore_transaction_start_fn transaction_start;
> +    xenstore_transaction_end_fn transaction_end;
> +    xenstore_introduce_domain_fn introduce_domain;
> +    xenstore_resume_domain_fn resume_domain;
> +    xenstore_release_domain_fn release_domain;
> +    xenstore_get_domain_path_fn get_domain_path;
> +    xenstore_is_domain_introduced_fn is_domain_introduced;
> +};
> +typedef struct XenStoreOps XenStoreOps;
> +extern XenStoreOps xs_ops;
> +
> +/* ------------------------------------------------------------- */
> +/* xen grant table interface                                     */
> +
> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION<  410
> +typedef int XenGnttab;
> +#else
> +typedef xc_gnttab *XenGnttab;
> +#endif
> +
> +typedef XenGnttab (*xc_gnttab_open_fn)
> +    (xentoollog_logger *logger, unsigned open_flags);
> +typedef int (*xc_gnttab_close_fn)(XenGnttab xcg);
> +typedef void *(*xc_gnttab_map_grant_ref_fn)
> +    (XenGnttab xcg, uint32_t domid, uint32_t ref, int prot);
> +typedef void *(*xc_gnttab_map_grant_refs_fn)
> +    (XenGnttab xcg, uint32_t count, uint32_t *domids, uint32_t *refs, int prot);
> +typedef int (*xc_gnttab_munmap_fn)
> +    (XenGnttab xcg, void *start_address, uint32_t count);
> +
> +struct XenGnttabOps {
> +    xc_gnttab_open_fn open;
> +    xc_gnttab_close_fn close;
> +    xc_gnttab_map_grant_ref_fn map_grant_ref;
> +    xc_gnttab_map_grant_refs_fn map_grant_refs;
> +    xc_gnttab_munmap_fn munmap;
> +};
> +typedef struct XenGnttabOps XenGnttabOps;
> +extern XenGnttabOps xc_gnttab_ops;
> +
> +/* ------------------------------------------------------------- */
> +/* xen hypercall interface                                       */
> +
> +typedef XenXC (*xc_interface_open_fn)
> +    (xentoollog_logger *logger, xentoollog_logger *dombuild_logger,
> +     unsigned open_flags);
> +typedef int (*xc_interface_close_fn)(XenXC xc_handle);
> +typedef void *(*xc_map_foreign_range_fn)
> +    (XenXC xc_handle, uint32_t dom, int size, int prot, unsigned long mfn);
> +typedef void *(*xc_map_foreign_pages_fn)
> +    (XenXC xc_handle, uint32_t dom, int prot, const xen_pfn_t *arr, int num);
> +typedef void *(*xc_map_foreign_bulk_fn)
> +    (XenXC xc_handle, uint32_t dom, int prot, const xen_pfn_t *arr, int *err,
> +     unsigned int num);
> +typedef int (*xc_domain_populate_physmap_exact_fn)
> +    (XenXC xc_handle, uint32_t domid, unsigned long nr_extents,
> +     unsigned int extent_order, unsigned int mem_flags, xen_pfn_t *extent_start);
> +
> +struct XenIfOps {
> +    xc_interface_open_fn interface_open;
> +    xc_interface_close_fn interface_close;
> +    xc_map_foreign_range_fn map_foreign_range;
> +    xc_map_foreign_pages_fn map_foreign_pages;
> +    xc_map_foreign_bulk_fn map_foreign_bulk;
> +    xc_domain_populate_physmap_exact_fn domain_populate_physmap_exact;
> +};
> +typedef struct XenIfOps XenIfOps;
> +extern XenIfOps xc_ops;
> +
> +/* ------------------------------------------------------------- */
> +
> +void xen_interfaces_init(void);
> +
> +#endif /* QEMU_HW_XEN_INTERFACES_H */
> diff --git a/hw/xen_nic.c b/hw/xen_nic.c
> index 8fcf856..6cb6fc4 100644
> --- a/hw/xen_nic.c
> +++ b/hw/xen_nic.c
> @@ -166,9 +166,9 @@ static void net_tx_packets(struct XenNetDev *netdev)
>                             (txreq.flags&  NETTXF_more_data)      ? " more_data"      : "",
>                             (txreq.flags&  NETTXF_extra_info)     ? " extra_info"     : "");
>
> -            page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
> -                                           netdev->xendev.dom,
> -                                           txreq.gref, PROT_READ);
> +            page = xc_gnttab_ops.map_grant_ref(netdev->xendev.gnttabdev,
> +                                               netdev->xendev.dom,
> +                                               txreq.gref, PROT_READ);
>               if (page == NULL) {
>                   xen_be_printf(&netdev->xendev, 0, "error: tx gref dereference failed (%d)\n",
>                                 txreq.gref);
> @@ -185,7 +185,7 @@ static void net_tx_packets(struct XenNetDev *netdev)
>               } else {
>                   qemu_send_packet(&netdev->nic->nc, page + txreq.offset, txreq.size);
>               }
> -            xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);
> +            xc_gnttab_ops.munmap(netdev->xendev.gnttabdev, page, 1);
>               net_tx_response(netdev,&txreq, NETIF_RSP_OKAY);
>           }
>           if (!netdev->tx_work)
> @@ -272,9 +272,9 @@ static ssize_t net_rx_packet(VLANClientState *nc, const uint8_t *buf, size_t siz
>       memcpy(&rxreq, RING_GET_REQUEST(&netdev->rx_ring, rc), sizeof(rxreq));
>       netdev->rx_ring.req_cons = ++rc;
>
> -    page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
> -                                   netdev->xendev.dom,
> -                                   rxreq.gref, PROT_WRITE);
> +    page = xc_gnttab_ops.map_grant_ref(netdev->xendev.gnttabdev,
> +                                       netdev->xendev.dom,
> +                                       rxreq.gref, PROT_WRITE);
>       if (page == NULL) {
>           xen_be_printf(&netdev->xendev, 0, "error: rx gref dereference failed (%d)\n",
>                         rxreq.gref);
> @@ -282,7 +282,7 @@ static ssize_t net_rx_packet(VLANClientState *nc, const uint8_t *buf, size_t siz
>           return -1;
>       }
>       memcpy(page + NET_IP_ALIGN, buf, size);
> -    xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);
> +    xc_gnttab_ops.munmap(netdev->xendev.gnttabdev, page, 1);
>       net_rx_response(netdev,&rxreq, NETIF_RSP_OKAY, NET_IP_ALIGN, size, 0);
>
>       return size;
> @@ -350,14 +350,14 @@ static int net_connect(struct XenDevice *xendev)
>           return -1;
>       }
>
> -    netdev->txs = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
> -                                          netdev->xendev.dom,
> -                                          netdev->tx_ring_ref,
> -                                          PROT_READ | PROT_WRITE);
> -    netdev->rxs = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
> -                                          netdev->xendev.dom,
> -                                          netdev->rx_ring_ref,
> -                                          PROT_READ | PROT_WRITE);
> +    netdev->txs = xc_gnttab_ops.map_grant_ref(netdev->xendev.gnttabdev,
> +                                              netdev->xendev.dom,
> +                                              netdev->tx_ring_ref,
> +                                              PROT_READ | PROT_WRITE);
> +    netdev->rxs = xc_gnttab_ops.map_grant_ref(netdev->xendev.gnttabdev,
> +                                              netdev->xendev.dom,
> +                                              netdev->rx_ring_ref,
> +                                              PROT_READ | PROT_WRITE);
>       if (!netdev->txs || !netdev->rxs)
>           return -1;
>       BACK_RING_INIT(&netdev->tx_ring, netdev->txs, XC_PAGE_SIZE);
> @@ -381,11 +381,11 @@ static void net_disconnect(struct XenDevice *xendev)
>       xen_be_unbind_evtchn(&netdev->xendev);
>
>       if (netdev->txs) {
> -        xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->txs, 1);
> +        xc_gnttab_ops.munmap(netdev->xendev.gnttabdev, netdev->txs, 1);
>           netdev->txs = NULL;
>       }
>       if (netdev->rxs) {
> -        xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->rxs, 1);
> +        xc_gnttab_ops.munmap(netdev->xendev.gnttabdev, netdev->rxs, 1);
>           netdev->rxs = NULL;
>       }
>       if (netdev->nic) {
> diff --git a/hw/xenfb.c b/hw/xenfb.c
> index da5297b..7ff7885 100644
> --- a/hw/xenfb.c
> +++ b/hw/xenfb.c
> @@ -105,9 +105,9 @@ static int common_bind(struct common *c)
>       if (xenstore_read_fe_int(&c->xendev, "event-channel",&c->xendev.remote_port) == -1)
>   	return -1;
>
> -    c->page = xc_map_foreign_range(xen_xc, c->xendev.dom,
> -				   XC_PAGE_SIZE,
> -				   PROT_READ | PROT_WRITE, mfn);
> +    c->page = xc_ops.map_foreign_range(xen_xc, c->xendev.dom,
> +                                       XC_PAGE_SIZE,
> +                                       PROT_READ | PROT_WRITE, mfn);
>       if (c->page == NULL)
>   	return -1;
>
> @@ -483,15 +483,15 @@ static int xenfb_map_fb(struct XenFB *xenfb)
>       fbmfns = qemu_mallocz(sizeof(unsigned long) * xenfb->fbpages);
>
>       xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
> -    map = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
> -			       PROT_READ, pgmfns, n_fbdirs);
> +    map = xc_ops.map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
> +                                   PROT_READ, pgmfns, n_fbdirs);
>       if (map == NULL)
>   	goto out;
>       xenfb_copy_mfns(mode, xenfb->fbpages, fbmfns, map);
>       munmap(map, n_fbdirs * XC_PAGE_SIZE);
>
> -    xenfb->pixels = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
> -					 PROT_READ | PROT_WRITE, fbmfns, xenfb->fbpages);
> +    xenfb->pixels = xc_ops.map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
> +                                             PROT_READ | PROT_WRITE, fbmfns, xenfb->fbpages);
>       if (xenfb->pixels == NULL)
>   	goto out;
>
>
Anthony PERARD - Feb. 25, 2011, 2:06 p.m.
On Thu, Feb 24, 2011 at 17:29, Anthony Liguori <anthony@codemonkey.ws> wrote:
> On 02/02/2011 08:49 AM, anthony.perard@citrix.com wrote:
>>
>> From: Anthony PERARD<anthony.perard@citrix.com>
>>
>> This patch adds a generic layer for xc calls, allowing us to choose
>> between the
>> xenner and xen implementations at runtime.
>>
>> It also update the libxenctrl calls in Qemu to use the new interface,
>> otherwise Qemu wouldn't be able to build against new versions of the
>> library.
>>
>> We check libxenctrl version in configure, from Xen 3.3.0 to Xen
>> unstable.
>>
>> Signed-off-by: Anthony PERARD<anthony.perard@citrix.com>
>> Signed-off-by: Stefano Stabellini<stefano.stabellini@eu.citrix.com>
>> Acked-by: Alexander Graf<agraf@suse.de>
>> ---
>>  Makefile.target      |    3 +
>>  configure            |   62 +++++++++++++++-
>>  hw/xen_backend.c     |   74 ++++++++++---------
>>  hw/xen_backend.h     |    7 +-
>>  hw/xen_common.h      |   38 ++++++----
>>  hw/xen_console.c     |   10 +-
>>  hw/xen_devconfig.c   |   10 +-
>>  hw/xen_disk.c        |   28 ++++---
>>  hw/xen_domainbuild.c |   29 ++++----
>>  hw/xen_interfaces.c  |  191
>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>  hw/xen_interfaces.h  |  198
>> ++++++++++++++++++++++++++++++++++++++++++++++++++
>>  hw/xen_nic.c         |   36 +++++-----
>>  hw/xenfb.c           |   14 ++--
>>  13 files changed, 584 insertions(+), 116 deletions(-)
>>  create mode 100644 hw/xen_interfaces.c
>>  create mode 100644 hw/xen_interfaces.h
>>
>> diff --git a/Makefile.target b/Makefile.target
>> index db29e96..d09719f 100644
>> --- a/Makefile.target
>> +++ b/Makefile.target
>> @@ -205,6 +205,9 @@ QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
>>  QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
>>  QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
>>
>> +# xen support
>> +obj-$(CONFIG_XEN) += xen_interfaces.o
>> +
>>  # xen backend driver support
>>  obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o
>>  obj-$(CONFIG_XEN) += xen_console.o xenfb.o xen_disk.o xen_nic.o
>> diff --git a/configure b/configure
>> index 5a9121d..fde9bad 100755
>> --- a/configure
>> +++ b/configure
>> @@ -126,6 +126,7 @@ vnc_jpeg=""
>>  vnc_png=""
>>  vnc_thread="no"
>>  xen=""
>> +xen_ctrl_version=""
>>  linux_aio=""
>>  attr=""
>>  vhost_net=""
>> @@ -1144,13 +1145,71 @@ fi
>>
>>  if test "$xen" != "no" ; then
>>    xen_libs="-lxenstore -lxenctrl -lxenguest"
>> +
>> +  # Xen unstable
>>    cat>  $TMPC<<EOF
>>  #include<xenctrl.h>
>>  #include<xs.h>
>> -int main(void) { xs_daemon_open(); xc_interface_open(); return 0; }
>> +#include<stdint.h>
>> +#include<xen/hvm/hvm_info_table.h>
>> +#if !defined(HVM_MAX_VCPUS)
>> +# error HVM_MAX_VCPUS not defined
>> +#endif
>> +int main(void) {
>> +  xc_interface *xc;
>> +  xs_daemon_open();
>> +  xc = xc_interface_open(0, 0, 0);
>> +  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
>> +  xc_gnttab_open(NULL, 0);
>> +  return 0;
>> +}
>>  EOF
>>    if compile_prog "" "$xen_libs" ; then
>> +    xen_ctrl_version=410
>> +    xen=yes
>> +
>> +  # Xen 4.0.0
>> +  elif (
>> +      cat>  $TMPC<<EOF
>> +#include<xenctrl.h>
>> +#include<xs.h>
>> +#include<stdint.h>
>> +#include<xen/hvm/hvm_info_table.h>
>> +#if !defined(HVM_MAX_VCPUS)
>> +# error HVM_MAX_VCPUS not defined
>> +#endif
>> +int main(void) {
>> +  xs_daemon_open();
>> +  xc_interface_open();
>> +  xc_gnttab_open();
>> +  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
>> +  return 0;
>> +}
>> +EOF
>> +      compile_prog "" "$xen_libs"
>> +    ) ; then
>> +    xen_ctrl_version=400
>> +    xen=yes
>> +
>> +  # Xen 3.3.0, 3.4.0
>> +  elif (
>> +      cat>  $TMPC<<EOF
>> +#include<xenctrl.h>
>> +#include<xs.h>
>> +int main(void) {
>> +  xs_daemon_open();
>> +  xc_interface_open();
>> +  xc_gnttab_open();
>> +  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
>> +  return 0;
>> +}
>> +EOF
>> +      compile_prog "" "$xen_libs"
>> +    ) ; then
>> +    xen_ctrl_version=330
>>      xen=yes
>> +
>> +  # Xen not found or unsupported
>>    else
>>      if test "$xen" = "yes" ; then
>>        feature_not_found "xen"
>> @@ -3009,6 +3068,7 @@ case "$target_arch2" in
>>      if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
>>        echo "CONFIG_XEN=y">>  $config_target_mak
>>        echo "LIBS+=$xen_libs">>  $config_target_mak
>> +      echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version">>
>>  $config_target_mak
>>      fi
>>  esac
>>  case "$target_arch2" in
>> diff --git a/hw/xen_backend.c b/hw/xen_backend.c
>> index 860b038..cf081e1 100644
>> --- a/hw/xen_backend.c
>> +++ b/hw/xen_backend.c
>> @@ -43,7 +43,8 @@
>>  /* ------------------------------------------------------------- */
>>
>>  /* public */
>> -int xen_xc;
>> +XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
>> +XenGnttab xen_xcg = XC_HANDLER_INITIAL_VALUE;
>>  struct xs_handle *xenstore = NULL;
>>  const char *xen_protocol;
>>
>> @@ -58,7 +59,7 @@ 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)))
>> +    if (!xs_ops.write(xenstore, 0, abspath, val, strlen(val)))
>>          return -1;
>>      return 0;
>>  }
>> @@ -70,7 +71,7 @@ char *xenstore_read_str(const char *base, const char
>> *node)
>>      char *str, *ret = NULL;
>>
>>      snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
>> -    str = xs_read(xenstore, 0, abspath,&len);
>> +    str = xs_ops.read(xenstore, 0, abspath,&len);
>>
>
> I think I gave this feedback before but I'd really like to see static
> inlines here.
>
> It's very likely that you'll either want to have tracing or some commands
> can have a NULL function pointer in which case having a central location to
> do this is very useful.
>
> Plus, it's more natural to read code that's making a function call instead
> of going through a function pointer in a structure redirection.
>
> Can probably do this with just a sed over the current patch.


Is it good to have a .h with functions like that? :

static inline XenXC qemu_xc_interface_open(xentoollog_logger *logger,
                            xentoollog_logger *dombuild_logger,
                            unsigned open_flags)
{
#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
    return xc_interface_open();
#else
    return xc_interface_open(logger, dombuild_logger, open_flags);
#endif
}


So there will have no more structure redirection.

Regards,
Anthony Liguori - Feb. 25, 2011, 2:11 p.m.
On 02/25/2011 08:06 AM, Anthony PERARD wrote:
> On Thu, Feb 24, 2011 at 17:29, Anthony Liguori<anthony@codemonkey.ws>  wrote:
>    
>> On 02/02/2011 08:49 AM, anthony.perard@citrix.com wrote:
>>      
>>> From: Anthony PERARD<anthony.perard@citrix.com>
>>>
>>> This patch adds a generic layer for xc calls, allowing us to choose
>>> between the
>>> xenner and xen implementations at runtime.
>>>
>>> It also update the libxenctrl calls in Qemu to use the new interface,
>>> otherwise Qemu wouldn't be able to build against new versions of the
>>> library.
>>>
>>> We check libxenctrl version in configure, from Xen 3.3.0 to Xen
>>> unstable.
>>>
>>> Signed-off-by: Anthony PERARD<anthony.perard@citrix.com>
>>> Signed-off-by: Stefano Stabellini<stefano.stabellini@eu.citrix.com>
>>> Acked-by: Alexander Graf<agraf@suse.de>
>>> ---
>>>   Makefile.target      |    3 +
>>>   configure            |   62 +++++++++++++++-
>>>   hw/xen_backend.c     |   74 ++++++++++---------
>>>   hw/xen_backend.h     |    7 +-
>>>   hw/xen_common.h      |   38 ++++++----
>>>   hw/xen_console.c     |   10 +-
>>>   hw/xen_devconfig.c   |   10 +-
>>>   hw/xen_disk.c        |   28 ++++---
>>>   hw/xen_domainbuild.c |   29 ++++----
>>>   hw/xen_interfaces.c  |  191
>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>>   hw/xen_interfaces.h  |  198
>>> ++++++++++++++++++++++++++++++++++++++++++++++++++
>>>   hw/xen_nic.c         |   36 +++++-----
>>>   hw/xenfb.c           |   14 ++--
>>>   13 files changed, 584 insertions(+), 116 deletions(-)
>>>   create mode 100644 hw/xen_interfaces.c
>>>   create mode 100644 hw/xen_interfaces.h
>>>
>>> diff --git a/Makefile.target b/Makefile.target
>>> index db29e96..d09719f 100644
>>> --- a/Makefile.target
>>> +++ b/Makefile.target
>>> @@ -205,6 +205,9 @@ QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
>>>   QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
>>>   QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
>>>
>>> +# xen support
>>> +obj-$(CONFIG_XEN) += xen_interfaces.o
>>> +
>>>   # xen backend driver support
>>>   obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o
>>>   obj-$(CONFIG_XEN) += xen_console.o xenfb.o xen_disk.o xen_nic.o
>>> diff --git a/configure b/configure
>>> index 5a9121d..fde9bad 100755
>>> --- a/configure
>>> +++ b/configure
>>> @@ -126,6 +126,7 @@ vnc_jpeg=""
>>>   vnc_png=""
>>>   vnc_thread="no"
>>>   xen=""
>>> +xen_ctrl_version=""
>>>   linux_aio=""
>>>   attr=""
>>>   vhost_net=""
>>> @@ -1144,13 +1145,71 @@ fi
>>>
>>>   if test "$xen" != "no" ; then
>>>     xen_libs="-lxenstore -lxenctrl -lxenguest"
>>> +
>>> +  # Xen unstable
>>>     cat>    $TMPC<<EOF
>>>   #include<xenctrl.h>
>>>   #include<xs.h>
>>> -int main(void) { xs_daemon_open(); xc_interface_open(); return 0; }
>>> +#include<stdint.h>
>>> +#include<xen/hvm/hvm_info_table.h>
>>> +#if !defined(HVM_MAX_VCPUS)
>>> +# error HVM_MAX_VCPUS not defined
>>> +#endif
>>> +int main(void) {
>>> +  xc_interface *xc;
>>> +  xs_daemon_open();
>>> +  xc = xc_interface_open(0, 0, 0);
>>> +  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
>>> +  xc_gnttab_open(NULL, 0);
>>> +  return 0;
>>> +}
>>>   EOF
>>>     if compile_prog "" "$xen_libs" ; then
>>> +    xen_ctrl_version=410
>>> +    xen=yes
>>> +
>>> +  # Xen 4.0.0
>>> +  elif (
>>> +      cat>    $TMPC<<EOF
>>> +#include<xenctrl.h>
>>> +#include<xs.h>
>>> +#include<stdint.h>
>>> +#include<xen/hvm/hvm_info_table.h>
>>> +#if !defined(HVM_MAX_VCPUS)
>>> +# error HVM_MAX_VCPUS not defined
>>> +#endif
>>> +int main(void) {
>>> +  xs_daemon_open();
>>> +  xc_interface_open();
>>> +  xc_gnttab_open();
>>> +  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
>>> +  return 0;
>>> +}
>>> +EOF
>>> +      compile_prog "" "$xen_libs"
>>> +    ) ; then
>>> +    xen_ctrl_version=400
>>> +    xen=yes
>>> +
>>> +  # Xen 3.3.0, 3.4.0
>>> +  elif (
>>> +      cat>    $TMPC<<EOF
>>> +#include<xenctrl.h>
>>> +#include<xs.h>
>>> +int main(void) {
>>> +  xs_daemon_open();
>>> +  xc_interface_open();
>>> +  xc_gnttab_open();
>>> +  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
>>> +  return 0;
>>> +}
>>> +EOF
>>> +      compile_prog "" "$xen_libs"
>>> +    ) ; then
>>> +    xen_ctrl_version=330
>>>       xen=yes
>>> +
>>> +  # Xen not found or unsupported
>>>     else
>>>       if test "$xen" = "yes" ; then
>>>         feature_not_found "xen"
>>> @@ -3009,6 +3068,7 @@ case "$target_arch2" in
>>>       if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
>>>         echo "CONFIG_XEN=y">>    $config_target_mak
>>>         echo "LIBS+=$xen_libs">>    $config_target_mak
>>> +      echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version">>
>>>   $config_target_mak
>>>       fi
>>>   esac
>>>   case "$target_arch2" in
>>> diff --git a/hw/xen_backend.c b/hw/xen_backend.c
>>> index 860b038..cf081e1 100644
>>> --- a/hw/xen_backend.c
>>> +++ b/hw/xen_backend.c
>>> @@ -43,7 +43,8 @@
>>>   /* ------------------------------------------------------------- */
>>>
>>>   /* public */
>>> -int xen_xc;
>>> +XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
>>> +XenGnttab xen_xcg = XC_HANDLER_INITIAL_VALUE;
>>>   struct xs_handle *xenstore = NULL;
>>>   const char *xen_protocol;
>>>
>>> @@ -58,7 +59,7 @@ 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)))
>>> +    if (!xs_ops.write(xenstore, 0, abspath, val, strlen(val)))
>>>           return -1;
>>>       return 0;
>>>   }
>>> @@ -70,7 +71,7 @@ char *xenstore_read_str(const char *base, const char
>>> *node)
>>>       char *str, *ret = NULL;
>>>
>>>       snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
>>> -    str = xs_read(xenstore, 0, abspath,&len);
>>> +    str = xs_ops.read(xenstore, 0, abspath,&len);
>>>
>>>        
>> I think I gave this feedback before but I'd really like to see static
>> inlines here.
>>
>> It's very likely that you'll either want to have tracing or some commands
>> can have a NULL function pointer in which case having a central location to
>> do this is very useful.
>>
>> Plus, it's more natural to read code that's making a function call instead
>> of going through a function pointer in a structure redirection.
>>
>> Can probably do this with just a sed over the current patch.
>>      
>
> Is it good to have a .h with functions like that? :
>
> static inline XenXC qemu_xc_interface_open(xentoollog_logger *logger,
>                              xentoollog_logger *dombuild_logger,
>                              unsigned open_flags)
> {
> #if CONFIG_XEN_CTRL_INTERFACE_VERSION<  410
>      return xc_interface_open();
> #else
>      return xc_interface_open(logger, dombuild_logger, open_flags);
> #endif
> }
>
>
> So there will have no more structure redirection.
>    

It would be better to have two versions of the header, one that 
implemented the < 410 functions and one that implemented the newer 
functions.

If you're just using the new signature for everything, you could even 
just #define in the later header.

Regards,

Anthony Liguori

> Regards,
>
>
Anthony PERARD - Feb. 25, 2011, 4:01 p.m.
On Fri, Feb 25, 2011 at 14:11, Anthony Liguori <anthony@codemonkey.ws> wrote:
>>> I think I gave this feedback before but I'd really like to see static
>>> inlines here.
>>>
>>> It's very likely that you'll either want to have tracing or some commands
>>> can have a NULL function pointer in which case having a central location
>>> to
>>> do this is very useful.
>>>
>>> Plus, it's more natural to read code that's making a function call
>>> instead
>>> of going through a function pointer in a structure redirection.
>>>
>>> Can probably do this with just a sed over the current patch.
>>>
>>
>> Is it good to have a .h with functions like that? :
>>
>> static inline XenXC qemu_xc_interface_open(xentoollog_logger *logger,
>>                             xentoollog_logger *dombuild_logger,
>>                             unsigned open_flags)
>> {
>> #if CONFIG_XEN_CTRL_INTERFACE_VERSION<  410
>>     return xc_interface_open();
>> #else
>>     return xc_interface_open(logger, dombuild_logger, open_flags);
>> #endif
>> }
>>
>>
>> So there will have no more structure redirection.
>>
>
> It would be better to have two versions of the header, one that implemented
> the < 410 functions and one that implemented the newer functions.
>
> If you're just using the new signature for everything, you could even just
> #define in the later header.

Actually, the #define in the later header was done in a previous
version of this patch series. But I change to the structure
redirection after a comment of Alexander Graf and by taking one of his
patches for Xenner.

Here is the comment of Alexander:
http://lists.nongnu.org/archive/html/qemu-devel/2010-11/msg01251.html
The function pointers help switch at run time to either Xen or Xenner
implementation.

This message is why I did not use static inline.
http://lists.nongnu.org/archive/html/qemu-devel/2011-01/msg03125.html


So, I can go for multiple version of the header that defines the
static inlines functions, or just have a few define.
BTW, I think there are now only 4 functions with a different prototype
between old and new version of Xen. Other prototype change are only
the "handler" parameter, but a typedef handle it.

Regards,

Patch

diff --git a/Makefile.target b/Makefile.target
index db29e96..d09719f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -205,6 +205,9 @@  QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
 QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
 QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
 
+# xen support
+obj-$(CONFIG_XEN) += xen_interfaces.o
+
 # xen backend driver support
 obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o
 obj-$(CONFIG_XEN) += xen_console.o xenfb.o xen_disk.o xen_nic.o
diff --git a/configure b/configure
index 5a9121d..fde9bad 100755
--- a/configure
+++ b/configure
@@ -126,6 +126,7 @@  vnc_jpeg=""
 vnc_png=""
 vnc_thread="no"
 xen=""
+xen_ctrl_version=""
 linux_aio=""
 attr=""
 vhost_net=""
@@ -1144,13 +1145,71 @@  fi
 
 if test "$xen" != "no" ; then
   xen_libs="-lxenstore -lxenctrl -lxenguest"
+
+  # Xen unstable
   cat > $TMPC <<EOF
 #include <xenctrl.h>
 #include <xs.h>
-int main(void) { xs_daemon_open(); xc_interface_open(); return 0; }
+#include <stdint.h>
+#include <xen/hvm/hvm_info_table.h>
+#if !defined(HVM_MAX_VCPUS)
+# error HVM_MAX_VCPUS not defined
+#endif
+int main(void) {
+  xc_interface *xc;
+  xs_daemon_open();
+  xc = xc_interface_open(0, 0, 0);
+  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
+  xc_gnttab_open(NULL, 0);
+  return 0;
+}
 EOF
   if compile_prog "" "$xen_libs" ; then
+    xen_ctrl_version=410
+    xen=yes
+
+  # Xen 4.0.0
+  elif (
+      cat > $TMPC <<EOF
+#include <xenctrl.h>
+#include <xs.h>
+#include <stdint.h>
+#include <xen/hvm/hvm_info_table.h>
+#if !defined(HVM_MAX_VCPUS)
+# error HVM_MAX_VCPUS not defined
+#endif
+int main(void) {
+  xs_daemon_open();
+  xc_interface_open();
+  xc_gnttab_open();
+  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
+  return 0;
+}
+EOF
+      compile_prog "" "$xen_libs"
+    ) ; then
+    xen_ctrl_version=400
+    xen=yes
+
+  # Xen 3.3.0, 3.4.0
+  elif (
+      cat > $TMPC <<EOF
+#include <xenctrl.h>
+#include <xs.h>
+int main(void) {
+  xs_daemon_open();
+  xc_interface_open();
+  xc_gnttab_open();
+  xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
+  return 0;
+}
+EOF
+      compile_prog "" "$xen_libs"
+    ) ; then
+    xen_ctrl_version=330
     xen=yes
+
+  # Xen not found or unsupported
   else
     if test "$xen" = "yes" ; then
       feature_not_found "xen"
@@ -3009,6 +3068,7 @@  case "$target_arch2" in
     if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
       echo "CONFIG_XEN=y" >> $config_target_mak
       echo "LIBS+=$xen_libs" >> $config_target_mak
+      echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_target_mak
     fi
 esac
 case "$target_arch2" in
diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index 860b038..cf081e1 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -43,7 +43,8 @@ 
 /* ------------------------------------------------------------- */
 
 /* public */
-int xen_xc;
+XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
+XenGnttab xen_xcg = XC_HANDLER_INITIAL_VALUE;
 struct xs_handle *xenstore = NULL;
 const char *xen_protocol;
 
@@ -58,7 +59,7 @@  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)))
+    if (!xs_ops.write(xenstore, 0, abspath, val, strlen(val)))
         return -1;
     return 0;
 }
@@ -70,7 +71,7 @@  char *xenstore_read_str(const char *base, const char *node)
     char *str, *ret = NULL;
 
     snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
-    str = xs_read(xenstore, 0, abspath, &len);
+    str = xs_ops.read(xenstore, 0, abspath, &len);
     if (str != NULL) {
         /* move to qemu-allocated memory to make sure
          * callers can savely qemu_free() stuff. */
@@ -197,7 +198,7 @@  static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
     xendev->dev   = dev;
     xendev->ops   = ops;
 
-    dom0 = xs_get_domain_path(xenstore, 0);
+    dom0 = xs_ops.get_domain_path(xenstore, 0);
     snprintf(xendev->be, sizeof(xendev->be), "%s/backend/%s/%d/%d",
              dom0, xendev->type, xendev->dom, xendev->dev);
     snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
@@ -207,24 +208,24 @@  static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
     xendev->debug      = debug;
     xendev->local_port = -1;
 
-    xendev->evtchndev = xc_evtchn_open();
-    if (xendev->evtchndev < 0) {
+    xendev->evtchndev = xc_evtchn_ops.open(NULL, 0);
+    if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
         xen_be_printf(NULL, 0, "can't open evtchn device\n");
         qemu_free(xendev);
         return NULL;
     }
-    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
+    fcntl(xc_evtchn_ops.fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
 
     if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
-        xendev->gnttabdev = xc_gnttab_open();
-        if (xendev->gnttabdev < 0) {
+        xendev->gnttabdev = xc_gnttab_ops.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);
+            xc_evtchn_ops.close(xendev->evtchndev);
             qemu_free(xendev);
             return NULL;
         }
     } else {
-        xendev->gnttabdev = -1;
+        xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
     }
 
     QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
@@ -262,14 +263,16 @@  static struct XenDevice *xen_be_del_xendev(int dom, int dev)
         if (xendev->fe) {
             char token[XEN_BUFSIZE];
             snprintf(token, sizeof(token), "fe:%p", xendev);
-            xs_unwatch(xenstore, xendev->fe, token);
+            xs_ops.unwatch(xenstore, xendev->fe, token);
             qemu_free(xendev->fe);
         }
 
-        if (xendev->evtchndev >= 0)
-            xc_evtchn_close(xendev->evtchndev);
-        if (xendev->gnttabdev >= 0)
-            xc_gnttab_close(xendev->gnttabdev);
+        if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
+            xc_evtchn_ops.close(xendev->evtchndev);
+        }
+        if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
+            xc_gnttab_ops.close(xendev->gnttabdev);
+        }
 
         QTAILQ_REMOVE(&xendevs, xendev, next);
         qemu_free(xendev);
@@ -358,7 +361,7 @@  static int xen_be_try_setup(struct XenDevice *xendev)
 
     /* setup frontend watch */
     snprintf(token, sizeof(token), "fe:%p", xendev);
-    if (!xs_watch(xenstore, xendev->fe, token)) {
+    if (!xs_ops.watch(xenstore, xendev->fe, token)) {
         xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
                       xendev->fe);
         return -1;
@@ -506,17 +509,17 @@  static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
     unsigned int cdev, j;
 
     /* setup watch */
-    dom0 = xs_get_domain_path(xenstore, 0);
+    dom0 = xs_ops.get_domain_path(xenstore, 0);
     snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
     snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
     free(dom0);
-    if (!xs_watch(xenstore, path, token)) {
+    if (!xs_ops.watch(xenstore, path, token)) {
         xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
         return -1;
     }
 
     /* look for backends */
-    dev = xs_directory(xenstore, 0, path, &cdev);
+    dev = xs_ops.directory(xenstore, 0, path, &cdev);
     if (!dev)
         return 0;
     for (j = 0; j < cdev; j++) {
@@ -536,7 +539,7 @@  static void xenstore_update_be(char *watch, char *type, int dom,
     char path[XEN_BUFSIZE], *dom0;
     unsigned int len, dev;
 
-    dom0 = xs_get_domain_path(xenstore, 0);
+    dom0 = xs_ops.get_domain_path(xenstore, 0);
     len = snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
     free(dom0);
     if (strncmp(path, watch, len) != 0)
@@ -583,7 +586,7 @@  static void xenstore_update(void *unused)
     intptr_t type, ops, ptr;
     unsigned int dom, count;
 
-    vec = xs_read_watch(xenstore, &count);
+    vec = xs_ops.read_watch(xenstore, &count);
     if (vec == NULL)
         goto cleanup;
 
@@ -602,13 +605,13 @@  static void xen_be_evtchn_event(void *opaque)
     struct XenDevice *xendev = opaque;
     evtchn_port_t port;
 
-    port = xc_evtchn_pending(xendev->evtchndev);
+    port = xc_evtchn_ops.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);
+    xc_evtchn_ops.unmask(xendev->evtchndev, port);
 
     if (xendev->ops->event)
         xendev->ops->event(xendev);
@@ -618,25 +621,26 @@  static void xen_be_evtchn_event(void *opaque)
 
 int xen_be_init(void)
 {
-    xenstore = xs_daemon_open();
+    xenstore = xs_ops.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)
+    if (qemu_set_fd_handler(xs_ops.fileno(xenstore), xenstore_update, NULL, NULL) < 0) {
         goto err;
+    }
 
-    xen_xc = xc_interface_open();
-    if (xen_xc == -1) {
+    xen_xc = xc_ops.interface_open(0, 0, 0);
+    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
         xen_be_printf(NULL, 0, "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);
+    qemu_set_fd_handler(xs_ops.fileno(xenstore), NULL, NULL, NULL);
+    xs_ops.daemon_close(xenstore);
     xenstore = NULL;
 
     return -1;
@@ -651,14 +655,14 @@  int xen_be_bind_evtchn(struct XenDevice *xendev)
 {
     if (xendev->local_port != -1)
         return 0;
-    xendev->local_port = xc_evtchn_bind_interdomain
+    xendev->local_port = xc_evtchn_ops.bind_interdomain
         (xendev->evtchndev, xendev->dom, xendev->remote_port);
     if (xendev->local_port == -1) {
         xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
         return -1;
     }
     xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
-    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
+    qemu_set_fd_handler(xc_evtchn_ops.fd(xendev->evtchndev),
                         xen_be_evtchn_event, NULL, xendev);
     return 0;
 }
@@ -667,15 +671,15 @@  void xen_be_unbind_evtchn(struct XenDevice *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);
+    qemu_set_fd_handler(xc_evtchn_ops.fd(xendev->evtchndev), NULL, NULL, NULL);
+    xc_evtchn_ops.unbind(xendev->evtchndev, xendev->local_port);
     xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
     xendev->local_port = -1;
 }
 
 int xen_be_send_notify(struct XenDevice *xendev)
 {
-    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
+    return xc_evtchn_ops.notify(xendev->evtchndev, xendev->local_port);
 }
 
 /*
diff --git a/hw/xen_backend.h b/hw/xen_backend.h
index 1b428e3..5af09b8 100644
--- a/hw/xen_backend.h
+++ b/hw/xen_backend.h
@@ -2,6 +2,7 @@ 
 #define QEMU_HW_XEN_BACKEND_H 1
 
 #include "xen_common.h"
+#include "xen_interfaces.h"
 #include "sysemu.h"
 #include "net.h"
 
@@ -45,8 +46,8 @@  struct XenDevice {
     int                remote_port;
     int                local_port;
 
-    int                evtchndev;
-    int                gnttabdev;
+    XenEvtchn          evtchndev;
+    XenGnttab          gnttabdev;
 
     struct XenDevOps   *ops;
     QTAILQ_ENTRY(XenDevice) next;
@@ -55,7 +56,7 @@  struct XenDevice {
 /* ------------------------------------------------------------- */
 
 /* variables */
-extern int xen_xc;
+extern XenXC xen_xc;
 extern struct xs_handle *xenstore;
 extern const char *xen_protocol;
 
diff --git a/hw/xen_common.h b/hw/xen_common.h
index 8a55b44..3a08f6a 100644
--- a/hw/xen_common.h
+++ b/hw/xen_common.h
@@ -1,6 +1,8 @@ 
 #ifndef QEMU_HW_XEN_COMMON_H
 #define QEMU_HW_XEN_COMMON_H 1
 
+#include "config-target.h"
+
 #include <stddef.h>
 #include <inttypes.h>
 
@@ -13,22 +15,28 @@ 
 #include "qemu-queue.h"
 
 /*
- * tweaks needed to build with different xen versions
- *  0x00030205 -> 3.1.0
- *  0x00030207 -> 3.2.0
- *  0x00030208 -> unstable
+ * We don't support Xen prior to 3.3.0.
  */
-#include <xen/xen-compat.h>
-#if __XEN_LATEST_INTERFACE_VERSION__ < 0x00030205
-# define evtchn_port_or_error_t int
-#endif
-#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()
+
+/* Xen unstable */
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
+typedef int XenXC;
+#  define XC_INTERFACE_FMT "%i"
+#  define XC_HANDLER_INITIAL_VALUE    -1
+static inline int xc_fd(int xen_xc)
+{
+    return xen_xc;
+}
+#else
+typedef xc_interface *XenXC;
+#  define XC_INTERFACE_FMT "%p"
+#  define XC_HANDLER_INITIAL_VALUE    NULL
+/* FIXME The fd of xen_xc is now xen_xc->fd */
+/* fd is the first field, so this works */
+static inline int xc_fd(xc_interface *xen_xc)
+{
+    return *(int*)xen_xc;
+}
 #endif
 
 #endif /* QEMU_HW_XEN_COMMON_H */
diff --git a/hw/xen_console.c b/hw/xen_console.c
index d2261f4..7f79df9 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -183,7 +183,7 @@  static int con_init(struct XenDevice *xendev)
     char *type, *dom;
 
     /* setup */
-    dom = xs_get_domain_path(xenstore, con->xendev.dom);
+    dom = xs_ops.get_domain_path(xenstore, con->xendev.dom);
     snprintf(con->console, sizeof(con->console), "%s/console", dom);
     free(dom);
 
@@ -214,10 +214,10 @@  static int con_connect(struct XenDevice *xendev)
     if (xenstore_read_int(con->console, "limit", &limit) == 0)
 	con->buffer.max_capacity = limit;
 
-    con->sring = xc_map_foreign_range(xen_xc, con->xendev.dom,
-				      XC_PAGE_SIZE,
-				      PROT_READ|PROT_WRITE,
-				      con->ring_ref);
+    con->sring = xc_ops.map_foreign_range(xen_xc, con->xendev.dom,
+                                          XC_PAGE_SIZE,
+                                          PROT_READ|PROT_WRITE,
+                                          con->ring_ref);
     if (!con->sring)
 	return -1;
 
diff --git a/hw/xen_devconfig.c b/hw/xen_devconfig.c
index 8d50216..b79c444 100644
--- a/hw/xen_devconfig.c
+++ b/hw/xen_devconfig.c
@@ -24,7 +24,7 @@  void xen_config_cleanup(void)
     struct xs_dirs *d;
 
     QTAILQ_FOREACH(d, &xs_cleanup, list) {
-	xs_rm(xenstore, 0, d->xs_dir);
+	xs_ops.rm(xenstore, 0, d->xs_dir);
     }
 }
 
@@ -39,13 +39,13 @@  static int xen_config_dev_mkdir(char *dev, int p)
             .perms = p,
         }};
 
-    if (!xs_mkdir(xenstore, 0, dev)) {
+    if (!xs_ops.mkdir(xenstore, 0, dev)) {
 	xen_be_printf(NULL, 0, "xs_mkdir %s: failed\n", dev);
 	return -1;
     }
     xen_config_cleanup_dir(qemu_strdup(dev));
 
-    if (!xs_set_permissions(xenstore, 0, dev, perms, 2)) {
+    if (!xs_ops.set_permissions(xenstore, 0, dev, perms, 2)) {
 	xen_be_printf(NULL, 0, "xs_set_permissions %s: failed\n", dev);
 	return -1;
     }
@@ -57,11 +57,11 @@  static int xen_config_dev_dirs(const char *ftype, const char *btype, int vdev,
 {
     char *dom;
 
-    dom = xs_get_domain_path(xenstore, xen_domid);
+    dom = xs_ops.get_domain_path(xenstore, xen_domid);
     snprintf(fe, len, "%s/device/%s/%d", dom, ftype, vdev);
     free(dom);
 
-    dom = xs_get_domain_path(xenstore, 0);
+    dom = xs_ops.get_domain_path(xenstore, 0);
     snprintf(be, len, "%s/backend/%s/%d/%d", dom, btype, xen_domid, vdev);
     free(dom);
 
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 7f6aaca..7fe7d56 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -239,7 +239,7 @@  err:
 
 static void ioreq_unmap(struct ioreq *ioreq)
 {
-    int gnt = ioreq->blkdev->xendev.gnttabdev;
+    XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
     int i;
 
     if (ioreq->v.niov == 0)
@@ -247,18 +247,20 @@  static void ioreq_unmap(struct ioreq *ioreq)
     if (batch_maps) {
         if (!ioreq->pages)
             return;
-        if (xc_gnttab_munmap(gnt, ioreq->pages, ioreq->v.niov) != 0)
-            xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
+        if (xc_gnttab_ops.munmap(gnt, ioreq->pages, ioreq->v.niov) != 0) {
+            xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_ops.munmap failed: %s\n",
                           strerror(errno));
+        }
         ioreq->blkdev->cnt_map -= ioreq->v.niov;
         ioreq->pages = NULL;
     } else {
         for (i = 0; i < ioreq->v.niov; i++) {
             if (!ioreq->page[i])
                 continue;
-            if (xc_gnttab_munmap(gnt, ioreq->page[i], 1) != 0)
-                xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n",
+            if (xc_gnttab_ops.munmap(gnt, ioreq->page[i], 1) != 0) {
+                xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_ops.munmap failed: %s\n",
                               strerror(errno));
+            }
             ioreq->blkdev->cnt_map--;
             ioreq->page[i] = NULL;
         }
@@ -267,13 +269,13 @@  static void ioreq_unmap(struct ioreq *ioreq)
 
 static int ioreq_map(struct ioreq *ioreq)
 {
-    int gnt = ioreq->blkdev->xendev.gnttabdev;
+    XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev;
     int i;
 
     if (ioreq->v.niov == 0)
         return 0;
     if (batch_maps) {
-        ioreq->pages = xc_gnttab_map_grant_refs
+        ioreq->pages = xc_gnttab_ops.map_grant_refs
             (gnt, ioreq->v.niov, ioreq->domids, ioreq->refs, ioreq->prot);
         if (ioreq->pages == NULL) {
             xen_be_printf(&ioreq->blkdev->xendev, 0,
@@ -287,7 +289,7 @@  static int ioreq_map(struct ioreq *ioreq)
         ioreq->blkdev->cnt_map += ioreq->v.niov;
     } else  {
         for (i = 0; i < ioreq->v.niov; i++) {
-            ioreq->page[i] = xc_gnttab_map_grant_ref
+            ioreq->page[i] = xc_gnttab_ops.map_grant_ref
                 (gnt, ioreq->domids[i], ioreq->refs[i], ioreq->prot);
             if (ioreq->page[i] == NULL) {
                 xen_be_printf(&ioreq->blkdev->xendev, 0,
@@ -687,10 +689,10 @@  static int blk_connect(struct XenDevice *xendev)
             blkdev->protocol = BLKIF_PROTOCOL_X86_64;
     }
 
-    blkdev->sring = xc_gnttab_map_grant_ref(blkdev->xendev.gnttabdev,
-                                            blkdev->xendev.dom,
-                                            blkdev->ring_ref,
-                                            PROT_READ | PROT_WRITE);
+    blkdev->sring = xc_gnttab_ops.map_grant_ref(blkdev->xendev.gnttabdev,
+                                                blkdev->xendev.dom,
+                                                blkdev->ring_ref,
+                                                PROT_READ | PROT_WRITE);
     if (!blkdev->sring)
         return -1;
     blkdev->cnt_map++;
@@ -742,7 +744,7 @@  static void blk_disconnect(struct XenDevice *xendev)
     xen_be_unbind_evtchn(&blkdev->xendev);
 
     if (blkdev->sring) {
-        xc_gnttab_munmap(blkdev->xendev.gnttabdev, blkdev->sring, 1);
+        xc_gnttab_ops.munmap(blkdev->xendev.gnttabdev, blkdev->sring, 1);
         blkdev->cnt_map--;
         blkdev->sring = NULL;
     }
diff --git a/hw/xen_domainbuild.c b/hw/xen_domainbuild.c
index 7f1fd66..ae241fa 100644
--- a/hw/xen_domainbuild.c
+++ b/hw/xen_domainbuild.c
@@ -25,22 +25,22 @@  static int xenstore_domain_mkdir(char *path)
     char subpath[256];
     int i;
 
-    if (!xs_mkdir(xenstore, 0, path)) {
+    if (!xs_ops.mkdir(xenstore, 0, path)) {
         fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
 	return -1;
     }
-    if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
+    if (!xs_ops.set_permissions(xenstore, 0, path, perms_ro, 2)) {
         fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
 	return -1;
     }
 
     for (i = 0; writable[i]; i++) {
         snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
-        if (!xs_mkdir(xenstore, 0, subpath)) {
+        if (!xs_ops.mkdir(xenstore, 0, subpath)) {
             fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
             return -1;
         }
-        if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
+        if (!xs_ops.set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
             fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
             return -1;
         }
@@ -59,7 +59,7 @@  int xenstore_domain_init1(const char *kernel, const char *ramdisk,
              qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
              qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
              qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
-    dom = xs_get_domain_path(xenstore, xen_domid);
+    dom = xs_ops.get_domain_path(xenstore, xen_domid);
     snprintf(vm,  sizeof(vm),  "/vm/%s", uuid_string);
 
     xenstore_domain_mkdir(dom);
@@ -104,13 +104,13 @@  int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
 {
     char *dom;
 
-    dom = xs_get_domain_path(xenstore, xen_domid);
+    dom = xs_ops.get_domain_path(xenstore, xen_domid);
 
     /* signal new domain */
-    xs_introduce_domain(xenstore,
-                        xen_domid,
-                        xenstore_mfn,
-                        xenstore_port);
+    xs_ops.introduce_domain(xenstore,
+                            xen_domid,
+                            xenstore_mfn,
+                            xenstore_port);
 
     /* xenstore */
     xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
@@ -176,8 +176,9 @@  static int xen_domain_watcher(void)
     for (i = 3; i < n; i++) {
         if (i == fd[0])
             continue;
-        if (i == xen_xc)
+        if (i == xc_fd(xen_xc)) {
             continue;
+        }
         close(i);
     }
 
@@ -216,12 +217,12 @@  static void xen_domain_cleanup(void)
 {
     char *dom;
 
-    dom = xs_get_domain_path(xenstore, xen_domid);
+    dom = xs_ops.get_domain_path(xenstore, xen_domid);
     if (dom) {
-        xs_rm(xenstore, 0, dom);
+        xs_ops.rm(xenstore, 0, dom);
         free(dom);
     }
-    xs_release_domain(xenstore, xen_domid);
+    xs_ops.release_domain(xenstore, xen_domid);
 }
 
 int xen_domain_build_pv(const char *kernel, const char *ramdisk,
diff --git a/hw/xen_interfaces.c b/hw/xen_interfaces.c
new file mode 100644
index 0000000..96f33fe
--- /dev/null
+++ b/hw/xen_interfaces.c
@@ -0,0 +1,191 @@ 
+/*
+ * Copyright (C) 2011       Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "config-host.h"
+
+#include <xenctrl.h>
+#include <xs.h>
+
+#include "hw.h"
+#include "xen.h"
+#include "xen_common.h"
+#include "xen_interfaces.h"
+
+#ifdef CONFIG_XEN
+
+#  if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
+static int evtchn_open(xentoollog_logger *logger, unsigned open_flags)
+{
+    return xc_evtchn_open();
+}
+
+static XenEvtOps xc_evtchn_xen = {
+    .open               = evtchn_open,
+    .close              = xc_evtchn_close,
+    .fd                 = xc_evtchn_fd,
+    .notify             = xc_evtchn_notify,
+    .bind_unbound_port  = xc_evtchn_bind_unbound_port,
+    .bind_interdomain   = xc_evtchn_bind_interdomain,
+    .bind_virq          = xc_evtchn_bind_virq,
+    .unbind             = xc_evtchn_unbind,
+    .pending            = xc_evtchn_pending,
+    .unmask             = xc_evtchn_unmask,
+};
+
+#  else /* CONFIG_XEN_CTRL_INTERFACE_VERSION >= 410 */
+static XenEvtOps xc_evtchn_xen = {
+    .open               = xc_evtchn_open,
+    .close              = xc_evtchn_close,
+    .fd                 = xc_evtchn_fd,
+    .notify             = xc_evtchn_notify,
+    .bind_unbound_port  = xc_evtchn_bind_unbound_port,
+    .bind_interdomain   = xc_evtchn_bind_interdomain,
+    .bind_virq          = xc_evtchn_bind_virq,
+    .unbind             = xc_evtchn_unbind,
+    .pending            = xc_evtchn_pending,
+    .unmask             = xc_evtchn_unmask,
+};
+#  endif
+
+static int xs_domid(struct xs_handle *h, int domid)
+{
+    return -1;
+}
+
+static XenStoreOps xs_xen = {
+    .daemon_open           = xs_daemon_open,
+    .domain_open           = xs_domain_open,
+    .daemon_open_readonly  = xs_daemon_open_readonly,
+    .domid                 = xs_domid,
+    .daemon_close          = xs_daemon_close,
+    .directory             = xs_directory,
+    .read                  = xs_read,
+    .write                 = xs_write,
+    .mkdir                 = xs_mkdir,
+    .rm                    = xs_rm,
+    .get_permissions       = xs_get_permissions,
+    .set_permissions       = xs_set_permissions,
+    .watch                 = xs_watch,
+    .fileno                = xs_fileno,
+    .read_watch            = xs_read_watch,
+    .unwatch               = xs_unwatch,
+    .transaction_start     = xs_transaction_start,
+    .transaction_end       = xs_transaction_end,
+    .introduce_domain      = xs_introduce_domain,
+    .resume_domain         = xs_resume_domain,
+    .release_domain        = xs_release_domain,
+    .get_domain_path       = xs_get_domain_path,
+    .is_domain_introduced  = xs_is_domain_introduced,
+};
+
+/* ------------------------------------------------------------- */
+/* xen grant table interface                                     */
+
+#  if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
+static int gnttab_open(xentoollog_logger *logger, unsigned open_flags)
+{
+    return xc_gnttab_open();
+}
+
+static XenGnttabOps xc_gnttab_xen = {
+    .open            = gnttab_open,
+    .close           = xc_gnttab_close,
+    .map_grant_ref   = xc_gnttab_map_grant_ref,
+    .map_grant_refs  = xc_gnttab_map_grant_refs,
+    .munmap          = xc_gnttab_munmap,
+};
+
+#  else /* CONFIG_XEN_CTRL_INTERFACE_VERSION >= 410 */
+static XenGnttabOps xc_gnttab_xen = {
+    .open            = xc_gnttab_open,
+    .close           = xc_gnttab_close,
+    .map_grant_ref   = xc_gnttab_map_grant_ref,
+    .map_grant_refs  = xc_gnttab_map_grant_refs,
+    .munmap          = xc_gnttab_munmap,
+};
+#  endif
+
+/* ------------------------------------------------------------- */
+/* xen hypercall interface                                       */
+
+#  if CONFIG_XEN_CTRL_INTERFACE_VERSION < 400
+static XenXC interface_open(xentoollog_logger *logger,
+                            xentoollog_logger *dombuild_logger,
+                            unsigned open_flags)
+{
+    return xc_interface_open();
+}
+
+static void *map_foreign_batch(int xc_handle, uint32_t dom, int prot,
+                               const xen_pfn_t *arr, int *err, unsigned int num)
+{
+    return xc_map_foreign_batch(xc_handle, dom, prot, (xen_pfn_t*)arr, num);
+}
+
+struct XenIfOps xc_xen = {
+    .interface_open                 = interface_open,
+    .interface_close                = xc_interface_close,
+    .map_foreign_range              = xc_map_foreign_range,
+    .map_foreign_pages              = xc_map_foreign_pages,
+    .map_foreign_bulk               = map_foreign_batch,
+    .domain_populate_physmap_exact  = xc_domain_memory_populate_physmap,
+};
+
+#  elif CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
+static XenXC interface_open(xentoollog_logger *logger,
+                            xentoollog_logger *dombuild_logger,
+                            unsigned open_flags)
+{
+    return xc_interface_open();
+}
+
+struct XenIfOps xc_xen = {
+    .interface_open                 = interface_open,
+    .interface_close                = xc_interface_close,
+    .map_foreign_range              = xc_map_foreign_range,
+    .map_foreign_pages              = xc_map_foreign_pages,
+    .map_foreign_bulk               = xc_map_foreign_bulk,
+    .domain_populate_physmap_exact  = xc_domain_memory_populate_physmap,
+};
+
+#  else /* CONFIG_XEN_CTRL_INTERFACE_VERSION >= 410 */
+struct XenIfOps xc_xen = {
+    .interface_open                 = xc_interface_open,
+    .interface_close                = xc_interface_close,
+    .map_foreign_range              = xc_map_foreign_range,
+    .map_foreign_pages              = xc_map_foreign_pages,
+    .map_foreign_bulk               = xc_map_foreign_bulk,
+    .domain_populate_physmap_exact  = xc_domain_populate_physmap_exact,
+};
+#  endif
+
+#endif /* CONFIG_XEN */
+
+XenEvtOps xc_evtchn_ops;
+XenGnttabOps xc_gnttab_ops;
+XenIfOps xc_ops;
+XenStoreOps xs_ops;
+
+void xen_interfaces_init(void)
+{
+    switch (xen_mode) {
+#ifdef CONFIG_XEN
+    case XEN_ATTACH:
+    case XEN_CREATE:
+        xc_evtchn_ops = xc_evtchn_xen;
+        xc_gnttab_ops = xc_gnttab_xen;
+        xc_ops        = xc_xen;
+        xs_ops        = xs_xen;
+        break;
+#endif
+    default:
+        fprintf(stderr, "ERROR: Compiled without %s support, sorry.\n",
+                xen_mode == XEN_EMULATE ? "xenner" : "Xen");
+        exit(1);
+    }
+}
diff --git a/hw/xen_interfaces.h b/hw/xen_interfaces.h
new file mode 100644
index 0000000..ec0ab68
--- /dev/null
+++ b/hw/xen_interfaces.h
@@ -0,0 +1,198 @@ 
+/*
+ * Copyright (C) 2011       Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_HW_XEN_INTERFACES_H
+#define QEMU_HW_XEN_INTERFACES_H 1
+
+#include <xenctrl.h>
+#include <xs.h>
+
+#include "hw/xen_common.h"
+
+
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
+typedef struct xentoollog_logger xentoollog_logger;
+#endif
+
+/* ------------------------------------------------------------- */
+/* xen event channel interface                                   */
+
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
+typedef int XenEvtchn;
+#else
+typedef xc_evtchn *XenEvtchn;
+#endif
+
+typedef XenEvtchn (*xc_evtchn_open_fn)
+    (xentoollog_logger *logger, unsigned open_flags);
+typedef int (*xc_evtchn_close_fn)(XenEvtchn xce);
+typedef int (*xc_evtchn_fd_fn)(XenEvtchn xce);
+typedef int (*xc_evtchn_notify_fn)(XenEvtchn xce, evtchn_port_t port);
+typedef evtchn_port_or_error_t (*xc_evtchn_bind_unbound_port_fn)
+    (XenEvtchn xce, int domid);
+typedef evtchn_port_or_error_t (*xc_evtchn_bind_interdomain_fn)
+    (XenEvtchn xce, int domid, evtchn_port_t remote_port);
+typedef evtchn_port_or_error_t (*xc_evtchn_bind_virq_fn)
+    (XenEvtchn xce, unsigned int virq);
+typedef int (*xc_evtchn_unbind_fn) (XenEvtchn xce, evtchn_port_t port);
+typedef evtchn_port_or_error_t (*xc_evtchn_pending_fn)(XenEvtchn xce);
+typedef int (*xc_evtchn_unmask_fn)(XenEvtchn xce, evtchn_port_t port);
+
+struct XenEvtOps {
+    xc_evtchn_open_fn               open;
+    xc_evtchn_close_fn              close;
+    xc_evtchn_fd_fn                 fd;
+    xc_evtchn_notify_fn             notify;
+    xc_evtchn_bind_unbound_port_fn  bind_unbound_port;
+    xc_evtchn_bind_interdomain_fn   bind_interdomain;
+    xc_evtchn_bind_virq_fn          bind_virq;
+    xc_evtchn_unbind_fn             unbind;
+    xc_evtchn_pending_fn            pending;
+    xc_evtchn_unmask_fn             unmask;
+};
+typedef struct XenEvtOps XenEvtOps;
+extern XenEvtOps xc_evtchn_ops;
+
+/* ------------------------------------------------------------- */
+/* xenstore interface                                            */
+
+struct xs_handle;
+
+typedef struct xs_handle *(*xenstore_daemon_open_fn)(void);
+typedef struct xs_handle *(*xenstore_domain_open_fn)(void);
+typedef struct xs_handle *(*xenstore_daemon_open_readonly_fn)(void);
+typedef int (*xenstore_domid_fn)(struct xs_handle *h, int domid);
+typedef void (*xenstore_daemon_close_fn)(struct xs_handle *);
+typedef char **(*xenstore_directory_fn)
+    (struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *num);
+typedef void *(*xenstore_read_fn)
+    (struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *len);
+typedef bool (*xenstore_write_fn)
+    (struct xs_handle *h, xs_transaction_t t, const char *path,
+     const void *data, unsigned int len);
+typedef bool (*xenstore_mkdir_fn)
+    (struct xs_handle *h, xs_transaction_t t, const char *path);
+typedef bool (*xenstore_rm_fn)
+    (struct xs_handle *h, xs_transaction_t t, const char *path);
+typedef struct xs_permissions *(*xenstore_get_permissions_fn)
+    (struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *num);
+typedef bool (*xenstore_set_permissions_fn)
+    (struct xs_handle *h, xs_transaction_t t, const char *path,
+     struct xs_permissions *perms, unsigned int num_perms);
+typedef bool (*xenstore_watch_fn)
+    (struct xs_handle *h, const char *path, const char *token);
+typedef int (*xenstore_fileno_fn)(struct xs_handle *h);
+typedef char **(*xenstore_read_watch_fn)(struct xs_handle *h, unsigned int *num);
+typedef bool (*xenstore_unwatch_fn)
+    (struct xs_handle *h, const char *path, const char *token);
+typedef xs_transaction_t (*xenstore_transaction_start_fn)(struct xs_handle *h);
+typedef bool (*xenstore_transaction_end_fn)
+    (struct xs_handle *h, xs_transaction_t t, bool abort);
+typedef bool (*xenstore_introduce_domain_fn)
+    (struct xs_handle *h, unsigned int domid, unsigned long mfn,
+     unsigned int eventchn);
+typedef bool (*xenstore_resume_domain_fn)
+    (struct xs_handle *h, unsigned int domid);
+typedef bool (*xenstore_release_domain_fn)
+    (struct xs_handle *h, unsigned int domid);
+typedef char *(*xenstore_get_domain_path_fn)
+    (struct xs_handle *h, unsigned int domid);
+typedef bool (*xenstore_is_domain_introduced_fn)
+    (struct xs_handle *h, unsigned int domid);
+
+struct XenStoreOps {
+    xenstore_daemon_open_fn daemon_open;
+    xenstore_domain_open_fn domain_open;
+    xenstore_daemon_open_readonly_fn daemon_open_readonly;
+    xenstore_domid_fn domid;
+    xenstore_daemon_close_fn daemon_close;
+    xenstore_directory_fn directory;
+    xenstore_read_fn read;
+    xenstore_write_fn write;
+    xenstore_mkdir_fn mkdir;
+    xenstore_rm_fn rm;
+    xenstore_get_permissions_fn get_permissions;
+    xenstore_set_permissions_fn set_permissions;
+    xenstore_watch_fn watch;
+    xenstore_fileno_fn fileno;
+    xenstore_read_watch_fn read_watch;
+    xenstore_unwatch_fn unwatch;
+    xenstore_transaction_start_fn transaction_start;
+    xenstore_transaction_end_fn transaction_end;
+    xenstore_introduce_domain_fn introduce_domain;
+    xenstore_resume_domain_fn resume_domain;
+    xenstore_release_domain_fn release_domain;
+    xenstore_get_domain_path_fn get_domain_path;
+    xenstore_is_domain_introduced_fn is_domain_introduced;
+};
+typedef struct XenStoreOps XenStoreOps;
+extern XenStoreOps xs_ops;
+
+/* ------------------------------------------------------------- */
+/* xen grant table interface                                     */
+
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410
+typedef int XenGnttab;
+#else
+typedef xc_gnttab *XenGnttab;
+#endif
+
+typedef XenGnttab (*xc_gnttab_open_fn)
+    (xentoollog_logger *logger, unsigned open_flags);
+typedef int (*xc_gnttab_close_fn)(XenGnttab xcg);
+typedef void *(*xc_gnttab_map_grant_ref_fn)
+    (XenGnttab xcg, uint32_t domid, uint32_t ref, int prot);
+typedef void *(*xc_gnttab_map_grant_refs_fn)
+    (XenGnttab xcg, uint32_t count, uint32_t *domids, uint32_t *refs, int prot);
+typedef int (*xc_gnttab_munmap_fn)
+    (XenGnttab xcg, void *start_address, uint32_t count);
+
+struct XenGnttabOps {
+    xc_gnttab_open_fn open;
+    xc_gnttab_close_fn close;
+    xc_gnttab_map_grant_ref_fn map_grant_ref;
+    xc_gnttab_map_grant_refs_fn map_grant_refs;
+    xc_gnttab_munmap_fn munmap;
+};
+typedef struct XenGnttabOps XenGnttabOps;
+extern XenGnttabOps xc_gnttab_ops;
+
+/* ------------------------------------------------------------- */
+/* xen hypercall interface                                       */
+
+typedef XenXC (*xc_interface_open_fn)
+    (xentoollog_logger *logger, xentoollog_logger *dombuild_logger,
+     unsigned open_flags);
+typedef int (*xc_interface_close_fn)(XenXC xc_handle);
+typedef void *(*xc_map_foreign_range_fn)
+    (XenXC xc_handle, uint32_t dom, int size, int prot, unsigned long mfn);
+typedef void *(*xc_map_foreign_pages_fn)
+    (XenXC xc_handle, uint32_t dom, int prot, const xen_pfn_t *arr, int num);
+typedef void *(*xc_map_foreign_bulk_fn)
+    (XenXC xc_handle, uint32_t dom, int prot, const xen_pfn_t *arr, int *err,
+     unsigned int num);
+typedef int (*xc_domain_populate_physmap_exact_fn)
+    (XenXC xc_handle, uint32_t domid, unsigned long nr_extents,
+     unsigned int extent_order, unsigned int mem_flags, xen_pfn_t *extent_start);
+
+struct XenIfOps {
+    xc_interface_open_fn interface_open;
+    xc_interface_close_fn interface_close;
+    xc_map_foreign_range_fn map_foreign_range;
+    xc_map_foreign_pages_fn map_foreign_pages;
+    xc_map_foreign_bulk_fn map_foreign_bulk;
+    xc_domain_populate_physmap_exact_fn domain_populate_physmap_exact;
+};
+typedef struct XenIfOps XenIfOps;
+extern XenIfOps xc_ops;
+
+/* ------------------------------------------------------------- */
+
+void xen_interfaces_init(void);
+
+#endif /* QEMU_HW_XEN_INTERFACES_H */
diff --git a/hw/xen_nic.c b/hw/xen_nic.c
index 8fcf856..6cb6fc4 100644
--- a/hw/xen_nic.c
+++ b/hw/xen_nic.c
@@ -166,9 +166,9 @@  static void net_tx_packets(struct XenNetDev *netdev)
                           (txreq.flags & NETTXF_more_data)      ? " more_data"      : "",
                           (txreq.flags & NETTXF_extra_info)     ? " extra_info"     : "");
 
-            page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
-                                           netdev->xendev.dom,
-                                           txreq.gref, PROT_READ);
+            page = xc_gnttab_ops.map_grant_ref(netdev->xendev.gnttabdev,
+                                               netdev->xendev.dom,
+                                               txreq.gref, PROT_READ);
             if (page == NULL) {
                 xen_be_printf(&netdev->xendev, 0, "error: tx gref dereference failed (%d)\n",
                               txreq.gref);
@@ -185,7 +185,7 @@  static void net_tx_packets(struct XenNetDev *netdev)
             } else {
                 qemu_send_packet(&netdev->nic->nc, page + txreq.offset, txreq.size);
             }
-            xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);
+            xc_gnttab_ops.munmap(netdev->xendev.gnttabdev, page, 1);
             net_tx_response(netdev, &txreq, NETIF_RSP_OKAY);
         }
         if (!netdev->tx_work)
@@ -272,9 +272,9 @@  static ssize_t net_rx_packet(VLANClientState *nc, const uint8_t *buf, size_t siz
     memcpy(&rxreq, RING_GET_REQUEST(&netdev->rx_ring, rc), sizeof(rxreq));
     netdev->rx_ring.req_cons = ++rc;
 
-    page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
-                                   netdev->xendev.dom,
-                                   rxreq.gref, PROT_WRITE);
+    page = xc_gnttab_ops.map_grant_ref(netdev->xendev.gnttabdev,
+                                       netdev->xendev.dom,
+                                       rxreq.gref, PROT_WRITE);
     if (page == NULL) {
         xen_be_printf(&netdev->xendev, 0, "error: rx gref dereference failed (%d)\n",
                       rxreq.gref);
@@ -282,7 +282,7 @@  static ssize_t net_rx_packet(VLANClientState *nc, const uint8_t *buf, size_t siz
         return -1;
     }
     memcpy(page + NET_IP_ALIGN, buf, size);
-    xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);
+    xc_gnttab_ops.munmap(netdev->xendev.gnttabdev, page, 1);
     net_rx_response(netdev, &rxreq, NETIF_RSP_OKAY, NET_IP_ALIGN, size, 0);
 
     return size;
@@ -350,14 +350,14 @@  static int net_connect(struct XenDevice *xendev)
         return -1;
     }
 
-    netdev->txs = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
-                                          netdev->xendev.dom,
-                                          netdev->tx_ring_ref,
-                                          PROT_READ | PROT_WRITE);
-    netdev->rxs = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,
-                                          netdev->xendev.dom,
-                                          netdev->rx_ring_ref,
-                                          PROT_READ | PROT_WRITE);
+    netdev->txs = xc_gnttab_ops.map_grant_ref(netdev->xendev.gnttabdev,
+                                              netdev->xendev.dom,
+                                              netdev->tx_ring_ref,
+                                              PROT_READ | PROT_WRITE);
+    netdev->rxs = xc_gnttab_ops.map_grant_ref(netdev->xendev.gnttabdev,
+                                              netdev->xendev.dom,
+                                              netdev->rx_ring_ref,
+                                              PROT_READ | PROT_WRITE);
     if (!netdev->txs || !netdev->rxs)
         return -1;
     BACK_RING_INIT(&netdev->tx_ring, netdev->txs, XC_PAGE_SIZE);
@@ -381,11 +381,11 @@  static void net_disconnect(struct XenDevice *xendev)
     xen_be_unbind_evtchn(&netdev->xendev);
 
     if (netdev->txs) {
-        xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->txs, 1);
+        xc_gnttab_ops.munmap(netdev->xendev.gnttabdev, netdev->txs, 1);
         netdev->txs = NULL;
     }
     if (netdev->rxs) {
-        xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->rxs, 1);
+        xc_gnttab_ops.munmap(netdev->xendev.gnttabdev, netdev->rxs, 1);
         netdev->rxs = NULL;
     }
     if (netdev->nic) {
diff --git a/hw/xenfb.c b/hw/xenfb.c
index da5297b..7ff7885 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -105,9 +105,9 @@  static int common_bind(struct common *c)
     if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1)
 	return -1;
 
-    c->page = xc_map_foreign_range(xen_xc, c->xendev.dom,
-				   XC_PAGE_SIZE,
-				   PROT_READ | PROT_WRITE, mfn);
+    c->page = xc_ops.map_foreign_range(xen_xc, c->xendev.dom,
+                                       XC_PAGE_SIZE,
+                                       PROT_READ | PROT_WRITE, mfn);
     if (c->page == NULL)
 	return -1;
 
@@ -483,15 +483,15 @@  static int xenfb_map_fb(struct XenFB *xenfb)
     fbmfns = qemu_mallocz(sizeof(unsigned long) * xenfb->fbpages);
 
     xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
-    map = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
-			       PROT_READ, pgmfns, n_fbdirs);
+    map = xc_ops.map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
+                                   PROT_READ, pgmfns, n_fbdirs);
     if (map == NULL)
 	goto out;
     xenfb_copy_mfns(mode, xenfb->fbpages, fbmfns, map);
     munmap(map, n_fbdirs * XC_PAGE_SIZE);
 
-    xenfb->pixels = xc_map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
-					 PROT_READ | PROT_WRITE, fbmfns, xenfb->fbpages);
+    xenfb->pixels = xc_ops.map_foreign_pages(xen_xc, xenfb->c.xendev.dom,
+                                             PROT_READ | PROT_WRITE, fbmfns, xenfb->fbpages);
     if (xenfb->pixels == NULL)
 	goto out;