[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen master] tools: Refactor hypercall calling wrappers into libxencall.



commit 3e9b0d540837c4641783adcc5449d3762469ff9d
Author:     Ian Campbell <ian.campbell@xxxxxxxxxx>
AuthorDate: Mon Jun 1 16:20:09 2015 +0100
Commit:     Ian Campbell <ian.campbell@xxxxxxxxxx>
CommitDate: Fri Jan 22 12:23:30 2016 +0000

    tools: Refactor hypercall calling wrappers into libxencall.
    
    libxencall will provide a stable API and ABI for calling hypercalls
    (although those hypercalls themselves may not have a stable API). As
    well as the hypercall buffer infrastructure needed in order to safely
    provide pointer arguments to hypercalls.
    
    libxenctrl encapsulates a instance of this interface, so users of that
    library are not currently subjected to any actual changes. However all
    hypercalls made internally by libxc now use the correct interface. It
    is expected that most users of this library will be other libraries
    providing a higher level interface, rather than applications directly.
    
    Only the basic functionality to allocate hypercall safe memory is
    moved, the type safe stuff and bounce buffers remain in libxc.
    
    Note that the functionality to map foreign pages using privcmd is not
    yet moved, meaning that an xc_interface will now contain two open
    privcmd file descriptors. Foreign memory mapping is logically separate
    functionality and will be moved into its own library.
    
    The new library uses a version script to ensure that only expected
    symbols are exported and to version them such that ABI guarantees can
    be kept in the future.
    
    Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
    Acked-by: Wei Liu <wei.liu2@xxxxxxxxxx>
    [ ijc -- updated MINIOS_UPSTREAM_REVISION and QEMU_TRADITIONAL_REVISION ]
---
 .gitignore                        |    2 +
 Config.mk                         |   12 +-
 stubdom/Makefile                  |   17 +++-
 tools/Makefile                    |    1 +
 tools/Rules.mk                    |    7 +-
 tools/libs/Makefile               |    1 +
 tools/libs/call/Makefile          |   71 ++++++++++++++
 tools/libs/call/buffer.c          |  192 +++++++++++++++++++++++++++++++++++++
 tools/libs/call/core.c            |  147 ++++++++++++++++++++++++++++
 tools/libs/call/freebsd.c         |  140 +++++++++++++++++++++++++++
 tools/libs/call/include/xencall.h |   84 ++++++++++++++++
 tools/libs/call/libxencall.map    |   19 ++++
 tools/libs/call/linux.c           |  138 ++++++++++++++++++++++++++
 tools/libs/call/minios.c          |   81 ++++++++++++++++
 tools/libs/call/netbsd.c          |  121 +++++++++++++++++++++++
 tools/libs/call/private.h         |   68 +++++++++++++
 tools/libs/call/solaris.c         |   97 +++++++++++++++++++
 tools/libxc/Makefile              |    7 +-
 tools/libxc/xc_altp2m.c           |   64 +++---------
 tools/libxc/xc_domain.c           |  105 +++++++-------------
 tools/libxc/xc_evtchn.c           |    9 +-
 tools/libxc/xc_flask.c            |    8 +-
 tools/libxc/xc_freebsd_osdep.c    |   47 ---------
 tools/libxc/xc_gnttab.c           |    9 +--
 tools/libxc/xc_hcall_buf.c        |  138 +-------------------------
 tools/libxc/xc_kexec.c            |   36 +++-----
 tools/libxc/xc_linux_osdep.c      |   49 ----------
 tools/libxc/xc_minios.c           |   32 ------
 tools/libxc/xc_misc.c             |   79 +++++----------
 tools/libxc/xc_netbsd.c           |   40 --------
 tools/libxc/xc_private.c          |   64 +++++--------
 tools/libxc/xc_private.h          |   76 ++++-----------
 tools/libxc/xc_solaris.c          |   16 ---
 tools/libxc/xc_tmem.c             |    7 +-
 tools/misc/Makefile               |    4 +-
 tools/xcutils/Makefile            |    2 +-
 tools/xenpaging/Makefile          |    2 +-
 37 files changed, 1354 insertions(+), 638 deletions(-)

diff --git a/.gitignore b/.gitignore
index ea75fda..6272f6b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,6 +62,7 @@ stubdom/ioemu
 stubdom/ioemu/
 stubdom/libs-*
 stubdom/libxc-*
+stubdom/libxencall-*
 stubdom/libxenevtchn-*
 stubdom/libxengnttab-*
 stubdom/libxentoollog-*
@@ -91,6 +92,7 @@ config/Docs.mk
 tools/libs/toollog/headers.chk
 tools/libs/evtchn/headers.chk
 tools/libs/gnttab/headers.chk
+tools/libs/call/headers.chk
 tools/blktap2/daemon/blktapctrl
 tools/blktap2/drivers/img2qcow
 tools/blktap2/drivers/lock-util
diff --git a/Config.mk b/Config.mk
index d2f22a3..174c192 100644
--- a/Config.mk
+++ b/Config.mk
@@ -251,9 +251,9 @@ MINIOS_UPSTREAM_URL ?= git://xenbits.xen.org/mini-os.git
 endif
 OVMF_UPSTREAM_REVISION ?= 52a99493cce88a9d4ec8a02d7f1bd1a1001ce60d
 QEMU_UPSTREAM_REVISION ?= master
-MINIOS_UPSTREAM_REVISION ?= 9faa4c3b862291315912b81fe1d4ccca800f530d
-# Fri Jan 15 13:24:01 2016 +0000
-# mini-os: Include libxengnttab with libxc
+MINIOS_UPSTREAM_REVISION ?= c7d4f84e52d901068f9c7d5cd2cc05ced93c0157
+# Fri Jan 15 13:24:02 2016 +0000
+# mini-os: Include libxencall with libxc
 
 SEABIOS_UPSTREAM_REVISION ?= 3403ac4313812752be6e6aac35239ca6888a8cab
 # Mon Dec 28 13:50:41 2015 +0100
@@ -262,9 +262,9 @@ SEABIOS_UPSTREAM_REVISION ?= 
3403ac4313812752be6e6aac35239ca6888a8cab
 ETHERBOOT_NICS ?= rtl8139 8086100e
 
 
-QEMU_TRADITIONAL_REVISION ?= d8b5666074fdbc4ddba5283d70898a2edd785028
-# Fri Jan 15 13:23:54 2016 +0000
-# qemu-xen-traditional: Use libxengnttab
+QEMU_TRADITIONAL_REVISION ?= 79ed2c5733742a7b00f9c774bece30a620150a30
+# Fri Jan 15 13:23:55 2016 +0000
+# qemu-xen-traditional: Add libxencall to rpath-link
 
 # Specify which qemu-dm to use. This may be `ioemu' to use the old
 # Mercurial in-tree version, or a local directory, or a git URL.
