diff --git a/hw/xc_dom.h b/hw/xc_dom.h
new file mode 100644
index 0000000..c835a37
--- /dev/null
+++ b/hw/xc_dom.h
@@ -0,0 +1,273 @@
+#include <libelf.h>
+
+#define INVALID_P2M_ENTRY   ((xen_pfn_t)-1)
+
+/* --- typedefs and structs ---------------------------------------- */
+
+typedef uint64_t xen_vaddr_t;
+typedef uint64_t xen_paddr_t;
+
+#define PRIpfn PRI_xen_pfn
+
+struct xc_dom_seg {
+    xen_vaddr_t vstart;
+    xen_vaddr_t vend;
+    xen_pfn_t pfn;
+};
+
+struct xc_dom_mem {
+    struct xc_dom_mem *next;
+    void *mmap_ptr;
+    size_t mmap_len;
+    unsigned char memory[0];
+};
+
+struct xc_dom_phys {
+    struct xc_dom_phys *next;
+    void *ptr;
+    xen_pfn_t first;
+    xen_pfn_t count;
+};
+
+struct xc_dom_image {
+    /* files */
+    void *kernel_blob;
+    size_t kernel_size;
+    void *ramdisk_blob;
+    size_t ramdisk_size;
+
+    /* arguments and parameters */
+    char *cmdline;
+    uint32_t f_requested[XENFEAT_NR_SUBMAPS];
+
+    /* info from (elf) kernel image */
+    struct {
+        uint64_t virt_base;
+    } parms;
+
+    char *guest_type;
+
+    /* memory layout */
+    struct xc_dom_seg kernel_seg;
+    struct xc_dom_seg ramdisk_seg;
+    struct xc_dom_seg p2m_seg;
+    struct xc_dom_seg pgtables_seg;
+    struct xc_dom_seg devicetree_seg;
+    xen_pfn_t start_info_pfn;
+    xen_pfn_t console_pfn;
+    xen_pfn_t xenstore_pfn;
+    xen_pfn_t shared_info_pfn;
+    xen_pfn_t bootstack_pfn;
+    xen_vaddr_t virt_alloc_end;
+    xen_vaddr_t bsd_symtab_start;
+
+    /* initial page tables */
+    unsigned int pgtables;
+    unsigned int pg_l4;
+    unsigned int pg_l3;
+    unsigned int pg_l2;
+    unsigned int pg_l1;
+    unsigned int alloc_bootstack;
+    unsigned int extra_pages;
+    xen_vaddr_t virt_pgtab_end;
+
+    /* other state info */
+    uint32_t f_active[XENFEAT_NR_SUBMAPS];
+    xen_pfn_t *p2m_host;
+    void *p2m_guest;
+
+    /* physical memory */
+    xen_pfn_t total_pages;
+    struct xc_dom_phys *phys_pages;
+    int realmodearea_log;
+
+    /* malloc memory pool */
+    struct xc_dom_mem *memblocks;
+
+    /* memory footprint stats */
+    size_t alloc_malloc;
+    size_t alloc_mem_map;
+    size_t alloc_file_map;
+    size_t alloc_domU_map;
+
+    /* misc xen domain config stuff */
+    unsigned long flags;
+    unsigned int console_evtchn;
+    unsigned int xenstore_evtchn;
+    xen_pfn_t shared_info_mfn;
+
+    int guest_xc;
+    domid_t guest_domid;
+    int shadow_enabled;
+
+    int xen_version;
+    xen_capabilities_info_t xen_caps;
+
+    /* kernel loader, arch hooks */
+    struct xc_dom_loader *kernel_loader;
+    void *private_loader;
+
+    /* kernel loader */
+    struct xc_dom_arch *arch_hooks;
+};
+
+/* --- pluggable kernel loader ------------------------------------- */
+
+struct xc_dom_loader {
+    char *name;
+    int (*probe) (struct xc_dom_image * dom);
+    int (*parser) (struct xc_dom_image * dom);
+    int (*loader) (struct xc_dom_image * dom);
+
+    struct xc_dom_loader *next;
+};
+
+#define __init __attribute__ ((constructor))
+void xc_dom_register_loader(struct xc_dom_loader *loader);
+
+/* --- arch specific hooks ----------------------------------------- */
+
+struct xc_dom_arch {
+    /* pagetable setup */
+    int (*alloc_magic_pages) (struct xc_dom_image * dom);
+    int (*count_pgtables) (struct xc_dom_image * dom);
+    int (*setup_pgtables) (struct xc_dom_image * dom);
+
+    /* arch-specific data structs setup */
+    int (*start_info) (struct xc_dom_image * dom);
+    int (*shared_info) (struct xc_dom_image * dom, void *shared_info);
+    int (*vcpu) (struct xc_dom_image * dom, void *vcpu_ctxt);
+
+    char *guest_type;
+    int page_shift;
+    int sizeof_pfn;
+
+    struct xc_dom_arch *next;
+};
+void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks);
+
+#define XC_DOM_PAGE_SHIFT(dom)  ((dom)->arch_hooks->page_shift)
+#define XC_DOM_PAGE_SIZE(dom)   (1 << (dom)->arch_hooks->page_shift)
+
+/* --- main functions ---------------------------------------------- */
+
+struct xc_dom_image *xc_dom_allocate(const char *cmdline, const char *features);
+void xc_dom_release_phys(struct xc_dom_image *dom);
+void xc_dom_release(struct xc_dom_image *dom);
+int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb);
+
+size_t xc_dom_check_gzip(void *blob, size_t ziplen);
+int xc_dom_do_gunzip(void *src, size_t srclen, void *dst, size_t dstlen);
+int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size);
+
+int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename);
+int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename);
+int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem,
+                      size_t memsize);
+int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem,
+                       size_t memsize);
+
+int xc_dom_parse_image(struct xc_dom_image *dom);
+int xc_dom_build_image(struct xc_dom_image *dom);
+int xc_dom_update_guest_p2m(struct xc_dom_image *dom);
+
+int xc_dom_boot_xen_init(struct xc_dom_image *dom, int xc, domid_t domid);
+int xc_dom_boot_mem_init(struct xc_dom_image *dom);
+void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn,
+                           xen_pfn_t count);
+int xc_dom_boot_image(struct xc_dom_image *dom);
+int xc_dom_compat_check(struct xc_dom_image *dom);
+
+/* --- debugging bits ---------------------------------------------- */
+
+extern FILE *xc_dom_logfile;
+
+void xc_dom_loginit(void);
+int xc_dom_printf(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+int xc_dom_panic_func(const char *file, int line, xc_error_code err,
+                      const char *fmt, ...)
+    __attribute__ ((format(printf, 4, 5)));
+#define xc_dom_panic(err, fmt, args...) \
+    xc_dom_panic_func(__FILE__, __LINE__, err, fmt, ## args)
+#define xc_dom_trace(mark) \
+    xc_dom_printf("%s:%d: trace %s\n", __FILE__, __LINE__, mark)
+
+void xc_dom_log_memory_footprint(struct xc_dom_image *dom);
+
+/* --- simple memory pool ------------------------------------------ */
+
+void *xc_dom_malloc(struct xc_dom_image *dom, size_t size);
+void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size);
+void *xc_dom_malloc_filemap(struct xc_dom_image *dom,
+                            const char *filename, size_t * size);
+char *xc_dom_strdup(struct xc_dom_image *dom, const char *str);
+
+/* --- alloc memory pool ------------------------------------------- */
+
+int xc_dom_alloc_page(struct xc_dom_image *dom, char *name);
+int xc_dom_alloc_segment(struct xc_dom_image *dom,
+                         struct xc_dom_seg *seg, char *name,
+                         xen_vaddr_t start, xen_vaddr_t size);
+
+/* --- misc bits --------------------------------------------------- */
+
+void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first,
+                        xen_pfn_t count);
+void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn);
+void xc_dom_unmap_all(struct xc_dom_image *dom);
+
+static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom,
+                                      struct xc_dom_seg *seg)
+{
+    xen_vaddr_t segsize = seg->vend - seg->vstart;
+    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+    xen_pfn_t pages = (segsize + page_size - 1) / page_size;
+
+    return xc_dom_pfn_to_ptr(dom, seg->pfn, pages);
+}
+
+static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom,
+                                        xen_vaddr_t vaddr)
+{
+    unsigned int page_size = XC_DOM_PAGE_SIZE(dom);
+    xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size;
+    unsigned int offset = (vaddr - dom->parms.virt_base) % page_size;
+    void *ptr = xc_dom_pfn_to_ptr(dom, page, 0);
+    return (ptr ? (ptr + offset) : NULL);
+}
+
+static inline int xc_dom_feature_translated(struct xc_dom_image *dom)
+{
+    return 0;
+}
+
+static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn)
+{
+    if (dom->shadow_enabled)
+        return pfn;
+    return dom->p2m_host[pfn];
+}
+
+static inline xen_pfn_t xc_dom_p2m_guest(struct xc_dom_image *dom,
+                                         xen_pfn_t pfn)
+{
+    if (xc_dom_feature_translated(dom))
+        return pfn;
+    return dom->p2m_host[pfn];
+}
+
+/* --- arch bits --------------------------------------------------- */
+
+int arch_setup_meminit(struct xc_dom_image *dom);
+int arch_setup_bootearly(struct xc_dom_image *dom);
+int arch_setup_bootlate(struct xc_dom_image *dom);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/hw/xen_interfaces.c b/hw/xen_interfaces.c
new file mode 100644
index 0000000..6dec9f9
--- /dev/null
+++ b/hw/xen_interfaces.c
@@ -0,0 +1,108 @@
+#include <xenctrl.h>
+#include <xs.h>
+
+#include "hw.h"
+#include "xen.h"
+#include "xen_interfaces.h"
+
+#ifdef CONFIG_XEN
+
+static int xc_evtchn_domid(int handle, int domid)
+{
+    return -1;
+}
+
+static struct XenEvtOps xc_evtchn_xen = {
+    .open               = xc_evtchn_open,
+    .domid              = xc_evtchn_domid,
+    .close              = xc_evtchn_close,
+    .fd                 = xc_evtchn_fd,
+    .notify             = xc_evtchn_notify,
+    .bind_unbound_port  = xc_evtchn_bind_unbound_port,
+    .bind_interdomain   = xc_evtchn_bind_interdomain,
+    .bind_virq          = xc_evtchn_bind_virq,
+    .unbind             = xc_evtchn_unbind,
+    .pending            = xc_evtchn_pending,
+    .unmask             = xc_evtchn_unmask,
+};
+
+static int xs_domid(struct xs_handle *h, int domid)
+{
+    return -1;
+}
+
+static struct XenStoreOps xs_xen = {
+    .daemon_open           = xs_daemon_open,
+    .domain_open           = xs_domain_open,
+    .daemon_open_readonly  = xs_daemon_open_readonly,
+    .domid                 = xs_domid,
+    .daemon_close          = xs_daemon_close,
+    .directory             = xs_directory,
+    .read                  = xs_read,
+    .write                 = xs_write,
+    .mkdir                 = xs_mkdir,
+    .rm                    = xs_rm,
+    .get_permissions       = xs_get_permissions,
+    .set_permissions       = xs_set_permissions,
+    .watch                 = xs_watch,
+    .fileno                = xs_fileno,
+    .read_watch            = xs_read_watch,
+    .unwatch               = xs_unwatch,
+    .transaction_start     = xs_transaction_start,
+    .transaction_end       = xs_transaction_end,
+    .introduce_domain      = xs_introduce_domain,
+    .resume_domain         = xs_resume_domain,
+    .release_domain        = xs_release_domain,
+    .get_domain_path       = xs_get_domain_path,
+    .is_domain_introduced  = xs_is_domain_introduced,
+};
+
+static struct XenGnttabOps xc_gnttab_xen = {
+    .open            = xc_gnttab_open,
+    .close           = xc_gnttab_close,
+    .map_grant_ref   = xc_gnttab_map_grant_ref,
+    .map_grant_refs  = xc_gnttab_map_grant_refs,
+    .munmap          = xc_gnttab_munmap,
+};
+
+struct XenIfOps xc_xen = {
+    .interface_open    = xc_interface_open,
+    .interface_close   = xc_interface_close,
+    .map_foreign_range = xc_map_foreign_range,
+    .map_foreign_batch = xc_map_foreign_batch,
+    .map_foreign_pages = xc_map_foreign_pages,
+};
+
+#endif
+
+struct XenEvtOps xc_evtchn;
+struct XenGnttabOps xc_gnttab;
+struct XenIfOps xc;
+struct XenStoreOps xs;
+
+void xen_interfaces_init(void)
+{
+    switch (xen_mode) {
+#ifdef CONFIG_XEN
+    case XEN_ATTACH:
+    case XEN_CREATE:
+        xc_evtchn = xc_evtchn_xen;
+        xc_gnttab = xc_gnttab_xen;
+        xc        = xc_xen;
+        xs        = xs_xen;
+        break;
+#endif
+#ifdef CONFIG_XENNER
+    case XEN_EMULATE:
+        xc_evtchn = xc_evtchn_xenner;
+        xc_gnttab = xc_gnttab_xenner;
+        xc        = xc_xenner;
+        xs        = xs_xenner;
+        break;
+#endif
+    default:
+        fprintf(stderr, "ERROR: Compiled without %s support, sorry.\n",
+                xen_mode == XEN_EMULATE ? "xenner" : "Xen");
+        exit(1);
+    }
+}
diff --git a/hw/xen_interfaces.h b/hw/xen_interfaces.h
new file mode 100644
index 0000000..95592e6
--- /dev/null
+++ b/hw/xen_interfaces.h
@@ -0,0 +1,111 @@
+#ifndef QEMU_HW_XEN_INTERFACES_H
+#define QEMU_HW_XEN_INTERFACES_H 1
+
+#include <xenctrl.h>
+#include <xs.h>
+
+/* ------------------------------------------------------------- */
+/* xen event channel interface                                   */
+
+struct XenEvtOps {
+    int (*open)(void);
+    int (*domid)(int xce_handle, int domid);
+    int (*close)(int xce_handle);
+    int (*fd)(int xce_handle);
+    int (*notify)(int xce_handle, evtchn_port_t port);
+    evtchn_port_or_error_t (*bind_unbound_port)(int xce_handle, int domid);
+    evtchn_port_or_error_t (*bind_interdomain)(int xce_handle, int domid,
+					       evtchn_port_t remote_port);
+    evtchn_port_or_error_t (*bind_virq)(int xce_handle, unsigned int virq);
+    int (*unbind)(int xce_handle, evtchn_port_t port);
+    evtchn_port_or_error_t (*pending)(int xce_handle);
+    int (*unmask)(int xce_handle, evtchn_port_t port);
+};
+extern struct XenEvtOps xc_evtchn;
+
+/* ------------------------------------------------------------- */
+/* xenstore interface                                            */
+
+struct xs_handle;
+struct XenStoreOps {
+    struct xs_handle *(*daemon_open)(void);
+    struct xs_handle *(*domain_open)(void);
+    struct xs_handle *(*daemon_open_readonly)(void);
+    int (*domid)(struct xs_handle *h, int domid);
+    void (*daemon_close)(struct xs_handle *);
+    char **(*directory)(struct xs_handle *h, xs_transaction_t t,
+			const char *path, unsigned int *num);
+    void *(*read)(struct xs_handle *h, xs_transaction_t t,
+		  const char *path, unsigned int *len);
+    bool (*write)(struct xs_handle *h, xs_transaction_t t,
+		  const char *path, const void *data, unsigned int len);
+    bool (*mkdir)(struct xs_handle *h, xs_transaction_t t,
+		  const char *path);
+    bool (*rm)(struct xs_handle *h, xs_transaction_t t,
+	       const char *path);
+    struct xs_permissions *(*get_permissions)(struct xs_handle *h,
+					      xs_transaction_t t,
+					      const char *path, unsigned int *num);
+    bool (*set_permissions)(struct xs_handle *h, xs_transaction_t t,
+			    const char *path, struct xs_permissions *perms,
+			    unsigned int num_perms);
+    bool (*watch)(struct xs_handle *h, const char *path, const char *token);
+    int (*fileno)(struct xs_handle *h);
+    char **(*read_watch)(struct xs_handle *h, unsigned int *num);
+    bool (*unwatch)(struct xs_handle *h, const char *path, const char *token);
+    xs_transaction_t (*transaction_start)(struct xs_handle *h);
+    bool (*transaction_end)(struct xs_handle *h, xs_transaction_t t,
+			    bool abort);
+    bool (*introduce_domain)(struct xs_handle *h,
+			     unsigned int domid,
+			     unsigned long mfn,
+			     unsigned int eventchn);
+    bool (*resume_domain)(struct xs_handle *h, unsigned int domid);
+    bool (*release_domain)(struct xs_handle *h, unsigned int domid);
+    char *(*get_domain_path)(struct xs_handle *h, unsigned int domid);
+    bool (*is_domain_introduced)(struct xs_handle *h, unsigned int domid);
+};
+extern struct XenStoreOps xs;
+
+/* ------------------------------------------------------------- */
+/* xen grant table interface                                     */
+
+struct XenGnttabOps {
+    int (*open)(void);
+    int (*close)(int xcg_handle);
+    void *(*map_grant_ref)(int xcg_handle, uint32_t domid,
+			  uint32_t ref, int prot);
+    void *(*map_grant_refs)(int xcg_handle, uint32_t count,
+			    uint32_t *domids, uint32_t *refs, int prot);
+    int (*munmap)(int xcg_handle, void *start_address, uint32_t count);
+};
+extern struct XenGnttabOps xc_gnttab;
+
+/* ------------------------------------------------------------- */
+/* xen hypercall interface                                       */
+
+struct XenIfOps {
+    int (*interface_open)(void);
+    int (*interface_close)(int xc_handle);
+    void *(*map_foreign_range)(int xc_handle, uint32_t dom,
+			       int size, int prot,
+			       unsigned long mfn);
+    void *(*map_foreign_batch)(int xc_handle, uint32_t dom, int prot,
+			       xen_pfn_t *arr, int num);
+    void *(*map_foreign_pages)(int xc_handle, uint32_t dom, int prot,
+			       const xen_pfn_t *arr, int num);
+};
+extern struct XenIfOps xc;
+
+/* ------------------------------------------------------------- */
+
+#ifdef CONFIG_XENNER
+extern struct XenEvtOps xc_evtchn_xenner;
+extern struct XenGnttabOps xc_gnttab_xenner;
+extern struct XenIfOps xc_xenner;
+extern struct XenStoreOps xs_xenner;
+#endif
+
+void xen_interfaces_init(void);
+
+#endif /* QEMU_HW_XEN_INTERFACES_H */
diff --git a/hw/xen_redirect.h b/hw/xen_redirect.h
new file mode 100644
index 0000000..491eaf8
--- /dev/null
+++ b/hw/xen_redirect.h
@@ -0,0 +1,56 @@
+#ifndef QEMU_HW_XEN_REDIRECT_H
+#define QEMU_HW_XEN_REDIRECT_H 1
+
+#include "xen_interfaces.h"
+
+/* xen event channel interface */
+#define xc_evtchn_open              xc_evtchn.open
+#define xc_evtchn_close             xc_evtchn.close
+#define xc_evtchn_fd                xc_evtchn.fd
+#define xc_evtchn_notify            xc_evtchn.notify
+#define xc_evtchn_bind_unbound_port xc_evtchn.bind_unbound_port
+#define xc_evtchn_bind_interdomain  xc_evtchn.bind_interdomain
+#define xc_evtchn_bind_virq         xc_evtchn.bind_virq
+#define xc_evtchn_unbind            xc_evtchn.unbind
+#define xc_evtchn_pending           xc_evtchn.pending
+#define xc_evtchn_unmask            xc_evtchn.unmask
+
+/* grant table interface */
+#define xc_gnttab_open              xc_gnttab.open
+#define xc_gnttab_close             xc_gnttab.close
+#define xc_gnttab_map_grant_ref     xc_gnttab.map_grant_ref
+#define xc_gnttab_map_grant_refs    xc_gnttab.map_grant_refs
+#define xc_gnttab_munmap            xc_gnttab.munmap
+
+/* xen hypercall interface */
+#define xc_interface_open           xc.interface_open
+#define xc_interface_close          xc.interface_close
+#define xc_map_foreign_range        xc.map_foreign_range
+#define xc_map_foreign_batch        xc.map_foreign_batch
+#define xc_map_foreign_pages        xc.map_foreign_pages
+
+/* xenstore interface */
+#define xs_daemon_open              xs.daemon_open
+#define xs_domain_open              xs.domain_open
+#define xs_daemon_open_readonly     xs.daemon_open_readonly
+#define xs_daemon_close             xs.daemon_close
+#define xs_directory                xs.directory
+#define xs_read                     xs.read
+#define xs_write                    xs.write
+#define xs_mkdir                    xs.mkdir
+#define xs_rm                       xs.rm
+#define xs_get_permissions          xs.get_permissions
+#define xs_set_permissions          xs.set_permissions
+#define xs_watch                    xs.watch
+#define xs_fileno                   xs.fileno
+#define xs_read_watch               xs.read_watch
+#define xs_unwatch                  xs.unwatch
+#define xs_transaction_start        xs.transaction_start
+#define xs_transaction_end          xs.transaction_end
+#define xs_introduce_domain         xs.introduce_domain
+#define xs_resume_domain            xs.resume_domain
+#define xs_release_domain           xs.release_domain
+#define xs_get_domain_path          xs.get_domain_path
+#define xs_is_domain_introduced     xs.is_domain_introduced
+
+#endif /* QEMU_HW_XEN_REDIRECT_H */
