diff --git a/stubdom/Makefile b/stubdom/Makefile
index f858210..39b81c9 100644
--- a/stubdom/Makefile
+++ b/stubdom/Makefile
@@ -337,13 +337,16 @@ libs-$(XEN_TARGET_ARCH)/call/stamp: $(XEN_ROOT)/tools/libs/call/Makefile
 libs-$(XEN_TARGET_ARCH)/foreignmemory/stamp: $(XEN_ROOT)/tools/libs/foreignmemory/Makefile
 	$(do_links)
 
+libs-$(XEN_TARGET_ARCH)/devicemodel/stamp: $(XEN_ROOT)/tools/libs/devicemodel/Makefile
+	$(do_links)
+
 libxc-$(XEN_TARGET_ARCH)/stamp: $(XEN_ROOT)/tools/libxc/Makefile
 	$(do_links)
 
 xenstore/stamp: $(XEN_ROOT)/tools/xenstore/Makefile
 	$(do_links)
 
-LINK_LIBS_DIRS := toollog evtchn gnttab call foreignmemory
+LINK_LIBS_DIRS := toollog evtchn gnttab call foreignmemory devicemodel
 LINK_DIRS := libxc-$(XEN_TARGET_ARCH) xenstore $(foreach dir,$(LINK_LIBS_DIRS),libs-$(XEN_TARGET_ARCH)/$(dir))
 LINK_STAMPS := $(foreach dir,$(LINK_DIRS),$(dir)/stamp)
 
