diff --git a/.gitignore b/.gitignore
index cc16649..2c9f905 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,6 +73,7 @@ stubdom/libxencall-*
 stubdom/libxenevtchn-*
 stubdom/libxenforeignmemory-*
 stubdom/libxengnttab-*
+stubdom/libxentoolcore-*
 stubdom/libxentoollog-*
 stubdom/lwip-*
 stubdom/lwip/
@@ -98,6 +99,8 @@ tools/config.cache
 config/Tools.mk
 config/Stubdom.mk
 config/Docs.mk
+tools/libs/toolcore/headers.chk
+tools/libs/toolcore/xentoolcore.pc
 tools/libs/toollog/headers.chk
 tools/libs/toollog/xentoollog.pc
 tools/libs/evtchn/headers.chk
@@ -352,6 +355,7 @@ tools/include/xen-foreign/arm64.h
 .git
 tools/misc/xen-hptool
 tools/misc/xen-mfndump
+tools/libs/toolcore/include/_*.h
 tools/libxc/_*.[ch]
 tools/libxl/_*.[ch]
 tools/libxl/testidl
diff --git a/tools/Rules.mk b/tools/Rules.mk
index dbc7635..5e1c7cb 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -10,6 +10,7 @@ export _INSTALL := $(INSTALL)
 INSTALL = $(XEN_ROOT)/tools/cross-install
 
 XEN_INCLUDE        = $(XEN_ROOT)/tools/include
+XEN_LIBXENTOOLCORE  = $(XEN_ROOT)/tools/libs/toolcore
 XEN_LIBXENTOOLLOG  = $(XEN_ROOT)/tools/libs/toollog
 XEN_LIBXENEVTCHN   = $(XEN_ROOT)/tools/libs/evtchn
 XEN_LIBXENGNTTAB   = $(XEN_ROOT)/tools/libs/gnttab
@@ -102,6 +103,11 @@ SHDEPS_libxentoollog =
 LDLIBS_libxentoollog = $(SHDEPS_libxentoollog) $(XEN_LIBXENTOOLLOG)/libxentoollog$(libextension)
 SHLIB_libxentoollog  = $(SHDEPS_libxentoollog) -Wl,-rpath-link=$(XEN_LIBXENTOOLLOG)
 
+CFLAGS_libxentoolcore = -I$(XEN_LIBXENTOOLCORE)/include $(CFLAGS_xeninclude)
+SHDEPS_libxentoolcore =
+LDLIBS_libxentoolcore = $(SHDEPS_libxentoolcore) $(XEN_LIBXENTOOLCORE)/libxentoolcore$(libextension)
+SHLIB_libxentoolcore  = $(SHDEPS_libxentoolcore) -Wl,-rpath-link=$(XEN_LIBXENTOOLCORE)
+
 CFLAGS_libxenevtchn = -I$(XEN_LIBXENEVTCHN)/include $(CFLAGS_xeninclude)
 SHDEPS_libxenevtchn =
 LDLIBS_libxenevtchn = $(SHDEPS_libxenevtchn) $(XEN_LIBXENEVTCHN)/libxenevtchn$(libextension)
diff --git a/tools/libs/Makefile b/tools/libs/Makefile
index 2035873..ea9a64d 100644
--- a/tools/libs/Makefile
+++ b/tools/libs/Makefile
@@ -2,6 +2,7 @@ XEN_ROOT = $(CURDIR)/../..
 include $(XEN_ROOT)/tools/Rules.mk
 
 SUBDIRS-y :=
+SUBDIRS-y += toolcore
 SUBDIRS-y += toollog
 SUBDIRS-y += evtchn
 SUBDIRS-y += gnttab
