@@ -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
@@ -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
@@ -263,6 +263,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 \
@@ -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)
@@ -5,5 +5,6 @@ SUBDIRS-y :=
SUBDIRS-y += toollog
SUBDIRS-y += evtchn
SUBDIRS-y += gnttab
+SUBDIRS-y += call
all clean install distclean: %: subdirs-%
new file mode 100644
@@ -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
new file mode 100644
@@ -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:
+ */
new file mode 100644
@@ -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:
+ */
new file mode 100644
@@ -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:
+ */
new file mode 100644
@@ -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:
+ */
new file mode 100644
@@ -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 */
+};
new file mode 100644
@@ -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:
+ */
new file mode 100644
@@ -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@eu.citrix.com>.
+ */
+
+#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:
+ */
new file mode 100644
@@ -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:
+ */
new file mode 100644
@@ -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:
+ */
new file mode 100644
@@ -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:
+ */
@@ -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
@@ -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;
@@ -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);
@@ -561,7 +558,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));
@@ -571,13 +567,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);
@@ -1356,7 +1351,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);
@@ -1367,20 +1361,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);
@@ -1391,12 +1383,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;
@@ -1424,7 +1415,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;
@@ -1432,14 +1422,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;
@@ -1454,7 +1442,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;
@@ -1462,14 +1449,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;
@@ -1491,7 +1476,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;
@@ -1499,17 +1483,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;
@@ -1519,7 +1501,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;
@@ -1527,17 +1508,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;
@@ -1548,7 +1527,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;
@@ -1561,10 +1539,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;
@@ -1578,7 +1552,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;
@@ -1589,7 +1565,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;
@@ -1602,10 +1577,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;
@@ -1614,7 +1585,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;
@@ -1624,7 +1597,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;
@@ -1632,14 +1604,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;
@@ -1650,7 +1620,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;
@@ -1658,15 +1627,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;
@@ -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);
@@ -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");
@@ -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,
@@ -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);
@@ -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)
@@ -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);
@@ -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)
{
@@ -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)
@@ -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);
@@ -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)
@@ -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:
@@ -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 */
int privcmdfd;
+
+ /* Hypercall interface */
+ xencall_handle *xcall;
};
int osdep_privcmd_open(xc_interface *xch);
@@ -232,24 +214,16 @@ void xc__hypercall_buffer_cache_release(xc_interface *xch);
* Hypercall interfaces.
*/
-int do_xen_hypercall(xc_interface *xch, privcmd_hypercall_t *hypercall);
-
static inline int do_xen_version(xc_interface *xch, int cmd, xc_hypercall_buffer_t *dest)
{
- DECLARE_HYPERCALL;
DECLARE_HYPERCALL_BUFFER_ARGUMENT(dest);
-
- hypercall.op = __HYPERVISOR_xen_version;
- hypercall.arg[0] = (unsigned long) cmd;
- hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(dest);
-
- return do_xen_hypercall(xch, &hypercall);
+ return xencall2(xch->xcall, __HYPERVISOR_xen_version,
+ cmd, HYPERCALL_BUFFER_AS_ARG(dest));
}
static inline int do_physdev_op(xc_interface *xch, int cmd, void *op, size_t len)
{
int ret = -1;
- DECLARE_HYPERCALL;
DECLARE_HYPERCALL_BOUNCE(op, len, XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
if ( xc_hypercall_bounce_pre(xch, op) )
@@ -258,11 +232,9 @@ static inline int do_physdev_op(xc_interface *xch, int cmd, void *op, size_t len
goto out1;
}
- hypercall.op = __HYPERVISOR_physdev_op;
- hypercall.arg[0] = (unsigned long) cmd;
- hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(op);
-
- if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+ ret = xencall2(xch->xcall, __HYPERVISOR_physdev_op,
+ cmd, HYPERCALL_BUFFER_AS_ARG(op));
+ if ( ret < 0 )
{
if ( errno == EACCES )
DPRINTF("physdev operation failed -- need to"
@@ -277,7 +249,6 @@ out1:
static inline int do_domctl(xc_interface *xch, struct xen_domctl *domctl)
{
int ret = -1;
- DECLARE_HYPERCALL;
DECLARE_HYPERCALL_BOUNCE(domctl, sizeof(*domctl), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
domctl->interface_version = XEN_DOMCTL_INTERFACE_VERSION;
@@ -288,10 +259,9 @@ static inline int do_domctl(xc_interface *xch, struct xen_domctl *domctl)
goto out1;
}
- hypercall.op = __HYPERVISOR_domctl;
- hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(domctl);
-
- if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+ ret = xencall1(xch->xcall, __HYPERVISOR_domctl,
+ HYPERCALL_BUFFER_AS_ARG(domctl));
+ if ( ret < 0 )
{
if ( errno == EACCES )
DPRINTF("domctl operation failed -- need to"
@@ -306,7 +276,6 @@ static inline int do_domctl(xc_interface *xch, struct xen_domctl *domctl)
static inline int do_sysctl(xc_interface *xch, struct xen_sysctl *sysctl)
{
int ret = -1;
- DECLARE_HYPERCALL;
DECLARE_HYPERCALL_BOUNCE(sysctl, sizeof(*sysctl), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
sysctl->interface_version = XEN_SYSCTL_INTERFACE_VERSION;
@@ -317,9 +286,9 @@ static inline int do_sysctl(xc_interface *xch, struct xen_sysctl *sysctl)
goto out1;
}
- hypercall.op = __HYPERVISOR_sysctl;
- hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(sysctl);
- if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+ ret = xencall1(xch->xcall, __HYPERVISOR_sysctl,
+ HYPERCALL_BUFFER_AS_ARG(sysctl));
+ if ( ret < 0 )
{
if ( errno == EACCES )
DPRINTF("sysctl operation failed -- need to"
@@ -335,7 +304,6 @@ static inline int do_platform_op(xc_interface *xch,
struct xen_platform_op *platform_op)
{
int ret = -1;
- DECLARE_HYPERCALL;
DECLARE_HYPERCALL_BOUNCE(platform_op, sizeof(*platform_op),
XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
@@ -347,9 +315,9 @@ static inline int do_platform_op(xc_interface *xch,
return -1;
}
- hypercall.op = __HYPERVISOR_platform_op;
- hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(platform_op);
- if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+ ret = xencall1(xch->xcall, __HYPERVISOR_platform_op,
+ HYPERCALL_BUFFER_AS_ARG(platform_op));
+ if ( ret < 0 )
{
if ( errno == EACCES )
DPRINTF("platform operation failed -- need to"
@@ -365,13 +333,11 @@ static inline int do_multicall_op(xc_interface *xch,
uint32_t nr_calls)
{
int ret = -1;
- DECLARE_HYPERCALL;
DECLARE_HYPERCALL_BUFFER_ARGUMENT(call_list);
- hypercall.op = __HYPERVISOR_multicall;
- hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(call_list);
- hypercall.arg[1] = nr_calls;
- if ( (ret = do_xen_hypercall(xch, &hypercall)) < 0 )
+ ret = xencall2(xch->xcall, __HYPERVISOR_multicall,
+ HYPERCALL_BUFFER_AS_ARG(call_list), nr_calls);
+ if ( ret < 0 )
{
if ( errno == EACCES )
DPRINTF("multicall operation failed -- need to"
@@ -67,22 +67,6 @@ int osdep_privcmd_close(xc_interface *xch)
return close(fd);
}
-void *osdep_alloc_hypercall_buffer(xc_interface *xch, int npages)
-{
- return xc_memalign(xch, XC_PAGE_SIZE, npages * XC_PAGE_SIZE);
-}
-
-static 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)
-{
- int fd = xch->privcmdfd;
- return ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, hypercall);
-}
-
void *xc_map_foreign_batch(xc_interface *xch,
uint32_t dom, int prot,
xen_pfn_t *arr, int num)
@@ -23,7 +23,6 @@
static int do_tmem_op(xc_interface *xch, tmem_op_t *op)
{
int ret;
- DECLARE_HYPERCALL;
DECLARE_HYPERCALL_BOUNCE(op, sizeof(*op), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
if ( xc_hypercall_bounce_pre(xch, op) )
@@ -32,9 +31,9 @@ static int do_tmem_op(xc_interface *xch, tmem_op_t *op)
return -EFAULT;
}
- hypercall.op = __HYPERVISOR_tmem_op;
- hypercall.arg[0] = HYPERCALL_BUFFER_AS_ARG(op);
- if ((ret = do_xen_hypercall(xch, &hypercall)) < 0)
+ ret = xencall1(xch->xcall, __HYPERVISOR_tmem_op,
+ HYPERCALL_BUFFER_AS_ARG(op));
+ if ( ret < 0 )
{
if ( errno == EACCES )
DPRINTF("tmem operation failed -- need to"
@@ -87,12 +87,12 @@ xenlockprof: xenlockprof.o
$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS)
# xen-hptool incorrectly uses libxc internals
-xen-hptool.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc
+xen-hptool.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc $(CFLAGS_libxencall)
xen-hptool: xen-hptool.o
$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS)
# xen-mfndump incorrectly uses libxc internals
-xen-mfndump.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc
+xen-mfndump.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc $(CFLAGS_libxencall)
xen-mfndump: xen-mfndump.o
$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(APPEND_LDFLAGS)
@@ -16,7 +16,7 @@ PROGRAMS = readnotes lsevtchn
CFLAGS += -Werror
# incorrectly uses libxc internals
-CFLAGS_readnotes.o := $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) -I$(XEN_ROOT)/tools/libxc
+CFLAGS_readnotes.o := $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) -I$(XEN_ROOT)/tools/libxc $(CFLAGS_libxencall)
CFLAGS_lsevtchn.o := $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl)
.PHONY: all
@@ -2,7 +2,7 @@ XEN_ROOT=$(CURDIR)/../..
include $(XEN_ROOT)/tools/Rules.mk
# xenpaging.c and file_ops.c incorrectly use libxc internals
-CFLAGS += $(CFLAGS_libxentoollog) $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl) $(CFLAGS_libxenstore) $(PTHREAD_CFLAGS) -I$(XEN_ROOT)/tools/libxc
+CFLAGS += $(CFLAGS_libxentoollog) $(CFLAGS_libxenevtchn) $(CFLAGS_libxenctrl) $(CFLAGS_libxenstore) $(PTHREAD_CFLAGS) -I$(XEN_ROOT)/tools/libxc $(CFLAGS_libxencall)
LDLIBS += $(LDLIBS_libxentoollog) $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(PTHREAD_LIBS)
LDFLAGS += $(PTHREAD_LDFLAGS)