@@ -414,12 +417,21 @@ libs-$(XEN_TARGET_ARCH)/foreignmemory/libxenforeignmemory.a: mk-headers-$(XEN_TA
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libs-$(XEN_TARGET_ARCH)/foreignmemory
 
 #######
+# libxendevicemodel
+#######
+
+.PHONY: libxendevicemodel
+libxendevicemodel: libs-$(XEN_TARGET_ARCH)/devicemodel/libxendevicemodel.a
+libs-$(XEN_TARGET_ARCH)/devicemodel/libxendevicemodel.a: mk-headers-$(XEN_TARGET_ARCH) $(NEWLIB_STAMPFILE)
+	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libs-$(XEN_TARGET_ARCH)/devicemodel
+
+#######
 # libxc
 #######
 
 .PHONY: libxc
 libxc: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a libxc-$(XEN_TARGET_ARCH)/libxenguest.a
-libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: mk-headers-$(XEN_TARGET_ARCH) libxentoollog libxenevtchn libxengnttab libxencall libxenforeignmemory cross-zlib
+libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: mk-headers-$(XEN_TARGET_ARCH) libxentoollog libxenevtchn libxengnttab libxencall libxenforeignmemory libxendevicemodel cross-zlib
 	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= CONFIG_LIBXC_MINIOS=y -C libxc-$(XEN_TARGET_ARCH)
 
  libxc-$(XEN_TARGET_ARCH)/libxenguest.a: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a
@@ -616,6 +628,7 @@ clean:
 	[ ! -e libs-$(XEN_TARGET_ARCH)/gnttab/Makefile ] || $(MAKE) DESTDIR= -C libs-$(XEN_TARGET_ARCH)/gnttab clean
 	[ ! -e libs-$(XEN_TARGET_ARCH)/call/Makefile ] || $(MAKE) DESTDIR= -C libs-$(XEN_TARGET_ARCH)/call clean
 	[ ! -e libs-$(XEN_TARGET_ARCH)/foreignmemory/Makefile ] || $(MAKE) DESTDIR= -C libs-$(XEN_TARGET_ARCH)/foreignmemory clean
+	[ ! -e libs-$(XEN_TARGET_ARCH)/devicemodel/Makefile ] || $(MAKE) DESTDIR= -C libs-$(XEN_TARGET_ARCH)/devicemodel clean
 	[ ! -e libxc-$(XEN_TARGET_ARCH)/Makefile ] || $(MAKE) DESTDIR= -C libxc-$(XEN_TARGET_ARCH) clean
 	-[ ! -d ioemu ] || $(MAKE) DESTDIR= -C ioemu clean
 	-[ ! -d xenstore ] || $(MAKE) DESTDIR= -C xenstore clean
diff --git a/tools/Makefile b/tools/Makefile
index 77e0723..0890cc9 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -281,6 +281,7 @@ subdir-all-qemu-xen-dir: qemu-xen-dir-find
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libs/gnttab \
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libs/call \
 		-Wl,-rpath-link=$(XEN_ROOT)/tools/libs/foreignmemory \
+		-Wl,-rpath-link=$(XEN_ROOT)/tools/libs/devicemodel \
 		$(QEMU_UPSTREAM_RPATH)" \
 		--bindir=$(LIBEXEC_BIN) \
 		--datadir=$(SHAREDIR)/qemu-xen \
diff --git a/tools/Rules.mk b/tools/Rules.mk
index b35999b..e3415f0 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -15,6 +15,7 @@ XEN_LIBXENEVTCHN   = $(XEN_ROOT)/tools/libs/evtchn
 XEN_LIBXENGNTTAB   = $(XEN_ROOT)/tools/libs/gnttab
 XEN_LIBXENCALL     = $(XEN_ROOT)/tools/libs/call
 XEN_LIBXENFOREIGNMEMORY = $(XEN_ROOT)/tools/libs/foreignmemory
+XEN_LIBXENDEVICEMODEL = $(XEN_ROOT)/tools/libs/devicemodel
 XEN_LIBXC          = $(XEN_ROOT)/tools/libxc
 XEN_XENLIGHT       = $(XEN_ROOT)/tools/libxl
 XEN_XENSTORE       = $(XEN_ROOT)/tools/xenstore
@@ -117,10 +118,15 @@ CFLAGS_libxenforeignmemory = -I$(XEN_LIBXENFOREIGNMEMORY)/include $(CFLAGS_xenin
 LDLIBS_libxenforeignmemory = $(XEN_LIBXENFOREIGNMEMORY)/libxenforeignmemory$(libextension)
 SHLIB_libxenforeignmemory  = -Wl,-rpath-link=$(XEN_LIBXENFOREIGNMEMORY)
 
+CFLAGS_libxendevicemodel = -I$(XEN_LIBXENDEVICEMODEL)/include $(CFLAGS_xeninclude)
+SHDEPS_libxendevicemodel = $(SHLIB_libxentoollog)
+LDLIBS_libxendevicemodel = $(XEN_LIBXENDEVICEMODEL)/libxendevicemodel$(libextension)
+SHLIB_libxendevicemodel  = -Wl,-rpath-link=$(XEN_LIBXENDEVICEMODEL)
+
 # code which compiles against libxenctrl get __XEN_TOOLS__ and
 # therefore sees the unstable hypercall interfaces.
-CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) $(CFLAGS_libxenforeignmemory) $(CFLAGS_xeninclude) -D__XEN_TOOLS__
-SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn) $(SHLIB_libxengnttab) $(SHLIB_libxengntshr) $(SHLIB_libxencall) $(SHLIB_libxenforeignmemory)
+CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) $(CFLAGS_libxenforeignmemory) $(CFLAGS_libxendevicemodel) $(CFLAGS_xeninclude) -D__XEN_TOOLS__
+SHDEPS_libxenctrl = $(SHLIB_libxentoollog) $(SHLIB_libxenevtchn) $(SHLIB_libxengnttab) $(SHLIB_libxengntshr) $(SHLIB_libxencall) $(SHLIB_libxenforeignmemory) $(SHLIB_libxendevicemodel)
 LDLIBS_libxenctrl = $(SHDEPS_libxenctrl) $(XEN_LIBXC)/libxenctrl$(libextension)
 SHLIB_libxenctrl  = $(SHDEPS_libxenctrl) -Wl,-rpath-link=$(XEN_LIBXC)
 
diff --git a/tools/libs/Makefile b/tools/libs/Makefile
index dc5726d..deae4ae 100644
--- a/tools/libs/Makefile
+++ b/tools/libs/Makefile
@@ -7,5 +7,6 @@ SUBDIRS-y += evtchn
 SUBDIRS-y += gnttab
 SUBDIRS-y += call
 SUBDIRS-y += foreignmemory
+SUBDIRS-y += devicemodel
 
 all clean install distclean: %: subdirs-%
