From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ian Campbell Subject: [PATCH XEN v2 14/15] tools: Refactor foreign memory mapping into libxenforeignmemory Date: Wed, 15 Jul 2015 16:47:02 +0100 Message-ID: <1436975223-11098-14-git-send-email-ian.campbell@citrix.com> References: <1436975173.32371.121.camel@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1436975173.32371.121.camel@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: ian.jackson@eu.citrix.com, wei.liu2@citrix.com, xen-devel@lists.xen.org Cc: roger.pau@citrix.com, Ian Campbell , stefano.stabellini@eu.citrix.com List-Id: xen-devel@lists.xenproject.org libxenforeignmemory will provide a stable API and ABI for mapping foreign domain memory (subject to appropriate privileges). The new library exposes an interface equivalent to xc_map_foreign_memory_bulk, which all the other xc_map_foreign_memory_* functions (which remain in libxc) are implemented in terms of. Upon request (via #define XC_WANT_COMPAT_MAP_FOREIGN_API) libxenctrl will provide a compat API for the old names. This is used by qemu-xen and qemu-trad as well as various in tree things (which required de-dupping various #includes in some too to get the #define before the first). Signed-off-by: Ian Campbell --- Must be applied with: - "qemu-xen-traditional: qemu-xen-traditional: Add libxenforeignmemory to rpath-link" and a corresponding QEMU_TAG update folded here. - "mini-os: mini-os: Include libxenforeignmemory with libxc" and a corresponding bump to MINIOS_UPSTREAM_REVISION folded in here. --- .gitignore | 2 + docs/misc/toolstack-library-abis.pandoc | 22 +- stubdom/Makefile | 21 +- tools/Makefile | 3 + tools/Rules.mk | 11 +- tools/console/daemon/utils.c | 1 - tools/console/daemon/utils.h | 1 + tools/libxc/Makefile | 8 +- tools/libxc/include/xenctrl.h | 26 -- tools/libxc/include/xenctrl_compat.h | 36 +++ tools/libxc/xc_domain_restore.c | 4 +- tools/libxc/xc_domain_save.c | 4 +- tools/libxc/xc_foreign_memory.c | 49 +--- tools/libxc/xc_freebsd_osdep.c | 137 ---------- tools/libxc/xc_linux_osdep.c | 296 --------------------- tools/libxc/xc_minios.c | 29 -- tools/libxc/xc_netbsd.c | 73 ----- tools/libxc/xc_private.c | 13 +- tools/libxc/xc_private.h | 11 +- tools/libxc/xc_solaris.c | 73 ----- tools/libxc/xc_sr_restore.c | 4 +- tools/libxc/xc_sr_save.c | 4 +- tools/libxc/xc_vm_event.c | 10 +- tools/libxc/xg_private.h | 3 +- tools/libxenforeignmemory/Makefile | 67 +++++ tools/libxenforeignmemory/compat.c | 72 +++++ tools/libxenforeignmemory/core.c | 65 +++++ tools/libxenforeignmemory/freebsd.c | 126 +++++++++ .../libxenforeignmemory/include/xenforeignmemory.h | 68 +++++ tools/libxenforeignmemory/libxenforeignmemory.map | 7 + tools/libxenforeignmemory/linux.c | 284 ++++++++++++++++++++ tools/libxenforeignmemory/minios.c | 59 ++++ tools/libxenforeignmemory/netbsd.c | 92 +++++++ tools/libxenforeignmemory/private.h | 47 ++++ tools/libxenforeignmemory/solaris.c | 95 +++++++ tools/libxl/libxl_internal.h | 1 + tools/misc/xen-mfndump.c | 1 + tools/ocaml/libs/xc/xenctrl_stubs.c | 1 + tools/python/xen/lowlevel/xc/xc.c | 2 +- tools/xenmon/xenbaked.c | 1 + tools/xenpaging/pagein.c | 1 - tools/xenpaging/xenpaging.c | 1 - tools/xenpaging/xenpaging.h | 2 + tools/xenstore/xenstored_core.c | 1 - tools/xenstore/xenstored_core.h | 1 + tools/xentrace/xenctx.c | 3 +- tools/xentrace/xentrace.c | 1 + 47 files changed, 1118 insertions(+), 721 deletions(-) delete mode 100644 tools/libxc/xc_freebsd_osdep.c delete mode 100644 tools/libxc/xc_linux_osdep.c create mode 100644 tools/libxenforeignmemory/Makefile create mode 100644 tools/libxenforeignmemory/compat.c create mode 100644 tools/libxenforeignmemory/core.c create mode 100644 tools/libxenforeignmemory/freebsd.c create mode 100644 tools/libxenforeignmemory/include/xenforeignmemory.h create mode 100644 tools/libxenforeignmemory/libxenforeignmemory.map create mode 100644 tools/libxenforeignmemory/linux.c create mode 100644 tools/libxenforeignmemory/minios.c create mode 100644 tools/libxenforeignmemory/netbsd.c create mode 100644 tools/libxenforeignmemory/private.h create mode 100644 tools/libxenforeignmemory/solaris.c diff --git a/.gitignore b/.gitignore index 5841570..bb643f7 100644 --- a/.gitignore +++ b/.gitignore @@ -63,6 +63,7 @@ stubdom/libxentoollog-* stubdom/libxenevtchn-* stubdom/libxengnttab-* stubdom/libxencall-* +stubdom/libxenforeignmemory-* stubdom/libxc-* stubdom/lwip-* stubdom/mini-os-* @@ -93,6 +94,7 @@ tools/libxentoollog/headers.chk tools/libxenevtchn/headers.chk tools/libxengnttab/headers.chk tools/libxencall/headers.chk +tools/libxenforeignmemory/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 35674cc..63b83bc 100644 --- a/docs/misc/toolstack-library-abis.pandoc +++ b/docs/misc/toolstack-library-abis.pandoc @@ -166,6 +166,16 @@ Interface Underlying interface Known external `xencall_free_buffer` `xencall_free_buffer_pages` `xencall_free_buffer_pages` `munmap(2)`, `madvise(2)` +## `libxenforeignmemory`: privileged foreign mappings + +Mapping foreign guest memory. + +Interface Underlying interface Known external users +--------------------------------- ------------------------------ -------------------- +`xenforeignmemory_open` `open(2)` +`xenforeignmemory_close` `close(2)` +`xenforeignmemory_map` `IOCTL_PRIVCMD_MMAPBATCH` etc + # Unstable libraries These libraries do not provide a stable interface and are required to @@ -269,12 +279,14 @@ The following are private: ### Mapping foreign memory -Interface Underlying interface Known external users ---------------------------------- ------------------------------ -------------------- -`xc_map_foreign_pages` `IOCTL_PRIVCMD_MMAP...` qemu-pv -`xc_map_foreign_range` `IOCTL_PRIVCMD_MMAP...` qemu-dm, and qemu-pv +All implemented in terms of `xenforeignmemory_map`. + +Interface Known external users +--------------------------------- -------------------- +`xc_map_foreign_pages` qemu-pv +`xc_map_foreign_range` qemu-dm, qemu-pv `xc_map_foreign_ranges` -`xc_map_foreign_bulk` `IOCTL_PRIVCMD_MMAPBATCH_V2` qemu-dm +`xc_map_foreign_bulk` qemu-dm ### Managing guest memory map diff --git a/stubdom/Makefile b/stubdom/Makefile index ec058ca..529f5c3 100644 --- a/stubdom/Makefile +++ b/stubdom/Makefile @@ -336,6 +336,12 @@ mk-headers-$(XEN_TARGET_ARCH): $(IOEMU_LINKFARM_TARGET) 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 libxenforeignmemory-$(XEN_TARGET_ARCH)/include + [ -h libxenforeignmemory-$(XEN_TARGET_ARCH)/Makefile ] || ( cd libxenforeignmemory-$(XEN_TARGET_ARCH) && \ + ln -sf $(XEN_ROOT)/tools/libxenforeignmemory/*.h . && \ + ln -sf $(XEN_ROOT)/tools/libxenforeignmemory/include/*.h include/ && \ + ln -sf $(XEN_ROOT)/tools/libxenforeignmemory/*.c . && \ + ln -sf $(XEN_ROOT)/tools/libxenforeignmemory/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 . && \ @@ -390,6 +396,7 @@ libxengnttab-$(XEN_TARGET_ARCH)/libxengnttab.a: $(NEWLIB_STAMPFILE) $(MAKE) -C $(XEN_ROOT)/tools/include $(MAKE) DESTDIR= -C $(MINI_OS) links CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxengnttab-$(XEN_TARGET_ARCH) +APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxencall-$(MINIOS_TARGET_ARCH) -whole-archive -lxencall -no-whole-archive ####### # libxencall @@ -401,6 +408,18 @@ 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) +APP_LDLIBS += -L$(XEN_ROOT)/stubdom/libxencall-$(MINIOS_TARGET_ARCH) -whole-archive -lxencall -no-whole-archive + +####### +# libxenforeignmemory +####### + +.PHONY: libxenforeignmemory +libxenforeignmemory: libxenforeignmemory-$(XEN_TARGET_ARCH)/libxenforeignmemory.a +libxenforeignmemory-$(XEN_TARGET_ARCH)/libxenforeignmemory.a: $(NEWLIB_STAMPFILE) + $(MAKE) -C $(XEN_ROOT)/tools/include + $(MAKE) DESTDIR= -C $(MINI_OS) links + CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxenforeignmemory-$(XEN_TARGET_ARCH) ####### # libxc @@ -408,7 +427,7 @@ libxencall-$(XEN_TARGET_ARCH)/libxencall.a: $(NEWLIB_STAMPFILE) .PHONY: libxc libxc: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a libxc-$(XEN_TARGET_ARCH)/libxenguest.a -libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn libxengnttab libxencall cross-zlib +libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: libxentoollog libxenevtchn libxengnttab libxencall libxenforeignmemory 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 e5c8879..30abd57 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -7,6 +7,7 @@ SUBDIRS-y += libxentoollog SUBDIRS-y += libxenevtchn SUBDIRS-y += libxengnttab SUBDIRS-y += libxencall +SUBDIRS-y += libxenforeignmemory SUBDIRS-y += libxc SUBDIRS-$(FLASK_ENABLE) += flask SUBDIRS-y += xenstore @@ -253,6 +254,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find --source-path=$$source \ --extra-cflags="-DXC_WANT_COMPAT_EVTCHN_API=1 \ -DXC_WANT_COMPAT_GNTTAB_API=1 \ + -DXC_WANT_COMPAT_MAP_FOREIGN_API=1 \ -I$(XEN_ROOT)/tools/include \ -I$(XEN_ROOT)/tools/libxentoollog/include \ -I$(XEN_ROOT)/tools/libxenevtchn/include \ @@ -267,6 +269,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find -Wl,-rpath-link=$(XEN_ROOT)/tools/libxenevtchn \ -Wl,-rpath-link=$(XEN_ROOT)/tools/libxengnttab \ -Wl,-rpath-link=$(XEN_ROOT)/tools/libxencall \ + -Wl,-rpath-link=$(XEN_ROOT)/tools/libxenforeignmemory \ $(QEMU_UPSTREAM_RPATH)" \ --bindir=$(LIBEXEC_BIN) \ --datadir=$(SHAREDIR)/qemu-xen \ diff --git a/tools/Rules.mk b/tools/Rules.mk index 405a6a5..4a67f1f 100644 --- a/tools/Rules.mk +++ b/tools/Rules.mk @@ -14,6 +14,7 @@ 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_LIBXENFOREIGNMEMORY = $(XEN_ROOT)/tools/libxenforeignmemory XEN_LIBXC = $(XEN_ROOT)/tools/libxc XEN_XENLIGHT = $(XEN_ROOT)/tools/libxl XEN_XENSTORE = $(XEN_ROOT)/tools/xenstore @@ -103,12 +104,16 @@ 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) $(SHLIB_libxencall) +CFLAGS_libxenforeignmemory = -I$(XEN_LIBXENFOREIGNMEMORY)/include $(CFLAGS_xeninclude) +LDLIBS_libxenforeignmemory = $(XEN_LIBXENFOREIGNMEMORY)/libxenforeignmemory$(libextension) +SHLIB_libxenforeignmemory = -Wl,-rpath-link=$(XEN_LIBXENFOREIGNMEMORY) + +CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) $(CFLAGS_libxenforeignmemory) $(CFLAGS_xeninclude) +SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn) $(SHLIB_libxengnttab) $(SHLIB_libxengntshr) $(SHLIB_libxencall) $(SHLIB_libxenforeignmemory) LDLIBS_libxenctrl = $(SHDEPS_libxenctrl) $(XEN_LIBXC)/libxenctrl$(libextension) SHLIB_libxenctrl = $(SHDEPS_libxenctrl) -Wl,-rpath-link=$(XEN_LIBXC) -CFLAGS_libxenguest = -I$(XEN_LIBXC)/include $(CFLAGS_libxenevtchn) $(CFLAGS_xeninclude) +CFLAGS_libxenguest = -I$(XEN_LIBXC)/include $(CFLAGS_libxenevtchn) $(CFLAGS_libxenforeignmemory) $(CFLAGS_xeninclude) SHDEPS_libxenguest = $(SHLIB_libxenevtchn) LDLIBS_libxenguest = $(SHDEPS_libxenguest) $(XEN_LIBXC)/libxenguest$(libextension) SHLIB_libxenguest = $(SHDEPS_libxenguest) -Wl,-rpath-link=L$(XEN_LIBXC) diff --git a/tools/console/daemon/utils.c b/tools/console/daemon/utils.c index 71dd185..edc1595 100644 --- a/tools/console/daemon/utils.c +++ b/tools/console/daemon/utils.c @@ -34,7 +34,6 @@ #include #include -#include "xenctrl.h" #include "utils.h" struct xs_handle *xs; diff --git a/tools/console/daemon/utils.h b/tools/console/daemon/utils.h index 8725dcd..45c7c34 100644 --- a/tools/console/daemon/utils.h +++ b/tools/console/daemon/utils.h @@ -24,6 +24,7 @@ #include #include #include +#define XC_WANT_COMPAT_MAP_FOREIGN_API #include #include diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index 42fbabe..79afb78 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -41,8 +41,8 @@ CTRL_SRCS-y += xc_kexec.c CTRL_SRCS-y += xc_resource.c CTRL_SRCS-$(CONFIG_X86) += xc_psr.c CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c -CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c xc_linux_osdep.c -CTRL_SRCS-$(CONFIG_FreeBSD) += xc_freebsd.c xc_freebsd_osdep.c +CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c +CTRL_SRCS-$(CONFIG_FreeBSD) += xc_freebsd.c CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c CTRL_SRCS-$(CONFIG_NetBSDRump) += xc_netbsd.c @@ -126,7 +126,7 @@ $(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += -include $(XEN_ROOT)/tools/config. # 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_PIC_OBJS) $(GUEST_PIC_OBJS): CFLAGS += $(CFLAGS_libxencall) $(CFLAGS_libxenforeignmemory) $(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS): CFLAGS += $(CFLAGS_libxengnttab) $(CFLAGS_libxengntshr) @@ -208,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) $(LDLIBS_libxencall) $(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) $(LDLIBS_libxenforeignmemory) $(PTHREAD_LIBS) $(APPEND_LDFLAGS) # libxenguest diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h index 201fd70..bfa11a7 100644 --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1349,32 +1349,6 @@ int xc_lockprof_query(xc_interface *xch, void *xc_memalign(xc_interface *xch, size_t alignment, size_t size); /** - * Memory maps a range within one domain to a local address range. Mappings - * should be unmapped with munmap and should follow the same rules as mmap - * regarding page alignment. Returns NULL on failure. - * - * @parm xch a handle on an open hypervisor interface - * @parm dom the domain to map memory from - * @parm size the amount of memory to map (in multiples of page size) - * @parm prot same flag as in mmap(). - * @parm mfn the frame address to map. - */ -void *xc_map_foreign_range(xc_interface *xch, uint32_t dom, - int size, int prot, - unsigned long mfn ); - -void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot, - const xen_pfn_t *arr, int num ); - -/** - * Like xc_map_foreign_pages(), except it can succeed partially. - * When a page cannot be mapped, its respective field in @err is - * set to the corresponding errno value. - */ -void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot, - const xen_pfn_t *arr, int *err, unsigned int num); - -/** * Translates a virtual address in the context of a given domain and * vcpu returning the GFN containing the address (that is, an MFN for * PV guests, a PFN for HVM guests). Returns 0 for failure. diff --git a/tools/libxc/include/xenctrl_compat.h b/tools/libxc/include/xenctrl_compat.h index d99fa11..54c23a4 100644 --- a/tools/libxc/include/xenctrl_compat.h +++ b/tools/libxc/include/xenctrl_compat.h @@ -12,6 +12,42 @@ #ifndef XENCTRL_COMPAT_H #define XENCTRL_COMPAT_H +#ifdef XC_WANT_COMPAT_MAP_FOREIGN_API +/** + * Memory maps a range within one domain to a local address range. Mappings + * should be unmapped with munmap and should follow the same rules as mmap + * regarding page alignment. Returns NULL on failure. + * + * @parm xch a handle on an open hypervisor interface + * @parm dom the domain to map memory from + * @parm size the amount of memory to map (in multiples of page size) + * @parm prot same flag as in mmap(). + * @parm mfn the frame address to map. + */ +void *xc_map_foreign_range(xc_interface *xch, uint32_t dom, + int size, int prot, + unsigned long mfn ); + +void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot, + const xen_pfn_t *arr, int num ); + +/* Nothing within the library itself other than the compat wrapper + * itself should be using this, everything inside has access to + * xenforeignmemory_map(). + */ +#if !defined(XC_INTERNAL_COMPAT_MAP_FOREIGN_API) || \ + defined(XC_BUILDING_COMPAT_MAP_FOREIGN_API) +/** + * Like xc_map_foreign_pages(), except it can succeed partially. + * When a page cannot be mapped, its respective field in @err is + * set to the corresponding errno value. + */ +void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot, + const xen_pfn_t *arr, int *err, unsigned int num); +#endif + +#endif + #ifdef XC_WANT_COMPAT_EVTCHN_API typedef struct xenevtchn_handle xc_evtchn; diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c index 8435f6b..5d44512 100644 --- a/tools/libxc/xc_domain_restore.c +++ b/tools/libxc/xc_domain_restore.c @@ -1284,8 +1284,8 @@ static int apply_batch(xc_interface *xch, uint32_t dom, struct restore_ctx *ctx, PERROR("allocation for pfn_err failed"); return -1; } - region_base = xc_map_foreign_bulk( - xch, dom, PROT_WRITE, region_mfn, pfn_err, j); + region_base = xenforeignmemory_map(xch->fmem, + dom, PROT_WRITE, region_mfn, pfn_err, j); if ( region_base == NULL ) { diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c index 3222473..412819f 100644 --- a/tools/libxc/xc_domain_save.c +++ b/tools/libxc/xc_domain_save.c @@ -1265,8 +1265,8 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter if ( batch == 0 ) goto skip; /* vanishingly unlikely... */ - region_base = xc_map_foreign_bulk( - xch, dom, PROT_READ, pfn_type, pfn_err, batch); + region_base = xenforeignmemory_map(xch->fmem, + dom, PROT_READ, pfn_type, pfn_err, batch); if ( region_base == NULL ) { PERROR("map batch failed"); diff --git a/tools/libxc/xc_foreign_memory.c b/tools/libxc/xc_foreign_memory.c index c96489d..b6bf132 100644 --- a/tools/libxc/xc_foreign_memory.c +++ b/tools/libxc/xc_foreign_memory.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#define XC_BUILDING_COMPAT_MAP_FOREIGN_API #include "xc_private.h" void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot, @@ -35,7 +36,7 @@ void *xc_map_foreign_pages(xc_interface *xch, uint32_t dom, int prot, if (!err) return NULL; - res = xc_map_foreign_bulk(xch, dom, prot, arr, err, num); + res = xenforeignmemory_map(xch->fmem, dom, prot, arr, err, num); if (res) { for (i = 0; i < num; i++) { if (err[i]) { @@ -101,53 +102,11 @@ void *xc_map_foreign_ranges(xc_interface *xch, return ret; } -/* - * stub for all not yet converted OSes (NetBSD and Solaris). New OSes should - * just implement xc_map_foreign_bulk. - */ -#if defined(__NetBSD__) || defined(__sun__) -void *osdep_map_foreign_batch(xc_interface *xch, uint32_t dom, int prot, - xen_pfn_t *arr, int num ); -void *xc_map_foreign_bulk(xc_interface *xch, - uint32_t dom, int prot, +void *xc_map_foreign_bulk(xc_interface *xch, uint32_t dom, int prot, const xen_pfn_t *arr, int *err, unsigned int num) { - xen_pfn_t *pfn; - unsigned int i; - void *ret; - - if ((int)num <= 0) { - errno = EINVAL; - return NULL; - } - - pfn = malloc(num * sizeof(*pfn)); - if (!pfn) { - errno = ENOMEM; - return NULL; - } - - memcpy(pfn, arr, num * sizeof(*arr)); - ret = osdep_map_foreign_batch(xch, dom, prot, pfn, num); - - if (ret) { - for (i = 0; i < num; ++i) - switch (pfn[i] ^ arr[i]) { - case 0: - err[i] = 0; - break; - default: - err[i] = -EINVAL; - break; - } - } else - memset(err, 0, num * sizeof(*err)); - - free(pfn); - - return ret; + return xenforeignmemory_map(xch->fmem, dom, prot, arr, err, num); } -#endif /* * Local variables: diff --git a/tools/libxc/xc_freebsd_osdep.c b/tools/libxc/xc_freebsd_osdep.c deleted file mode 100644 index d09e0da..0000000 --- a/tools/libxc/xc_freebsd_osdep.c +++ /dev/null @@ -1,137 +0,0 @@ - /****************************************************************************** - * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - * xc_gnttab functions: - * Copyright (c) 2007-2008, D G Murray - * - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "xc_private.h" - -#define PRIVCMD_DEV "/dev/xen/privcmd" - -/*------------------------- Privcmd device interface -------------------------*/ -int osdep_privcmd_open(xc_interface *xch) -{ - 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; - } - - xch->privcmdfd = fd; - return 0; - - error: - saved_errno = errno; - close(fd); - errno = saved_errno; - - return -1; -} - -int osdep_privcmd_close(xc_interface *xch) -{ - int fd = xch->privcmdfd; - if ( fd == -1 ) - return 0; - return close(fd); -} - -/*----------------------- Privcmd foreign map interface ----------------------*/ -void *xc_map_foreign_bulk(xc_interface *xch, - uint32_t dom, int prot, - const xen_pfn_t *arr, int *err, - unsigned int num) -{ - int fd = xch->privcmdfd; - privcmd_mmapbatch_t ioctlx; - void *addr; - int rc; - - addr = mmap(NULL, num << XC_PAGE_SHIFT, prot, MAP_SHARED, fd, 0); - if ( addr == MAP_FAILED ) - { - PERROR("xc_map_foreign_bulk: mmap failed"); - return NULL; - } - - ioctlx.num = num; - ioctlx.dom = dom; - ioctlx.addr = (unsigned long)addr; - ioctlx.arr = arr; - ioctlx.err = err; - - rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx); - if ( rc < 0 ) - { - int saved_errno = errno; - PERROR("xc_map_foreign_bulk: ioctl failed"); - (void)munmap(addr, num << XC_PAGE_SHIFT); - errno = saved_errno; - return NULL; - } - - return addr; -} - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/tools/libxc/xc_linux_osdep.c b/tools/libxc/xc_linux_osdep.c deleted file mode 100644 index 9f8805a..0000000 --- a/tools/libxc/xc_linux_osdep.c +++ /dev/null @@ -1,296 +0,0 @@ - /****************************************************************************** - * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - * xc_gnttab functions: - * Copyright (c) 2007-2008, D G Murray - * - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "xenctrl.h" - -#include "xc_private.h" - -#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1)) - -int osdep_privcmd_open(xc_interface *xch) -{ - 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; - } - - xch->privcmdfd = fd; - return 0; - - error: - saved_errno = errno; - close(fd); - errno = saved_errno; - return -1; -} - -int osdep_privcmd_close(xc_interface *xch) -{ - int fd = xch->privcmdfd; - if (fd == -1) - return 0; - return close(fd); -} - -static int map_foreign_batch_single(int fd, uint32_t dom, - xen_pfn_t *mfn, unsigned long addr) -{ - privcmd_mmapbatch_t ioctlx; - int rc; - - ioctlx.num = 1; - ioctlx.dom = dom; - ioctlx.addr = addr; - ioctlx.arr = mfn; - - do - { - *mfn ^= PRIVCMD_MMAPBATCH_PAGED_ERROR; - usleep(100); - rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx); - } - while ( (rc < 0) && (errno == ENOENT) ); - - return rc; -} - -/* - * Retry mmap of all paged gfns in batches - * retuns < 0 on fatal error - * returns 0 if all gfns left paging state - * returns > 0 if some gfns are still in paging state - * - * Walk all gfns and try to assemble blocks of gfns in paging state. - * This will keep the request ring full and avoids delays. - */ -static int retry_paged(int fd, uint32_t dom, void *addr, - const xen_pfn_t *arr, int *err, unsigned int num) -{ - privcmd_mmapbatch_v2_t ioctlx; - int rc, paged = 0, i = 0; - - do - { - /* Skip gfns not in paging state */ - if ( err[i] != -ENOENT ) - { - i++; - continue; - } - - paged++; - - /* At least one gfn is still in paging state */ - ioctlx.num = 1; - ioctlx.dom = dom; - ioctlx.addr = (unsigned long)addr + ((unsigned long)i<privcmdfd; - privcmd_mmapbatch_v2_t ioctlx; - void *addr; - unsigned int i; - int rc; - - addr = mmap(NULL, (unsigned long)num << XC_PAGE_SHIFT, prot, MAP_SHARED, - fd, 0); - if ( addr == MAP_FAILED ) - { - PERROR("xc_map_foreign_bulk: mmap failed"); - return NULL; - } - - ioctlx.num = num; - ioctlx.dom = dom; - ioctlx.addr = (unsigned long)addr; - ioctlx.arr = arr; - ioctlx.err = err; - - rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH_V2, &ioctlx); - - /* Command was recognized, some gfn in arr are in paging state */ - if ( rc < 0 && errno == ENOENT ) - { - do { - usleep(100); - rc = retry_paged(fd, dom, addr, arr, err, num); - } while ( rc > 0 ); - } - /* Command was not recognized, use fall back */ - else if ( rc < 0 && errno == EINVAL && (int)num > 0 ) - { - /* - * IOCTL_PRIVCMD_MMAPBATCH_V2 is not supported - fall back to - * IOCTL_PRIVCMD_MMAPBATCH. - */ - privcmd_mmapbatch_t ioctlx; - xen_pfn_t *pfn; - unsigned int pfn_arr_size = ROUNDUP((num * sizeof(*pfn)), XC_PAGE_SHIFT); - - if ( pfn_arr_size <= XC_PAGE_SIZE ) - pfn = alloca(num * sizeof(*pfn)); - else - { - pfn = mmap(NULL, pfn_arr_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON | MAP_POPULATE, -1, 0); - if ( pfn == MAP_FAILED ) - { - PERROR("xc_map_foreign_bulk: mmap of pfn array failed"); - (void)munmap(addr, (unsigned long)num << XC_PAGE_SHIFT); - return NULL; - } - } - - memcpy(pfn, arr, num * sizeof(*arr)); - - ioctlx.num = num; - ioctlx.dom = dom; - ioctlx.addr = (unsigned long)addr; - ioctlx.arr = pfn; - - rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx); - - rc = rc < 0 ? -errno : 0; - - for ( i = 0; i < num; ++i ) - { - switch ( pfn[i] ^ arr[i] ) - { - case 0: - err[i] = rc != -ENOENT ? rc : 0; - continue; - default: - err[i] = -EINVAL; - continue; - case PRIVCMD_MMAPBATCH_PAGED_ERROR: - if ( rc != -ENOENT ) - { - err[i] = rc ?: -EINVAL; - continue; - } - rc = map_foreign_batch_single(fd, dom, pfn + i, - (unsigned long)addr + ((unsigned long)i< XC_PAGE_SIZE ) - munmap(pfn, pfn_arr_size); - - if ( rc == -ENOENT && i == num ) - rc = 0; - else if ( rc ) - { - errno = -rc; - rc = -1; - } - } - - if ( rc < 0 ) - { - int saved_errno = errno; - - PERROR("xc_map_foreign_bulk: ioctl failed"); - (void)munmap(addr, (unsigned long)num << XC_PAGE_SHIFT); - errno = saved_errno; - return NULL; - } - - return addr; -} - -/* - * Local variables: - * mode: C - * c-file-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c index 1616c58..7373e54 100644 --- a/tools/libxc/xc_minios.c +++ b/tools/libxc/xc_minios.c @@ -40,40 +40,11 @@ void minios_interface_close_fd(int fd); extern void minios_interface_close_fd(int fd); -int osdep_privcmd_open(xc_interface *xch) -{ - int fd = alloc_fd(FTYPE_XC); - - if ( fd == -1) - return -1; - - xch->privcmdfd = fd; - return 0; -} - -int osdep_privcmd_close(xc_interface *xch) -{ - int fd = xch->privcmdfd; - return close(fd); -} - void minios_interface_close_fd(int fd) { files[fd].type = FTYPE_NONE; } -void *xc_map_foreign_bulk(xc_interface *xch, - uint32_t dom, int prot, - const xen_pfn_t *arr, int *err, unsigned int num) -{ - unsigned long pt_prot = 0; - if (prot & PROT_READ) - pt_prot = L1_PROT_RO; - if (prot & PROT_WRITE) - pt_prot = L1_PROT; - return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot); -} - /* Optionally flush file to disk and discard page cache */ void discard_file_cache(xc_interface *xch, int fd, int flush) { diff --git a/tools/libxc/xc_netbsd.c b/tools/libxc/xc_netbsd.c index 2654d18..8d6742d 100644 --- a/tools/libxc/xc_netbsd.c +++ b/tools/libxc/xc_netbsd.c @@ -23,79 +23,6 @@ #include #include #include -#include - -int osdep_privcmd_open(xc_interface *xch) -{ - 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; - } - - xch->privcmdfd = fd; - return 0; - - error: - saved_errno = errno; - close(fd); - errno = saved_errno; - return -1; -} - -int osdep_privcmd_close(xc_interface *xch) -{ - int fd = xch->privcmdfd; - return close(fd); -} - -void *osdep_map_foreign_batch(xc_interface *xch, - uint32_t dom, int prot, - xen_pfn_t *arr, int num) -{ - int fd = xch->privcmdfd; - privcmd_mmapbatch_t ioctlx; - void *addr; - addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_ANON | MAP_SHARED, -1, 0); - if ( addr == MAP_FAILED ) { - PERROR("osdep_map_foreign_batch: mmap failed"); - return NULL; - } - - ioctlx.num=num; - ioctlx.dom=dom; - ioctlx.addr=(unsigned long)addr; - ioctlx.arr=arr; - if ( ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 ) - { - int saved_errno = errno; - PERROR("osdep_map_foreign_batch: ioctl failed"); - (void)munmap(addr, num*XC_PAGE_SIZE); - errno = saved_errno; - return NULL; - } - return addr; - -} /* Optionally flush file to disk and discard page cache */ void discard_file_cache(xc_interface *xch, int fd, int flush) diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 00f96ba..94ec444 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -59,11 +59,12 @@ struct xc_interface_core *xc_interface_open(xentoollog_logger *logger, 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; + + xch->fmem = xenforeignmemory_open(xch->error_handler, 0); if ( xch->xcall == NULL ) goto err; @@ -71,7 +72,7 @@ struct xc_interface_core *xc_interface_open(xentoollog_logger *logger, return xch; err: - osdep_privcmd_close(xch); + xencall_close(xch->xcall); xtl_logger_destroy(xch->error_handler_tofree); if (xch != &xch_buf) free(xch); return NULL; @@ -87,8 +88,8 @@ int xc_interface_close(xc_interface *xch) 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"); + rc = xenforeignmemory_close(xch->fmem); + if (rc) PERROR("Could not close foreign memory interface"); xtl_logger_destroy(xch->dombuild_logger_tofree); xtl_logger_destroy(xch->error_handler_tofree); diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index c8c2bdc..b230854 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -30,8 +30,13 @@ #include #include "_paths.h" + +#define XC_WANT_COMPAT_MAP_FOREIGN_API +#define XC_INTERNAL_COMPAT_MAP_FOREIGN_API #include "xenctrl.h" + #include +#include #include @@ -95,11 +100,11 @@ struct xc_interface_core { FILE *dombuild_logger_file; const char *currently_progress_reporting; - /* Privcmd interface */ - int privcmdfd; - /* Hypercall interface */ xencall_handle *xcall; + + /* Foreign mappings */ + xenforeignmemory_handle *fmem; }; int osdep_privcmd_open(xc_interface *xch); diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c index e1e126d..c2e87d1 100644 --- a/tools/libxc/xc_solaris.c +++ b/tools/libxc/xc_solaris.c @@ -20,81 +20,8 @@ #include "xc_private.h" -#include -#include -#include #include -int osdep_privcmd_open(xc_interface *xch) -{ - 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; - } - - xch->privcmdfd = fd; - return 0; - - error: - saved_errno = errno; - close(fd); - errno = saved_errno; - return -1; -} - -int osdep_privcmd_close(xc_interface *xch) -{ - int fd = xch->privcmdfd; - return close(fd); -} - -void *osdep_map_foreign_batch(xc_interface *xch, - uint32_t dom, int prot, - xen_pfn_t *arr, int num) -{ - int fd = xch->privcmdfd; - privcmd_mmapbatch_t ioctlx; - void *addr; - addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_SHARED, fd, 0); - if ( addr == MAP_FAILED ) - return NULL; - - ioctlx.num=num; - ioctlx.dom=dom; - ioctlx.addr=(unsigned long)addr; - ioctlx.arr=arr; - if ( ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 ) - { - int saved_errno = errno; - PERROR("XXXXXXXX"); - (void)munmap(addr, num*XC_PAGE_SIZE); - errno = saved_errno; - return NULL; - } - return addr; - -} - /* Optionally flush file to disk and discard page cache */ void discard_file_cache(xc_interface *xch, int fd, int flush) { diff --git a/tools/libxc/xc_sr_restore.c b/tools/libxc/xc_sr_restore.c index bf1ee15..4bbda9d 100644 --- a/tools/libxc/xc_sr_restore.c +++ b/tools/libxc/xc_sr_restore.c @@ -315,8 +315,8 @@ static int process_page_data(struct xc_sr_context *ctx, unsigned count, if ( nr_pages == 0 ) goto done; - mapping = guest_page = xc_map_foreign_bulk( - xch, ctx->domid, PROT_READ | PROT_WRITE, + mapping = guest_page = xenforeignmemory_map(xch->fmem, + ctx->domid, PROT_READ | PROT_WRITE, mfns, map_errs, nr_pages); if ( !mapping ) { diff --git a/tools/libxc/xc_sr_save.c b/tools/libxc/xc_sr_save.c index d63b783..2672ad3 100644 --- a/tools/libxc/xc_sr_save.c +++ b/tools/libxc/xc_sr_save.c @@ -153,8 +153,8 @@ static int write_batch(struct xc_sr_context *ctx) if ( nr_pages > 0 ) { - guest_mapping = xc_map_foreign_bulk( - xch, ctx->domid, PROT_READ, mfns, errors, nr_pages); + guest_mapping = xenforeignmemory_map(xch->fmem, + ctx->domid, PROT_READ, mfns, errors, nr_pages); if ( !guest_mapping ) { PERROR("Failed to map guest pages"); diff --git a/tools/libxc/xc_vm_event.c b/tools/libxc/xc_vm_event.c index 4d7e7cc..940efd7 100644 --- a/tools/libxc/xc_vm_event.c +++ b/tools/libxc/xc_vm_event.c @@ -74,8 +74,9 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param, ring_pfn = pfn; mmap_pfn = pfn; - ring_page = xc_map_foreign_bulk(xch, domain_id, PROT_READ | PROT_WRITE, - &mmap_pfn, &err, 1); + ring_page = xenforeignmemory_map(xch->fmem, + domain_id, PROT_READ | PROT_WRITE, + &mmap_pfn, &err, 1); if ( !ring_page ) { /* Map failed, populate ring page */ @@ -88,8 +89,9 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param, } mmap_pfn = ring_pfn; - ring_page = xc_map_foreign_bulk(xch, domain_id, PROT_READ | PROT_WRITE, - &mmap_pfn, &err, 1); + ring_page = xenforeignmemory_map(xch->fmem, + domain_id, PROT_READ | PROT_WRITE, + &mmap_pfn, &err, 1); if ( !ring_page ) { PERROR("Could not map the ring page: %d\n", err); diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h index 1910361..0baf403 100644 --- a/tools/libxc/xg_private.h +++ b/tools/libxc/xg_private.h @@ -27,9 +27,8 @@ #include #include -#include "xenctrl.h" -#include "xenguest.h" #include "xc_private.h" +#include "xenguest.h" #include #include diff --git a/tools/libxenforeignmemory/Makefile b/tools/libxenforeignmemory/Makefile new file mode 100644 index 0000000..4c84115 --- /dev/null +++ b/tools/libxenforeignmemory/Makefile @@ -0,0 +1,67 @@ +XEN_ROOT = $(CURDIR)/../.. +include $(XEN_ROOT)/tools/Rules.mk + +MAJOR = 1 +MINOR = 0 +SHLIB_LDFLAGS += -Wl,--version-script=libxenforeignmemory.map + +CFLAGS += -Werror -Wmissing-prototypes +CFLAGS += -I./include $(CFLAGS_xeninclude) +CFLAGS += $(CFLAGS_libxentoollog) + +SRCS-y += core.c +SRCS-$(CONFIG_Linux) += linux.c +SRCS-$(CONFIG_FreeBSD) += freebsd.c +SRCS-$(CONFIG_SunOS) += compat.c solaris.c +SRCS-$(CONFIG_NetBSD) += compat.c netbsd.c +SRCS-$(CONFIG_MiniOS) += minios.c + +LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y)) +PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y)) + +LIB := libxenforeignmemory.a +ifneq ($(nosharedlibs),y) +LIB += libxenforeignmemory.so +endif + +.PHONY: all +all: build + +.PHONY: build +build: + $(MAKE) libs + +.PHONY: libs +libs: headers.chk $(LIB) + +headers.chk: $(wildcard include/*.h) + +libxenforeignmemory.a: $(LIB_OBJS) + $(AR) rc $@ $^ + +libxenforeignmemory.so: libxenforeignmemory.so.$(MAJOR) + $(SYMLINK_SHLIB) $< $@ +libxenforeignmemory.so.$(MAJOR): libxenforeignmemory.so.$(MAJOR).$(MINOR) + $(SYMLINK_SHLIB) $< $@ + +libxenforeignmemory.so.$(MAJOR).$(MINOR): $(PIC_OBJS) libxenforeignmemory.map + $(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenforeignmemory.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) libxenforeignmemory.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir) + $(INSTALL_DATA) libxenforeignmemory.a $(DESTDIR)$(libdir) + $(SYMLINK_SHLIB) libxenforeignmemory.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxenforeignmemory.so.$(MAJOR) + $(SYMLINK_SHLIB) libxenforeignmemory.so.$(MAJOR) $(DESTDIR)$(libdir)/libxenforeignmemory.so + $(INSTALL_DATA) include/xenforeignmemory.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/libxenforeignmemory/compat.c b/tools/libxenforeignmemory/compat.c new file mode 100644 index 0000000..0d2cf36 --- /dev/null +++ b/tools/libxenforeignmemory/compat.c @@ -0,0 +1,72 @@ +/****************************************************************************** + * + * Compatibility functions for mapping foreign domain's memory. + * + * 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_foreign_memory.c + */ +#if !defined(__NetBSD__) && !defined(__sun__) +#error Please implement xc_map_foreign_bulk directly for new ports. +#endif + +#include "private.h" + +void *xc_map_foreign_bulk(xenforeignmem_handle *fmem, + uint32_t dom, int prot, + const xen_pfn_t *arr, int *err, unsigned int num) +{ + xen_pfn_t *pfn; + unsigned int i; + void *ret; + + if ((int)num <= 0) { + errno = EINVAL; + return NULL; + } + + pfn = malloc(num * sizeof(*pfn)); + if (!pfn) { + errno = ENOMEM; + return NULL; + } + + memcpy(pfn, arr, num * sizeof(*arr)); + ret = osdep_map_foreign_batch(fmem, dom, prot, pfn, num); + + if (ret) { + for (i = 0; i < num; ++i) + switch (pfn[i] ^ arr[i]) { + case 0: + err[i] = 0; + break; + default: + err[i] = -EINVAL; + break; + } + } else + memset(err, 0, num * sizeof(*err)); + + free(pfn); + + return ret; +} +#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/libxenforeignmemory/core.c b/tools/libxenforeignmemory/core.c new file mode 100644 index 0000000..efb3e54 --- /dev/null +++ b/tools/libxenforeignmemory/core.c @@ -0,0 +1,65 @@ +/* + * 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 + +#include "private.h" + +xenforeignmemory_handle *xenforeignmemory_open(xentoollog_logger *logger, + unsigned open_flags) +{ + xenforeignmemory_handle *fmem = malloc(sizeof(*fmem)); + int rc; + + if (!fmem) return NULL; + + fmem->logger = logger; + fmem->logger_tofree = NULL; + + if (!fmem->logger) { + fmem->logger = fmem->logger_tofree = + (xentoollog_logger*) + xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0); + if (!fmem->logger) goto err; + } + + rc = osdep_xenforeignmemory_open(fmem); + if ( rc < 0 ) goto err; + + return fmem; + +err: + osdep_xenforeignmemory_close(fmem); + xtl_logger_destroy(fmem->logger_tofree); + free(fmem); + return NULL; +} + +int xenforeignmemory_close(xenforeignmemory_handle *fmem) +{ + int rc; + + rc = osdep_xenforeignmemory_close(fmem); + xtl_logger_destroy(fmem->logger_tofree); + free(fmem); + return rc; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxenforeignmemory/freebsd.c b/tools/libxenforeignmemory/freebsd.c new file mode 100644 index 0000000..b93db51 --- /dev/null +++ b/tools/libxenforeignmemory/freebsd.c @@ -0,0 +1,126 @@ + /****************************************************************************** + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "private.h" + +#define PRIVCMD_DEV "/dev/xen/privcmd" + +int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem) +{ + 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; + } + + fmem->fd = fd; + return 0; + + error: + saved_errno = errno; + close(fd); + errno = saved_errno; + + return -1; +} + +int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem) +{ + int fd = fmem->fd; + if ( fd == -1 ) + return 0; + return close(fd); +} + +void *xenforeignmemory_map(xenforeignmemory_handle *fmem, + uint32_t dom, int prot, + const xen_pfn_t *arr, int *err, + unsigned int num) +{ + int fd = fmem->fd; + privcmd_mmapbatch_t ioctlx; + void *addr; + int rc; + + addr = mmap(NULL, num << PAGE_SHIFT, prot, MAP_SHARED, fd, 0); + if ( addr == MAP_FAILED ) + { + PERROR("xc_map_foreign_bulk: mmap failed"); + return NULL; + } + + ioctlx.num = num; + ioctlx.dom = dom; + ioctlx.addr = (unsigned long)addr; + ioctlx.arr = arr; + ioctlx.err = err; + + rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx); + if ( rc < 0 ) + { + int saved_errno = errno; + PERROR("xc_map_foreign_bulk: ioctl failed"); + (void)munmap(addr, num << PAGE_SHIFT); + errno = saved_errno; + return NULL; + } + + return addr; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxenforeignmemory/include/xenforeignmemory.h b/tools/libxenforeignmemory/include/xenforeignmemory.h new file mode 100644 index 0000000..3f3d1c7 --- /dev/null +++ b/tools/libxenforeignmemory/include/xenforeignmemory.h @@ -0,0 +1,68 @@ +/* + * 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 XENFOREIGNMEMORY_H +#define XENFOREIGNMEMORY_H + +/* + * This library allows you to map foreign domain memory, subject to + * permissions for both the process and the domain in which the + * process runs. + */ + +#include +#include + +#include + +/* Callers who don't care don't need to #include */ +typedef struct xentoollog_logger xentoollog_logger; + +typedef struct xenforeignmemory_handle xenforeignmemory_handle; + +/* + * Return a handle onto the hypercall driver. Logs errors. + */ +xenforeignmemory_handle *xenforeignmemory_open(xentoollog_logger *logger, + unsigned open_flags); + +/* + * Close a handle previously allocated with xenforeignmemory_open(). + */ +int xenforeignmemory_close(xenforeignmemory_handle *xmem); + +/* + * Maps a range within one domain to a local address range. Mappings + * should be unmapped with munmap and should follow the same rules as mmap + * regarding page alignment. + * + * prot is as for mmap(2). + * + * Can partially succeed. When a page cannot be mapped, its respective + * field in @err is set to the corresponding errno value. + * + * Returns NULL if no pages can be mapped. + */ +void *xenforeignmemory_map(xenforeignmemory_handle *fmem, uint32_t dom, + int prot, const xen_pfn_t *arr, int *err, + unsigned int num); + +#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/libxenforeignmemory/libxenforeignmemory.map b/tools/libxenforeignmemory/libxenforeignmemory.map new file mode 100644 index 0000000..11f0d2b --- /dev/null +++ b/tools/libxenforeignmemory/libxenforeignmemory.map @@ -0,0 +1,7 @@ +VERS_1.0 { + global: + xenforeignmemory_open; + xenforeignmemory_close; + xenforeignmemory_map; + local: *; /* Do not expose anything by default */ +}; diff --git a/tools/libxenforeignmemory/linux.c b/tools/libxenforeignmemory/linux.c new file mode 100644 index 0000000..6343ebe --- /dev/null +++ b/tools/libxenforeignmemory/linux.c @@ -0,0 +1,284 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include + +#include "private.h" + +#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1)) + +int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem) +{ + 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; + } + + fmem->fd = fd; + return 0; + + error: + saved_errno = errno; + close(fd); + errno = saved_errno; + return -1; +} + +int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem) +{ + int fd = fmem->fd; + if (fd == -1) + return 0; + return close(fd); +} + +static int map_foreign_batch_single(int fd, uint32_t dom, + xen_pfn_t *mfn, unsigned long addr) +{ + privcmd_mmapbatch_t ioctlx; + int rc; + + ioctlx.num = 1; + ioctlx.dom = dom; + ioctlx.addr = addr; + ioctlx.arr = mfn; + + do + { + *mfn ^= PRIVCMD_MMAPBATCH_PAGED_ERROR; + usleep(100); + rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx); + } + while ( (rc < 0) && (errno == ENOENT) ); + + return rc; +} + +/* + * Retry mmap of all paged gfns in batches + * retuns < 0 on fatal error + * returns 0 if all gfns left paging state + * returns > 0 if some gfns are still in paging state + * + * Walk all gfns and try to assemble blocks of gfns in paging state. + * This will keep the request ring full and avoids delays. + */ +static int retry_paged(int fd, uint32_t dom, void *addr, + const xen_pfn_t *arr, int *err, unsigned int num) +{ + privcmd_mmapbatch_v2_t ioctlx; + int rc, paged = 0, i = 0; + + do + { + /* Skip gfns not in paging state */ + if ( err[i] != -ENOENT ) + { + i++; + continue; + } + + paged++; + + /* At least one gfn is still in paging state */ + ioctlx.num = 1; + ioctlx.dom = dom; + ioctlx.addr = (unsigned long)addr + ((unsigned long)i<fd; + privcmd_mmapbatch_v2_t ioctlx; + void *addr; + unsigned int i; + int rc; + + addr = mmap(NULL, (unsigned long)num << PAGE_SHIFT, prot, MAP_SHARED, + fd, 0); + if ( addr == MAP_FAILED ) + { + PERROR("mmap failed"); + return NULL; + } + + ioctlx.num = num; + ioctlx.dom = dom; + ioctlx.addr = (unsigned long)addr; + ioctlx.arr = arr; + ioctlx.err = err; + + rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH_V2, &ioctlx); + + /* Command was recognized, some gfn in arr are in paging state */ + if ( rc < 0 && errno == ENOENT ) + { + do { + usleep(100); + rc = retry_paged(fd, dom, addr, arr, err, num); + } while ( rc > 0 ); + } + /* Command was not recognized, use fall back */ + else if ( rc < 0 && errno == EINVAL && (int)num > 0 ) + { + /* + * IOCTL_PRIVCMD_MMAPBATCH_V2 is not supported - fall back to + * IOCTL_PRIVCMD_MMAPBATCH. + */ + privcmd_mmapbatch_t ioctlx; + xen_pfn_t *pfn; + unsigned int pfn_arr_size = ROUNDUP((num * sizeof(*pfn)), PAGE_SHIFT); + + if ( pfn_arr_size <= PAGE_SIZE ) + pfn = alloca(num * sizeof(*pfn)); + else + { + pfn = mmap(NULL, pfn_arr_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_POPULATE, -1, 0); + if ( pfn == MAP_FAILED ) + { + PERROR("mmap of pfn array failed"); + (void)munmap(addr, (unsigned long)num << PAGE_SHIFT); + return NULL; + } + } + + memcpy(pfn, arr, num * sizeof(*arr)); + + ioctlx.num = num; + ioctlx.dom = dom; + ioctlx.addr = (unsigned long)addr; + ioctlx.arr = pfn; + + rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx); + + rc = rc < 0 ? -errno : 0; + + for ( i = 0; i < num; ++i ) + { + switch ( pfn[i] ^ arr[i] ) + { + case 0: + err[i] = rc != -ENOENT ? rc : 0; + continue; + default: + err[i] = -EINVAL; + continue; + case PRIVCMD_MMAPBATCH_PAGED_ERROR: + if ( rc != -ENOENT ) + { + err[i] = rc ?: -EINVAL; + continue; + } + rc = map_foreign_batch_single(fd, dom, pfn + i, + (unsigned long)addr + ((unsigned long)i< PAGE_SIZE ) + munmap(pfn, pfn_arr_size); + + if ( rc == -ENOENT && i == num ) + rc = 0; + else if ( rc ) + { + errno = -rc; + rc = -1; + } + } + + if ( rc < 0 ) + { + int saved_errno = errno; + + PERROR("ioctl failed"); + (void)munmap(addr, (unsigned long)num << PAGE_SHIFT); + errno = saved_errno; + return NULL; + } + + return addr; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxenforeignmemory/minios.c b/tools/libxenforeignmemory/minios.c new file mode 100644 index 0000000..ac7c0ce --- /dev/null +++ b/tools/libxenforeignmemory/minios.c @@ -0,0 +1,59 @@ +/* + * 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 . + */ + +#include +#include +#include +#include + +#include + +#include + +#include "private.h" + +int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem) +{ + /* No fd required */ + return 0; +} + +int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem) +{ + return 0; +} + +void *xenforeignmemory_map(xenforeignmemory_handle *fmem, + uint32_t dom, int prot, + const xen_pfn_t *arr, int *err, unsigned int num) +{ + unsigned long pt_prot = 0; + if (prot & PROT_READ) + pt_prot = L1_PROT_RO; + if (prot & PROT_WRITE) + pt_prot = L1_PROT; + return map_frames_ex(arr, num, 1, 0, 1, dom, err, pt_prot); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxenforeignmemory/netbsd.c b/tools/libxenforeignmemory/netbsd.c new file mode 100644 index 0000000..b2d8b88 --- /dev/null +++ b/tools/libxenforeignmemory/netbsd.c @@ -0,0 +1,92 @@ +/****************************************************************************** + * + * 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. + */ + +#include +#include +#include + +#include "private.h" + +int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem) +{ + 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; + } + + fmem->fd = fd; + return 0; + + error: + saved_errno = errno; + close(fd); + errno = saved_errno; + return -1; +} + +int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem) +{ + int fd = fmem->fd; + return close(fd); +} + +void *compat_mapforeign_batch(xenforeignmem_handle *fmem, uint32_t dom, + int prot, xen_pfn_t *arr, int num) +{ + int fd = fmem->fd; + privcmd_mmapbatch_t ioctlx; + void *addr; + addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_ANON | MAP_SHARED, -1, 0); + if ( addr == MAP_FAILED ) { + PERROR("osdep_map_foreign_batch: mmap failed"); + return NULL; + } + + ioctlx.num=num; + ioctlx.dom=dom; + ioctlx.addr=(unsigned long)addr; + ioctlx.arr=arr; + if ( ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 ) + { + int saved_errno = errno; + PERROR("osdep_map_foreign_batch: ioctl failed"); + (void)munmap(addr, num*XC_PAGE_SIZE); + errno = saved_errno; + return NULL; + } + return addr; + +} diff --git a/tools/libxenforeignmemory/private.h b/tools/libxenforeignmemory/private.h new file mode 100644 index 0000000..54dd7d5 --- /dev/null +++ b/tools/libxenforeignmemory/private.h @@ -0,0 +1,47 @@ +#ifndef XENFOREIGNMEMORY_PRIVATE_H +#define XENFOREIGNMEMORY_PRIVATE_H + +#include + +#include + +#include +#include + +#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 xenforeignmemory_handle { + xentoollog_logger *logger, *logger_tofree; + unsigned flags; + int fd; +}; + +int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem); +int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem); + +#if defined(__NetBSD__) || defined(__sun__) +/* Strictly compat for those two only only */ +void *compat_mapforeign_batch(xenforeignmem_handle *fmem, uint32_t dom, + int prot, xen_pfn_t *arr, int num); +#endif + +#define PERROR(_f...) \ + xtl_log(fmem->logger, XTL_ERROR, errno, "xenforeignmemory", _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/libxenforeignmemory/solaris.c b/tools/libxenforeignmemory/solaris.c new file mode 100644 index 0000000..035484b --- /dev/null +++ b/tools/libxenforeignmemory/solaris.c @@ -0,0 +1,95 @@ +/****************************************************************************** + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xc_private.h" + +#include +#include +#include +#include + +int osdep_xenforeignmemory_open(xenforeignmemory_handle *fmem) +{ + 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; + } + + fmem->fd = fd; + return 0; + + error: + saved_errno = errno; + close(fd); + errno = saved_errno; + return -1; +} + +int osdep_xenforeignmemory_close(xenforeignmemory_handle *fmem) +{ + int fd = fmem->fd; + return close(fd); +} + +void *compat_mapforeign_batch(xenforeignmem_handle *fmem, uint32_t dom, + int prot, xen_pfn_t *arr, int num) +{ + int fd = fmem->fd; + privcmd_mmapbatch_t ioctlx; + void *addr; + addr = mmap(NULL, num*XC_PAGE_SIZE, prot, MAP_SHARED, fd, 0); + if ( addr == MAP_FAILED ) + return NULL; + + ioctlx.num=num; + ioctlx.dom=dom; + ioctlx.addr=(unsigned long)addr; + ioctlx.arr=arr; + if ( ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 ) + { + int saved_errno = errno; + PERROR("XXXXXXXX"); + (void)munmap(addr, num*XC_PAGE_SIZE); + errno = saved_errno; + return NULL; + } + return addr; + +} diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 4b59cad..101acb0 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -50,6 +50,7 @@ #include #include +#define XC_WANT_COMPAT_MAP_FOREIGN_API #include #include diff --git a/tools/misc/xen-mfndump.c b/tools/misc/xen-mfndump.c index ceeeaa9..1b22ad7 100644 --- a/tools/misc/xen-mfndump.c +++ b/tools/misc/xen-mfndump.c @@ -1,3 +1,4 @@ +#define XC_WANT_COMPAT_MAP_FOREIGN_API #include #include #include diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c index 9a201ee..1f5aba7 100644 --- a/tools/ocaml/libs/xc/xenctrl_stubs.c +++ b/tools/ocaml/libs/xc/xenctrl_stubs.c @@ -29,6 +29,7 @@ #include #include +#define XC_WANT_COMPAT_MAP_FOREIGN_API #include #include "mmap_stubs.h" diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index ee3e1d0..6750ee1 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -5,6 +5,7 @@ */ #include +#define XC_WANT_COMPAT_MAP_FOREIGN_API #include #include #include @@ -17,7 +18,6 @@ #include #include -#include "xenctrl.h" #include #include #include "xc_dom.h" diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c index 9e2a49b..ad77286 100644 --- a/tools/xenmon/xenbaked.c +++ b/tools/xenmon/xenbaked.c @@ -39,6 +39,7 @@ #include #include #include +#define XC_WANT_COMPAT_MAP_FOREIGN_API #include #include #include diff --git a/tools/xenpaging/pagein.c b/tools/xenpaging/pagein.c index 18699ec..0ea8680 100644 --- a/tools/xenpaging/pagein.c +++ b/tools/xenpaging/pagein.c @@ -1,6 +1,5 @@ /* Trigger a page-in in a separate thread-of-execution to avoid deadlock */ #include -#include #include "xenpaging.h" struct page_in_args { diff --git a/tools/xenpaging/xenpaging.c b/tools/xenpaging/xenpaging.c index a819a5b..8a05e98 100644 --- a/tools/xenpaging/xenpaging.c +++ b/tools/xenpaging/xenpaging.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff --git a/tools/xenpaging/xenpaging.h b/tools/xenpaging/xenpaging.h index 6c12030..3cdd1a8 100644 --- a/tools/xenpaging/xenpaging.h +++ b/tools/xenpaging/xenpaging.h @@ -26,6 +26,8 @@ #include +#define XC_WANT_COMPAT_MAP_FOREIGN_API +#include #include #include #include diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index 7f1e489..120fd64 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -51,7 +51,6 @@ #include "xenstored_watch.h" #include "xenstored_transaction.h" #include "xenstored_domain.h" -#include "xenctrl.h" #include "tdb.h" #include "hashtable.h" diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h index 2b01076..e0fa843 100644 --- a/tools/xenstore/xenstored_core.h +++ b/tools/xenstore/xenstored_core.h @@ -20,6 +20,7 @@ #ifndef _XENSTORED_CORE_H #define _XENSTORED_CORE_H +#define XC_WANT_COMPAT_MAP_FOREIGN_API #include #include diff --git a/tools/xentrace/xenctx.c b/tools/xentrace/xenctx.c index 4ed120a..e647179 100644 --- a/tools/xentrace/xenctx.c +++ b/tools/xentrace/xenctx.c @@ -25,7 +25,8 @@ #include #include -#include "xenctrl.h" +#define XC_WANT_COMPAT_MAP_FOREIGN_API +#include #include #include #include diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c index f66a77c..28c2b3c 100644 --- a/tools/xentrace/xentrace.c +++ b/tools/xentrace/xentrace.c @@ -30,6 +30,7 @@ #include #include +#define XC_WANT_COMPAT_MAP_FOREIGN_API #include #include -- 2.1.4