diff --git a/tools/libs/toolcore/Makefile b/tools/libs/toolcore/Makefile
new file mode 100644
index 0000000..f86f839
--- /dev/null
+++ b/tools/libs/toolcore/Makefile
@@ -0,0 +1,101 @@
+XEN_ROOT = $(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR	= 1
+MINOR	= 0
+SHLIB_LDFLAGS += -Wl,--version-script=libxentoolcore.map
+
+CFLAGS	+= -Werror -Wmissing-prototypes
+CFLAGS	+= -I./include
+
+SRCS-y	+= handlereg.c
+
+LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y))
+PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y))
+
+LIB := libxentoolcore.a
+ifneq ($(nosharedlibs),y)
+LIB += libxentoolcore.so
+endif
+
+PKG_CONFIG := xentoolcore.pc
+PKG_CONFIG_VERSION := $(MAJOR).$(MINOR)
+
+ifneq ($(CONFIG_LIBXC_MINIOS),y)
+PKG_CONFIG_INST := $(PKG_CONFIG)
+$(PKG_CONFIG_INST): PKG_CONFIG_PREFIX = $(prefix)
+$(PKG_CONFIG_INST): PKG_CONFIG_INCDIR = $(includedir)
+$(PKG_CONFIG_INST): PKG_CONFIG_LIBDIR = $(libdir)
+endif
+
+PKG_CONFIG_LOCAL := $(foreach pc,$(PKG_CONFIG),$(PKG_CONFIG_DIR)/$(pc))
+
+$(PKG_CONFIG_LOCAL): PKG_CONFIG_PREFIX = $(XEN_ROOT)
+$(PKG_CONFIG_LOCAL): PKG_CONFIG_INCDIR = $(XEN_LIBXENTOOLCORE)/include
+$(PKG_CONFIG_LOCAL): PKG_CONFIG_LIBDIR = $(CURDIR)
+
+AUTOINCS=include/_xentoolcore_list.h
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build:
+	$(MAKE) libs
+
+.PHONY: libs
+libs: headers.chk $(LIB) $(PKG_CONFIG_INST) $(PKG_CONFIG_LOCAL)
+
+%.o: $(AUTOINCS)
+%.opic: $(AUTOINCS)
+
+headers.chk: $(wildcard include/*.h) $(AUTOINCS)
+
+include/_xentoolcore_list.h: $(XEN_INCLUDE)/xen-external/bsd-sys-queue-h-seddery $(XEN_INCLUDE)/xen-external/bsd-sys-queue.h
+	$(PERL) $^ --prefix=xentoolcore >$@.new
+	$(call move-if-changed,$@.new,$@)
+
+libxentoolcore.a: $(LIB_OBJS)
+	$(AR) rc $@ $^
+
+libxentoolcore.so: libxentoolcore.so.$(MAJOR)
+	$(SYMLINK_SHLIB) $< $@
+libxentoolcore.so.$(MAJOR): libxentoolcore.so.$(MAJOR).$(MINOR)
+	$(SYMLINK_SHLIB) $< $@
+
+libxentoolcore.so.$(MAJOR).$(MINOR): $(PIC_OBJS) libxentoolcore.map
+	$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxentoolcore.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $(PIC_OBJS) $(APPEND_LDFLAGS)
+
+.PHONY: install
+install: build
+	$(INSTALL_DIR) $(DESTDIR)$(libdir)
+	$(INSTALL_DIR) $(DESTDIR)$(includedir)
+	$(INSTALL_SHLIB) libxentoolcore.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
+	$(INSTALL_DATA) libxentoolcore.a $(DESTDIR)$(libdir)
+	$(SYMLINK_SHLIB) libxentoolcore.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxentoolcore.so.$(MAJOR)
+	$(SYMLINK_SHLIB) libxentoolcore.so.$(MAJOR) $(DESTDIR)$(libdir)/libxentoolcore.so
+	$(INSTALL_DATA) include/xentoolcore.h $(DESTDIR)$(includedir)
+	$(INSTALL_DATA) xentoolcore.pc $(DESTDIR)$(PKG_INSTALLDIR)
+
+.PHONY: uinstall
+uninstall:
+	rm -f $(DESTDIR)$(PKG_INSTALLDIR)/xentoolcore.pc
+	rm -f $(DESTDIR)$(includedir)/xentoolcore.h
+	rm -f $(DESTDIR)$(libdir)/libxentoolcore.so
+	rm -f $(DESTDIR)$(libdir)/libxentoolcore.so.$(MAJOR)
+	rm -f $(DESTDIR)$(libdir)/libxentoolcore.so.$(MAJOR).$(MINOR)
+	rm -f $(DESTDIR)$(libdir)/libxentoolcore.a
+
+.PHONY: TAGS
+TAGS:
+	etags -t *.c *.h
+
+.PHONY: clean
+clean:
+	rm -rf *.rpm $(LIB) *~ $(DEPS_RM) $(LIB_OBJS) $(PIC_OBJS)
+	rm -f libxentoolcore.so.$(MAJOR).$(MINOR) libxentoolcore.so.$(MAJOR)
+	rm -f headers.chk
+	rm -f xentoolcore.pc
+
+.PHONY: distclean
+distclean: clean
diff --git a/tools/libs/toolcore/handlereg.c b/tools/libs/toolcore/handlereg.c
new file mode 100644
index 0000000..efeffb1
--- /dev/null
+++ b/tools/libs/toolcore/handlereg.c
@@ -0,0 +1,77 @@
+/*
+ * handlreg.c
+ *
+ * implementation of xentoolcore_restrict_all
+ *
+ * Copyright (c) 2017 Citrix
+ * Part of a generic logging interface used by various dom0 userland libraries.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "xentoolcore_internal.h"
+
+#include <pthread.h>
+#include <assert.h>
+
+static pthread_mutex_t handles_lock = PTHREAD_MUTEX_INITIALIZER;
+static XENTOOLCORE_LIST_HEAD(, Xentoolcore__Active_Handle) handles;
+
+static void lock(void) {
+    int e = pthread_mutex_unlock(&handles_lock);
+    assert(!e);
+}
+
+static void unlock(void) {
+    int e = pthread_mutex_unlock(&handles_lock);
+    assert(!e);
+}
+
+void xentoolcore__register_active_handle(Xentoolcore__Active_Handle *ah) {
+    lock();
+    XENTOOLCORE_LIST_INSERT_HEAD(&handles, ah, entry);
+    unlock();
+}
+
+void xentoolcore__deregister_active_handle(Xentoolcore__Active_Handle *ah) {
+    lock();
+    XENTOOLCORE_LIST_REMOVE(ah, entry);
+    unlock();
+}
+
+int xentoolcore_restrict_all(uint32_t domid) {
+    int r;
+    Xentoolcore__Active_Handle *ah;
+
+    lock();
+    XENTOOLCORE_LIST_FOREACH(ah, &handles, entry) {
+        r = ah->restrict_callback(ah, domid);
+        if (r) goto out;
+    }
+
+    r = 0;
+ out:
+    unlock();
+    return r;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/toolcore/include/xentoolcore.h b/tools/libs/toolcore/include/xentoolcore.h
new file mode 100644
index 0000000..32e2af1
--- /dev/null
+++ b/tools/libs/toolcore/include/xentoolcore.h
@@ -0,0 +1,73 @@
+/*
+ * xentoolcore.h
+ *
+ * Copyright (c) 2017 Citrix
+ * 
+ * Common features used/provided by all Xen tools libraries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef XENTOOLCORE_H
+#define XENTOOLCORE_H
+
+#include <stdint.h>
+
+/*
+ * int xentoolcore_restrict_all(uint32_t domid);
+ *
+ * Arranges that Xen library handles (fds etc.) which are currently held
+ * by Xen libraries, can no longer be used other than to affect domid.
+ *
+ * If this cannot be achieved, returns -1 and sets errno.
+ * If called again with the same domid, it may succeed, or it may
+ * fail (even though such a call is potentially meaningful).
+ * (If called again with a different domid, it will necessarily fail.)
+ *
+ *  ====================================================================
+ *  IMPORTANT - IMPLEMENTATION STATUS
+ *
+ *  This function will be implemented insofar as it appears necessary
+ *  for the purposes of running a deprivileged qemu.
+ *
+ *  However, this function is NOT implemented for all Xen libraries.
+ *  For each use case of this function, the designer must evaluate and
+ *  audit whether the implementation is sufficient in their specific
+ *  context.
+ *
+ *  Of course, patches to extend the implementation are very welcome.
+ *  ====================================================================
+ *
+ * Thread safe.
+ *
+ * We expect that no callers do the following:
+ *   - in one thread call xen_somelibrary_open|close
+ *   - in another thread call fork
+ *   - in the child of the fork, before exec, call
+ *     xen_some[other]library_open|close or xentoolcore_restrict_all
+ *
+ */
+int xentoolcore_restrict_all(uint32_t domid);
+
+#endif /* XENTOOLCORE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/toolcore/include/xentoolcore_internal.h b/tools/libs/toolcore/include/xentoolcore_internal.h
new file mode 100644
index 0000000..670e29d
--- /dev/null
+++ b/tools/libs/toolcore/include/xentoolcore_internal.h
@@ -0,0 +1,102 @@
+/*
+ * xentoolcore_internal.h
+ *
+ * Interfaces of xentoolcore directed internally at other Xen libraries
+ *
+ * Copyright (c) 2017 Citrix
+ * 
+ * Common code used by all Xen tools libraries
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef XENTOOLCORE_INTERNAL_H
+#define XENTOOLCORE_INTERNAL_H
+
+#include "xentoolcore.h"
+#include "_xentoolcore_list.h"
+
+/*---------- active handle registration ----------*/
+
+/*
+ * This is all to support xentoolcore_restrict_all
+ *
+ * Any libxl library that opens a Xen control handle of any kind which
+ * might allow manipulation of dom0, of other domains, or of the whole
+ * machine, must:
+ *   I. arrange that their own datastructure contains a
+ *          Xentoolcore__Active_Handle
+ * 
+ *   II. during the "open handle" function
+ *     1. allocate the memory for the own datastructure and initialise it
+ *     2. set Xentoolcore__Active_Handle.restrict_callback
+ *     3. call xentoolcore__register_active_handle
+ *       3a. if the open fails, call xentoolcore__deregister_active_handle
+ *     4. ONLY THEN actually open the relevant fd or whatever
+ *
+ *   III. during the "close handle" function
+ *     1. FIRST close the relevant fd or whatever
+ *     2. call xentoolcore__deregister_active_handle
+ *
+ *   IV. in the restrict_callback function
+ *     * Arrange that the fd (or other handle) can no longer by used
+ *       other than with respect to domain domid.
+ *     * Future attempts to manipulate other domains (or the whole
+ *       host) via this handle must cause an error return (and
+ *       perhaps a log message), not a crash
+ *     * If selective restriction is not possible, the handle must
+ *       be completely invalidated so that it is not useable;
+ *       subsequent manipulations may not crash
+ *     * The restrict_callback function should not normally fail
+ *       if this can be easily avoided - it is better to make the
+ *       handle nonfunction instead.
+ *     * NB that restrict_callback might be called again.  That must
+ *       work properly: if the domid is the same, it is idempotent.
+ *       If the domid is different. then either the handle must be
+ *       completely invalidated, or restrict_callback must fail.)
+ *
+ * Thread safety:
+ *    xentoolcore__[de]register_active_handle are threadsafe
+ *      but MUST NOT be called within restrict_callback
+ *
+ * Fork safety:
+ *    Libraries which use these functions do not on that account
+ *    need to take any special care over forks occurring in
+ *    other threads, provided that they obey the rules above.
+ */
+
+typedef struct Xentoolcore__Active_Handle Xentoolcore__Active_Handle;
+
+typedef int Xentoolcore__Restrict_Callback(Xentoolcore__Active_Handle*,
+                                           uint32_t domid);
+
+struct Xentoolcore__Active_Handle {
+    Xentoolcore__Restrict_Callback *restrict_callback;
+    XENTOOLCORE_LIST_ENTRY(Xentoolcore__Active_Handle) entry;
+};
+
+void xentoolcore__register_active_handle(Xentoolcore__Active_Handle*);
+void xentoolcore__deregister_active_handle(Xentoolcore__Active_Handle*);
+
+#endif /* XENTOOLCORE_INTERNAL_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/toolcore/libxentoolcore.map b/tools/libs/toolcore/libxentoolcore.map
new file mode 100644
index 0000000..eb5d251
--- /dev/null
+++ b/tools/libs/toolcore/libxentoolcore.map
@@ -0,0 +1,7 @@
+VERS_1.0 {
+	global:
+		xentoolcore_restrict_all;
+		xentoolcore__register_active_handle;
+		xentoolcore__deregister_active_handle;
+	local: *; /* Do not expose anything by default */
+};
diff --git a/tools/libs/toolcore/xentoolcore.pc.in b/tools/libs/toolcore/xentoolcore.pc.in
new file mode 100644
index 0000000..55ff4e2
--- /dev/null
+++ b/tools/libs/toolcore/xentoolcore.pc.in
@@ -0,0 +1,9 @@
+prefix=@@prefix@@
+includedir=@@incdir@@
+libdir=@@libdir@@
+
+Name: Xentoolcore
+Description: Central support for Xen Hypervisor userland libraries
+Version: @@version@@
+Cflags: -I${includedir}
+Libs: @@libsflag@@${libdir} -lxentoolcore