diff --git a/stubdom/Makefile b/stubdom/Makefile
index 2dbf4a8..5bf4ed6 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -331,6 +331,12 @@ mk-headers-$(XEN_TARGET_ARCH): $(IOEMU_LINKFARM_TARGET)
          ln -sf $(XEN_ROOT)/tools/libs/gnttab/include/*.h include/ && \
          ln -sf $(XEN_ROOT)/tools/libs/gnttab/*.c . && \
          ln -sf $(XEN_ROOT)/tools/libs/gnttab/Makefile . )
+       mkdir -p libs-$(XEN_TARGET_ARCH)/call/include
+       [ -h libs-$(XEN_TARGET_ARCH)/call/Makefile ] || ( cd 
libs-$(XEN_TARGET_ARCH)/call && \
+         ln -sf $(XEN_ROOT)/tools/libs/call/*.h . && \
+         ln -sf $(XEN_ROOT)/tools/libs/call/include/*.h include/ && \
+         ln -sf $(XEN_ROOT)/tools/libs/call/*.c . && \
+         ln -sf $(XEN_ROOT)/tools/libs/call/Makefile . )
        mkdir -p libxc-$(XEN_TARGET_ARCH)
        [ -h libxc-$(XEN_TARGET_ARCH)/Makefile ] || ( cd 
libxc-$(XEN_TARGET_ARCH) && \
          ln -sf $(XEN_ROOT)/tools/libxc/*.h . && \
@@ -381,12 +387,21 @@ libs-$(XEN_TARGET_ARCH)/gnttab/libxengnttab.a: 
mk-headers-$(XEN_TARGET_ARCH) $(N
        CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) 
DESTDIR= -C libs-$(XEN_TARGET_ARCH)/gnttab
 
 #######
+# libxencall
+#######
+
+.PHONY: libxencall
+libxencall: libs-$(XEN_TARGET_ARCH)/call/libxencall.a
+libs-$(XEN_TARGET_ARCH)/call/libxencall.a: mk-headers-$(XEN_TARGET_ARCH) 
$(NEWLIB_STAMPFILE)
+       CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) 
DESTDIR= -C libs-$(XEN_TARGET_ARCH)/call
+
+#######
 # libxc
 #######
 
 .PHONY: libxc
 libxc: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a 
libxc-$(XEN_TARGET_ARCH)/libxenguest.a
-libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: mk-headers-$(XEN_TARGET_ARCH) 
libxentoollog libxenevtchn libxengnttab cross-zlib
+libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: mk-headers-$(XEN_TARGET_ARCH) 
libxentoollog libxenevtchn libxengnttab libxencall cross-zlib
        CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) 
DESTDIR= CONFIG_LIBXC_MINIOS=y -C libxc-$(XEN_TARGET_ARCH)
 
  libxc-$(XEN_TARGET_ARCH)/libxenguest.a: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a
diff --git a/tools/Makefile b/tools/Makefile
index 50ccc75..05d8bdb 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -264,6 +264,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find
                -Wl,-rpath-link=$(XEN_ROOT)/tools/libs/toollog \
                -Wl,-rpath-link=$(XEN_ROOT)/tools/libs/evtchn \
                -Wl,-rpath-link=$(XEN_ROOT)/tools/libs/gnttab \
+               -Wl,-rpath-link=$(XEN_ROOT)/tools/libs/call \
                $(QEMU_UPSTREAM_RPATH)" \
                --bindir=$(LIBEXEC_BIN) \
                --datadir=$(SHAREDIR)/qemu-xen \
diff --git a/tools/Rules.mk b/tools/Rules.mk
index 379990f..18e3688 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -13,6 +13,7 @@ XEN_INCLUDE        = $(XEN_ROOT)/tools/include
 XEN_LIBXENTOOLLOG  = $(XEN_ROOT)/tools/libs/toollog
 XEN_LIBXENEVTCHN   = $(XEN_ROOT)/tools/libs/evtchn
 XEN_LIBXENGNTTAB   = $(XEN_ROOT)/tools/libs/gnttab
+XEN_LIBXENCALL     = $(XEN_ROOT)/tools/libs/call
 XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
 XEN_XENLIGHT       = $(XEN_ROOT)/tools/libxl
 XEN_XENSTORE       = $(XEN_ROOT)/tools/xenstore
@@ -98,8 +99,12 @@ CFLAGS_libxengntshr = -I$(XEN_LIBXENGNTTAB)/include 
$(CFLAGS_xeninclude)
 LDLIBS_libxengntshr = $(XEN_LIBXENGNTTAB)/libxengnttab$(libextension)
 SHLIB_libxengntshr  = -Wl,-rpath-link=$(XEN_LIBXENGNTTAB)
 
+CFLAGS_libxencall = -I$(XEN_LIBXENCALL)/include $(CFLAGS_xeninclude)
+LDLIBS_libxencall = $(XEN_LIBXENCALL)/libxencall$(libextension)
+SHLIB_libxencall  = -Wl,-rpath-link=$(XEN_LIBXENCALL)
+
 CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) 
$(CFLAGS_xeninclude)
-SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn) 
$(SHLIB_libxengnttab) $(SHLIB_libxengntshr)
+SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn) 
$(SHLIB_libxengnttab) $(SHLIB_libxengntshr) $(SHLIB_libxencall)
 LDLIBS_libxenctrl = $(SHDEPS_libxenctrl) $(XEN_LIBXC)/libxenctrl$(libextension)
 SHLIB_libxenctrl  = $(SHDEPS_libxenctrl) -Wl,-rpath-link=$(XEN_LIBXC)
 
diff --git a/tools/libs/Makefile b/tools/libs/Makefile
index 00156ae..f4f5d57 100644
--- a/tools/libs/Makefile
+++ b/tools/libs/Makefile
@@ -5,5 +5,6 @@ SUBDIRS-y :=
 SUBDIRS-y += toollog
 SUBDIRS-y += evtchn
 SUBDIRS-y += gnttab
+SUBDIRS-y += call
 
 all clean install distclean: %: subdirs-%
diff --git a/tools/libs/call/Makefile b/tools/libs/call/Makefile
new file mode 100644
index 0000000..9402ea5
--- /dev/null
+++ b/tools/libs/call/Makefile
@@ -0,0 +1,71 @@
+XEN_ROOT = $(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR    = 1
+MINOR    = 0
+SHLIB_LDFLAGS += -Wl,--version-script=libxencall.map
+
+CFLAGS   += -Werror -Wmissing-prototypes
+CFLAGS   += -I./include $(CFLAGS_xeninclude)
+CFLAGS   += $(CFLAGS_libxentoollog)
+
+SRCS-y                 += core.c buffer.c
+SRCS-$(CONFIG_Linux)   += linux.c
+SRCS-$(CONFIG_FreeBSD) += freebsd.c
+SRCS-$(CONFIG_SunOS)   += solaris.c
+SRCS-$(CONFIG_NetBSD)  += netbsd.c
+SRCS-$(CONFIG_MiniOS)  += minios.c
+
+LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y))
+PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y))
+
+LIB := libxencall.a
+ifneq ($(nosharedlibs),y)
+LIB += libxencall.so
+endif
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build:
+       $(MAKE) libs
+
+.PHONY: libs
+libs: headers.chk $(LIB)
+
+headers.chk: $(wildcard include/*.h)
+
+libxencall.a: $(LIB_OBJS)
+       $(AR) rc $@ $^
+
+libxencall.so: libxencall.so.$(MAJOR)
+       $(SYMLINK_SHLIB) $< $@
+libxencall.so.$(MAJOR): libxencall.so.$(MAJOR).$(MINOR)
+       $(SYMLINK_SHLIB) $< $@
+
+libxencall.so.$(MAJOR).$(MINOR): $(PIC_OBJS) libxencall.map
+       $(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) 
-Wl,libxencall.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(PIC_OBJS) 
$(LDLIBS_libxentoollog) $(APPEND_LDFLAGS)
+
+.PHONY: install
+install: build
+       $(INSTALL_DIR) $(DESTDIR)$(libdir)
+       $(INSTALL_DIR) $(DESTDIR)$(includedir)
+       $(INSTALL_SHLIB) libxencall.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
+       $(INSTALL_DATA) libxencall.a $(DESTDIR)$(libdir)
+       $(SYMLINK_SHLIB) libxencall.so.$(MAJOR).$(MINOR) 
$(DESTDIR)$(libdir)/libxencall.so.$(MAJOR)
+       $(SYMLINK_SHLIB) libxencall.so.$(MAJOR) 
$(DESTDIR)$(libdir)/libxencall.so
+       $(INSTALL_DATA) include/xencall.h $(DESTDIR)$(includedir)
+
+.PHONY: TAGS
+TAGS:
+       etags -t *.c *.h
+
+.PHONY: clean
+clean:
+       rm -rf *.rpm $(LIB) *~ $(DEPS) $(LIB_OBJS) $(PIC_OBJS)
+       rm -f libxencall.so.$(MAJOR).$(MINOR) libxencall.so.$(MAJOR)
+       rm -f headers.chk
+
+.PHONY: distclean
+distclean: clean
diff --git a/tools/libs/call/buffer.c b/tools/libs/call/buffer.c
new file mode 100644
index 0000000..1a1b27a
--- /dev/null
+++ b/tools/libs/call/buffer.c
@@ -0,0 +1,192 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "private.h"
+
+#define DBGPRINTF(_m...) \
+       xtl_log(xcall->logger, XTL_DEBUG, -1, "xencall:buffer", _m)
+
+#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
+
+pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void cache_lock(xencall_handle *xcall)
+{
+    int saved_errno = errno;
+    if ( xcall->flags & XENCALL_OPENFLAG_NON_REENTRANT )
+        return;
+    pthread_mutex_lock(&cache_mutex);
+    /* Ignore pthread errors. */
+    errno = saved_errno;
+}
+
+static void cache_unlock(xencall_handle *xcall)
+{
+    int saved_errno = errno;
+    if ( xcall->flags & XENCALL_OPENFLAG_NON_REENTRANT )
+        return;
+    pthread_mutex_unlock(&cache_mutex);
+    /* Ignore pthread errors. */
+    errno = saved_errno;
+}
+
+static void *cache_alloc(xencall_handle *xcall, size_t nr_pages)
+{
+    void *p = NULL;
+
+    cache_lock(xcall);
+
+    xcall->buffer_total_allocations++;
+    xcall->buffer_current_allocations++;
+    if ( xcall->buffer_current_allocations > xcall->buffer_maximum_allocations 
)
+        xcall->buffer_maximum_allocations = xcall->buffer_current_allocations;
+
+    if ( nr_pages > 1 )
+    {
+        xcall->buffer_cache_toobig++;
+    }
+    else if ( xcall->buffer_cache_nr > 0 )
+    {
+        p = xcall->buffer_cache[--xcall->buffer_cache_nr];
+        xcall->buffer_cache_hits++;
+    }
+    else
+    {
+        xcall->buffer_cache_misses++;
+    }
+
+    cache_unlock(xcall);
+
+    return p;
+}
+
+static int cache_free(xencall_handle *xcall, void *p, size_t nr_pages)
+{
+    int rc = 0;
+
+    cache_lock(xcall);
+
+    xcall->buffer_total_releases++;
+    xcall->buffer_current_allocations--;
+
+    if ( nr_pages == 1 &&
+        xcall->buffer_cache_nr < BUFFER_CACHE_SIZE )
+    {
+        xcall->buffer_cache[xcall->buffer_cache_nr++] = p;
+        rc = 1;
+    }
+
+    cache_unlock(xcall);
+
+    return rc;
+}
+
+void buffer_release_cache(xencall_handle *xcall)
+{
+    void *p;
+
+    cache_lock(xcall);
+
+    DBGPRINTF("total allocations:%d total releases:%d",
+              xcall->buffer_total_allocations,
+              xcall->buffer_total_releases);
+    DBGPRINTF("current allocations:%d maximum allocations:%d",
+              xcall->buffer_current_allocations,
+              xcall->buffer_maximum_allocations);
+    DBGPRINTF("cache current size:%d",
+              xcall->buffer_cache_nr);
+    DBGPRINTF("cache hits:%d misses:%d toobig:%d",
+              xcall->buffer_cache_hits,
+              xcall->buffer_cache_misses,
+              xcall->buffer_cache_toobig);
+
+    while ( xcall->buffer_cache_nr > 0 )
+    {
+        p = xcall->buffer_cache[--xcall->buffer_cache_nr];
+        osdep_free_pages(xcall, p, 1);
+    }
+
+    cache_unlock(xcall);
+}
+
+void *xencall_alloc_buffer_pages(xencall_handle *xcall, size_t nr_pages)
+{
+    void *p = cache_alloc(xcall, nr_pages);
+
+    if ( !p )
+        p = osdep_alloc_pages(xcall, nr_pages);
+
+    if (!p)
+        return NULL;
+
+    memset(p, 0, nr_pages * PAGE_SIZE);
+
+    return p;
+}
+
+void xencall_free_buffer_pages(xencall_handle *xcall, void *p, size_t nr_pages)
+{
+    if ( p == NULL )
+        return;
+
+    if ( !cache_free(xcall, p, nr_pages) )
+        osdep_free_pages(xcall, p, nr_pages);
+}
+
+struct allocation_header {
+    int nr_pages;
+};
+
+void *xencall_alloc_buffer(xencall_handle *xcall, size_t size)
+{
+    size_t actual_size = ROUNDUP(size + sizeof(struct allocation_header), 
PAGE_SHIFT);
+    int nr_pages = actual_size >> PAGE_SHIFT;
+    struct allocation_header *hdr;
+
+    hdr = xencall_alloc_buffer_pages(xcall, nr_pages);
+    if ( hdr == NULL )
+        return NULL;
+
+    hdr->nr_pages = nr_pages;
+
+    return (void *)(hdr+1);
+}
+
+void xencall_free_buffer(xencall_handle *xcall, void *p)
+{
+    struct allocation_header *hdr;
+
+    if (p == NULL)
+        return;
+
+    hdr = p;
+    --hdr;
+
+    xencall_free_buffer_pages(xcall, hdr, hdr->nr_pages);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/call/core.c b/tools/libs/call/core.c
new file mode 100644
index 0000000..a342871
--- /dev/null
+++ b/tools/libs/call/core.c
@@ -0,0 +1,147 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#include "private.h"
+
+xencall_handle *xencall_open(xentoollog_logger *logger, unsigned open_flags)
+{
+       xencall_handle *xcall = malloc(sizeof(*xcall));
+    int rc;
+
+    if (!xcall) return NULL;
+
+    xcall->flags = open_flags;
+    xcall->buffer_cache_nr = 0;
+
+    xcall->buffer_total_allocations = 0;
+    xcall->buffer_total_releases = 0;
+    xcall->buffer_current_allocations = 0;
+    xcall->buffer_maximum_allocations = 0;
+    xcall->buffer_cache_hits = 0;
+    xcall->buffer_cache_misses = 0;
+    xcall->buffer_cache_toobig = 0;
+    xcall->logger = logger;
+    xcall->logger_tofree = NULL;
+
+    if (!xcall->logger) {
+        xcall->logger = xcall->logger_tofree =
+            (xentoollog_logger*)
+            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
+        if (!xcall->logger) goto err;
+    }
+
+    rc = osdep_xencall_open(xcall);
+    if ( rc  < 0 ) goto err;
+
+    return xcall;
+
+err:
+    osdep_xencall_close(xcall);
+    xtl_logger_destroy(xcall->logger_tofree);
+    free(xcall);
+    return NULL;
+}
+
+int xencall_close(xencall_handle *xcall)
+{
+    int rc;
+
+    if ( !xcall )
+        return 0;
+
+    rc = osdep_xencall_close(xcall);
+    buffer_release_cache(xcall);
+    xtl_logger_destroy(xcall->logger_tofree);
+    free(xcall);
+    return rc;
+}
+
+int xencall0(xencall_handle *xcall, unsigned int op)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+int xencall1(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+        .arg = { arg1 },
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+int xencall2(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+        .arg = { arg1, arg2 },
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+int xencall3(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+        .arg = { arg1, arg2, arg3},
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+int xencall4(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3,
+             uint64_t arg4)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+        .arg = { arg1, arg2, arg3, arg4 },
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+int xencall5(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3,
+             uint64_t arg4, uint64_t arg5)
+{
+    privcmd_hypercall_t call = {
+        .op = op,
+        .arg = { arg1, arg2, arg3, arg4, arg5 },
+    };
+
+    return osdep_hypercall(xcall, &call);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/call/freebsd.c b/tools/libs/call/freebsd.c
new file mode 100644
index 0000000..2413966
--- /dev/null
+++ b/tools/libs/call/freebsd.c
@@ -0,0 +1,140 @@
+ 
/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Split from xc_freebsd_osdep.c
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "private.h"
+
+#define PRIVCMD_DEV     "/dev/xen/privcmd"
+
+int osdep_xencall_open(xencall_handle *xcall)
+{
+    int flags, saved_errno;
+    int fd = open(PRIVCMD_DEV, O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface "
+               PRIVCMD_DEV);
+        return -1;
+    }
+
+    /*
+     * Although we return the file handle as the 'xc handle' the API
+     * does not specify / guarentee that this integer is in fact
+     * a file handle. Thus we must take responsiblity to ensure
+     * it doesn't propagate (ie leak) outside the process.
+     */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+
+    flags |= FD_CLOEXEC;
+
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    xcall->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+
+    return -1;
+}
+
+int osdep_xencall_close(xencall_handle *xcall)
+{
+    int fd = xcall->fd;
+    if ( fd == -1 )
+        return 0;
+    return close(fd);
+}
+
+int osdep_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
+{
+    int fd = xcall->fd;
+    int ret;
+
+    ret = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
+
+    return (ret == 0) ? hypercall->retval : ret;
+}
+
+void *osdep_alloc_pages(xencall_handle *xcall, size_t npages)
+{
+    size_t size = npages * PAGE_SIZE;
+    void *p;
+
+    /* Address returned by mmap is page aligned. */
+    p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
+             -1, 0);
+    if (p == NULL)
+        return NULL;
+
+    /*
+     * Since FreeBSD doesn't have the MAP_LOCKED flag,
+     * lock memory using mlock.
+     */
+    if ( mlock(p, size) < 0 )
+    {
+        munmap(p, size);
+        return NULL;
+    }
+
+    return p;
+}
+
+void osdep_free_pages(xencall_handle *xcall, void *ptr, size_t npages)
+{
+    int saved_errno = errno;
+    /* Unlock pages */
+    munlock(ptr, npages * PAGE_SIZE);
+
+    munmap(ptr, npages * PAGE_SIZE);
+    /* We MUST propagate the hypercall errno, not unmap call's. */
+    errno = saved_errno;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/call/include/xencall.h 
b/tools/libs/call/include/xencall.h
new file mode 100644
index 0000000..0d91aa8
--- /dev/null
+++ b/tools/libs/call/include/xencall.h
@@ -0,0 +1,84 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef XENCALL_H
+#define XENCALL_H
+
+/*
+ * This library allows you to make arbitrary hypercalls (subject to
+ * sufficient permission for the process and the domain itself). Note
+ * that while the library interface is stable the hypercalls are
+ * subject to their own rules.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* Callers who don't care don't need to #include <xentoollog.h> */
+typedef struct xentoollog_logger xentoollog_logger;
+
+typedef struct xencall_handle xencall_handle;
+
+/*
+ */
+#define XENCALL_OPENFLAG_NON_REENTRANT (1U<<0)
+
+/*
+ * Return a handle onto the hypercall driver.  Logs errors.
+ */
+xencall_handle *xencall_open(xentoollog_logger *logger, unsigned open_flags);
+
+/*
+ * Close a handle previously allocated with xencall_open().
+ */
+int xencall_close(xencall_handle *xcall);
+
+/*
+ * Call hypercalls with varying numbers of arguments.
+ */
+int xencall0(xencall_handle *xcall, unsigned int op);
+int xencall1(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1);
+int xencall2(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2);
+int xencall3(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3);
+int xencall4(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3,
+             uint64_t arg4);
+int xencall5(xencall_handle *xcall, unsigned int op,
+             uint64_t arg1, uint64_t arg2, uint64_t arg3,
+             uint64_t arg4, uint64_t arg5);
+
+/*
+ * Allocate and free memory which is suitable for use as a pointer
+ * argument to a hypercall.
+ */
+void *xencall_alloc_buffer_pages(xencall_handle *xcall, size_t nr_pages);
+void xencall_free_buffer_pages(xencall_handle *xcall, void *p, size_t 
nr_pages);
+
+void *xencall_alloc_buffer(xencall_handle *xcall, size_t size);
+void xencall_free_buffer(xencall_handle *xcall, void *p);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/call/libxencall.map b/tools/libs/call/libxencall.map
new file mode 100644
index 0000000..2f96144
--- /dev/null
+++ b/tools/libs/call/libxencall.map
@@ -0,0 +1,19 @@
+VERS_1.0 {
+       global:
+               xencall_open;
+               xencall_close;
+
+               xencall0;
+               xencall1;
+               xencall2;
+               xencall3;
+               xencall4;
+               xencall5;
+               xencall6;
+
+               xencall_alloc_buffer;
+               xencall_free_buffer;
+               xencall_alloc_buffer_pages;
+               xencall_free_buffer_pages;
+       local: *; /* Do not expose anything by default */
+};
diff --git a/tools/libs/call/linux.c b/tools/libs/call/linux.c
new file mode 100644
index 0000000..55e1e83
--- /dev/null
+++ b/tools/libs/call/linux.c
@@ -0,0 +1,138 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Split out from xc_linus_osdep.c:
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "private.h"
+
+int osdep_xencall_open(xencall_handle *xcall)
+{
+    int flags, saved_errno;
+    int fd = open("/dev/xen/privcmd", O_RDWR); /* prefer this newer interface 
*/
+
+    if ( fd == -1 && ( errno == ENOENT || errno == ENXIO || errno == ENODEV ))
+    {
+        /* Fallback to /proc/xen/privcmd */
+        fd = open("/proc/xen/privcmd", O_RDWR);
+    }
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface");
+        return -1;
+    }
+
+    /* Although we return the file handle as the 'xc handle' the API
+       does not specify / guarentee that this integer is in fact
+       a file handle. Thus we must take responsiblity to ensure
+       it doesn't propagate (ie leak) outside the process */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+
+    flags |= FD_CLOEXEC;
+
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    xcall->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return -1;
+}
+
+int osdep_xencall_close(xencall_handle *xcall)
+{
+    int fd = xcall->fd;
+    if (fd == -1)
+        return 0;
+    return close(fd);
+}
+
+int osdep_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
+{
+    return ioctl(xcall->fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
+}
+
+void *osdep_alloc_pages(xencall_handle *xcall, size_t npages)
+{
+    size_t size = npages * PAGE_SIZE;
+    void *p;
+    int rc, saved_errno;
+
+    /* Address returned by mmap is page aligned. */
+    p = mmap(NULL, size, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0);
+    if ( p == MAP_FAILED )
+    {
+        PERROR("xc_alloc_hypercall_buffer: mmap failed");
+        return NULL;
+    }
+
+    /* Do not copy the VMA to child process on fork. Avoid the page being COW
+        on hypercall. */
+    rc = madvise(p, npages * PAGE_SIZE, MADV_DONTFORK);
+    if ( rc < 0 )
+    {
+        PERROR("xc_alloc_hypercall_buffer: madvise failed");
+        goto out;
+    }
+
+    return p;
+
+out:
+    saved_errno = errno;
+    (void)munmap(p, size);
+    errno = saved_errno;
+    return NULL;
+}
+
+void osdep_free_pages(xencall_handle *xcall, void *ptr, size_t npages)
+{
+    int saved_errno = errno;
+    /* Recover the VMA flags. Maybe it's not necessary */
+    madvise(ptr, npages * PAGE_SIZE, MADV_DOFORK);
+
+    munmap(ptr, npages * PAGE_SIZE);
+    /* We MUST propagate the hypercall errno, not unmap call's. */
+    errno = saved_errno;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/call/minios.c b/tools/libs/call/minios.c
new file mode 100644
index 0000000..3bee7be
--- /dev/null
+++ b/tools/libs/call/minios.c
@@ -0,0 +1,81 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Split out from xc_minios.c
+ *
+ * Copyright 2007-2008 Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>.
+ */
+
+#include <mini-os/types.h>
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/lib.h>
+
+#include <errno.h>
+#include <malloc.h>
+
+#include "private.h"
+
+int osdep_xencall_open(xencall_handle *xcall)
+{
+    /* No fd required */
+    return 0;
+}
+
+int osdep_xencall_close(xencall_handle *xcall)
+{
+    return 0;
+}
+
+int osdep_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
+{
+    multicall_entry_t call;
+    int i, ret;
+
+    call.op = hypercall->op;
+    for (i = 0; i < 5; i++)
+        call.args[i] = hypercall->arg[i];
+
+    ret = HYPERVISOR_multicall(&call, 1);
+
+    if (ret < 0) {
+       errno = -ret;
+       return -1;
+    }
+    if ((long) call.result < 0) {
+        errno = - (long) call.result;
+        return -1;
+    }
+    return call.result;
+}
+
+void *osdep_alloc_pages(xencall_handle *xcall, size_t npages)
+{
+    return memalign(PAGE_SIZE, npages * PAGE_SIZE);
+}
+
+void osdep_free_pages(xencall_handle *xcall, void *ptr, size_t npages)
+{
+    free(ptr);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/call/netbsd.c b/tools/libs/call/netbsd.c
new file mode 100644
index 0000000..2aa02f1
--- /dev/null
+++ b/tools/libs/call/netbsd.c
@@ -0,0 +1,121 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Split from xc_netbsd.c
+ */
+
+#include "xc_private.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <sys/mman.h>
+
+int osdep_xencall_open(xencall_handle *xcall)
+{
+    int flags, saved_errno;
+    int fd = open("/kern/xen/privcmd", O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface");
+        return -1;
+    }
+
+    /* Although we return the file handle as the 'xc handle' the API
+       does not specify / guarentee that this integer is in fact
+       a file handle. Thus we must take responsiblity to ensure
+       it doesn't propagate (ie leak) outside the process */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+    flags |= FD_CLOEXEC;
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    xcall->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return -1;
+}
+
+int osdep_xencall_close(xencall_handle *xcall)
+{
+    int fd = xcall->fd;
+    return close(fd);
+}
+
+void *osdep_alloc_hypercall_buffer(xencall_handle *xcall, size_t npages)
+{
+    size_t size = npages * XC_PAGE_SIZE;
+    void *p;
+
+    p = xc_memalign(xcall, XC_PAGE_SIZE, size);
+    if (!p)
+        return NULL;
+
+    if ( mlock(p, size) < 0 )
+    {
+        free(p);
+        return NULL;
+    }
+    return p;
+}
+
+void osdep_free_hypercall_buffer(xencall_handle *xcall, void *ptr,
+                                 size_t npages)
+{
+    (void) munlock(ptr, npages * XC_PAGE_SIZE);
+    free(ptr);
+}
+
+int do_xen_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
+{
+    int fd = xcall->fd;
+    int error = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
+
+    /*
+     * Since NetBSD ioctl can only return 0 on success or < 0 on
+     * error, if we want to return a value from ioctl we should
+     * do so by setting hypercall->retval, to mimic Linux ioctl
+     * implementation.
+     */
+    if (error < 0)
+        return error;
+    else
+        return hypercall->retval;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/call/private.h b/tools/libs/call/private.h
new file mode 100644
index 0000000..37dd15f
--- /dev/null
+++ b/tools/libs/call/private.h
@@ -0,0 +1,68 @@
+#ifndef XENCALL_PRIVATE_H
+#define XENCALL_PRIVATE_H
+
+#include <xentoollog.h>
+
+#include <xencall.h>
+
+#include <xen/xen.h>
+#include <xen/sys/privcmd.h>
+
+#ifndef PAGE_SHIFT /* Mini-os, Yukk */
+#define PAGE_SHIFT           12
+#endif
+#ifndef __MINIOS__ /* Yukk */
+#define PAGE_SIZE            (1UL << PAGE_SHIFT)
+#define PAGE_MASK            (~(PAGE_SIZE-1))
+#endif
+
+struct xencall_handle {
+    xentoollog_logger *logger, *logger_tofree;
+    unsigned flags;
+    int fd;
+
+    /*
+     * A simple cache of unused, single page, hypercall buffers
+     *
+     * Protected by a global lock.
+     */
+#define BUFFER_CACHE_SIZE 4
+    int buffer_cache_nr;
+    void *buffer_cache[BUFFER_CACHE_SIZE];
+
+    /*
+     * Hypercall buffer statistics. All protected by the global
+     * buffer_cache lock.
+     */
+    int buffer_total_allocations;
+    int buffer_total_releases;
+    int buffer_current_allocations;
+    int buffer_maximum_allocations;
+    int buffer_cache_hits;
+    int buffer_cache_misses;
+    int buffer_cache_toobig;
+};
+
+int osdep_xencall_open(xencall_handle *xcall);
+int osdep_xencall_close(xencall_handle *xcall);
+
+int osdep_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall);
+
+void *osdep_alloc_pages(xencall_handle *xcall, size_t nr_pages);
+void osdep_free_pages(xencall_handle *xcall, void *p, size_t nr_pages);
+
+void buffer_release_cache(xencall_handle *xcall);
+
+#define PERROR(_f...) xtl_log(xcall->logger, XTL_ERROR, errno, "xencall", _f)
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/call/solaris.c b/tools/libs/call/solaris.c
new file mode 100644
index 0000000..945d867
--- /dev/null
+++ b/tools/libs/call/solaris.c
@@ -0,0 +1,97 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Split from xc_solaris.c
+ */
+
+#include "xc_private.h"
+
+#include <xen/memory.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <malloc.h>
+
+int osdep_xencall_open(xencall_handle *xcall)
+{
+    int flags, saved_errno;
+    int fd = open("/dev/xen/privcmd", O_RDWR);
+
+    if ( fd == -1 )
+    {
+        PERROR("Could not obtain handle on privileged command interface");
+        return -1;
+    }
+
+    /* Although we return the file handle as the 'xc handle' the API
+       does not specify / guarentee that this integer is in fact
+       a file handle. Thus we must take responsiblity to ensure
+       it doesn't propagate (ie leak) outside the process */
+    if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+    {
+        PERROR("Could not get file handle flags");
+        goto error;
+    }
+    flags |= FD_CLOEXEC;
+    if ( fcntl(fd, F_SETFD, flags) < 0 )
+    {
+        PERROR("Could not set file handle flags");
+        goto error;
+    }
+
+    xcall->fd = fd;
+    return 0;
+
+ error:
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return -1;
+}
+
+int osdep_xencall_close(xencall_handle *xcall)
+{
+    int fd = xcall->fd;
+    return close(fd);
+}
+
+void *osdep_alloc_hypercall_buffer(xencall_handle *xcall, size_t npages)
+{
+    return xc_memalign(xcall, XC_PAGE_SIZE, npages * XC_PAGE_SIZE);
+}
+
+void osdep_free_hypercall_buffer(xencall_handle *xcall, void *ptr,
+                                 size_t npages)
+{
+    free(ptr);
+}
+
+int do_xen_hypercall(xencall_handle *xcall, privcmd_hypercall_t *hypercall)
+{
+    int fd = xcall->fd;
+    return ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 3305fdd..a122f73 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -122,6 +122,11 @@ GUEST_PIC_OBJS := $(patsubst %.c,%.opic,$(GUEST_SRCS-y))
 $(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) \
 $(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += -include 
$(XEN_ROOT)/tools/config.h
 
+# libxenguest includes xc_private.h, so needs this despite not using
+# this functionality directly.
+$(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) \
+$(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += $(CFLAGS_libxencall)
+
 $(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS): CFLAGS += $(CFLAGS_libxengnttab) 
$(CFLAGS_libxengntshr)
 
 LIB := libxenctrl.a
@@ -202,7 +207,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
        $(SYMLINK_SHLIB) $< $@
 
 libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
-       $(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) 
-Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) 
$(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) 
$(PTHREAD_LIBS) $(APPEND_LDFLAGS)
+       $(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) 
-Wl,libxenctrl.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDLIBS_libxentoollog) 
$(LDLIBS_libxenevtchn) $(LDLIBS_libxengnttab) $(LDLIBS_libxengntshr) 
$(LDLIBS_libxencall) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
 
 # libxenguest
 
diff --git a/tools/libxc/xc_altp2m.c b/tools/libxc/xc_altp2m.c
index 87a0fdf..0639632 100644
--- a/tools/libxc/xc_altp2m.c
+++ b/tools/libxc/xc_altp2m.c
@@ -27,22 +27,18 @@
 int xc_altp2m_get_domain_state(xc_interface *handle, domid_t dom, bool *state)
 {
     int rc;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
 
     arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_altp2m;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
     arg->cmd = HVMOP_altp2m_get_domain_state;
     arg->domain = dom;
 
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
+                 HYPERCALL_BUFFER_AS_ARG(arg));
 
     if ( !rc )
         *state = arg->u.domain_state.state;
@@ -54,23 +50,19 @@ int xc_altp2m_get_domain_state(xc_interface *handle, 
domid_t dom, bool *state)
 int xc_altp2m_set_domain_state(xc_interface *handle, domid_t dom, bool state)
 {
     int rc;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
 
     arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_altp2m;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
     arg->cmd = HVMOP_altp2m_set_domain_state;
     arg->domain = dom;
     arg->u.domain_state.state = state;
 
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
+                 HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(handle, arg);
     return rc;
@@ -81,24 +73,20 @@ int xc_altp2m_set_vcpu_enable_notify(xc_interface *handle, 
domid_t domid,
                                      uint32_t vcpuid, xen_pfn_t gfn)
 {
     int rc;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
 
     arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_altp2m;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
     arg->cmd = HVMOP_altp2m_vcpu_enable_notify;
     arg->domain = domid;
     arg->u.enable_notify.vcpu_id = vcpuid;
     arg->u.enable_notify.gfn = gfn;
 
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
+                 HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(handle, arg);
     return rc;
@@ -108,24 +96,20 @@ int xc_altp2m_create_view(xc_interface *handle, domid_t 
domid,
                           xenmem_access_t default_access, uint16_t *view_id)
 {
     int rc;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
 
     arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_altp2m;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
     arg->cmd = HVMOP_altp2m_create_p2m;
     arg->domain = domid;
     arg->u.view.view = -1;
     arg->u.view.hvmmem_default_access = default_access;
 
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
+                 HYPERCALL_BUFFER_AS_ARG(arg));
 
     if ( !rc )
         *view_id = arg->u.view.view;
@@ -138,23 +122,19 @@ int xc_altp2m_destroy_view(xc_interface *handle, domid_t 
domid,
                            uint16_t view_id)
 {
     int rc;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
 
     arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_altp2m;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
     arg->cmd = HVMOP_altp2m_destroy_p2m;
     arg->domain = domid;
     arg->u.view.view = view_id;
 
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
+                 HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(handle, arg);
     return rc;
@@ -165,23 +145,19 @@ int xc_altp2m_switch_to_view(xc_interface *handle, 
domid_t domid,
                              uint16_t view_id)
 {
     int rc;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
 
     arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_altp2m;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
     arg->cmd = HVMOP_altp2m_switch_p2m;
     arg->domain = domid;
     arg->u.view.view = view_id;
 
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
+                 HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(handle, arg);
     return rc;
@@ -192,17 +168,12 @@ int xc_altp2m_set_mem_access(xc_interface *handle, 
domid_t domid,
                              xenmem_access_t access)
 {
     int rc;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
 
     arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_altp2m;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
     arg->cmd = HVMOP_altp2m_set_mem_access;
     arg->domain = domid;
@@ -210,7 +181,8 @@ int xc_altp2m_set_mem_access(xc_interface *handle, domid_t 
domid,
     arg->u.set_mem_access.hvmmem_access = access;
     arg->u.set_mem_access.gfn = gfn;
 
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
+                 HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(handle, arg);
     return rc;
@@ -221,17 +193,12 @@ int xc_altp2m_change_gfn(xc_interface *handle, domid_t 
domid,
                          xen_pfn_t new_gfn)
 {
     int rc;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_altp2m_op_t, arg);
 
     arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_altp2m;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->version = HVMOP_ALTP2M_INTERFACE_VERSION;
     arg->cmd = HVMOP_altp2m_change_gfn;
     arg->domain = domid;
@@ -239,7 +206,8 @@ int xc_altp2m_change_gfn(xc_interface *handle, domid_t 
domid,
     arg->u.change_gfn.old_gfn = old_gfn;
     arg->u.change_gfn.new_gfn = new_gfn;
 
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op, HVMOP_altp2m,
+                 HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(handle, arg);
     return rc;
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 99e0d48..921113d 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -122,7 +122,6 @@ int xc_domain_shutdown(xc_interface *xch,
                        int reason)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(sched_remote_shutdown_t, arg);
 
     arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
@@ -132,13 +131,11 @@ int xc_domain_shutdown(xc_interface *xch,
         goto out1;
     }
 
-    hypercall.op     = __HYPERVISOR_sched_op;
-    hypercall.arg[0] = (unsigned long)SCHEDOP_remote_shutdown;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
     arg->domain_id = domid;
     arg->reason = reason;
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_sched_op,
+                   SCHEDOP_remote_shutdown,
+                   HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -562,7 +559,6 @@ int xc_watchdog(xc_interface *xch,
                 uint32_t timeout)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(sched_watchdog_t, arg);
 
     arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
@@ -572,13 +568,12 @@ int xc_watchdog(xc_interface *xch,
         goto out1;
     }
 
-    hypercall.op     = __HYPERVISOR_sched_op;
-    hypercall.arg[0] = (unsigned long)SCHEDOP_watchdog;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
     arg->id = id;
     arg->timeout = timeout;
 
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_sched_op,
+                   SCHEDOP_watchdog,
+                   HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -1357,7 +1352,6 @@ static inline int xc_hvm_param_deprecated_check(uint32_t 
param)
 
 int xc_hvm_param_set(xc_interface *handle, domid_t dom, uint32_t param, 
uint64_t value)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_param_t, arg);
     int rc = xc_hvm_param_deprecated_check(param);
 
@@ -1368,20 +1362,18 @@ int xc_hvm_param_set(xc_interface *handle, domid_t dom, 
uint32_t param, uint64_t
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_param;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
     arg->domid = dom;
     arg->index = param;
     arg->value = value;
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_param,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
     xc_hypercall_buffer_free(handle, arg);
     return rc;
 }
 
 int xc_hvm_param_get(xc_interface *handle, domid_t dom, uint32_t param, 
uint64_t *value)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_param_t, arg);
     int rc = xc_hvm_param_deprecated_check(param);
 
@@ -1392,12 +1384,11 @@ int xc_hvm_param_get(xc_interface *handle, domid_t dom, 
uint32_t param, uint64_t
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_get_param;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
     arg->domid = dom;
     arg->index = param;
-    rc = do_xen_hypercall(handle, &hypercall);
+    rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_get_param,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
     *value = arg->value;
     xc_hypercall_buffer_free(handle, arg);
     return rc;
@@ -1425,7 +1416,6 @@ int xc_hvm_create_ioreq_server(xc_interface *xch,
                                int handle_bufioreq,
                                ioservid_t *id)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_create_ioreq_server_t, arg);
     int rc;
 
@@ -1433,14 +1423,12 @@ int xc_hvm_create_ioreq_server(xc_interface *xch,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_create_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->handle_bufioreq = handle_bufioreq;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_create_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     *id = arg->id;
 
@@ -1455,7 +1443,6 @@ int xc_hvm_get_ioreq_server_info(xc_interface *xch,
                                  xen_pfn_t *bufioreq_pfn,
                                  evtchn_port_t *bufioreq_port)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_get_ioreq_server_info_t, arg);
     int rc;
 
@@ -1463,14 +1450,12 @@ int xc_hvm_get_ioreq_server_info(xc_interface *xch,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_get_ioreq_server_info;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_get_ioreq_server_info,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
     if ( rc != 0 )
         goto done;
 
@@ -1492,7 +1477,6 @@ int xc_hvm_map_io_range_to_ioreq_server(xc_interface 
*xch, domid_t domid,
                                         ioservid_t id, int is_mmio,
                                         uint64_t start, uint64_t end)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
     int rc;
 
@@ -1500,17 +1484,15 @@ int xc_hvm_map_io_range_to_ioreq_server(xc_interface 
*xch, domid_t domid,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_map_io_range_to_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
     arg->type = is_mmio ? HVMOP_IO_RANGE_MEMORY : HVMOP_IO_RANGE_PORT;
     arg->start = start;
     arg->end = end;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_map_io_range_to_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
@@ -1520,7 +1502,6 @@ int xc_hvm_unmap_io_range_from_ioreq_server(xc_interface 
*xch, domid_t domid,
                                             ioservid_t id, int is_mmio,
                                             uint64_t start, uint64_t end)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
     int rc;
 
@@ -1528,17 +1509,15 @@ int 
xc_hvm_unmap_io_range_from_ioreq_server(xc_interface *xch, domid_t domid,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_unmap_io_range_from_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
     arg->type = is_mmio ? HVMOP_IO_RANGE_MEMORY : HVMOP_IO_RANGE_PORT;
     arg->start = start;
     arg->end = end;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_unmap_io_range_from_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
@@ -1549,7 +1528,6 @@ int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch, 
domid_t domid,
                                       uint8_t bus, uint8_t device,
                                       uint8_t function)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
     int rc;
 
@@ -1562,10 +1540,6 @@ int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch, 
domid_t domid,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_map_io_range_to_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
     arg->type = HVMOP_IO_RANGE_PCI;
@@ -1579,7 +1553,9 @@ int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch, 
domid_t domid,
                                            (uint64_t)device,
                                            (uint64_t)function);
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_map_io_range_to_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
@@ -1590,7 +1566,6 @@ int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface 
*xch, domid_t domid,
                                           uint8_t bus, uint8_t device,
                                           uint8_t function)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_io_range_t, arg);
     int rc;
 
@@ -1603,10 +1578,6 @@ int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface 
*xch, domid_t domid,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_unmap_io_range_from_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
     arg->type = HVMOP_IO_RANGE_PCI;
@@ -1615,7 +1586,9 @@ int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface 
*xch, domid_t domid,
                                            (uint64_t)device,
                                            (uint64_t)function);
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_unmap_io_range_from_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
@@ -1625,7 +1598,6 @@ int xc_hvm_destroy_ioreq_server(xc_interface *xch,
                                 domid_t domid,
                                 ioservid_t id)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_destroy_ioreq_server_t, arg);
     int rc;
 
@@ -1633,14 +1605,12 @@ int xc_hvm_destroy_ioreq_server(xc_interface *xch,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_destroy_ioreq_server;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_destroy_ioreq_server,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
@@ -1651,7 +1621,6 @@ int xc_hvm_set_ioreq_server_state(xc_interface *xch,
                                   ioservid_t id,
                                   int enabled)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_set_ioreq_server_state_t, arg);
     int rc;
 
@@ -1659,15 +1628,13 @@ int xc_hvm_set_ioreq_server_state(xc_interface *xch,
     if ( arg == NULL )
         return -1;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_ioreq_server_state;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = domid;
     arg->id = id;
     arg->enabled = !!enabled;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_ioreq_server_state,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
     return rc;
diff --git a/tools/libxc/xc_evtchn.c b/tools/libxc/xc_evtchn.c
index ae2fe1a..53f7605 100644
--- a/tools/libxc/xc_evtchn.c
+++ b/tools/libxc/xc_evtchn.c
@@ -25,7 +25,6 @@ static int do_evtchn_op(xc_interface *xch, int cmd, void *arg,
                         size_t arg_size, int silently_fail)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(arg, arg_size, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     if ( xc_hypercall_bounce_pre(xch, arg) )
@@ -34,11 +33,9 @@ static int do_evtchn_op(xc_interface *xch, int cmd, void 
*arg,
         goto out;
     }
 
-    hypercall.op     = __HYPERVISOR_event_channel_op;
-    hypercall.arg[0] = cmd;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
-    if ((ret = do_xen_hypercall(xch, &hypercall)) < 0 && !silently_fail)
+    ret = xencall2(xch->xcall, __HYPERVISOR_event_channel_op,
+                   cmd, HYPERCALL_BUFFER_AS_ARG(arg));
+    if ( ret < 0 && !silently_fail )
         ERROR("do_evtchn_op: HYPERVISOR_event_channel_op failed: %d", ret);
 
     xc_hypercall_bounce_post(xch, arg);
diff --git a/tools/libxc/xc_flask.c b/tools/libxc/xc_flask.c
index b533656..ec52b0f 100644
--- a/tools/libxc/xc_flask.c
+++ b/tools/libxc/xc_flask.c
@@ -37,7 +37,6 @@
 int xc_flask_op(xc_interface *xch, xen_flask_op_t *op)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(op, sizeof(*op), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     op->interface_version = XEN_FLASK_INTERFACE_VERSION;
@@ -48,10 +47,9 @@ int xc_flask_op(xc_interface *xch, xen_flask_op_t *op)
         goto out;
     }
 
-    hypercall.op     = __HYPERVISOR_xsm_op;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(op);
-
-    if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+    ret = xencall1(xch->xcall, __HYPERVISOR_xsm_op,
+                   HYPERCALL_BUFFER_AS_ARG(op));
+    if ( ret < 0 )
     {
         if ( errno == EACCES )
             fprintf(stderr, "XSM operation failed!\n");
diff --git a/tools/libxc/xc_freebsd_osdep.c b/tools/libxc/xc_freebsd_osdep.c
index f6a2ccd..6b440ee 100644
--- a/tools/libxc/xc_freebsd_osdep.c
+++ b/tools/libxc/xc_freebsd_osdep.c
@@ -88,53 +88,6 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-/*------------------------ Privcmd hypercall interface 
-----------------------*/
-void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
-{
-    size_t size = npages * XC_PAGE_SIZE;
-    void *p;
-
-    /* Address returned by mmap is page aligned. */
-    p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-             -1, 0);
-    if (p == NULL)
-        return NULL;
-
-    /*
-     * Since FreeBSD doesn't have the MAP_LOCKED flag,
-     * lock memory using mlock.
-     */
-    if ( mlock(p, size) < 0 )
-    {
-        munmap(p, size);
-        return NULL;
-    }
-
-    return p;
-}
-
-void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
-{
-
-    int saved_errno = errno;
-    /* Unlock pages */
-    munlock(ptr, npages * XC_PAGE_SIZE);
-
-    munmap(ptr, npages * XC_PAGE_SIZE);
-    /* We MUST propagate the hypercall errno, not unmap call's. */
-    errno = saved_errno;
-}
-
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
-{
-    int fd = xch->privcmdfd;
-    int ret;
-
-    ret = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
-
-    return (ret == 0) ? hypercall->retval : ret;
-}
-
 /*----------------------- Privcmd foreign map interface 
----------------------*/
 void *xc_map_foreign_bulk(xc_interface *xch,
                           uint32_t dom, int prot,
diff --git a/tools/libxc/xc_gnttab.c b/tools/libxc/xc_gnttab.c
index dd32aa2..af53fac 100644
--- a/tools/libxc/xc_gnttab.c
+++ b/tools/libxc/xc_gnttab.c
@@ -21,7 +21,6 @@
 int xc_gnttab_op(xc_interface *xch, int cmd, void * op, int op_size, int count)
 {
     int ret = 0;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(op, count * op_size, 
XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     if ( xc_hypercall_bounce_pre(xch, op) )
@@ -30,12 +29,8 @@ int xc_gnttab_op(xc_interface *xch, int cmd, void * op, int 
op_size, int count)
         goto out1;
     }
 
-    hypercall.op = __HYPERVISOR_grant_table_op;
-    hypercall.arg[0] = cmd;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(op);
-    hypercall.arg[2] = count;
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall3(xch->xcall,  __HYPERVISOR_grant_table_op,
+                   cmd, HYPERCALL_BUFFER_AS_ARG(op), count);
 
     xc_hypercall_bounce_post(xch, op);
 
diff --git a/tools/libxc/xc_hcall_buf.c b/tools/libxc/xc_hcall_buf.c
index 517b5b4..c1230a1 100644
--- a/tools/libxc/xc_hcall_buf.c
+++ b/tools/libxc/xc_hcall_buf.c
@@ -17,7 +17,6 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <pthread.h>
 
 #include "xc_private.h"
 #include "xg_private.h"
@@ -28,163 +27,38 @@ xc_hypercall_buffer_t 
XC__HYPERCALL_BUFFER_NAME(HYPERCALL_BUFFER_NULL) = {
     HYPERCALL_BUFFER_INIT_NO_BOUNCE
 };
 
-pthread_mutex_t hypercall_buffer_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-static void hypercall_buffer_cache_lock(xc_interface *xch)
-{
-    int saved_errno = errno;
-    if ( xch->flags & XC_OPENFLAG_NON_REENTRANT )
-        return;
-    pthread_mutex_lock(&hypercall_buffer_cache_mutex);
-    /* Ignore pthread errors. */
-    errno = saved_errno;
-}
-
-static void hypercall_buffer_cache_unlock(xc_interface *xch)
-{
-    int saved_errno = errno;
-    if ( xch->flags & XC_OPENFLAG_NON_REENTRANT )
-        return;
-    pthread_mutex_unlock(&hypercall_buffer_cache_mutex);
-    /* Ignore pthread errors. */
-    errno = saved_errno;
-}
-
-static void *hypercall_buffer_cache_alloc(xc_interface *xch, int nr_pages)
-{
-    void *p = NULL;
-
-    hypercall_buffer_cache_lock(xch);
-
-    xch->hypercall_buffer_total_allocations++;
-    xch->hypercall_buffer_current_allocations++;
-    if ( xch->hypercall_buffer_current_allocations > 
xch->hypercall_buffer_maximum_allocations )
-        xch->hypercall_buffer_maximum_allocations = 
xch->hypercall_buffer_current_allocations;
-
-    if ( nr_pages > 1 )
-    {
-        xch->hypercall_buffer_cache_toobig++;
-    }
-    else if ( xch->hypercall_buffer_cache_nr > 0 )
-    {
-        p = xch->hypercall_buffer_cache[--xch->hypercall_buffer_cache_nr];
-        xch->hypercall_buffer_cache_hits++;
-    }
-    else
-    {
-        xch->hypercall_buffer_cache_misses++;
-    }
-
-    hypercall_buffer_cache_unlock(xch);
-
-    return p;
-}
-
-static int hypercall_buffer_cache_free(xc_interface *xch, void *p, int 
nr_pages)
-{
-    int rc = 0;
-
-    hypercall_buffer_cache_lock(xch);
-
-    xch->hypercall_buffer_total_releases++;
-    xch->hypercall_buffer_current_allocations--;
-
-    if ( nr_pages == 1 && xch->hypercall_buffer_cache_nr < 
HYPERCALL_BUFFER_CACHE_SIZE )
-    {
-        xch->hypercall_buffer_cache[xch->hypercall_buffer_cache_nr++] = p;
-        rc = 1;
-    }
-
-    hypercall_buffer_cache_unlock(xch);
-
-    return rc;
-}
-
-void xc__hypercall_buffer_cache_release(xc_interface *xch)
-{
-    void *p;
-
-    hypercall_buffer_cache_lock(xch);
-
-    DBGPRINTF("hypercall buffer: total allocations:%d total releases:%d",
-              xch->hypercall_buffer_total_allocations,
-              xch->hypercall_buffer_total_releases);
-    DBGPRINTF("hypercall buffer: current allocations:%d maximum 
allocations:%d",
-              xch->hypercall_buffer_current_allocations,
-              xch->hypercall_buffer_maximum_allocations);
-    DBGPRINTF("hypercall buffer: cache current size:%d",
-              xch->hypercall_buffer_cache_nr);
-    DBGPRINTF("hypercall buffer: cache hits:%d misses:%d toobig:%d",
-              xch->hypercall_buffer_cache_hits,
-              xch->hypercall_buffer_cache_misses,
-              xch->hypercall_buffer_cache_toobig);
-
-    while ( xch->hypercall_buffer_cache_nr > 0 )
-    {
-        p = xch->hypercall_buffer_cache[--xch->hypercall_buffer_cache_nr];
-        osdep_free_hypercall_buffer(xch, p, 1);
-    }
-
-    hypercall_buffer_cache_unlock(xch);
-}
-
 void *xc__hypercall_buffer_alloc_pages(xc_interface *xch, 
xc_hypercall_buffer_t *b, int nr_pages)
 {
-    void *p = hypercall_buffer_cache_alloc(xch, nr_pages);
-
-    if ( !p )
-        p = osdep_alloc_hypercall_buffer(xch, nr_pages);
+    void *p = xencall_alloc_buffer_pages(xch->xcall, nr_pages);
 
     if (!p)
         return NULL;
 
     b->hbuf = p;
 
-    memset(p, 0, nr_pages * PAGE_SIZE);
-
     return b->hbuf;
 }
 
 void xc__hypercall_buffer_free_pages(xc_interface *xch, xc_hypercall_buffer_t 
*b, int nr_pages)
 {
-    if ( b->hbuf == NULL )
-        return;
-
-    if ( !hypercall_buffer_cache_free(xch, b->hbuf, nr_pages) )
-        osdep_free_hypercall_buffer(xch, b->hbuf, nr_pages);
+    xencall_free_buffer_pages(xch->xcall, b->hbuf, nr_pages);
 }
 
-struct allocation_header {
-    int nr_pages;
-};
-
 void *xc__hypercall_buffer_alloc(xc_interface *xch, xc_hypercall_buffer_t *b, 
size_t size)
 {
-    size_t actual_size = ROUNDUP(size + sizeof(struct allocation_header), 
PAGE_SHIFT);
-    int nr_pages = actual_size >> PAGE_SHIFT;
-    struct allocation_header *hdr;
+    void *p = xencall_alloc_buffer(xch->xcall, size);
 
-    hdr = xc__hypercall_buffer_alloc_pages(xch, b, nr_pages);
-    if ( hdr == NULL )
+    if (!p)
         return NULL;
 
-    b->hbuf = (void *)(hdr+1);
+    b->hbuf = p;
 
-    hdr->nr_pages = nr_pages;
     return b->hbuf;
 }
 
 void xc__hypercall_buffer_free(xc_interface *xch, xc_hypercall_buffer_t *b)
 {
-    struct allocation_header *hdr;
-
-    if (b->hbuf == NULL)
-        return;
-
-    hdr = b->hbuf;
-    b->hbuf = --hdr;
-
-    xc__hypercall_buffer_free_pages(xch, b, hdr->nr_pages);
+    xencall_free_buffer(xch->xcall, b->hbuf);
 }
 
 int xc__hypercall_bounce_pre(xc_interface *xch, xc_hypercall_buffer_t *b)
diff --git a/tools/libxc/xc_kexec.c b/tools/libxc/xc_kexec.c
index a49cffb..1cceb5d 100644
--- a/tools/libxc/xc_kexec.c
+++ b/tools/libxc/xc_kexec.c
@@ -14,7 +14,6 @@
 
 int xc_kexec_exec(xc_interface *xch, int type)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_kexec_exec_t, exec);
     int ret = -1;
 
@@ -27,11 +26,9 @@ int xc_kexec_exec(xc_interface *xch, int type)
 
     exec->type = type;
 
-    hypercall.op = __HYPERVISOR_kexec_op;
-    hypercall.arg[0] = KEXEC_CMD_kexec;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(exec);
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_kexec_op,
+                  KEXEC_CMD_kexec,
+                  HYPERCALL_BUFFER_AS_ARG(exec));
 
 out:
     xc_hypercall_buffer_free(xch, exec);
@@ -42,7 +39,6 @@ out:
 int xc_kexec_get_range(xc_interface *xch, int range,  int nr,
                        uint64_t *size, uint64_t *start)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_kexec_range_t, get_range);
     int ret = -1;
 
@@ -56,11 +52,9 @@ int xc_kexec_get_range(xc_interface *xch, int range,  int nr,
     get_range->range = range;
     get_range->nr = nr;
 
-    hypercall.op = __HYPERVISOR_kexec_op;
-    hypercall.arg[0] = KEXEC_CMD_kexec_get_range;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(get_range);
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_kexec_op,
+                  KEXEC_CMD_kexec_get_range,
+                  HYPERCALL_BUFFER_AS_ARG(get_range));
 
     *size = get_range->size;
     *start = get_range->start;
@@ -76,7 +70,6 @@ int xc_kexec_load(xc_interface *xch, uint8_t type, uint16_t 
arch,
                   uint32_t nr_segments, xen_kexec_segment_t *segments)
 {
     int ret = -1;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(segments, sizeof(*segments) * nr_segments,
                              XC_HYPERCALL_BUFFER_BOUNCE_IN);
     DECLARE_HYPERCALL_BUFFER(xen_kexec_load_t, load);
@@ -99,11 +92,9 @@ int xc_kexec_load(xc_interface *xch, uint8_t type, uint16_t 
arch,
     load->nr_segments = nr_segments;
     set_xen_guest_handle(load->segments.h, segments);
 
-    hypercall.op = __HYPERVISOR_kexec_op;
-    hypercall.arg[0] = KEXEC_CMD_kexec_load;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(load);
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_kexec_op,
+                  KEXEC_CMD_kexec_load,
+                  HYPERCALL_BUFFER_AS_ARG(load));
 
 out:
     xc_hypercall_buffer_free(xch, load);
@@ -114,7 +105,6 @@ out:
 
 int xc_kexec_unload(xc_interface *xch, int type)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_kexec_unload_t, unload);
     int ret = -1;
 
@@ -127,11 +117,9 @@ int xc_kexec_unload(xc_interface *xch, int type)
 
     unload->type = type;
 
-    hypercall.op = __HYPERVISOR_kexec_op;
-    hypercall.arg[0] = KEXEC_CMD_kexec_unload;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(unload);
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_kexec_op,
+                  KEXEC_CMD_kexec_unload,
+                  HYPERCALL_BUFFER_AS_ARG(unload));
 
 out:
     xc_hypercall_buffer_free(xch, unload);
diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c
index 9f4c707..e68c495 100644
--- a/tools/libxc/xc_linux_osdep.c
+++ b/tools/libxc/xc_linux_osdep.c
@@ -91,55 +91,6 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
-{
-    size_t size = npages * XC_PAGE_SIZE;
-    void *p;
-    int rc, saved_errno;
-
-    /* Address returned by mmap is page aligned. */
-    p = mmap(NULL, size, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0);
-    if ( p == MAP_FAILED )
-    {
-        PERROR("xc_alloc_hypercall_buffer: mmap failed");
-        return NULL;
-    }
-
-    /* Do not copy the VMA to child process on fork. Avoid the page being COW
-        on hypercall. */
-    rc = madvise(p, npages * XC_PAGE_SIZE, MADV_DONTFORK);
-    if ( rc < 0 )
-    {
-        PERROR("xc_alloc_hypercall_buffer: madvise failed");
-        goto out;
-    }
-
-    return p;
-
-out:
-    saved_errno = errno;
-    (void)munmap(p, size);
-    errno = saved_errno;
-    return NULL;
-}
-
-void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
-{
-    int saved_errno = errno;
-    /* Recover the VMA flags. Maybe it's not necessary */
-    madvise(ptr, npages * XC_PAGE_SIZE, MADV_DOFORK);
-
-    munmap(ptr, npages * XC_PAGE_SIZE);
-    /* We MUST propagate the hypercall errno, not unmap call's. */
-    errno = saved_errno;
-}
-
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
-{
-    int fd = xch->privcmdfd;
-    return ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
-}
-
 static int xc_map_foreign_batch_single(int fd, uint32_t dom,
                                        xen_pfn_t *mfn, unsigned long addr)
 {
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
index 047e13b..e3c8241 100644
--- a/tools/libxc/xc_minios.c
+++ b/tools/libxc/xc_minios.c
@@ -61,38 +61,6 @@ void minios_interface_close_fd(int fd)
     files[fd].type = FTYPE_NONE;
 }
 
-void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
-{
-    return xc_memalign(xch, PAGE_SIZE, npages * PAGE_SIZE);
-}
-
-void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
-{
-    free(ptr);
-}
-
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
-{
-    multicall_entry_t call;
-    int i, ret;
-
-    call.op = hypercall->op;
-    for (i = 0; i < ARRAY_SIZE(hypercall->arg); i++)
-       call.args[i] = hypercall->arg[i];
-
-    ret = HYPERVISOR_multicall(&call, 1);
-
-    if (ret < 0) {
-       errno = -ret;
-       return -1;
-    }
-    if ((long) call.result < 0) {
-        errno = - (long) call.result;
-        return -1;
-    }
-    return call.result;
-}
-
 void *xc_map_foreign_bulk(xc_interface *xch,
                           uint32_t dom, int prot,
                           const xen_pfn_t *arr, int *err, unsigned int num)
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index c613545..124537b 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -323,7 +323,6 @@ int xc_sched_id(xc_interface *xch,
 int xc_mca_op(xc_interface *xch, struct xen_mc *mc)
 {
     int ret = 0;
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(mc, sizeof(*mc), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     if ( xc_hypercall_bounce_pre(xch, mc) )
@@ -333,9 +332,9 @@ int xc_mca_op(xc_interface *xch, struct xen_mc *mc)
     }
     mc->interface_version = XEN_MCA_INTERFACE_VERSION;
 
-    hypercall.op = __HYPERVISOR_mca;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(mc);
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall1(xch->xcall, __HYPERVISOR_mca,
+                   HYPERCALL_BUFFER_AS_ARG(mc));
+
     xc_hypercall_bounce_post(xch, mc);
     return ret;
 }
@@ -471,7 +470,6 @@ int xc_hvm_set_pci_intx_level(
     uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,
     unsigned int level)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_pci_intx_level, arg);
     int rc;
 
@@ -482,10 +480,6 @@ int xc_hvm_set_pci_intx_level(
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_pci_intx_level;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid  = dom;
     arg->domain = domain;
     arg->bus    = bus;
@@ -493,7 +487,9 @@ int xc_hvm_set_pci_intx_level(
     arg->intx   = intx;
     arg->level  = level;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_pci_intx_level,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -505,7 +501,6 @@ int xc_hvm_set_isa_irq_level(
     uint8_t isa_irq,
     unsigned int level)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_isa_irq_level, arg);
     int rc;
 
@@ -516,15 +511,13 @@ int xc_hvm_set_isa_irq_level(
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_isa_irq_level;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid   = dom;
     arg->isa_irq = isa_irq;
     arg->level   = level;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_isa_irq_level,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -534,7 +527,6 @@ int xc_hvm_set_isa_irq_level(
 int xc_hvm_set_pci_link_route(
     xc_interface *xch, domid_t dom, uint8_t link, uint8_t isa_irq)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_pci_link_route, arg);
     int rc;
 
@@ -545,15 +537,13 @@ int xc_hvm_set_pci_link_route(
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_pci_link_route;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid   = dom;
     arg->link    = link;
     arg->isa_irq = isa_irq;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_pci_link_route,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -563,7 +553,6 @@ int xc_hvm_set_pci_link_route(
 int xc_hvm_inject_msi(
     xc_interface *xch, domid_t dom, uint64_t addr, uint32_t data)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_inject_msi, arg);
     int rc;
 
@@ -574,15 +563,13 @@ int xc_hvm_inject_msi(
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_inject_msi;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid = dom;
     arg->addr  = addr;
     arg->data  = data;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_inject_msi,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -594,7 +581,6 @@ int xc_hvm_track_dirty_vram(
     uint64_t first_pfn, uint64_t nr,
     unsigned long *dirty_bitmap)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(dirty_bitmap, (nr+7) / 8, 
XC_HYPERCALL_BUFFER_BOUNCE_OUT);
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_track_dirty_vram, arg);
     int rc;
@@ -607,16 +593,14 @@ int xc_hvm_track_dirty_vram(
         goto out;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_track_dirty_vram;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid     = dom;
     arg->first_pfn = first_pfn;
     arg->nr        = nr;
     set_xen_guest_handle(arg->dirty_bitmap, dirty_bitmap);
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_track_dirty_vram,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
 out:
     xc_hypercall_buffer_free(xch, arg);
@@ -627,7 +611,6 @@ out:
 int xc_hvm_modified_memory(
     xc_interface *xch, domid_t dom, uint64_t first_pfn, uint64_t nr)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_modified_memory, arg);
     int rc;
 
@@ -638,15 +621,13 @@ int xc_hvm_modified_memory(
         return -1;
     }
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_modified_memory;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
     arg->domid     = dom;
     arg->first_pfn = first_pfn;
     arg->nr        = nr;
 
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_modified_memory,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -656,7 +637,6 @@ int xc_hvm_modified_memory(
 int xc_hvm_set_mem_type(
     xc_interface *xch, domid_t dom, hvmmem_type_t mem_type, uint64_t 
first_pfn, uint64_t nr)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_set_mem_type, arg);
     int rc;
 
@@ -672,11 +652,9 @@ int xc_hvm_set_mem_type(
     arg->first_pfn    = first_pfn;
     arg->nr           = nr;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_set_mem_type;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_set_mem_type,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
@@ -688,7 +666,6 @@ int xc_hvm_inject_trap(
     uint32_t type, uint32_t error_code, uint32_t insn_len,
     uint64_t cr2)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(struct xen_hvm_inject_trap, arg);
     int rc;
 
@@ -707,11 +684,9 @@ int xc_hvm_inject_trap(
     arg->insn_len    = insn_len;
     arg->cr2         = cr2;
 
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_inject_trap;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
-    rc = do_xen_hypercall(xch, &hypercall);
+    rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
+                  HVMOP_inject_trap,
+                  HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_buffer_free(xch, arg);
 
diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c
index 9abb3b6..5e3b343 100644
--- a/tools/libxc/xc_netbsd.c
+++ b/tools/libxc/xc_netbsd.c
@@ -67,46 +67,6 @@ int osdep_privcmd_close(xc_interface *xch)
     return close(fd);
 }
 
-void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
-{
-    size_t size = npages * XC_PAGE_SIZE;
-    void *p;
-
-    p = xc_memalign(xch, XC_PAGE_SIZE, size);
-    if (!p)
-        return NULL;
-
-    if ( mlock(p, size) < 0 )
-    {
-        free(p);
-        return NULL;
-    }
-    return p;
-}
-
-void osdep_free_hypercall_buffer(xc_interface *xch, void *ptr, int npages)
-{
-    (void) munlock(ptr, npages * XC_PAGE_SIZE);
-    free(ptr);
-}
-
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall)
-{
-    int fd = xch->privcmdfd;
-    int error = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
-
-    /*
-     * Since NetBSD ioctl can only return 0 on success or < 0 on
-     * error, if we want to return a value from ioctl we should
-     * do so by setting hypercall->retval, to mimic Linux ioctl
-     * implementation.
-     */
-    if (error < 0)
-        return error;
-    else
-        return hypercall->retval;
-}
-
 void *xc_map_foreign_bulk(xc_interface *xch,
                           uint32_t dom, int prot,
                           const xen_pfn_t *arr, int *err, unsigned int num)
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index de5873e..ca4c17a 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -39,16 +39,6 @@ struct xc_interface_core 
*xc_interface_open(xentoollog_logger *logger,
     xch->error_handler   = logger;           xch->error_handler_tofree   = 0;
     xch->dombuild_logger = dombuild_logger;  xch->dombuild_logger_tofree = 0;
 
-    xch->hypercall_buffer_cache_nr = 0;
-
-    xch->hypercall_buffer_total_allocations = 0;
-    xch->hypercall_buffer_total_releases = 0;
-    xch->hypercall_buffer_current_allocations = 0;
-    xch->hypercall_buffer_maximum_allocations = 0;
-    xch->hypercall_buffer_cache_hits = 0;
-    xch->hypercall_buffer_cache_misses = 0;
-    xch->hypercall_buffer_cache_toobig = 0;
-
     if (!xch->error_handler) {
         xch->error_handler = xch->error_handler_tofree =
             (xentoollog_logger*)
@@ -65,14 +55,22 @@ struct xc_interface_core 
*xc_interface_open(xentoollog_logger *logger,
     }
     *xch = xch_buf;
 
-    if (!(open_flags & XC_OPENFLAG_DUMMY)) {
-        if ( osdep_privcmd_open(xch) < 0 )
-            goto err;
-    }
+    if (open_flags & XC_OPENFLAG_DUMMY)
+        return xch; /* We are done */
+
+    if ( osdep_privcmd_open(xch) < 0 )
+        goto err;
+
+    xch->xcall = xencall_open(xch->error_handler,
+        open_flags & XC_OPENFLAG_NON_REENTRANT ? 
XENCALL_OPENFLAG_NON_REENTRANT : 0U);
+
+    if ( xch->xcall == NULL )
+        goto err;
 
     return xch;
 
  err:
+    osdep_privcmd_close(xch);
     xtl_logger_destroy(xch->error_handler_tofree);
     if (xch != &xch_buf) free(xch);
     return NULL;
@@ -85,11 +83,12 @@ int xc_interface_close(xc_interface *xch)
     if (!xch)
         return 0;
 
+    rc = xencall_close(xch->xcall);
+    if (rc) PERROR("Could not close xencall interface");
+
     rc = osdep_privcmd_close(xch);
     if (rc) PERROR("Could not close hypervisor interface");
 
-    xc__hypercall_buffer_cache_release(xch);
-
     xtl_logger_destroy(xch->dombuild_logger_tofree);
     xtl_logger_destroy(xch->error_handler_tofree);
 
@@ -228,7 +227,6 @@ int xc_mmuext_op(
     unsigned int nr_ops,
     domid_t dom)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(op, nr_ops*sizeof(*op), 
XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
     long ret = -1;
 
@@ -238,13 +236,9 @@ int xc_mmuext_op(
         goto out1;
     }
 
-    hypercall.op     = __HYPERVISOR_mmuext_op;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(op);
-    hypercall.arg[1] = (unsigned long)nr_ops;
-    hypercall.arg[2] = (unsigned long)0;
-    hypercall.arg[3] = (unsigned long)dom;
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall4(xch->xcall, __HYPERVISOR_mmuext_op,
+                   HYPERCALL_BUFFER_AS_ARG(op),
+                   nr_ops, 0, dom);
 
     xc_hypercall_bounce_post(xch, op);
 
@@ -254,8 +248,7 @@ int xc_mmuext_op(
 
 static int flush_mmu_updates(xc_interface *xch, struct xc_mmu *mmu)
 {
-    int err = 0;
-    DECLARE_HYPERCALL;
+    int rc, err = 0;
     DECLARE_NAMED_HYPERCALL_BOUNCE(updates, mmu->updates, 
mmu->idx*sizeof(*mmu->updates), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
 
     if ( mmu->idx == 0 )
@@ -268,13 +261,10 @@ static int flush_mmu_updates(xc_interface *xch, struct 
xc_mmu *mmu)
         goto out;
     }
 
-    hypercall.op     = __HYPERVISOR_mmu_update;
-    hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(updates);
-    hypercall.arg[1] = (unsigned long)mmu->idx;
-    hypercall.arg[2] = 0;
-    hypercall.arg[3] = mmu->subject;
-
-    if ( do_xen_hypercall(xch, &hypercall) < 0 )
+    rc = xencall4(xch->xcall, __HYPERVISOR_mmu_update,
+                  HYPERCALL_BUFFER_AS_ARG(updates),
+                  mmu->idx, 0, mmu->subject);
+    if ( rc < 0 )
     {
         ERROR("Failure when submitting mmu updates");
         err = 1;
@@ -317,7 +307,6 @@ int xc_flush_mmu_updates(xc_interface *xch, struct xc_mmu 
*mmu)
 
 long do_memory_op(xc_interface *xch, int cmd, void *arg, size_t len)
 {
-    DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BOUNCE(arg, len, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
     long ret = -1;
 
@@ -327,11 +316,8 @@ long do_memory_op(xc_interface *xch, int cmd, void *arg, 
size_t len)
         goto out1;
     }
 
-    hypercall.op     = __HYPERVISOR_memory_op;
-    hypercall.arg[0] = (unsigned long) cmd;
-    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
-
-    ret = do_xen_hypercall(xch, &hypercall);
+    ret = xencall2(xch->xcall, __HYPERVISOR_memory_op,
+                   cmd, HYPERCALL_BUFFER_AS_ARG(arg));
 
     xc_hypercall_bounce_post(xch, arg);
  out1:
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 30157cf..c93df7f 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -30,6 +30,7 @@
 
 #include "_paths.h"
 #include "xenctrl.h"
+#include <xencall.h>
 
 #include <xen/sys/privcmd.h>
 
@@ -53,7 +54,6 @@ struct iovec {
 #include <sys/uio.h>
 #endif
 
-#define DECLARE_HYPERCALL privcmd_hypercall_t hypercall
 #define DECLARE_DOMCTL struct xen_domctl domctl
 #define DECLARE_SYSCTL struct xen_sysctl sysctl
 #define DECLARE_PHYSDEV_OP struct physdev_op physdev_op
@@ -94,29 +94,11 @@ struct xc_interface_core {
     FILE *dombuild_logger_file;
     const char *currently_progress_reporting;
 
-    /*
-     * A simple cache of unused, single page, hypercall buffers
-     *
-     * Protected by a global lock.
-     */
-#define HYPERCALL_BUFFER_CACHE_SIZE 4
-    int hypercall_buffer_cache_nr;
-    void *hypercall_buffer_cache[HYPERCALL_BUFFER_CACHE_SIZE];
-
-    /*
-     * Hypercall buffer statistics. All protected by the global
-     * hypercall_buffer_cache lock.
-     */
-    int hypercall_buffer_total_allocations;
-    int hypercall_buffer_total_releases;
-    int hypercall_buffer_current_allocations;
-    int hypercall_buffer_maximum_allocations;
-    int hypercall_buffer_cache_hits;
-    int hypercall_buffer_cache_misses;
-    int hypercall_buffer_cache_toobig;
-
     /* Privcmd interface */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.