diff --git a/tools/libs/devicemodel/Makefile b/tools/libs/devicemodel/Makefile
new file mode 100644
index 0000000..4f1e616
--- /dev/null
+++ b/tools/libs/devicemodel/Makefile
@@ -0,0 +1,66 @@
+XEN_ROOT = $(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR    = 1
+MINOR    = 0
+SHLIB_LDFLAGS += -Wl,--version-script=libxendevicemodel.map
+
+CFLAGS   += -Werror -Wmissing-prototypes
+CFLAGS   += -I./include $(CFLAGS_xeninclude)
+CFLAGS   += $(CFLAGS_libxentoollog)
+
+SRCS-y   += core.c
+
+LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y))
+PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y))
+
+LIB := libxendevicemodel.a
+ifneq ($(nosharedlibs),y)
+LIB += libxendevicemodel.so
+endif
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build:
+	$(MAKE) libs
+
+.PHONY: libs
+libs: headers.chk $(LIB)
+
+headers.chk: $(wildcard include/*.h)
+
+libxendevicemodel.a: $(LIB_OBJS)
+	$(AR) rc $@ $^
+
+libxendevicemodel.so: libxendevicemodel.so.$(MAJOR)
+	$(SYMLINK_SHLIB) $< $@
+libxendevicemodel.so.$(MAJOR): libxendevicemodel.so.$(MAJOR).$(MINOR)
+	$(SYMLINK_SHLIB) $< $@
+
+libxendevicemodel.so.$(MAJOR).$(MINOR): $(PIC_OBJS) libxendevicemodel.map
+	$(CC) $(LDFLAGS) $(PTHREAD_LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxendevicemodel.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) libxendevicemodel.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)
+	$(INSTALL_DATA) libxendevicemodel.a $(DESTDIR)$(libdir)
+	$(SYMLINK_SHLIB) libxendevicemodel.so.$(MAJOR).$(MINOR) $(DESTDIR)$(libdir)/libxendevicemodel.so.$(MAJOR)
+	$(SYMLINK_SHLIB) libxendevicemodel.so.$(MAJOR) $(DESTDIR)$(libdir)/libxendevicemodel.so
+	$(INSTALL_DATA) include/xendevicemodel.h $(DESTDIR)$(includedir)
+
+.PHONY: TAGS
+TAGS:
+	etags -t *.c *.h
+
+.PHONY: clean
+clean:
+	rm -rf *.rpm $(LIB) *~ $(DEPS) $(LIB_OBJS) $(PIC_OBJS)
+	rm -f libxendevicemodel.so.$(MAJOR).$(MINOR) libxendevicemodel.so.$(MAJOR)
+	rm -f headers.chk
+
+.PHONY: distclean
+distclean: clean
diff --git a/tools/libs/devicemodel/core.c b/tools/libs/devicemodel/core.c
new file mode 100644
index 0000000..ec18142
--- /dev/null
+++ b/tools/libs/devicemodel/core.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 Citrix Systems Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#include "private.h"
+
+xendevicemodel_handle *xendevicemodel_open(xentoollog_logger *logger,
+                                           unsigned open_flags)
+{
+    xendevicemodel_handle *dmod = malloc(sizeof(*dmod));
+
+    if (!dmod)
+        return NULL;
+
+    dmod->flags = open_flags;
+    dmod->logger = logger;
+    dmod->logger_tofree = NULL;
+
+    if (!dmod->logger) {
+        dmod->logger = dmod->logger_tofree =
+            (xentoollog_logger*)
+            xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
+        if (!dmod->logger)
+            goto err;
+    }
+
+    return dmod;
+
+err:
+    xtl_logger_destroy(dmod->logger_tofree);
+    free(dmod);
+    return NULL;
+}
+
+int xendevicemodel_close(xendevicemodel_handle *dmod)
+{
+    if (!dmod)
+        return 0;
+
+    xtl_logger_destroy(dmod->logger_tofree);
+    free(dmod);
+    return 0;
+}
+
+/*
+ * 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/devicemodel/include/xendevicemodel.h b/tools/libs/devicemodel/include/xendevicemodel.h
new file mode 100644
index 0000000..f977b0e
--- /dev/null
+++ b/tools/libs/devicemodel/include/xendevicemodel.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017 Citrix Systems Inc.
+ *
+ * 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 XENDEVICEMODEL_H
+#define XENDEVICEMODEL_H
+
+/* Callers who don't care don't need to #include <xentoollog.h> */
+struct xentoollog_logger;
+
+typedef struct xendevicemodel_handle xendevicemodel_handle;
+
+xendevicemodel_handle *xendevicemodel_open(struct xentoollog_logger *logger,
+                                           unsigned int open_flags);
+
+int xendevicemodel_close(xendevicemodel_handle *dmod);
+
+#endif /* XENDEVICEMODEL_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/devicemodel/libxendevicemodel.map b/tools/libs/devicemodel/libxendevicemodel.map
new file mode 100644
index 0000000..980c429
--- /dev/null
+++ b/tools/libs/devicemodel/libxendevicemodel.map
@@ -0,0 +1,6 @@
+VERS_1.0 {
+	global:
+		xendevicemodel_open;
+		xendevicemodel_close;
+	local: *; /* Do not expose anything by default */
+};
diff --git a/tools/libs/devicemodel/private.h b/tools/libs/devicemodel/private.h
new file mode 100644
index 0000000..cf1e4b0
--- /dev/null
+++ b/tools/libs/devicemodel/private.h
@@ -0,0 +1,22 @@
+#ifndef XENDEVICEMODEL_PRIVATE_H
+#define XENDEVICEMODEL_PRIVATE_H
+
+#include <xentoollog.h>
+#include <xendevicemodel.h>
+
+struct xendevicemodel_handle {
+    xentoollog_logger *logger, *logger_tofree;
+    unsigned int flags;
+};
+
+#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/libxc/Makefile b/tools/libxc/Makefile
index 37235e3..af5e49c 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -113,6 +113,7 @@ CFLAGS-$(CONFIG_Linux) += -D_GNU_SOURCE
 CFLAGS	+= $(PTHREAD_CFLAGS)
 CFLAGS	+= $(CFLAGS_libxentoollog)
 CFLAGS	+= $(CFLAGS_libxenevtchn)
+CFLAGS	+= $(CFLAGS_libxendevicemodel)
 
 CTRL_LIB_OBJS := $(patsubst %.c,%.o,$(CTRL_SRCS-y))
 CTRL_PIC_OBJS := $(patsubst %.c,%.opic,$(CTRL_SRCS-y))
@@ -217,7 +218,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) $(LDLIBS_libxenforeignmemory) $(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) $(LDLIBS_libxendevicemodel) $(PTHREAD_LIBS) $(APPEND_LDFLAGS)
 
 # libxenguest
 
diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c
index f0e089c..32379b6 100644
--- a/tools/libxc/xc_private.c
+++ b/tools/libxc/xc_private.c
@@ -65,12 +65,18 @@ struct xc_interface_core *xc_interface_open(xentoollog_logger *logger,
 
     xch->fmem = xenforeignmemory_open(xch->error_handler, 0);
 
-    if ( xch->xcall == NULL )
+    if ( xch->fmem == NULL )
+        goto err;
+
+    xch->dmod = xendevicemodel_open(xch->error_handler, 0);
+
+    if ( xch->dmod == NULL )
         goto err;
 
     return xch;
 
  err:
+    xenforeignmemory_close(xch->fmem);
     xencall_close(xch->xcall);
     xtl_logger_destroy(xch->error_handler_tofree);
     if (xch != &xch_buf) free(xch);
@@ -90,6 +96,9 @@ int xc_interface_close(xc_interface *xch)
     rc = xenforeignmemory_close(xch->fmem);
     if (rc) PERROR("Could not close foreign memory interface");
 
+    rc = xendevicemodel_close(xch->dmod);
+    if (rc) PERROR("Could not close device model 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 d0ff4b5..1c27b0f 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -36,6 +36,7 @@
 
 #include <xencall.h>
 #include <xenforeignmemory.h>
+#include <xendevicemodel.h>
 
 #include <xen/sys/privcmd.h>
 
@@ -97,6 +98,9 @@ struct xc_interface_core {
 
     /* Foreign mappings */
     xenforeignmemory_handle *fmem;
+
+    /* Device model */
+    xendevicemodel_handle *dmod;
 };
 
 int osdep_privcmd_open(xc_interface *xch);
