Message ID | 1296658172-16609-4-git-send-email-anthony.perard@citrix.com |
---|---|
State | New |
Headers | show |
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; > >
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,
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, > >
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,
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;