[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH XEN v2 10/15] 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> --- Must be applied with: - "qemu-xen-traditional: Add libxencall to rpath-link" and a corresponding QEMU_TAG update folded here. - "mini-os: Include libxencall with libxc" and a corresponding bump to MINIOS_UPSTREAM_REVISION folded in here. --- .gitignore | 2 + docs/misc/toolstack-library-abis.pandoc | 29 +++-- stubdom/Makefile | 19 +++- tools/Makefile | 2 + tools/Rules.mk | 7 +- tools/libxc/Makefile | 7 +- 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/libxencall/Makefile | 67 +++++++++++ tools/libxencall/buffer.c | 189 ++++++++++++++++++++++++++++++++ tools/libxencall/core.c | 141 ++++++++++++++++++++++++ tools/libxencall/freebsd.c | 137 +++++++++++++++++++++++ tools/libxencall/include/xencall.h | 81 ++++++++++++++ tools/libxencall/libxencall.map | 19 ++++ tools/libxencall/linux.c | 129 ++++++++++++++++++++++ tools/libxencall/minios.c | 78 +++++++++++++ tools/libxencall/netbsd.c | 118 ++++++++++++++++++++ tools/libxencall/private.h | 68 ++++++++++++ tools/libxencall/solaris.c | 94 ++++++++++++++++ tools/misc/Makefile | 4 +- tools/xcutils/Makefile | 2 +- tools/xenpaging/Makefile | 2 +- 35 files changed, 1316 insertions(+), 594 deletions(-) create mode 100644 tools/libxencall/Makefile create mode 100644 tools/libxencall/buffer.c create mode 100644 tools/libxencall/core.c create mode 100644 tools/libxencall/freebsd.c create mode 100644 tools/libxencall/include/xencall.h create mode 100644 tools/libxencall/libxencall.map create mode 100644 tools/libxencall/linux.c create mode 100644 tools/libxencall/minios.c create mode 100644 tools/libxencall/netbsd.c create mode 100644 tools/libxencall/private.h create mode 100644 tools/libxencall/solaris.c diff --git a/.gitignore b/.gitignore index 8cbd177..5841570 100644 --- a/.gitignore +++ b/.gitignore @@ -62,6 +62,7 @@ stubdom/xenstore stubdom/libxentoollog-* stubdom/libxenevtchn-* stubdom/libxengnttab-* +stubdom/libxencall-* stubdom/libxc-* stubdom/lwip-* stubdom/mini-os-* @@ -91,6 +92,7 @@ config/Docs.mk tools/libxentoollog/headers.chk tools/libxenevtchn/headers.chk tools/libxengnttab/headers.chk +tools/libxencall/headers.chk tools/blktap2/daemon/blktapctrl tools/blktap2/drivers/img2qcow tools/blktap2/drivers/lock-util diff --git a/docs/misc/toolstack-library-abis.pandoc b/docs/misc/toolstack-library-abis.pandoc index d1550a6..8339834 100644 --- a/docs/misc/toolstack-library-abis.pandoc +++ b/docs/misc/toolstack-library-abis.pandoc @@ -151,6 +151,21 @@ Interface Underlying interface Known external `xengnt???_*_notify` also use `IOCTL_GNTALLOC_SET_UNMAP_NOTIFY`, `IOCTL_GNTALLOC_SET_UNMAP_NOTIFY`, etc +## `libxencall`: making hypercalls + +Making hypercalls and allocating suitable memory to use as hypercall +pointer ("GUEST_HANDLE") arguments. + +Interface Underlying interface Known external users +--------------------------------- ------------------------------ -------------------- +`xencall_open` `open(2)` +`xencall_close` `close(2)` +`xencall0`, ..., `xencall5` `IOCTL_PRIVCMD_HYPERCALL` +`xencall_alloc_buffer` `xencall_alloc_buffer_pages` +`xencall_alloc_buffer_pages` `mmap(2)`, `madvise(2)` +`xencall_free_buffer` `xencall_free_buffer_pages` +`xencall_free_buffer_pages` `munmap(2)`, `madvise(2)` + # Unstable libraries These libraries do not provide a stable interface and are required to @@ -217,12 +232,6 @@ Interface Underlying interface Known external ### Hypercalls -#### Making hypercalls - -Interface Underlying interface Known external users ---------------------------------- ------------------------------ -------------------- -`do_xen_hypercall` `IOCTL_PRIVCMD_HYPERCALL` private - #### Wrappers Interface Known in-tree users Known external users @@ -440,7 +449,7 @@ Symbols: - xc_getcpuinfo - xc_get_cpumap_size - xc_get_device_group - - xc_get_hvm_param + - xc_get_hvm_param (Legacy, replaced by `xc_hvm_param_get`) - xc_get_last_error - xc_get_machine_memory_map. Used by kexec-tools - xc_get_max_cpus. Used by kexec-tools @@ -460,8 +469,8 @@ Symbols: - xc_hvm_map_io_range_to_ioreq_server - xc_hvm_map_pcidev_to_ioreq_server - xc_hvm_modified_memory (`HVMOP_modified_memory`). Used by qemu-dm. - - xc_hvm_param_get - - xc_hvm_param_set + - xc_hvm_param_get (`HVMOP_get_param`) + - xc_hvm_param_set (`HVMOP_set_param`) - xc_hvm_set_ioreq_server_state - xc_hvm_set_isa_irq_level (`HVMOP_set_isa_irq_level`). Used by qemu-dm. - xc_hvm_set_mem_type (`HVMOP_set_mem_type`). Used by qemu-dm. @@ -559,7 +568,7 @@ Symbols: - xc_set_cpufreq_gov - xc_set_cpufreq_para - xc_set_cpuidle_max_cstate - - xc_set_hvm_param (`HVMOP_set_param`). Used by qemu-dm. + - xc_set_hvm_param (`HVMOP_set_param`, legacy, replaced by `xc_hvm_param_set`). Used by qemu-dm. - xc_set_mem_access - xc_set_progress_prefix - xc_set_sched_opt_smt diff --git a/stubdom/Makefile b/stubdom/Makefile index 7eab97f..ec058ca 100644 --- a/stubdom/Makefile +++ b/stubdom/Makefile @@ -330,6 +330,12 @@ mk-headers-$(XEN_TARGET_ARCH): $(IOEMU_LINKFARM_TARGET) ln -sf $(XEN_ROOT)/tools/libxengnttab/include/*.h include/ && \ ln -sf $(XEN_ROOT)/tools/libxengnttab/*.c . && \ ln -sf $(XEN_ROOT)/tools/libxengnttab/Makefile . ) + mkdir -p libxencall-$(XEN_TARGET_ARCH)/include + [ -h libxencall-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxencall-$(XEN_TARGET_ARCH) && \ + ln -sf $(XEN_ROOT)/tools/libxencall/*.h . && \ + ln -sf $(XEN_ROOT)/tools/libxencall/include/*.h include/ && \ + ln -sf $(XEN_ROOT)/tools/libxencall/*.c . && \ + ln -sf $(XEN_ROOT)/tools/libxencall/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 . && \ @@ -386,12 +392,23 @@ libxengnttab-$(XEN_TARGET_ARCH)/libxengnttab.a: $(NEWLIB_STAMPFILE) CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxengnttab-$(XEN_TARGET_ARCH) ####### +# libxencall +####### + +.PHONY: libxencall +libxencall: libxencall-$(XEN_TARGET_ARCH)/libxencall.a +libxencall-$(XEN_TARGET_ARCH)/libxencall.a: $(NEWLIB_STAMPFILE) + $(MAKE) -C $(XEN_ROOT)/tools/include + $(MAKE) DESTDIR= -C $(MINI_OS) links + CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxencall-$(XEN_TARGET_ARCH) + +####### # libxc ####### .PHONY: libxc libxc: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a libxc-$(XEN_TARGET_ARCH)/libxenguest.a -libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn libxengnttab cross-zlib +libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn libxengnttab libxencall cross-zlib $(MAKE) -C $(XEN_ROOT)/tools/include $(MAKE) DESTDIR= -C $(MINI_OS) links CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= CONFIG_LIBXC_MINIOS=y -C libxc-$(XEN_TARGET_ARCH) diff --git a/tools/Makefile b/tools/Makefile index d3bf571..e5c8879 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -6,6 +6,7 @@ SUBDIRS-y += include SUBDIRS-y += libxentoollog SUBDIRS-y += libxenevtchn SUBDIRS-y += libxengnttab +SUBDIRS-y += libxencall SUBDIRS-y += libxc SUBDIRS-$(FLASK_ENABLE) += flask SUBDIRS-y += xenstore @@ -265,6 +266,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find -Wl,-rpath-link=$(XEN_ROOT)/tools/libxentoollog \ -Wl,-rpath-link=$(XEN_ROOT)/tools/libxenevtchn \ -Wl,-rpath-link=$(XEN_ROOT)/tools/libxengnttab \ + -Wl,-rpath-link=$(XEN_ROOT)/tools/libxencall \ $(QEMU_UPSTREAM_RPATH)" \ --bindir=$(LIBEXEC_BIN) \ --datadir=$(SHAREDIR)/qemu-xen \ diff --git a/tools/Rules.mk b/tools/Rules.mk index e3923e2..405a6a5 100644 --- a/tools/Rules.mk +++ b/tools/Rules.mk @@ -13,6 +13,7 @@ XEN_INCLUDE = $(XEN_ROOT)/tools/include XEN_LIBXENTOOLLOG = $(XEN_ROOT)/tools/libxentoollog XEN_LIBXENEVTCHN = $(XEN_ROOT)/tools/libxenevtchn XEN_LIBXENGNTTAB = $(XEN_ROOT)/tools/libxengnttab +XEN_LIBXENCALL = $(XEN_ROOT)/tools/libxencall 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/libxc/Makefile b/tools/libxc/Makefile index 77d2ae1..42fbabe 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -123,6 +123,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 @@ -203,7 +208,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_domain.c b/tools/libxc/xc_domain.c index 6db8d13..bda0173 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -132,7 +132,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)); @@ -142,13 +141,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); @@ -571,7 +568,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)); @@ -581,13 +577,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); @@ -1330,7 +1325,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); @@ -1341,20 +1335,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); @@ -1365,12 +1357,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; @@ -1398,7 +1389,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; @@ -1406,14 +1396,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; @@ -1428,7 +1416,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; @@ -1436,14 +1423,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; @@ -1465,7 +1450,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; @@ -1473,17 +1457,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; @@ -1493,7 +1475,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; @@ -1501,17 +1482,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; @@ -1522,7 +1501,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; @@ -1535,10 +1513,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; @@ -1552,7 +1526,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; @@ -1563,7 +1539,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; @@ -1576,10 +1551,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; @@ -1588,7 +1559,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; @@ -1598,7 +1571,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; @@ -1606,14 +1578,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; @@ -1624,7 +1594,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; @@ -1632,15 +1601,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 e6bd25c..59ba6c9 100644 --- a/tools/libxc/xc_evtchn.c +++ b/tools/libxc/xc_evtchn.c @@ -26,7 +26,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) ) @@ -35,11 +34,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 e24a2e7..07298a8 100644 --- a/tools/libxc/xc_flask.c +++ b/tools/libxc/xc_flask.c @@ -38,7 +38,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; @@ -49,10 +48,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 4c0e2fd..b0ec965 100644 --- a/tools/libxc/xc_freebsd_osdep.c +++ b/tools/libxc/xc_freebsd_osdep.c @@ -89,53 +89,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 8c7e906..3ee91bc 100644 --- a/tools/libxc/xc_gnttab.c +++ b/tools/libxc/xc_gnttab.c @@ -22,7 +22,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) ) @@ -31,12 +30,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 ab8bee5..b70b692 100644 --- a/tools/libxc/xc_hcall_buf.c +++ b/tools/libxc/xc_hcall_buf.c @@ -18,7 +18,6 @@ #include <stdlib.h> #include <string.h> -#include <pthread.h> #include "xc_private.h" #include "xg_private.h" @@ -29,163 +28,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 d17a52b..488e8df 100644 --- a/tools/libxc/xc_linux_osdep.c +++ b/tools/libxc/xc_linux_osdep.c @@ -86,55 +86,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 0a2ac5c..27a4c4a 100644 --- a/tools/libxc/xc_minios.c +++ b/tools/libxc/xc_minios.c @@ -62,38 +62,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 b827bbb..fb9f628 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -324,7 +324,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) ) @@ -334,9 +333,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; } @@ -472,7 +471,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; @@ -483,10 +481,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; @@ -494,7 +488,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); @@ -506,7 +502,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; @@ -517,15 +512,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); @@ -535,7 +528,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; @@ -546,15 +538,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); @@ -564,7 +554,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; @@ -575,15 +564,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); @@ -595,7 +582,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; @@ -608,16 +594,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); @@ -628,7 +612,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; @@ -639,15 +622,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); @@ -657,7 +638,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; @@ -673,11 +653,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); @@ -689,7 +667,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; @@ -708,11 +685,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 5361f2b..78683a2 100644 --- a/tools/libxc/xc_netbsd.c +++ b/tools/libxc/xc_netbsd.c @@ -68,46 +68,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 c56d748..00f96ba 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -40,16 +40,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*) @@ -66,14 +56,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; @@ -86,11 +84,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); @@ -229,7 +228,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; @@ -239,13 +237,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); @@ -255,8 +249,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 ) @@ -269,13 +262,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; @@ -318,7 +308,6 @@ int xc_flush_mmu_updates(xc_interface *xch, struct xc_mmu *mmu) int 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; @@ -328,11 +317,8 @@ int 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 408b1be..2288660 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -31,6 +31,7 @@ #include "_paths.h" #include "xenctrl.h" +#include <xencall.h> #include <xen/sys/privcmd.h> @@ -54,7 +55,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 @@ -95,29 +95,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); @@ -233,24 +215,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) ) @@ -259,11 +233,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" @@ -278,7 +250,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; @@ -289,10 +260,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" @@ -307,7 +277,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; @@ -318,9 +287,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" @@ -336,7 +305,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); @@ -348,9 +316,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" @@ -366,13 +334,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" diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c index d719a11..cbac826 100644 --- a/tools/libxc/xc_solaris.c +++ b/tools/libxc/xc_solaris.c @@ -68,22 +68,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) diff --git a/tools/libxc/xc_tmem.c b/tools/libxc/xc_tmem.c index 02797bf..bd6bcd5 100644 --- a/tools/libxc/xc_tmem.c +++ b/tools/libxc/xc_tmem.c @@ -24,7 +24,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) ) @@ -33,9 +32,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" diff --git a/tools/libxencall/Makefile b/tools/libxencall/Makefile new file mode 100644 index 0000000..1b581db --- /dev/null +++ b/tools/libxencall/Makefile @@ -0,0 +1,67 @@ +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 headers.chk diff --git a/tools/libxencall/buffer.c b/tools/libxencall/buffer.c new file mode 100644 index 0000000..57e2f51 --- /dev/null +++ b/tools/libxencall/buffer.c @@ -0,0 +1,189 @@ +/* + * 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. + */ + +#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, int 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, int 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, int 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, int 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/libxencall/core.c b/tools/libxencall/core.c new file mode 100644 index 0000000..81250f0 --- /dev/null +++ b/tools/libxencall/core.c @@ -0,0 +1,141 @@ +/* + * 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. + */ + +#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; + + 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/libxencall/freebsd.c b/tools/libxencall/freebsd.c new file mode 100644 index 0000000..3f162a0 --- /dev/null +++ b/tools/libxencall/freebsd.c @@ -0,0 +1,137 @@ + /****************************************************************************** + * + * 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. + * + * 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, unsigned int 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, unsigned int 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/libxencall/include/xencall.h b/tools/libxencall/include/xencall.h new file mode 100644 index 0000000..87e4618 --- /dev/null +++ b/tools/libxencall/include/xencall.h @@ -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. + */ +#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, int nr_pages); +void xencall_free_buffer_pages(xencall_handle *xcall, void *p, int 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/libxencall/libxencall.map b/tools/libxencall/libxencall.map new file mode 100644 index 0000000..2f96144 --- /dev/null +++ b/tools/libxencall/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/libxencall/linux.c b/tools/libxencall/linux.c new file mode 100644 index 0000000..9a93f75 --- /dev/null +++ b/tools/libxencall/linux.c @@ -0,0 +1,129 @@ +/* + * 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. + * + * 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("/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, unsigned int 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, unsigned int 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/libxencall/minios.c b/tools/libxencall/minios.c new file mode 100644 index 0000000..de8036b --- /dev/null +++ b/tools/libxencall/minios.c @@ -0,0 +1,78 @@ +/* + * 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. + * + * 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, unsigned npages) +{ + return memalign(PAGE_SIZE, npages * PAGE_SIZE); +} + +void osdep_free_pages(xencall_handle *xcall, void *ptr, unsigned 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/libxencall/netbsd.c b/tools/libxencall/netbsd.c new file mode 100644 index 0000000..b1d476a --- /dev/null +++ b/tools/libxencall/netbsd.c @@ -0,0 +1,118 @@ +/****************************************************************************** + * + * 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. + * + * 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, unsigned int 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, + unsigned int 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/libxencall/private.h b/tools/libxencall/private.h new file mode 100644 index 0000000..af727fd --- /dev/null +++ b/tools/libxencall/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, unsigned int nr_pages); +void osdep_free_pages(xencall_handle *xcall, void *p, unsigned int 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/libxencall/solaris.c b/tools/libxencall/solaris.c new file mode 100644 index 0000000..9887bf6 --- /dev/null +++ b/tools/libxencall/solaris.c @@ -0,0 +1,94 @@ +/****************************************************************************** + * + * 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. + * + * 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, unsigned int npages) +{ + return xc_memalign(xcall, XC_PAGE_SIZE, npages * XC_PAGE_SIZE); +} + +void osdep_free_hypercall_buffer(xencall_handle *xcall, void *ptr, + unsigned int 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/misc/Makefile b/tools/misc/Makefile index cf6a475..a2ef0ec 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -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) diff --git a/tools/xcutils/Makefile b/tools/xcutils/Makefile index 2d1f112..e127af8 100644 --- a/tools/xcutils/Makefile +++ b/tools/xcutils/Makefile @@ -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 diff --git a/tools/xenpaging/Makefile b/tools/xenpaging/Makefile index d491867..64876b3 100644 --- a/tools/xenpaging/Makefile +++ b/tools/xenpaging/Makefile @@ -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) -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |