All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
@ 2014-03-25 15:59 ` Wei Liu
  0 siblings, 0 replies; 18+ messages in thread
From: Wei Liu @ 2014-03-25 15:59 UTC (permalink / raw)
  To: xen-devel, qemu-devel; +Cc: anthony.perard, Wei Liu, stefano.stabellini

This small series disentangles Xen-specific files in QEMU. PV and HVM guests
related files are moved to corresponding locations. Build system is updated to
reflect those changes.

This series was sent back in Jan but fell through the crack. It is now rebased
on current QEMU master and tested with usual Xen building runes. Everything
works as before.

Wei.

Wei Liu (3):
  xen: move Xen PV machine files to hw/xenpv
  xen: move Xen HVM files under hw/i386/xen
  xen: factor out common functions

 Makefile.target            |    6 +-
 hw/i386/Makefile.objs      |    2 +-
 hw/i386/xen/Makefile.objs  |    1 +
 hw/i386/xen/xen_apic.c     |   97 ++++
 hw/i386/xen/xen_platform.c |  450 ++++++++++++++++
 hw/i386/xen/xen_pvdevice.c |  135 +++++
 hw/i386/xen_domainbuild.c  |  299 -----------
 hw/i386/xen_domainbuild.h  |   13 -
 hw/i386/xen_machine_pv.c   |  109 ----
 hw/xen/Makefile.objs       |    1 -
 hw/xen/xen_apic.c          |   97 ----
 hw/xen/xen_platform.c      |  450 ----------------
 hw/xen/xen_pvdevice.c      |  135 -----
 hw/xenpv/Makefile.objs     |    2 +
 hw/xenpv/xen_domainbuild.c |  299 +++++++++++
 hw/xenpv/xen_domainbuild.h |   13 +
 hw/xenpv/xen_machine_pv.c  |  109 ++++
 xen-all.c                  | 1228 --------------------------------------------
 xen-common-stub.c          |   19 +
 xen-common.c               |  123 +++++
 xen-hvm-stub.c             |   66 +++
 xen-hvm.c                  | 1129 ++++++++++++++++++++++++++++++++++++++++
 xen-mapcache-stub.c        |   39 ++
 xen-stub.c                 |   70 ---
 24 files changed, 2487 insertions(+), 2405 deletions(-)
 create mode 100644 hw/i386/xen/Makefile.objs
 create mode 100644 hw/i386/xen/xen_apic.c
 create mode 100644 hw/i386/xen/xen_platform.c
 create mode 100644 hw/i386/xen/xen_pvdevice.c
 delete mode 100644 hw/i386/xen_domainbuild.c
 delete mode 100644 hw/i386/xen_domainbuild.h
 delete mode 100644 hw/i386/xen_machine_pv.c
 delete mode 100644 hw/xen/xen_apic.c
 delete mode 100644 hw/xen/xen_platform.c
 delete mode 100644 hw/xen/xen_pvdevice.c
 create mode 100644 hw/xenpv/Makefile.objs
 create mode 100644 hw/xenpv/xen_domainbuild.c
 create mode 100644 hw/xenpv/xen_domainbuild.h
 create mode 100644 hw/xenpv/xen_machine_pv.c
 delete mode 100644 xen-all.c
 create mode 100644 xen-common-stub.c
 create mode 100644 xen-common.c
 create mode 100644 xen-hvm-stub.c
 create mode 100644 xen-hvm.c
 create mode 100644 xen-mapcache-stub.c
 delete mode 100644 xen-stub.c

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
@ 2014-03-25 15:59 ` Wei Liu
  0 siblings, 0 replies; 18+ messages in thread
From: Wei Liu @ 2014-03-25 15:59 UTC (permalink / raw)
  To: xen-devel, qemu-devel; +Cc: anthony.perard, Wei Liu, stefano.stabellini

This small series disentangles Xen-specific files in QEMU. PV and HVM guests
related files are moved to corresponding locations. Build system is updated to
reflect those changes.

This series was sent back in Jan but fell through the crack. It is now rebased
on current QEMU master and tested with usual Xen building runes. Everything
works as before.

Wei.

Wei Liu (3):
  xen: move Xen PV machine files to hw/xenpv
  xen: move Xen HVM files under hw/i386/xen
  xen: factor out common functions

 Makefile.target            |    6 +-
 hw/i386/Makefile.objs      |    2 +-
 hw/i386/xen/Makefile.objs  |    1 +
 hw/i386/xen/xen_apic.c     |   97 ++++
 hw/i386/xen/xen_platform.c |  450 ++++++++++++++++
 hw/i386/xen/xen_pvdevice.c |  135 +++++
 hw/i386/xen_domainbuild.c  |  299 -----------
 hw/i386/xen_domainbuild.h  |   13 -
 hw/i386/xen_machine_pv.c   |  109 ----
 hw/xen/Makefile.objs       |    1 -
 hw/xen/xen_apic.c          |   97 ----
 hw/xen/xen_platform.c      |  450 ----------------
 hw/xen/xen_pvdevice.c      |  135 -----
 hw/xenpv/Makefile.objs     |    2 +
 hw/xenpv/xen_domainbuild.c |  299 +++++++++++
 hw/xenpv/xen_domainbuild.h |   13 +
 hw/xenpv/xen_machine_pv.c  |  109 ++++
 xen-all.c                  | 1228 --------------------------------------------
 xen-common-stub.c          |   19 +
 xen-common.c               |  123 +++++
 xen-hvm-stub.c             |   66 +++
 xen-hvm.c                  | 1129 ++++++++++++++++++++++++++++++++++++++++
 xen-mapcache-stub.c        |   39 ++
 xen-stub.c                 |   70 ---
 24 files changed, 2487 insertions(+), 2405 deletions(-)
 create mode 100644 hw/i386/xen/Makefile.objs
 create mode 100644 hw/i386/xen/xen_apic.c
 create mode 100644 hw/i386/xen/xen_platform.c
 create mode 100644 hw/i386/xen/xen_pvdevice.c
 delete mode 100644 hw/i386/xen_domainbuild.c
 delete mode 100644 hw/i386/xen_domainbuild.h
 delete mode 100644 hw/i386/xen_machine_pv.c
 delete mode 100644 hw/xen/xen_apic.c
 delete mode 100644 hw/xen/xen_platform.c
 delete mode 100644 hw/xen/xen_pvdevice.c
 create mode 100644 hw/xenpv/Makefile.objs
 create mode 100644 hw/xenpv/xen_domainbuild.c
 create mode 100644 hw/xenpv/xen_domainbuild.h
 create mode 100644 hw/xenpv/xen_machine_pv.c
 delete mode 100644 xen-all.c
 create mode 100644 xen-common-stub.c
 create mode 100644 xen-common.c
 create mode 100644 xen-hvm-stub.c
 create mode 100644 xen-hvm.c
 create mode 100644 xen-mapcache-stub.c
 delete mode 100644 xen-stub.c

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH resend 1/3] xen: move Xen PV machine files to hw/xenpv
  2014-03-25 15:59 ` Wei Liu
@ 2014-03-25 15:59   ` Wei Liu
  -1 siblings, 0 replies; 18+ messages in thread
From: Wei Liu @ 2014-03-25 15:59 UTC (permalink / raw)
  To: xen-devel, qemu-devel; +Cc: anthony.perard, Wei Liu, stefano.stabellini

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 hw/i386/Makefile.objs      |    2 +-
 hw/i386/xen_domainbuild.c  |  299 --------------------------------------------
 hw/i386/xen_domainbuild.h  |   13 --
 hw/i386/xen_machine_pv.c   |  109 ----------------
 hw/xenpv/Makefile.objs     |    2 +
 hw/xenpv/xen_domainbuild.c |  299 ++++++++++++++++++++++++++++++++++++++++++++
 hw/xenpv/xen_domainbuild.h |   13 ++
 hw/xenpv/xen_machine_pv.c  |  109 ++++++++++++++++
 8 files changed, 424 insertions(+), 422 deletions(-)
 delete mode 100644 hw/i386/xen_domainbuild.c
 delete mode 100644 hw/i386/xen_domainbuild.h
 delete mode 100644 hw/i386/xen_machine_pv.c
 create mode 100644 hw/xenpv/Makefile.objs
 create mode 100644 hw/xenpv/xen_domainbuild.c
 create mode 100644 hw/xenpv/xen_domainbuild.h
 create mode 100644 hw/xenpv/xen_machine_pv.c

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 3df1612..f9899a3 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -2,7 +2,7 @@ obj-$(CONFIG_KVM) += kvm/
 obj-y += multiboot.o smbios.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
-obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
+obj-$(CONFIG_XEN) += ../xenpv/
 
 obj-y += kvmvapic.o
 obj-y += acpi-build.o
diff --git a/hw/i386/xen_domainbuild.c b/hw/i386/xen_domainbuild.c
deleted file mode 100644
index c0ab753..0000000
--- a/hw/i386/xen_domainbuild.c
+++ /dev/null
@@ -1,299 +0,0 @@
-#include <signal.h>
-#include "hw/xen/xen_backend.h"
-#include "xen_domainbuild.h"
-#include "qemu/timer.h"
-#include "qemu/log.h"
-
-#include <xenguest.h>
-
-static int xenstore_domain_mkdir(char *path)
-{
-    struct xs_permissions perms_ro[] = {{
-            .id    = 0, /* set owner: dom0 */
-        },{
-            .id    = xen_domid,
-            .perms = XS_PERM_READ,
-        }};
-    struct xs_permissions perms_rw[] = {{
-            .id    = 0, /* set owner: dom0 */
-        },{
-            .id    = xen_domid,
-            .perms = XS_PERM_READ | XS_PERM_WRITE,
-        }};
-    const char *writable[] = { "device", "control", "error", NULL };
-    char subpath[256];
-    int i;
-
-    if (!xs_mkdir(xenstore, 0, path)) {
-        fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
-	return -1;
-    }
-    if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
-        fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
-	return -1;
-    }
-
-    for (i = 0; writable[i]; i++) {
-        snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
-        if (!xs_mkdir(xenstore, 0, subpath)) {
-            fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
-            return -1;
-        }
-        if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
-            fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-int xenstore_domain_init1(const char *kernel, const char *ramdisk,
-                          const char *cmdline)
-{
-    char *dom, uuid_string[42], vm[256], path[256];
-    int i;
-
-    snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
-             qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3],
-             qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
-             qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
-             qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
-    dom = xs_get_domain_path(xenstore, xen_domid);
-    snprintf(vm,  sizeof(vm),  "/vm/%s", uuid_string);
-
-    xenstore_domain_mkdir(dom);
-
-    xenstore_write_str(vm, "image/ostype",  "linux");
-    if (kernel)
-        xenstore_write_str(vm, "image/kernel",  kernel);
-    if (ramdisk)
-        xenstore_write_str(vm, "image/ramdisk", ramdisk);
-    if (cmdline)
-        xenstore_write_str(vm, "image/cmdline", cmdline);
-
-    /* name + id */
-    xenstore_write_str(vm,  "name",   qemu_name ? qemu_name : "no-name");
-    xenstore_write_str(vm,  "uuid",   uuid_string);
-    xenstore_write_str(dom, "name",   qemu_name ? qemu_name : "no-name");
-    xenstore_write_int(dom, "domid",  xen_domid);
-    xenstore_write_str(dom, "vm",     vm);
-
-    /* memory */
-    xenstore_write_int(dom, "memory/target", ram_size >> 10);  // kB
-    xenstore_write_int(vm, "memory",         ram_size >> 20);  // MB
-    xenstore_write_int(vm, "maxmem",         ram_size >> 20);  // MB
-
-    /* cpus */
-    for (i = 0; i < smp_cpus; i++) {
-	snprintf(path, sizeof(path), "cpu/%d/availability",i);
-	xenstore_write_str(dom, path, "online");
-    }
-    xenstore_write_int(vm, "vcpu_avail",  smp_cpus);
-    xenstore_write_int(vm, "vcpus",       smp_cpus);
-
-    /* vnc password */
-    xenstore_write_str(vm, "vncpassword", "" /* FIXME */);
-
-    free(dom);
-    return 0;
-}
-
-int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
-                          int console_port, int console_mfn)
-{
-    char *dom;
-
-    dom = xs_get_domain_path(xenstore, xen_domid);
-
-    /* signal new domain */
-    xs_introduce_domain(xenstore,
-                        xen_domid,
-                        xenstore_mfn,
-                        xenstore_port);
-
-    /* xenstore */
-    xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
-    xenstore_write_int(dom, "store/port",       xenstore_port);
-
-    /* console */
-    xenstore_write_str(dom, "console/type",     "ioemu");
-    xenstore_write_int(dom, "console/limit",    128 * 1024);
-    xenstore_write_int(dom, "console/ring-ref", console_mfn);
-    xenstore_write_int(dom, "console/port",     console_port);
-    xen_config_dev_console(0);
-
-    free(dom);
-    return 0;
-}
-
-/* ------------------------------------------------------------- */
-
-static QEMUTimer *xen_poll;
-
-/* check domain state once per second */
-static void xen_domain_poll(void *opaque)
-{
-    struct xc_dominfo info;
-    int rc;
-
-    rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
-    if ((rc != 1) || (info.domid != xen_domid)) {
-        qemu_log("xen: domain %d is gone\n", xen_domid);
-        goto quit;
-    }
-    if (info.dying) {
-        qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid,
-                 info.crashed  ? "crashed"  : "",
-                 info.shutdown ? "shutdown" : "");
-        goto quit;
-    }
-
-    timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
-    return;
-
-quit:
-    qemu_system_shutdown_request();
-}
-
-static int xen_domain_watcher(void)
-{
-    int qemu_running = 1;
-    int fd[2], i, n, rc;
-    char byte;
-
-    if (pipe(fd) != 0) {
-        qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno));
-        return -1;
-    }
-    if (fork() != 0)
-        return 0; /* not child */
-
-    /* close all file handles, except stdio/out/err,
-     * our watch pipe and the xen interface handle */
-    n = getdtablesize();
-    for (i = 3; i < n; i++) {
-        if (i == fd[0])
-            continue;
-        if (i == xc_fd(xen_xc)) {
-            continue;
-        }
-        close(i);
-    }
-
-    /* ignore term signals */
-    signal(SIGINT,  SIG_IGN);
-    signal(SIGTERM, SIG_IGN);
-
-    /* wait for qemu exiting */
-    while (qemu_running) {
-        rc = read(fd[0], &byte, 1);
-        switch (rc) {
-        case -1:
-            if (errno == EINTR)
-                continue;
-            qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno));
-            qemu_running = 0;
-            break;
-        case 0:
-            /* EOF -> qemu exited */
-            qemu_running = 0;
-            break;
-        default:
-            qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__);
-            break;
-        }
-    }
-
-    /* cleanup */
-    qemu_log("%s: destroy domain %d\n", __FUNCTION__, xen_domid);
-    xc_domain_destroy(xen_xc, xen_domid);
-    _exit(0);
-}
-
-/* normal cleanup */
-static void xen_domain_cleanup(void)
-{
-    char *dom;
-
-    dom = xs_get_domain_path(xenstore, xen_domid);
-    if (dom) {
-        xs_rm(xenstore, 0, dom);
-        free(dom);
-    }
-    xs_release_domain(xenstore, xen_domid);
-}
-
-int xen_domain_build_pv(const char *kernel, const char *ramdisk,
-                        const char *cmdline)
-{
-    uint32_t ssidref = 0;
-    uint32_t flags = 0;
-    xen_domain_handle_t uuid;
-    unsigned int xenstore_port = 0, console_port = 0;
-    unsigned long xenstore_mfn = 0, console_mfn = 0;
-    int rc;
-
-    memcpy(uuid, qemu_uuid, sizeof(uuid));
-    rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_create() failed\n");
-        goto err;
-    }
-    qemu_log("xen: created domain %d\n", xen_domid);
-    atexit(xen_domain_cleanup);
-    if (xen_domain_watcher() == -1) {
-        goto err;
-    }
-
-    xenstore_domain_init1(kernel, ramdisk, cmdline);
-
-    rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n");
-        goto err;
-    }
-
-#if 0
-    rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n");
-        goto err;
-    }
-#endif
-
-    rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size >> 10);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n");
-        goto err;
-    }
-
-    xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
-    console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
-
-    rc = xc_linux_build(xen_xc, xen_domid, ram_size >> 20,
-                        kernel, ramdisk, cmdline,
-                        0, flags,
-                        xenstore_port, &xenstore_mfn,
-                        console_port, &console_mfn);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_linux_build() failed\n");
-        goto err;
-    }
-
-    xenstore_domain_init2(xenstore_port, xenstore_mfn,
-                          console_port, console_mfn);
-
-    qemu_log("xen: unpausing domain %d\n", xen_domid);
-    rc = xc_domain_unpause(xen_xc, xen_domid);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_unpause() failed\n");
-        goto err;
-    }
-
-    xen_poll = timer_new_ms(QEMU_CLOCK_REALTIME, xen_domain_poll, NULL);
-    timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
-    return 0;
-
-err:
-    return -1;
-}
diff --git a/hw/i386/xen_domainbuild.h b/hw/i386/xen_domainbuild.h
deleted file mode 100644
index 29a91ea..0000000
--- a/hw/i386/xen_domainbuild.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef QEMU_HW_XEN_DOMAINBUILD_H
-#define QEMU_HW_XEN_DOMAINBUILD_H 1
-
-#include "hw/xen/xen_common.h"
-
-int xenstore_domain_init1(const char *kernel, const char *ramdisk,
-                          const char *cmdline);
-int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
-                          int console_port, int console_mfn);
-int xen_domain_build_pv(const char *kernel, const char *ramdisk,
-                        const char *cmdline);
-
-#endif /* QEMU_HW_XEN_DOMAINBUILD_H */
diff --git a/hw/i386/xen_machine_pv.c b/hw/i386/xen_machine_pv.c
deleted file mode 100644
index 9adb57f..0000000
--- a/hw/i386/xen_machine_pv.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * QEMU Xen PV Machine
- *
- * Copyright (c) 2007 Red Hat
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw/hw.h"
-#include "hw/boards.h"
-#include "hw/xen/xen_backend.h"
-#include "xen_domainbuild.h"
-#include "sysemu/blockdev.h"
-
-static void xen_init_pv(QEMUMachineInitArgs *args)
-{
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    DriveInfo *dinfo;
-    int i;
-
-    /* Initialize backend core & drivers */
-    if (xen_be_init() != 0) {
-        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
-        exit(1);
-    }
-
-    switch (xen_mode) {
-    case XEN_ATTACH:
-        /* nothing to do, xend handles everything */
-        break;
-    case XEN_CREATE:
-        if (xen_domain_build_pv(kernel_filename, initrd_filename,
-                                kernel_cmdline) < 0) {
-            fprintf(stderr, "xen pv domain creation failed\n");
-            exit(1);
-        }
-        break;
-    case XEN_EMULATE:
-        fprintf(stderr, "xen emulation not implemented (yet)\n");
-        exit(1);
-        break;
-    }
-
-    xen_be_register("console", &xen_console_ops);
-    xen_be_register("vkbd", &xen_kbdmouse_ops);
-    xen_be_register("vfb", &xen_framebuffer_ops);
-    xen_be_register("qdisk", &xen_blkdev_ops);
-    xen_be_register("qnic", &xen_netdev_ops);
-
-    /* configure framebuffer */
-    if (xenfb_enabled) {
-        xen_config_dev_vfb(0, "vnc");
-        xen_config_dev_vkbd(0);
-    }
-
-    /* configure disks */
-    for (i = 0; i < 16; i++) {
-        dinfo = drive_get(IF_XEN, 0, i);
-        if (!dinfo)
-            continue;
-        xen_config_dev_blk(dinfo);
-    }
-
-    /* configure nics */
-    for (i = 0; i < nb_nics; i++) {
-        if (!nd_table[i].model || 0 != strcmp(nd_table[i].model, "xen"))
-            continue;
-        xen_config_dev_nic(nd_table + i);
-    }
-
-    /* config cleanup hook */
-    atexit(xen_config_cleanup);
-
-    /* setup framebuffer */
-    xen_init_display(xen_domid);
-}
-
-static QEMUMachine xenpv_machine = {
-    .name = "xenpv",
-    .desc = "Xen Para-virtualized PC",
-    .init = xen_init_pv,
-    .max_cpus = 1,
-    .default_machine_opts = "accel=xen",
-};
-
-static void xenpv_machine_init(void)
-{
-    qemu_register_machine(&xenpv_machine);
-}
-
-machine_init(xenpv_machine_init);
diff --git a/hw/xenpv/Makefile.objs b/hw/xenpv/Makefile.objs
new file mode 100644
index 0000000..49f6e9e
--- /dev/null
+++ b/hw/xenpv/Makefile.objs
@@ -0,0 +1,2 @@
+# Xen PV machine support
+obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
diff --git a/hw/xenpv/xen_domainbuild.c b/hw/xenpv/xen_domainbuild.c
new file mode 100644
index 0000000..c0ab753
--- /dev/null
+++ b/hw/xenpv/xen_domainbuild.c
@@ -0,0 +1,299 @@
+#include <signal.h>
+#include "hw/xen/xen_backend.h"
+#include "xen_domainbuild.h"
+#include "qemu/timer.h"
+#include "qemu/log.h"
+
+#include <xenguest.h>
+
+static int xenstore_domain_mkdir(char *path)
+{
+    struct xs_permissions perms_ro[] = {{
+            .id    = 0, /* set owner: dom0 */
+        },{
+            .id    = xen_domid,
+            .perms = XS_PERM_READ,
+        }};
+    struct xs_permissions perms_rw[] = {{
+            .id    = 0, /* set owner: dom0 */
+        },{
+            .id    = xen_domid,
+            .perms = XS_PERM_READ | XS_PERM_WRITE,
+        }};
+    const char *writable[] = { "device", "control", "error", NULL };
+    char subpath[256];
+    int i;
+
+    if (!xs_mkdir(xenstore, 0, path)) {
+        fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
+	return -1;
+    }
+    if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
+        fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
+	return -1;
+    }
+
+    for (i = 0; writable[i]; i++) {
+        snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
+        if (!xs_mkdir(xenstore, 0, subpath)) {
+            fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
+            return -1;
+        }
+        if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
+            fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int xenstore_domain_init1(const char *kernel, const char *ramdisk,
+                          const char *cmdline)
+{
+    char *dom, uuid_string[42], vm[256], path[256];
+    int i;
+
+    snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
+             qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3],
+             qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
+             qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
+             qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
+    dom = xs_get_domain_path(xenstore, xen_domid);
+    snprintf(vm,  sizeof(vm),  "/vm/%s", uuid_string);
+
+    xenstore_domain_mkdir(dom);
+
+    xenstore_write_str(vm, "image/ostype",  "linux");
+    if (kernel)
+        xenstore_write_str(vm, "image/kernel",  kernel);
+    if (ramdisk)
+        xenstore_write_str(vm, "image/ramdisk", ramdisk);
+    if (cmdline)
+        xenstore_write_str(vm, "image/cmdline", cmdline);
+
+    /* name + id */
+    xenstore_write_str(vm,  "name",   qemu_name ? qemu_name : "no-name");
+    xenstore_write_str(vm,  "uuid",   uuid_string);
+    xenstore_write_str(dom, "name",   qemu_name ? qemu_name : "no-name");
+    xenstore_write_int(dom, "domid",  xen_domid);
+    xenstore_write_str(dom, "vm",     vm);
+
+    /* memory */
+    xenstore_write_int(dom, "memory/target", ram_size >> 10);  // kB
+    xenstore_write_int(vm, "memory",         ram_size >> 20);  // MB
+    xenstore_write_int(vm, "maxmem",         ram_size >> 20);  // MB
+
+    /* cpus */
+    for (i = 0; i < smp_cpus; i++) {
+	snprintf(path, sizeof(path), "cpu/%d/availability",i);
+	xenstore_write_str(dom, path, "online");
+    }
+    xenstore_write_int(vm, "vcpu_avail",  smp_cpus);
+    xenstore_write_int(vm, "vcpus",       smp_cpus);
+
+    /* vnc password */
+    xenstore_write_str(vm, "vncpassword", "" /* FIXME */);
+
+    free(dom);
+    return 0;
+}
+
+int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
+                          int console_port, int console_mfn)
+{
+    char *dom;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+
+    /* signal new domain */
+    xs_introduce_domain(xenstore,
+                        xen_domid,
+                        xenstore_mfn,
+                        xenstore_port);
+
+    /* xenstore */
+    xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
+    xenstore_write_int(dom, "store/port",       xenstore_port);
+
+    /* console */
+    xenstore_write_str(dom, "console/type",     "ioemu");
+    xenstore_write_int(dom, "console/limit",    128 * 1024);
+    xenstore_write_int(dom, "console/ring-ref", console_mfn);
+    xenstore_write_int(dom, "console/port",     console_port);
+    xen_config_dev_console(0);
+
+    free(dom);
+    return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static QEMUTimer *xen_poll;
+
+/* check domain state once per second */
+static void xen_domain_poll(void *opaque)
+{
+    struct xc_dominfo info;
+    int rc;
+
+    rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
+    if ((rc != 1) || (info.domid != xen_domid)) {
+        qemu_log("xen: domain %d is gone\n", xen_domid);
+        goto quit;
+    }
+    if (info.dying) {
+        qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid,
+                 info.crashed  ? "crashed"  : "",
+                 info.shutdown ? "shutdown" : "");
+        goto quit;
+    }
+
+    timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
+    return;
+
+quit:
+    qemu_system_shutdown_request();
+}
+
+static int xen_domain_watcher(void)
+{
+    int qemu_running = 1;
+    int fd[2], i, n, rc;
+    char byte;
+
+    if (pipe(fd) != 0) {
+        qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno));
+        return -1;
+    }
+    if (fork() != 0)
+        return 0; /* not child */
+
+    /* close all file handles, except stdio/out/err,
+     * our watch pipe and the xen interface handle */
+    n = getdtablesize();
+    for (i = 3; i < n; i++) {
+        if (i == fd[0])
+            continue;
+        if (i == xc_fd(xen_xc)) {
+            continue;
+        }
+        close(i);
+    }
+
+    /* ignore term signals */
+    signal(SIGINT,  SIG_IGN);
+    signal(SIGTERM, SIG_IGN);
+
+    /* wait for qemu exiting */
+    while (qemu_running) {
+        rc = read(fd[0], &byte, 1);
+        switch (rc) {
+        case -1:
+            if (errno == EINTR)
+                continue;
+            qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno));
+            qemu_running = 0;
+            break;
+        case 0:
+            /* EOF -> qemu exited */
+            qemu_running = 0;
+            break;
+        default:
+            qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__);
+            break;
+        }
+    }
+
+    /* cleanup */
+    qemu_log("%s: destroy domain %d\n", __FUNCTION__, xen_domid);
+    xc_domain_destroy(xen_xc, xen_domid);
+    _exit(0);
+}
+
+/* normal cleanup */
+static void xen_domain_cleanup(void)
+{
+    char *dom;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+    if (dom) {
+        xs_rm(xenstore, 0, dom);
+        free(dom);
+    }
+    xs_release_domain(xenstore, xen_domid);
+}
+
+int xen_domain_build_pv(const char *kernel, const char *ramdisk,
+                        const char *cmdline)
+{
+    uint32_t ssidref = 0;
+    uint32_t flags = 0;
+    xen_domain_handle_t uuid;
+    unsigned int xenstore_port = 0, console_port = 0;
+    unsigned long xenstore_mfn = 0, console_mfn = 0;
+    int rc;
+
+    memcpy(uuid, qemu_uuid, sizeof(uuid));
+    rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_create() failed\n");
+        goto err;
+    }
+    qemu_log("xen: created domain %d\n", xen_domid);
+    atexit(xen_domain_cleanup);
+    if (xen_domain_watcher() == -1) {
+        goto err;
+    }
+
+    xenstore_domain_init1(kernel, ramdisk, cmdline);
+
+    rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n");
+        goto err;
+    }
+
+#if 0
+    rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n");
+        goto err;
+    }
+#endif
+
+    rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size >> 10);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n");
+        goto err;
+    }
+
+    xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
+    console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
+
+    rc = xc_linux_build(xen_xc, xen_domid, ram_size >> 20,
+                        kernel, ramdisk, cmdline,
+                        0, flags,
+                        xenstore_port, &xenstore_mfn,
+                        console_port, &console_mfn);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_linux_build() failed\n");
+        goto err;
+    }
+
+    xenstore_domain_init2(xenstore_port, xenstore_mfn,
+                          console_port, console_mfn);
+
+    qemu_log("xen: unpausing domain %d\n", xen_domid);
+    rc = xc_domain_unpause(xen_xc, xen_domid);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_unpause() failed\n");
+        goto err;
+    }
+
+    xen_poll = timer_new_ms(QEMU_CLOCK_REALTIME, xen_domain_poll, NULL);
+    timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
+    return 0;
+
+err:
+    return -1;
+}
diff --git a/hw/xenpv/xen_domainbuild.h b/hw/xenpv/xen_domainbuild.h
new file mode 100644
index 0000000..29a91ea
--- /dev/null
+++ b/hw/xenpv/xen_domainbuild.h
@@ -0,0 +1,13 @@
+#ifndef QEMU_HW_XEN_DOMAINBUILD_H
+#define QEMU_HW_XEN_DOMAINBUILD_H 1
+
+#include "hw/xen/xen_common.h"
+
+int xenstore_domain_init1(const char *kernel, const char *ramdisk,
+                          const char *cmdline);
+int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
+                          int console_port, int console_mfn);
+int xen_domain_build_pv(const char *kernel, const char *ramdisk,
+                        const char *cmdline);
+
+#endif /* QEMU_HW_XEN_DOMAINBUILD_H */
diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c
new file mode 100644
index 0000000..9adb57f
--- /dev/null
+++ b/hw/xenpv/xen_machine_pv.c
@@ -0,0 +1,109 @@
+/*
+ * QEMU Xen PV Machine
+ *
+ * Copyright (c) 2007 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/xen/xen_backend.h"
+#include "xen_domainbuild.h"
+#include "sysemu/blockdev.h"
+
+static void xen_init_pv(QEMUMachineInitArgs *args)
+{
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    DriveInfo *dinfo;
+    int i;
+
+    /* Initialize backend core & drivers */
+    if (xen_be_init() != 0) {
+        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
+        exit(1);
+    }
+
+    switch (xen_mode) {
+    case XEN_ATTACH:
+        /* nothing to do, xend handles everything */
+        break;
+    case XEN_CREATE:
+        if (xen_domain_build_pv(kernel_filename, initrd_filename,
+                                kernel_cmdline) < 0) {
+            fprintf(stderr, "xen pv domain creation failed\n");
+            exit(1);
+        }
+        break;
+    case XEN_EMULATE:
+        fprintf(stderr, "xen emulation not implemented (yet)\n");
+        exit(1);
+        break;
+    }
+
+    xen_be_register("console", &xen_console_ops);
+    xen_be_register("vkbd", &xen_kbdmouse_ops);
+    xen_be_register("vfb", &xen_framebuffer_ops);
+    xen_be_register("qdisk", &xen_blkdev_ops);
+    xen_be_register("qnic", &xen_netdev_ops);
+
+    /* configure framebuffer */
+    if (xenfb_enabled) {
+        xen_config_dev_vfb(0, "vnc");
+        xen_config_dev_vkbd(0);
+    }
+
+    /* configure disks */
+    for (i = 0; i < 16; i++) {
+        dinfo = drive_get(IF_XEN, 0, i);
+        if (!dinfo)
+            continue;
+        xen_config_dev_blk(dinfo);
+    }
+
+    /* configure nics */
+    for (i = 0; i < nb_nics; i++) {
+        if (!nd_table[i].model || 0 != strcmp(nd_table[i].model, "xen"))
+            continue;
+        xen_config_dev_nic(nd_table + i);
+    }
+
+    /* config cleanup hook */
+    atexit(xen_config_cleanup);
+
+    /* setup framebuffer */
+    xen_init_display(xen_domid);
+}
+
+static QEMUMachine xenpv_machine = {
+    .name = "xenpv",
+    .desc = "Xen Para-virtualized PC",
+    .init = xen_init_pv,
+    .max_cpus = 1,
+    .default_machine_opts = "accel=xen",
+};
+
+static void xenpv_machine_init(void)
+{
+    qemu_register_machine(&xenpv_machine);
+}
+
+machine_init(xenpv_machine_init);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH resend 1/3] xen: move Xen PV machine files to hw/xenpv
@ 2014-03-25 15:59   ` Wei Liu
  0 siblings, 0 replies; 18+ messages in thread
From: Wei Liu @ 2014-03-25 15:59 UTC (permalink / raw)
  To: xen-devel, qemu-devel; +Cc: anthony.perard, Wei Liu, stefano.stabellini

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 hw/i386/Makefile.objs      |    2 +-
 hw/i386/xen_domainbuild.c  |  299 --------------------------------------------
 hw/i386/xen_domainbuild.h  |   13 --
 hw/i386/xen_machine_pv.c   |  109 ----------------
 hw/xenpv/Makefile.objs     |    2 +
 hw/xenpv/xen_domainbuild.c |  299 ++++++++++++++++++++++++++++++++++++++++++++
 hw/xenpv/xen_domainbuild.h |   13 ++
 hw/xenpv/xen_machine_pv.c  |  109 ++++++++++++++++
 8 files changed, 424 insertions(+), 422 deletions(-)
 delete mode 100644 hw/i386/xen_domainbuild.c
 delete mode 100644 hw/i386/xen_domainbuild.h
 delete mode 100644 hw/i386/xen_machine_pv.c
 create mode 100644 hw/xenpv/Makefile.objs
 create mode 100644 hw/xenpv/xen_domainbuild.c
 create mode 100644 hw/xenpv/xen_domainbuild.h
 create mode 100644 hw/xenpv/xen_machine_pv.c

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 3df1612..f9899a3 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -2,7 +2,7 @@ obj-$(CONFIG_KVM) += kvm/
 obj-y += multiboot.o smbios.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
-obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
+obj-$(CONFIG_XEN) += ../xenpv/
 
 obj-y += kvmvapic.o
 obj-y += acpi-build.o
diff --git a/hw/i386/xen_domainbuild.c b/hw/i386/xen_domainbuild.c
deleted file mode 100644
index c0ab753..0000000
--- a/hw/i386/xen_domainbuild.c
+++ /dev/null
@@ -1,299 +0,0 @@
-#include <signal.h>
-#include "hw/xen/xen_backend.h"
-#include "xen_domainbuild.h"
-#include "qemu/timer.h"
-#include "qemu/log.h"
-
-#include <xenguest.h>
-
-static int xenstore_domain_mkdir(char *path)
-{
-    struct xs_permissions perms_ro[] = {{
-            .id    = 0, /* set owner: dom0 */
-        },{
-            .id    = xen_domid,
-            .perms = XS_PERM_READ,
-        }};
-    struct xs_permissions perms_rw[] = {{
-            .id    = 0, /* set owner: dom0 */
-        },{
-            .id    = xen_domid,
-            .perms = XS_PERM_READ | XS_PERM_WRITE,
-        }};
-    const char *writable[] = { "device", "control", "error", NULL };
-    char subpath[256];
-    int i;
-
-    if (!xs_mkdir(xenstore, 0, path)) {
-        fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
-	return -1;
-    }
-    if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
-        fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
-	return -1;
-    }
-
-    for (i = 0; writable[i]; i++) {
-        snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
-        if (!xs_mkdir(xenstore, 0, subpath)) {
-            fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
-            return -1;
-        }
-        if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
-            fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-int xenstore_domain_init1(const char *kernel, const char *ramdisk,
-                          const char *cmdline)
-{
-    char *dom, uuid_string[42], vm[256], path[256];
-    int i;
-
-    snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
-             qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3],
-             qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
-             qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
-             qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
-    dom = xs_get_domain_path(xenstore, xen_domid);
-    snprintf(vm,  sizeof(vm),  "/vm/%s", uuid_string);
-
-    xenstore_domain_mkdir(dom);
-
-    xenstore_write_str(vm, "image/ostype",  "linux");
-    if (kernel)
-        xenstore_write_str(vm, "image/kernel",  kernel);
-    if (ramdisk)
-        xenstore_write_str(vm, "image/ramdisk", ramdisk);
-    if (cmdline)
-        xenstore_write_str(vm, "image/cmdline", cmdline);
-
-    /* name + id */
-    xenstore_write_str(vm,  "name",   qemu_name ? qemu_name : "no-name");
-    xenstore_write_str(vm,  "uuid",   uuid_string);
-    xenstore_write_str(dom, "name",   qemu_name ? qemu_name : "no-name");
-    xenstore_write_int(dom, "domid",  xen_domid);
-    xenstore_write_str(dom, "vm",     vm);
-
-    /* memory */
-    xenstore_write_int(dom, "memory/target", ram_size >> 10);  // kB
-    xenstore_write_int(vm, "memory",         ram_size >> 20);  // MB
-    xenstore_write_int(vm, "maxmem",         ram_size >> 20);  // MB
-
-    /* cpus */
-    for (i = 0; i < smp_cpus; i++) {
-	snprintf(path, sizeof(path), "cpu/%d/availability",i);
-	xenstore_write_str(dom, path, "online");
-    }
-    xenstore_write_int(vm, "vcpu_avail",  smp_cpus);
-    xenstore_write_int(vm, "vcpus",       smp_cpus);
-
-    /* vnc password */
-    xenstore_write_str(vm, "vncpassword", "" /* FIXME */);
-
-    free(dom);
-    return 0;
-}
-
-int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
-                          int console_port, int console_mfn)
-{
-    char *dom;
-
-    dom = xs_get_domain_path(xenstore, xen_domid);
-
-    /* signal new domain */
-    xs_introduce_domain(xenstore,
-                        xen_domid,
-                        xenstore_mfn,
-                        xenstore_port);
-
-    /* xenstore */
-    xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
-    xenstore_write_int(dom, "store/port",       xenstore_port);
-
-    /* console */
-    xenstore_write_str(dom, "console/type",     "ioemu");
-    xenstore_write_int(dom, "console/limit",    128 * 1024);
-    xenstore_write_int(dom, "console/ring-ref", console_mfn);
-    xenstore_write_int(dom, "console/port",     console_port);
-    xen_config_dev_console(0);
-
-    free(dom);
-    return 0;
-}
-
-/* ------------------------------------------------------------- */
-
-static QEMUTimer *xen_poll;
-
-/* check domain state once per second */
-static void xen_domain_poll(void *opaque)
-{
-    struct xc_dominfo info;
-    int rc;
-
-    rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
-    if ((rc != 1) || (info.domid != xen_domid)) {
-        qemu_log("xen: domain %d is gone\n", xen_domid);
-        goto quit;
-    }
-    if (info.dying) {
-        qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid,
-                 info.crashed  ? "crashed"  : "",
-                 info.shutdown ? "shutdown" : "");
-        goto quit;
-    }
-
-    timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
-    return;
-
-quit:
-    qemu_system_shutdown_request();
-}
-
-static int xen_domain_watcher(void)
-{
-    int qemu_running = 1;
-    int fd[2], i, n, rc;
-    char byte;
-
-    if (pipe(fd) != 0) {
-        qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno));
-        return -1;
-    }
-    if (fork() != 0)
-        return 0; /* not child */
-
-    /* close all file handles, except stdio/out/err,
-     * our watch pipe and the xen interface handle */
-    n = getdtablesize();
-    for (i = 3; i < n; i++) {
-        if (i == fd[0])
-            continue;
-        if (i == xc_fd(xen_xc)) {
-            continue;
-        }
-        close(i);
-    }
-
-    /* ignore term signals */
-    signal(SIGINT,  SIG_IGN);
-    signal(SIGTERM, SIG_IGN);
-
-    /* wait for qemu exiting */
-    while (qemu_running) {
-        rc = read(fd[0], &byte, 1);
-        switch (rc) {
-        case -1:
-            if (errno == EINTR)
-                continue;
-            qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno));
-            qemu_running = 0;
-            break;
-        case 0:
-            /* EOF -> qemu exited */
-            qemu_running = 0;
-            break;
-        default:
-            qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__);
-            break;
-        }
-    }
-
-    /* cleanup */
-    qemu_log("%s: destroy domain %d\n", __FUNCTION__, xen_domid);
-    xc_domain_destroy(xen_xc, xen_domid);
-    _exit(0);
-}
-
-/* normal cleanup */
-static void xen_domain_cleanup(void)
-{
-    char *dom;
-
-    dom = xs_get_domain_path(xenstore, xen_domid);
-    if (dom) {
-        xs_rm(xenstore, 0, dom);
-        free(dom);
-    }
-    xs_release_domain(xenstore, xen_domid);
-}
-
-int xen_domain_build_pv(const char *kernel, const char *ramdisk,
-                        const char *cmdline)
-{
-    uint32_t ssidref = 0;
-    uint32_t flags = 0;
-    xen_domain_handle_t uuid;
-    unsigned int xenstore_port = 0, console_port = 0;
-    unsigned long xenstore_mfn = 0, console_mfn = 0;
-    int rc;
-
-    memcpy(uuid, qemu_uuid, sizeof(uuid));
-    rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_create() failed\n");
-        goto err;
-    }
-    qemu_log("xen: created domain %d\n", xen_domid);
-    atexit(xen_domain_cleanup);
-    if (xen_domain_watcher() == -1) {
-        goto err;
-    }
-
-    xenstore_domain_init1(kernel, ramdisk, cmdline);
-
-    rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n");
-        goto err;
-    }
-
-#if 0
-    rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n");
-        goto err;
-    }
-#endif
-
-    rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size >> 10);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n");
-        goto err;
-    }
-
-    xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
-    console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
-
-    rc = xc_linux_build(xen_xc, xen_domid, ram_size >> 20,
-                        kernel, ramdisk, cmdline,
-                        0, flags,
-                        xenstore_port, &xenstore_mfn,
-                        console_port, &console_mfn);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_linux_build() failed\n");
-        goto err;
-    }
-
-    xenstore_domain_init2(xenstore_port, xenstore_mfn,
-                          console_port, console_mfn);
-
-    qemu_log("xen: unpausing domain %d\n", xen_domid);
-    rc = xc_domain_unpause(xen_xc, xen_domid);
-    if (rc < 0) {
-        fprintf(stderr, "xen: xc_domain_unpause() failed\n");
-        goto err;
-    }
-
-    xen_poll = timer_new_ms(QEMU_CLOCK_REALTIME, xen_domain_poll, NULL);
-    timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
-    return 0;
-
-err:
-    return -1;
-}
diff --git a/hw/i386/xen_domainbuild.h b/hw/i386/xen_domainbuild.h
deleted file mode 100644
index 29a91ea..0000000
--- a/hw/i386/xen_domainbuild.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef QEMU_HW_XEN_DOMAINBUILD_H
-#define QEMU_HW_XEN_DOMAINBUILD_H 1
-
-#include "hw/xen/xen_common.h"
-
-int xenstore_domain_init1(const char *kernel, const char *ramdisk,
-                          const char *cmdline);
-int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
-                          int console_port, int console_mfn);
-int xen_domain_build_pv(const char *kernel, const char *ramdisk,
-                        const char *cmdline);
-
-#endif /* QEMU_HW_XEN_DOMAINBUILD_H */
diff --git a/hw/i386/xen_machine_pv.c b/hw/i386/xen_machine_pv.c
deleted file mode 100644
index 9adb57f..0000000
--- a/hw/i386/xen_machine_pv.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * QEMU Xen PV Machine
- *
- * Copyright (c) 2007 Red Hat
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "hw/hw.h"
-#include "hw/boards.h"
-#include "hw/xen/xen_backend.h"
-#include "xen_domainbuild.h"
-#include "sysemu/blockdev.h"
-
-static void xen_init_pv(QEMUMachineInitArgs *args)
-{
-    const char *kernel_filename = args->kernel_filename;
-    const char *kernel_cmdline = args->kernel_cmdline;
-    const char *initrd_filename = args->initrd_filename;
-    DriveInfo *dinfo;
-    int i;
-
-    /* Initialize backend core & drivers */
-    if (xen_be_init() != 0) {
-        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
-        exit(1);
-    }
-
-    switch (xen_mode) {
-    case XEN_ATTACH:
-        /* nothing to do, xend handles everything */
-        break;
-    case XEN_CREATE:
-        if (xen_domain_build_pv(kernel_filename, initrd_filename,
-                                kernel_cmdline) < 0) {
-            fprintf(stderr, "xen pv domain creation failed\n");
-            exit(1);
-        }
-        break;
-    case XEN_EMULATE:
-        fprintf(stderr, "xen emulation not implemented (yet)\n");
-        exit(1);
-        break;
-    }
-
-    xen_be_register("console", &xen_console_ops);
-    xen_be_register("vkbd", &xen_kbdmouse_ops);
-    xen_be_register("vfb", &xen_framebuffer_ops);
-    xen_be_register("qdisk", &xen_blkdev_ops);
-    xen_be_register("qnic", &xen_netdev_ops);
-
-    /* configure framebuffer */
-    if (xenfb_enabled) {
-        xen_config_dev_vfb(0, "vnc");
-        xen_config_dev_vkbd(0);
-    }
-
-    /* configure disks */
-    for (i = 0; i < 16; i++) {
-        dinfo = drive_get(IF_XEN, 0, i);
-        if (!dinfo)
-            continue;
-        xen_config_dev_blk(dinfo);
-    }
-
-    /* configure nics */
-    for (i = 0; i < nb_nics; i++) {
-        if (!nd_table[i].model || 0 != strcmp(nd_table[i].model, "xen"))
-            continue;
-        xen_config_dev_nic(nd_table + i);
-    }
-
-    /* config cleanup hook */
-    atexit(xen_config_cleanup);
-
-    /* setup framebuffer */
-    xen_init_display(xen_domid);
-}
-
-static QEMUMachine xenpv_machine = {
-    .name = "xenpv",
-    .desc = "Xen Para-virtualized PC",
-    .init = xen_init_pv,
-    .max_cpus = 1,
-    .default_machine_opts = "accel=xen",
-};
-
-static void xenpv_machine_init(void)
-{
-    qemu_register_machine(&xenpv_machine);
-}
-
-machine_init(xenpv_machine_init);
diff --git a/hw/xenpv/Makefile.objs b/hw/xenpv/Makefile.objs
new file mode 100644
index 0000000..49f6e9e
--- /dev/null
+++ b/hw/xenpv/Makefile.objs
@@ -0,0 +1,2 @@
+# Xen PV machine support
+obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
diff --git a/hw/xenpv/xen_domainbuild.c b/hw/xenpv/xen_domainbuild.c
new file mode 100644
index 0000000..c0ab753
--- /dev/null
+++ b/hw/xenpv/xen_domainbuild.c
@@ -0,0 +1,299 @@
+#include <signal.h>
+#include "hw/xen/xen_backend.h"
+#include "xen_domainbuild.h"
+#include "qemu/timer.h"
+#include "qemu/log.h"
+
+#include <xenguest.h>
+
+static int xenstore_domain_mkdir(char *path)
+{
+    struct xs_permissions perms_ro[] = {{
+            .id    = 0, /* set owner: dom0 */
+        },{
+            .id    = xen_domid,
+            .perms = XS_PERM_READ,
+        }};
+    struct xs_permissions perms_rw[] = {{
+            .id    = 0, /* set owner: dom0 */
+        },{
+            .id    = xen_domid,
+            .perms = XS_PERM_READ | XS_PERM_WRITE,
+        }};
+    const char *writable[] = { "device", "control", "error", NULL };
+    char subpath[256];
+    int i;
+
+    if (!xs_mkdir(xenstore, 0, path)) {
+        fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
+	return -1;
+    }
+    if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
+        fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
+	return -1;
+    }
+
+    for (i = 0; writable[i]; i++) {
+        snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
+        if (!xs_mkdir(xenstore, 0, subpath)) {
+            fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
+            return -1;
+        }
+        if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
+            fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int xenstore_domain_init1(const char *kernel, const char *ramdisk,
+                          const char *cmdline)
+{
+    char *dom, uuid_string[42], vm[256], path[256];
+    int i;
+
+    snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
+             qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3],
+             qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
+             qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
+             qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
+    dom = xs_get_domain_path(xenstore, xen_domid);
+    snprintf(vm,  sizeof(vm),  "/vm/%s", uuid_string);
+
+    xenstore_domain_mkdir(dom);
+
+    xenstore_write_str(vm, "image/ostype",  "linux");
+    if (kernel)
+        xenstore_write_str(vm, "image/kernel",  kernel);
+    if (ramdisk)
+        xenstore_write_str(vm, "image/ramdisk", ramdisk);
+    if (cmdline)
+        xenstore_write_str(vm, "image/cmdline", cmdline);
+
+    /* name + id */
+    xenstore_write_str(vm,  "name",   qemu_name ? qemu_name : "no-name");
+    xenstore_write_str(vm,  "uuid",   uuid_string);
+    xenstore_write_str(dom, "name",   qemu_name ? qemu_name : "no-name");
+    xenstore_write_int(dom, "domid",  xen_domid);
+    xenstore_write_str(dom, "vm",     vm);
+
+    /* memory */
+    xenstore_write_int(dom, "memory/target", ram_size >> 10);  // kB
+    xenstore_write_int(vm, "memory",         ram_size >> 20);  // MB
+    xenstore_write_int(vm, "maxmem",         ram_size >> 20);  // MB
+
+    /* cpus */
+    for (i = 0; i < smp_cpus; i++) {
+	snprintf(path, sizeof(path), "cpu/%d/availability",i);
+	xenstore_write_str(dom, path, "online");
+    }
+    xenstore_write_int(vm, "vcpu_avail",  smp_cpus);
+    xenstore_write_int(vm, "vcpus",       smp_cpus);
+
+    /* vnc password */
+    xenstore_write_str(vm, "vncpassword", "" /* FIXME */);
+
+    free(dom);
+    return 0;
+}
+
+int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
+                          int console_port, int console_mfn)
+{
+    char *dom;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+
+    /* signal new domain */
+    xs_introduce_domain(xenstore,
+                        xen_domid,
+                        xenstore_mfn,
+                        xenstore_port);
+
+    /* xenstore */
+    xenstore_write_int(dom, "store/ring-ref",   xenstore_mfn);
+    xenstore_write_int(dom, "store/port",       xenstore_port);
+
+    /* console */
+    xenstore_write_str(dom, "console/type",     "ioemu");
+    xenstore_write_int(dom, "console/limit",    128 * 1024);
+    xenstore_write_int(dom, "console/ring-ref", console_mfn);
+    xenstore_write_int(dom, "console/port",     console_port);
+    xen_config_dev_console(0);
+
+    free(dom);
+    return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static QEMUTimer *xen_poll;
+
+/* check domain state once per second */
+static void xen_domain_poll(void *opaque)
+{
+    struct xc_dominfo info;
+    int rc;
+
+    rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
+    if ((rc != 1) || (info.domid != xen_domid)) {
+        qemu_log("xen: domain %d is gone\n", xen_domid);
+        goto quit;
+    }
+    if (info.dying) {
+        qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid,
+                 info.crashed  ? "crashed"  : "",
+                 info.shutdown ? "shutdown" : "");
+        goto quit;
+    }
+
+    timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
+    return;
+
+quit:
+    qemu_system_shutdown_request();
+}
+
+static int xen_domain_watcher(void)
+{
+    int qemu_running = 1;
+    int fd[2], i, n, rc;
+    char byte;
+
+    if (pipe(fd) != 0) {
+        qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno));
+        return -1;
+    }
+    if (fork() != 0)
+        return 0; /* not child */
+
+    /* close all file handles, except stdio/out/err,
+     * our watch pipe and the xen interface handle */
+    n = getdtablesize();
+    for (i = 3; i < n; i++) {
+        if (i == fd[0])
+            continue;
+        if (i == xc_fd(xen_xc)) {
+            continue;
+        }
+        close(i);
+    }
+
+    /* ignore term signals */
+    signal(SIGINT,  SIG_IGN);
+    signal(SIGTERM, SIG_IGN);
+
+    /* wait for qemu exiting */
+    while (qemu_running) {
+        rc = read(fd[0], &byte, 1);
+        switch (rc) {
+        case -1:
+            if (errno == EINTR)
+                continue;
+            qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno));
+            qemu_running = 0;
+            break;
+        case 0:
+            /* EOF -> qemu exited */
+            qemu_running = 0;
+            break;
+        default:
+            qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__);
+            break;
+        }
+    }
+
+    /* cleanup */
+    qemu_log("%s: destroy domain %d\n", __FUNCTION__, xen_domid);
+    xc_domain_destroy(xen_xc, xen_domid);
+    _exit(0);
+}
+
+/* normal cleanup */
+static void xen_domain_cleanup(void)
+{
+    char *dom;
+
+    dom = xs_get_domain_path(xenstore, xen_domid);
+    if (dom) {
+        xs_rm(xenstore, 0, dom);
+        free(dom);
+    }
+    xs_release_domain(xenstore, xen_domid);
+}
+
+int xen_domain_build_pv(const char *kernel, const char *ramdisk,
+                        const char *cmdline)
+{
+    uint32_t ssidref = 0;
+    uint32_t flags = 0;
+    xen_domain_handle_t uuid;
+    unsigned int xenstore_port = 0, console_port = 0;
+    unsigned long xenstore_mfn = 0, console_mfn = 0;
+    int rc;
+
+    memcpy(uuid, qemu_uuid, sizeof(uuid));
+    rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_create() failed\n");
+        goto err;
+    }
+    qemu_log("xen: created domain %d\n", xen_domid);
+    atexit(xen_domain_cleanup);
+    if (xen_domain_watcher() == -1) {
+        goto err;
+    }
+
+    xenstore_domain_init1(kernel, ramdisk, cmdline);
+
+    rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n");
+        goto err;
+    }
+
+#if 0
+    rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n");
+        goto err;
+    }
+#endif
+
+    rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size >> 10);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n");
+        goto err;
+    }
+
+    xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
+    console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
+
+    rc = xc_linux_build(xen_xc, xen_domid, ram_size >> 20,
+                        kernel, ramdisk, cmdline,
+                        0, flags,
+                        xenstore_port, &xenstore_mfn,
+                        console_port, &console_mfn);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_linux_build() failed\n");
+        goto err;
+    }
+
+    xenstore_domain_init2(xenstore_port, xenstore_mfn,
+                          console_port, console_mfn);
+
+    qemu_log("xen: unpausing domain %d\n", xen_domid);
+    rc = xc_domain_unpause(xen_xc, xen_domid);
+    if (rc < 0) {
+        fprintf(stderr, "xen: xc_domain_unpause() failed\n");
+        goto err;
+    }
+
+    xen_poll = timer_new_ms(QEMU_CLOCK_REALTIME, xen_domain_poll, NULL);
+    timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
+    return 0;
+
+err:
+    return -1;
+}
diff --git a/hw/xenpv/xen_domainbuild.h b/hw/xenpv/xen_domainbuild.h
new file mode 100644
index 0000000..29a91ea
--- /dev/null
+++ b/hw/xenpv/xen_domainbuild.h
@@ -0,0 +1,13 @@
+#ifndef QEMU_HW_XEN_DOMAINBUILD_H
+#define QEMU_HW_XEN_DOMAINBUILD_H 1
+
+#include "hw/xen/xen_common.h"
+
+int xenstore_domain_init1(const char *kernel, const char *ramdisk,
+                          const char *cmdline);
+int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
+                          int console_port, int console_mfn);
+int xen_domain_build_pv(const char *kernel, const char *ramdisk,
+                        const char *cmdline);
+
+#endif /* QEMU_HW_XEN_DOMAINBUILD_H */
diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c
new file mode 100644
index 0000000..9adb57f
--- /dev/null
+++ b/hw/xenpv/xen_machine_pv.c
@@ -0,0 +1,109 @@
+/*
+ * QEMU Xen PV Machine
+ *
+ * Copyright (c) 2007 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/xen/xen_backend.h"
+#include "xen_domainbuild.h"
+#include "sysemu/blockdev.h"
+
+static void xen_init_pv(QEMUMachineInitArgs *args)
+{
+    const char *kernel_filename = args->kernel_filename;
+    const char *kernel_cmdline = args->kernel_cmdline;
+    const char *initrd_filename = args->initrd_filename;
+    DriveInfo *dinfo;
+    int i;
+
+    /* Initialize backend core & drivers */
+    if (xen_be_init() != 0) {
+        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
+        exit(1);
+    }
+
+    switch (xen_mode) {
+    case XEN_ATTACH:
+        /* nothing to do, xend handles everything */
+        break;
+    case XEN_CREATE:
+        if (xen_domain_build_pv(kernel_filename, initrd_filename,
+                                kernel_cmdline) < 0) {
+            fprintf(stderr, "xen pv domain creation failed\n");
+            exit(1);
+        }
+        break;
+    case XEN_EMULATE:
+        fprintf(stderr, "xen emulation not implemented (yet)\n");
+        exit(1);
+        break;
+    }
+
+    xen_be_register("console", &xen_console_ops);
+    xen_be_register("vkbd", &xen_kbdmouse_ops);
+    xen_be_register("vfb", &xen_framebuffer_ops);
+    xen_be_register("qdisk", &xen_blkdev_ops);
+    xen_be_register("qnic", &xen_netdev_ops);
+
+    /* configure framebuffer */
+    if (xenfb_enabled) {
+        xen_config_dev_vfb(0, "vnc");
+        xen_config_dev_vkbd(0);
+    }
+
+    /* configure disks */
+    for (i = 0; i < 16; i++) {
+        dinfo = drive_get(IF_XEN, 0, i);
+        if (!dinfo)
+            continue;
+        xen_config_dev_blk(dinfo);
+    }
+
+    /* configure nics */
+    for (i = 0; i < nb_nics; i++) {
+        if (!nd_table[i].model || 0 != strcmp(nd_table[i].model, "xen"))
+            continue;
+        xen_config_dev_nic(nd_table + i);
+    }
+
+    /* config cleanup hook */
+    atexit(xen_config_cleanup);
+
+    /* setup framebuffer */
+    xen_init_display(xen_domid);
+}
+
+static QEMUMachine xenpv_machine = {
+    .name = "xenpv",
+    .desc = "Xen Para-virtualized PC",
+    .init = xen_init_pv,
+    .max_cpus = 1,
+    .default_machine_opts = "accel=xen",
+};
+
+static void xenpv_machine_init(void)
+{
+    qemu_register_machine(&xenpv_machine);
+}
+
+machine_init(xenpv_machine_init);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH resend 2/3] xen: move Xen HVM files under hw/i386/xen
  2014-03-25 15:59 ` Wei Liu
@ 2014-03-25 15:59   ` Wei Liu
  -1 siblings, 0 replies; 18+ messages in thread
From: Wei Liu @ 2014-03-25 15:59 UTC (permalink / raw)
  To: xen-devel, qemu-devel; +Cc: anthony.perard, Wei Liu, stefano.stabellini

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 hw/i386/Makefile.objs      |    2 +-
 hw/i386/xen/Makefile.objs  |    1 +
 hw/i386/xen/xen_apic.c     |   97 ++++++++++
 hw/i386/xen/xen_platform.c |  450 ++++++++++++++++++++++++++++++++++++++++++++
 hw/i386/xen/xen_pvdevice.c |  135 +++++++++++++
 hw/xen/Makefile.objs       |    1 -
 hw/xen/xen_apic.c          |   97 ----------
 hw/xen/xen_platform.c      |  450 --------------------------------------------
 hw/xen/xen_pvdevice.c      |  135 -------------
 9 files changed, 684 insertions(+), 684 deletions(-)
 create mode 100644 hw/i386/xen/Makefile.objs
 create mode 100644 hw/i386/xen/xen_apic.c
 create mode 100644 hw/i386/xen/xen_platform.c
 create mode 100644 hw/i386/xen/xen_pvdevice.c
 delete mode 100644 hw/xen/xen_apic.c
 delete mode 100644 hw/xen/xen_platform.c
 delete mode 100644 hw/xen/xen_pvdevice.c

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index f9899a3..f66c349 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -2,7 +2,7 @@ obj-$(CONFIG_KVM) += kvm/
 obj-y += multiboot.o smbios.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
-obj-$(CONFIG_XEN) += ../xenpv/
+obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
 obj-y += acpi-build.o
diff --git a/hw/i386/xen/Makefile.objs b/hw/i386/xen/Makefile.objs
new file mode 100644
index 0000000..801a68d
--- /dev/null
+++ b/hw/i386/xen/Makefile.objs
@@ -0,0 +1 @@
+obj-y += xen_platform.o xen_apic.o xen_pvdevice.o
diff --git a/hw/i386/xen/xen_apic.c b/hw/i386/xen/xen_apic.c
new file mode 100644
index 0000000..63bb7f7
--- /dev/null
+++ b/hw/i386/xen/xen_apic.c
@@ -0,0 +1,97 @@
+/*
+ * Xen basic APIC support
+ *
+ * Copyright (c) 2012 Citrix
+ *
+ * Authors:
+ *  Wei Liu <wei.liu2@citrix.com>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+#include "hw/i386/apic_internal.h"
+#include "hw/pci/msi.h"
+#include "hw/xen/xen.h"
+
+static uint64_t xen_apic_mem_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    return ~(uint64_t)0;
+}
+
+static void xen_apic_mem_write(void *opaque, hwaddr addr,
+                               uint64_t data, unsigned size)
+{
+    if (size != sizeof(uint32_t)) {
+        fprintf(stderr, "Xen: APIC write data size = %d, invalid\n", size);
+        return;
+    }
+
+    xen_hvm_inject_msi(addr, data);
+}
+
+static const MemoryRegionOps xen_apic_io_ops = {
+    .read = xen_apic_mem_read,
+    .write = xen_apic_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void xen_apic_realize(DeviceState *dev, Error **errp)
+{
+    APICCommonState *s = APIC_COMMON(dev);
+
+    memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s,
+                          "xen-apic-msi", APIC_SPACE_SIZE);
+
+#if defined(CONFIG_XEN_CTRL_INTERFACE_VERSION) \
+    && CONFIG_XEN_CTRL_INTERFACE_VERSION >= 420
+    msi_supported = true;
+#endif
+}
+
+static void xen_apic_set_base(APICCommonState *s, uint64_t val)
+{
+}
+
+static void xen_apic_set_tpr(APICCommonState *s, uint8_t val)
+{
+}
+
+static uint8_t xen_apic_get_tpr(APICCommonState *s)
+{
+    return 0;
+}
+
+static void xen_apic_vapic_base_update(APICCommonState *s)
+{
+}
+
+static void xen_apic_external_nmi(APICCommonState *s)
+{
+}
+
+static void xen_apic_class_init(ObjectClass *klass, void *data)
+{
+    APICCommonClass *k = APIC_COMMON_CLASS(klass);
+
+    k->realize = xen_apic_realize;
+    k->set_base = xen_apic_set_base;
+    k->set_tpr = xen_apic_set_tpr;
+    k->get_tpr = xen_apic_get_tpr;
+    k->vapic_base_update = xen_apic_vapic_base_update;
+    k->external_nmi = xen_apic_external_nmi;
+}
+
+static const TypeInfo xen_apic_info = {
+    .name = "xen-apic",
+    .parent = TYPE_APIC_COMMON,
+    .instance_size = sizeof(APICCommonState),
+    .class_init = xen_apic_class_init,
+};
+
+static void xen_apic_register_types(void)
+{
+    type_register_static(&xen_apic_info);
+}
+
+type_init(xen_apic_register_types)
diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
new file mode 100644
index 0000000..1d9d0e9
--- /dev/null
+++ b/hw/i386/xen/xen_platform.c
@@ -0,0 +1,450 @@
+/*
+ * XEN platform pci device, formerly known as the event channel device
+ *
+ * Copyright (c) 2003-2004 Intel Corp.
+ * Copyright (c) 2006 XenSource
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <assert.h>
+
+#include "hw/hw.h"
+#include "hw/i386/pc.h"
+#include "hw/ide.h"
+#include "hw/pci/pci.h"
+#include "hw/irq.h"
+#include "hw/xen/xen_common.h"
+#include "hw/xen/xen_backend.h"
+#include "trace.h"
+#include "exec/address-spaces.h"
+
+#include <xenguest.h>
+
+//#define DEBUG_PLATFORM
+
+#ifdef DEBUG_PLATFORM
+#define DPRINTF(fmt, ...) do { \
+    fprintf(stderr, "xen_platform: " fmt, ## __VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+#define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
+
+typedef struct PCIXenPlatformState {
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
+    MemoryRegion fixed_io;
+    MemoryRegion bar;
+    MemoryRegion mmio_bar;
+    uint8_t flags; /* used only for version_id == 2 */
+    int drivers_blacklisted;
+    uint16_t driver_product_version;
+
+    /* Log from guest drivers */
+    char log_buffer[4096];
+    int log_buffer_off;
+} PCIXenPlatformState;
+
+#define TYPE_XEN_PLATFORM "xen-platform"
+#define XEN_PLATFORM(obj) \
+    OBJECT_CHECK(PCIXenPlatformState, (obj), TYPE_XEN_PLATFORM)
+
+#define XEN_PLATFORM_IOPORT 0x10
+
+/* Send bytes to syslog */
+static void log_writeb(PCIXenPlatformState *s, char val)
+{
+    if (val == '\n' || s->log_buffer_off == sizeof(s->log_buffer) - 1) {
+        /* Flush buffer */
+        s->log_buffer[s->log_buffer_off] = 0;
+        trace_xen_platform_log(s->log_buffer);
+        s->log_buffer_off = 0;
+    } else {
+        s->log_buffer[s->log_buffer_off++] = val;
+    }
+}
+
+/* Xen Platform, Fixed IOPort */
+#define UNPLUG_ALL_IDE_DISKS 1
+#define UNPLUG_ALL_NICS 2
+#define UNPLUG_AUX_IDE_DISKS 4
+
+static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
+{
+    /* We have to ignore passthrough devices */
+    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
+            PCI_CLASS_NETWORK_ETHERNET
+            && strcmp(d->name, "xen-pci-passthrough") != 0) {
+        object_unparent(OBJECT(d));
+    }
+}
+
+static void pci_unplug_nics(PCIBus *bus)
+{
+    pci_for_each_device(bus, 0, unplug_nic, NULL);
+}
+
+static void unplug_disks(PCIBus *b, PCIDevice *d, void *o)
+{
+    /* We have to ignore passthrough devices */
+    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
+            PCI_CLASS_STORAGE_IDE
+            && strcmp(d->name, "xen-pci-passthrough") != 0) {
+        pci_piix3_xen_ide_unplug(DEVICE(d));
+    }
+}
+
+static void pci_unplug_disks(PCIBus *bus)
+{
+    pci_for_each_device(bus, 0, unplug_disks, NULL);
+}
+
+static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCIXenPlatformState *s = opaque;
+
+    switch (addr) {
+    case 0: {
+        PCIDevice *pci_dev = PCI_DEVICE(s);
+        /* Unplug devices.  Value is a bitmask of which devices to
+           unplug, with bit 0 the IDE devices, bit 1 the network
+           devices, and bit 2 the non-primary-master IDE devices. */
+        if (val & UNPLUG_ALL_IDE_DISKS) {
+            DPRINTF("unplug disks\n");
+            bdrv_drain_all();
+            bdrv_flush_all();
+            pci_unplug_disks(pci_dev->bus);
+        }
+        if (val & UNPLUG_ALL_NICS) {
+            DPRINTF("unplug nics\n");
+            pci_unplug_nics(pci_dev->bus);
+        }
+        if (val & UNPLUG_AUX_IDE_DISKS) {
+            DPRINTF("unplug auxiliary disks not supported\n");
+        }
+        break;
+    }
+    case 2:
+        switch (val) {
+        case 1:
+            DPRINTF("Citrix Windows PV drivers loaded in guest\n");
+            break;
+        case 0:
+            DPRINTF("Guest claimed to be running PV product 0?\n");
+            break;
+        default:
+            DPRINTF("Unknown PV product %d loaded in guest\n", val);
+            break;
+        }
+        s->driver_product_version = val;
+        break;
+    }
+}
+
+static void platform_fixed_ioport_writel(void *opaque, uint32_t addr,
+                                         uint32_t val)
+{
+    switch (addr) {
+    case 0:
+        /* PV driver version */
+        break;
+    }
+}
+
+static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCIXenPlatformState *s = opaque;
+
+    switch (addr) {
+    case 0: /* Platform flags */ {
+        hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
+            HVMMEM_ram_ro : HVMMEM_ram_rw;
+        if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type, 0xc0, 0x40)) {
+            DPRINTF("unable to change ro/rw state of ROM memory area!\n");
+        } else {
+            s->flags = val & PFFLAG_ROM_LOCK;
+            DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n",
+                    (mem_type == HVMMEM_ram_ro ? "ro":"rw"));
+        }
+        break;
+    }
+    case 2:
+        log_writeb(s, val);
+        break;
+    }
+}
+
+static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr)
+{
+    PCIXenPlatformState *s = opaque;
+
+    switch (addr) {
+    case 0:
+        if (s->drivers_blacklisted) {
+            /* The drivers will recognise this magic number and refuse
+             * to do anything. */
+            return 0xd249;
+        } else {
+            /* Magic value so that you can identify the interface. */
+            return 0x49d2;
+        }
+    default:
+        return 0xffff;
+    }
+}
+
+static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr)
+{
+    PCIXenPlatformState *s = opaque;
+
+    switch (addr) {
+    case 0:
+        /* Platform flags */
+        return s->flags;
+    case 2:
+        /* Version number */
+        return 1;
+    default:
+        return 0xff;
+    }
+}
+
+static void platform_fixed_ioport_reset(void *opaque)
+{
+    PCIXenPlatformState *s = opaque;
+
+    platform_fixed_ioport_writeb(s, 0, 0);
+}
+
+static uint64_t platform_fixed_ioport_read(void *opaque,
+                                           hwaddr addr,
+                                           unsigned size)
+{
+    switch (size) {
+    case 1:
+        return platform_fixed_ioport_readb(opaque, addr);
+    case 2:
+        return platform_fixed_ioport_readw(opaque, addr);
+    default:
+        return -1;
+    }
+}
+
+static void platform_fixed_ioport_write(void *opaque, hwaddr addr,
+
+                                        uint64_t val, unsigned size)
+{
+    switch (size) {
+    case 1:
+        platform_fixed_ioport_writeb(opaque, addr, val);
+        break;
+    case 2:
+        platform_fixed_ioport_writew(opaque, addr, val);
+        break;
+    case 4:
+        platform_fixed_ioport_writel(opaque, addr, val);
+        break;
+    }
+}
+
+
+static const MemoryRegionOps platform_fixed_io_ops = {
+    .read = platform_fixed_ioport_read,
+    .write = platform_fixed_ioport_write,
+    .valid = {
+        .unaligned = true,
+    },
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+        .unaligned = true,
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void platform_fixed_ioport_init(PCIXenPlatformState* s)
+{
+    memory_region_init_io(&s->fixed_io, OBJECT(s), &platform_fixed_io_ops, s,
+                          "xen-fixed", 16);
+    memory_region_add_subregion(get_system_io(), XEN_PLATFORM_IOPORT,
+                                &s->fixed_io);
+}
+
+/* Xen Platform PCI Device */
+
+static uint64_t xen_platform_ioport_readb(void *opaque, hwaddr addr,
+                                          unsigned int size)
+{
+    if (addr == 0) {
+        return platform_fixed_ioport_readb(opaque, 0);
+    } else {
+        return ~0u;
+    }
+}
+
+static void xen_platform_ioport_writeb(void *opaque, hwaddr addr,
+                                       uint64_t val, unsigned int size)
+{
+    PCIXenPlatformState *s = opaque;
+
+    switch (addr) {
+    case 0: /* Platform flags */
+        platform_fixed_ioport_writeb(opaque, 0, (uint32_t)val);
+        break;
+    case 8:
+        log_writeb(s, (uint32_t)val);
+        break;
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps xen_pci_io_ops = {
+    .read  = xen_platform_ioport_readb,
+    .write = xen_platform_ioport_writeb,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 1,
+};
+
+static void platform_ioport_bar_setup(PCIXenPlatformState *d)
+{
+    memory_region_init_io(&d->bar, OBJECT(d), &xen_pci_io_ops, d,
+                          "xen-pci", 0x100);
+}
+
+static uint64_t platform_mmio_read(void *opaque, hwaddr addr,
+                                   unsigned size)
+{
+    DPRINTF("Warning: attempted read from physical address "
+            "0x" TARGET_FMT_plx " in xen platform mmio space\n", addr);
+
+    return 0;
+}
+
+static void platform_mmio_write(void *opaque, hwaddr addr,
+                                uint64_t val, unsigned size)
+{
+    DPRINTF("Warning: attempted write of 0x%"PRIx64" to physical "
+            "address 0x" TARGET_FMT_plx " in xen platform mmio space\n",
+            val, addr);
+}
+
+static const MemoryRegionOps platform_mmio_handler = {
+    .read = &platform_mmio_read,
+    .write = &platform_mmio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void platform_mmio_setup(PCIXenPlatformState *d)
+{
+    memory_region_init_io(&d->mmio_bar, OBJECT(d), &platform_mmio_handler, d,
+                          "xen-mmio", 0x1000000);
+}
+
+static int xen_platform_post_load(void *opaque, int version_id)
+{
+    PCIXenPlatformState *s = opaque;
+
+    platform_fixed_ioport_writeb(s, 0, s->flags);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_xen_platform = {
+    .name = "platform",
+    .version_id = 4,
+    .minimum_version_id = 4,
+    .minimum_version_id_old = 4,
+    .post_load = xen_platform_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(parent_obj, PCIXenPlatformState),
+        VMSTATE_UINT8(flags, PCIXenPlatformState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int xen_platform_initfn(PCIDevice *dev)
+{
+    PCIXenPlatformState *d = XEN_PLATFORM(dev);
+    uint8_t *pci_conf;
+
+    pci_conf = dev->config;
+
+    pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+
+    pci_config_set_prog_interface(pci_conf, 0);
+
+    pci_conf[PCI_INTERRUPT_PIN] = 1;
+
+    platform_ioport_bar_setup(d);
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->bar);
+
+    /* reserve 16MB mmio address for share memory*/
+    platform_mmio_setup(d);
+    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                     &d->mmio_bar);
+
+    platform_fixed_ioport_init(d);
+
+    return 0;
+}
+
+static void platform_reset(DeviceState *dev)
+{
+    PCIXenPlatformState *s = XEN_PLATFORM(dev);
+
+    platform_fixed_ioport_reset(s);
+}
+
+static void xen_platform_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = xen_platform_initfn;
+    k->vendor_id = PCI_VENDOR_ID_XEN;
+    k->device_id = PCI_DEVICE_ID_XEN_PLATFORM;
+    k->class_id = PCI_CLASS_OTHERS << 8 | 0x80;
+    k->subsystem_vendor_id = PCI_VENDOR_ID_XEN;
+    k->subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM;
+    k->revision = 1;
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    dc->desc = "XEN platform pci device";
+    dc->reset = platform_reset;
+    dc->vmsd = &vmstate_xen_platform;
+}
+
+static const TypeInfo xen_platform_info = {
+    .name          = TYPE_XEN_PLATFORM,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIXenPlatformState),
+    .class_init    = xen_platform_class_init,
+};
+
+static void xen_platform_register_types(void)
+{
+    type_register_static(&xen_platform_info);
+}
+
+type_init(xen_platform_register_types)
diff --git a/hw/i386/xen/xen_pvdevice.c b/hw/i386/xen/xen_pvdevice.c
new file mode 100644
index 0000000..c218947
--- /dev/null
+++ b/hw/i386/xen/xen_pvdevice.c
@@ -0,0 +1,135 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "trace.h"
+
+#define TYPE_XEN_PV_DEVICE  "xen-pvdevice"
+
+#define XEN_PV_DEVICE(obj) \
+     OBJECT_CHECK(XenPVDevice, (obj), TYPE_XEN_PV_DEVICE)
+
+typedef struct XenPVDevice {
+    /*< private >*/
+    PCIDevice       parent_obj;
+    /*< public >*/
+    uint16_t        vendor_id;
+    uint16_t        device_id;
+    uint8_t         revision;
+    uint32_t        size;
+    MemoryRegion    mmio;
+} XenPVDevice;
+
+static uint64_t xen_pv_mmio_read(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    trace_xen_pv_mmio_read(addr);
+
+    return ~(uint64_t)0;
+}
+
+static void xen_pv_mmio_write(void *opaque, hwaddr addr,
+                              uint64_t val, unsigned size)
+{
+    trace_xen_pv_mmio_write(addr);
+}
+
+static const MemoryRegionOps xen_pv_mmio_ops = {
+    .read = &xen_pv_mmio_read,
+    .write = &xen_pv_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int xen_pv_init(PCIDevice *pci_dev)
+{
+    XenPVDevice *d = XEN_PV_DEVICE(pci_dev);
+    uint8_t *pci_conf;
+
+    /* device-id property must always be supplied */
+    if (d->device_id == 0xffff)
+	    return -1;
+
+    pci_conf = pci_dev->config;
+
+    pci_set_word(pci_conf + PCI_VENDOR_ID, d->vendor_id);
+    pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, d->vendor_id);
+    pci_set_word(pci_conf + PCI_DEVICE_ID, d->device_id);
+    pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, d->device_id);
+    pci_set_byte(pci_conf + PCI_REVISION_ID, d->revision);
+
+    pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_MEMORY);
+
+    pci_config_set_prog_interface(pci_conf, 0);
+
+    pci_conf[PCI_INTERRUPT_PIN] = 1;
+
+    memory_region_init_io(&d->mmio, NULL, &xen_pv_mmio_ops, d,
+                          "mmio", d->size);
+
+    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                     &d->mmio);
+
+    return 0;
+}
+
+static Property xen_pv_props[] = {
+    DEFINE_PROP_UINT16("vendor-id", XenPVDevice, vendor_id, PCI_VENDOR_ID_XEN),
+    DEFINE_PROP_UINT16("device-id", XenPVDevice, device_id, 0xffff),
+    DEFINE_PROP_UINT8("revision", XenPVDevice, revision, 0x01),
+    DEFINE_PROP_UINT32("size", XenPVDevice, size, 0x400000),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void xen_pv_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = xen_pv_init;
+    k->class_id = PCI_CLASS_SYSTEM_OTHER;
+    dc->desc = "Xen PV Device";
+    dc->props = xen_pv_props;
+}
+
+static const TypeInfo xen_pv_type_info = {
+    .name          = TYPE_XEN_PV_DEVICE,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(XenPVDevice),
+    .class_init    = xen_pv_class_init,
+};
+
+static void xen_pv_register_types(void)
+{
+    type_register_static(&xen_pv_type_info);
+}
+
+type_init(xen_pv_register_types)
diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs
index ce640c6..a0ca0aa 100644
--- a/hw/xen/Makefile.objs
+++ b/hw/xen/Makefile.objs
@@ -1,6 +1,5 @@
 # xen backend driver support
 common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
 
-obj-$(CONFIG_XEN_I386) += xen_platform.o xen_apic.o xen_pvdevice.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
diff --git a/hw/xen/xen_apic.c b/hw/xen/xen_apic.c
deleted file mode 100644
index 63bb7f7..0000000
--- a/hw/xen/xen_apic.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Xen basic APIC support
- *
- * Copyright (c) 2012 Citrix
- *
- * Authors:
- *  Wei Liu <wei.liu2@citrix.com>
- *
- * This work is licensed under the terms of the GNU GPL version 2 or
- * later. See the COPYING file in the top-level directory.
- */
-#include "hw/i386/apic_internal.h"
-#include "hw/pci/msi.h"
-#include "hw/xen/xen.h"
-
-static uint64_t xen_apic_mem_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    return ~(uint64_t)0;
-}
-
-static void xen_apic_mem_write(void *opaque, hwaddr addr,
-                               uint64_t data, unsigned size)
-{
-    if (size != sizeof(uint32_t)) {
-        fprintf(stderr, "Xen: APIC write data size = %d, invalid\n", size);
-        return;
-    }
-
-    xen_hvm_inject_msi(addr, data);
-}
-
-static const MemoryRegionOps xen_apic_io_ops = {
-    .read = xen_apic_mem_read,
-    .write = xen_apic_mem_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void xen_apic_realize(DeviceState *dev, Error **errp)
-{
-    APICCommonState *s = APIC_COMMON(dev);
-
-    memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s,
-                          "xen-apic-msi", APIC_SPACE_SIZE);
-
-#if defined(CONFIG_XEN_CTRL_INTERFACE_VERSION) \
-    && CONFIG_XEN_CTRL_INTERFACE_VERSION >= 420
-    msi_supported = true;
-#endif
-}
-
-static void xen_apic_set_base(APICCommonState *s, uint64_t val)
-{
-}
-
-static void xen_apic_set_tpr(APICCommonState *s, uint8_t val)
-{
-}
-
-static uint8_t xen_apic_get_tpr(APICCommonState *s)
-{
-    return 0;
-}
-
-static void xen_apic_vapic_base_update(APICCommonState *s)
-{
-}
-
-static void xen_apic_external_nmi(APICCommonState *s)
-{
-}
-
-static void xen_apic_class_init(ObjectClass *klass, void *data)
-{
-    APICCommonClass *k = APIC_COMMON_CLASS(klass);
-
-    k->realize = xen_apic_realize;
-    k->set_base = xen_apic_set_base;
-    k->set_tpr = xen_apic_set_tpr;
-    k->get_tpr = xen_apic_get_tpr;
-    k->vapic_base_update = xen_apic_vapic_base_update;
-    k->external_nmi = xen_apic_external_nmi;
-}
-
-static const TypeInfo xen_apic_info = {
-    .name = "xen-apic",
-    .parent = TYPE_APIC_COMMON,
-    .instance_size = sizeof(APICCommonState),
-    .class_init = xen_apic_class_init,
-};
-
-static void xen_apic_register_types(void)
-{
-    type_register_static(&xen_apic_info);
-}
-
-type_init(xen_apic_register_types)
diff --git a/hw/xen/xen_platform.c b/hw/xen/xen_platform.c
deleted file mode 100644
index 1d9d0e9..0000000
--- a/hw/xen/xen_platform.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * XEN platform pci device, formerly known as the event channel device
- *
- * Copyright (c) 2003-2004 Intel Corp.
- * Copyright (c) 2006 XenSource
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <assert.h>
-
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/ide.h"
-#include "hw/pci/pci.h"
-#include "hw/irq.h"
-#include "hw/xen/xen_common.h"
-#include "hw/xen/xen_backend.h"
-#include "trace.h"
-#include "exec/address-spaces.h"
-
-#include <xenguest.h>
-
-//#define DEBUG_PLATFORM
-
-#ifdef DEBUG_PLATFORM
-#define DPRINTF(fmt, ...) do { \
-    fprintf(stderr, "xen_platform: " fmt, ## __VA_ARGS__); \
-} while (0)
-#else
-#define DPRINTF(fmt, ...) do { } while (0)
-#endif
-
-#define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
-
-typedef struct PCIXenPlatformState {
-    /*< private >*/
-    PCIDevice parent_obj;
-    /*< public >*/
-
-    MemoryRegion fixed_io;
-    MemoryRegion bar;
-    MemoryRegion mmio_bar;
-    uint8_t flags; /* used only for version_id == 2 */
-    int drivers_blacklisted;
-    uint16_t driver_product_version;
-
-    /* Log from guest drivers */
-    char log_buffer[4096];
-    int log_buffer_off;
-} PCIXenPlatformState;
-
-#define TYPE_XEN_PLATFORM "xen-platform"
-#define XEN_PLATFORM(obj) \
-    OBJECT_CHECK(PCIXenPlatformState, (obj), TYPE_XEN_PLATFORM)
-
-#define XEN_PLATFORM_IOPORT 0x10
-
-/* Send bytes to syslog */
-static void log_writeb(PCIXenPlatformState *s, char val)
-{
-    if (val == '\n' || s->log_buffer_off == sizeof(s->log_buffer) - 1) {
-        /* Flush buffer */
-        s->log_buffer[s->log_buffer_off] = 0;
-        trace_xen_platform_log(s->log_buffer);
-        s->log_buffer_off = 0;
-    } else {
-        s->log_buffer[s->log_buffer_off++] = val;
-    }
-}
-
-/* Xen Platform, Fixed IOPort */
-#define UNPLUG_ALL_IDE_DISKS 1
-#define UNPLUG_ALL_NICS 2
-#define UNPLUG_AUX_IDE_DISKS 4
-
-static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
-{
-    /* We have to ignore passthrough devices */
-    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
-            PCI_CLASS_NETWORK_ETHERNET
-            && strcmp(d->name, "xen-pci-passthrough") != 0) {
-        object_unparent(OBJECT(d));
-    }
-}
-
-static void pci_unplug_nics(PCIBus *bus)
-{
-    pci_for_each_device(bus, 0, unplug_nic, NULL);
-}
-
-static void unplug_disks(PCIBus *b, PCIDevice *d, void *o)
-{
-    /* We have to ignore passthrough devices */
-    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
-            PCI_CLASS_STORAGE_IDE
-            && strcmp(d->name, "xen-pci-passthrough") != 0) {
-        pci_piix3_xen_ide_unplug(DEVICE(d));
-    }
-}
-
-static void pci_unplug_disks(PCIBus *bus)
-{
-    pci_for_each_device(bus, 0, unplug_disks, NULL);
-}
-
-static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
-    PCIXenPlatformState *s = opaque;
-
-    switch (addr) {
-    case 0: {
-        PCIDevice *pci_dev = PCI_DEVICE(s);
-        /* Unplug devices.  Value is a bitmask of which devices to
-           unplug, with bit 0 the IDE devices, bit 1 the network
-           devices, and bit 2 the non-primary-master IDE devices. */
-        if (val & UNPLUG_ALL_IDE_DISKS) {
-            DPRINTF("unplug disks\n");
-            bdrv_drain_all();
-            bdrv_flush_all();
-            pci_unplug_disks(pci_dev->bus);
-        }
-        if (val & UNPLUG_ALL_NICS) {
-            DPRINTF("unplug nics\n");
-            pci_unplug_nics(pci_dev->bus);
-        }
-        if (val & UNPLUG_AUX_IDE_DISKS) {
-            DPRINTF("unplug auxiliary disks not supported\n");
-        }
-        break;
-    }
-    case 2:
-        switch (val) {
-        case 1:
-            DPRINTF("Citrix Windows PV drivers loaded in guest\n");
-            break;
-        case 0:
-            DPRINTF("Guest claimed to be running PV product 0?\n");
-            break;
-        default:
-            DPRINTF("Unknown PV product %d loaded in guest\n", val);
-            break;
-        }
-        s->driver_product_version = val;
-        break;
-    }
-}
-
-static void platform_fixed_ioport_writel(void *opaque, uint32_t addr,
-                                         uint32_t val)
-{
-    switch (addr) {
-    case 0:
-        /* PV driver version */
-        break;
-    }
-}
-
-static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
-    PCIXenPlatformState *s = opaque;
-
-    switch (addr) {
-    case 0: /* Platform flags */ {
-        hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
-            HVMMEM_ram_ro : HVMMEM_ram_rw;
-        if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type, 0xc0, 0x40)) {
-            DPRINTF("unable to change ro/rw state of ROM memory area!\n");
-        } else {
-            s->flags = val & PFFLAG_ROM_LOCK;
-            DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n",
-                    (mem_type == HVMMEM_ram_ro ? "ro":"rw"));
-        }
-        break;
-    }
-    case 2:
-        log_writeb(s, val);
-        break;
-    }
-}
-
-static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr)
-{
-    PCIXenPlatformState *s = opaque;
-
-    switch (addr) {
-    case 0:
-        if (s->drivers_blacklisted) {
-            /* The drivers will recognise this magic number and refuse
-             * to do anything. */
-            return 0xd249;
-        } else {
-            /* Magic value so that you can identify the interface. */
-            return 0x49d2;
-        }
-    default:
-        return 0xffff;
-    }
-}
-
-static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr)
-{
-    PCIXenPlatformState *s = opaque;
-
-    switch (addr) {
-    case 0:
-        /* Platform flags */
-        return s->flags;
-    case 2:
-        /* Version number */
-        return 1;
-    default:
-        return 0xff;
-    }
-}
-
-static void platform_fixed_ioport_reset(void *opaque)
-{
-    PCIXenPlatformState *s = opaque;
-
-    platform_fixed_ioport_writeb(s, 0, 0);
-}
-
-static uint64_t platform_fixed_ioport_read(void *opaque,
-                                           hwaddr addr,
-                                           unsigned size)
-{
-    switch (size) {
-    case 1:
-        return platform_fixed_ioport_readb(opaque, addr);
-    case 2:
-        return platform_fixed_ioport_readw(opaque, addr);
-    default:
-        return -1;
-    }
-}
-
-static void platform_fixed_ioport_write(void *opaque, hwaddr addr,
-
-                                        uint64_t val, unsigned size)
-{
-    switch (size) {
-    case 1:
-        platform_fixed_ioport_writeb(opaque, addr, val);
-        break;
-    case 2:
-        platform_fixed_ioport_writew(opaque, addr, val);
-        break;
-    case 4:
-        platform_fixed_ioport_writel(opaque, addr, val);
-        break;
-    }
-}
-
-
-static const MemoryRegionOps platform_fixed_io_ops = {
-    .read = platform_fixed_ioport_read,
-    .write = platform_fixed_ioport_write,
-    .valid = {
-        .unaligned = true,
-    },
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 4,
-        .unaligned = true,
-    },
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void platform_fixed_ioport_init(PCIXenPlatformState* s)
-{
-    memory_region_init_io(&s->fixed_io, OBJECT(s), &platform_fixed_io_ops, s,
-                          "xen-fixed", 16);
-    memory_region_add_subregion(get_system_io(), XEN_PLATFORM_IOPORT,
-                                &s->fixed_io);
-}
-
-/* Xen Platform PCI Device */
-
-static uint64_t xen_platform_ioport_readb(void *opaque, hwaddr addr,
-                                          unsigned int size)
-{
-    if (addr == 0) {
-        return platform_fixed_ioport_readb(opaque, 0);
-    } else {
-        return ~0u;
-    }
-}
-
-static void xen_platform_ioport_writeb(void *opaque, hwaddr addr,
-                                       uint64_t val, unsigned int size)
-{
-    PCIXenPlatformState *s = opaque;
-
-    switch (addr) {
-    case 0: /* Platform flags */
-        platform_fixed_ioport_writeb(opaque, 0, (uint32_t)val);
-        break;
-    case 8:
-        log_writeb(s, (uint32_t)val);
-        break;
-    default:
-        break;
-    }
-}
-
-static const MemoryRegionOps xen_pci_io_ops = {
-    .read  = xen_platform_ioport_readb,
-    .write = xen_platform_ioport_writeb,
-    .impl.min_access_size = 1,
-    .impl.max_access_size = 1,
-};
-
-static void platform_ioport_bar_setup(PCIXenPlatformState *d)
-{
-    memory_region_init_io(&d->bar, OBJECT(d), &xen_pci_io_ops, d,
-                          "xen-pci", 0x100);
-}
-
-static uint64_t platform_mmio_read(void *opaque, hwaddr addr,
-                                   unsigned size)
-{
-    DPRINTF("Warning: attempted read from physical address "
-            "0x" TARGET_FMT_plx " in xen platform mmio space\n", addr);
-
-    return 0;
-}
-
-static void platform_mmio_write(void *opaque, hwaddr addr,
-                                uint64_t val, unsigned size)
-{
-    DPRINTF("Warning: attempted write of 0x%"PRIx64" to physical "
-            "address 0x" TARGET_FMT_plx " in xen platform mmio space\n",
-            val, addr);
-}
-
-static const MemoryRegionOps platform_mmio_handler = {
-    .read = &platform_mmio_read,
-    .write = &platform_mmio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void platform_mmio_setup(PCIXenPlatformState *d)
-{
-    memory_region_init_io(&d->mmio_bar, OBJECT(d), &platform_mmio_handler, d,
-                          "xen-mmio", 0x1000000);
-}
-
-static int xen_platform_post_load(void *opaque, int version_id)
-{
-    PCIXenPlatformState *s = opaque;
-
-    platform_fixed_ioport_writeb(s, 0, s->flags);
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_xen_platform = {
-    .name = "platform",
-    .version_id = 4,
-    .minimum_version_id = 4,
-    .minimum_version_id_old = 4,
-    .post_load = xen_platform_post_load,
-    .fields = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(parent_obj, PCIXenPlatformState),
-        VMSTATE_UINT8(flags, PCIXenPlatformState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int xen_platform_initfn(PCIDevice *dev)
-{
-    PCIXenPlatformState *d = XEN_PLATFORM(dev);
-    uint8_t *pci_conf;
-
-    pci_conf = dev->config;
-
-    pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-
-    pci_config_set_prog_interface(pci_conf, 0);
-
-    pci_conf[PCI_INTERRUPT_PIN] = 1;
-
-    platform_ioport_bar_setup(d);
-    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->bar);
-
-    /* reserve 16MB mmio address for share memory*/
-    platform_mmio_setup(d);
-    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
-                     &d->mmio_bar);
-
-    platform_fixed_ioport_init(d);
-
-    return 0;
-}
-
-static void platform_reset(DeviceState *dev)
-{
-    PCIXenPlatformState *s = XEN_PLATFORM(dev);
-
-    platform_fixed_ioport_reset(s);
-}
-
-static void xen_platform_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = xen_platform_initfn;
-    k->vendor_id = PCI_VENDOR_ID_XEN;
-    k->device_id = PCI_DEVICE_ID_XEN_PLATFORM;
-    k->class_id = PCI_CLASS_OTHERS << 8 | 0x80;
-    k->subsystem_vendor_id = PCI_VENDOR_ID_XEN;
-    k->subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM;
-    k->revision = 1;
-    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-    dc->desc = "XEN platform pci device";
-    dc->reset = platform_reset;
-    dc->vmsd = &vmstate_xen_platform;
-}
-
-static const TypeInfo xen_platform_info = {
-    .name          = TYPE_XEN_PLATFORM,
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIXenPlatformState),
-    .class_init    = xen_platform_class_init,
-};
-
-static void xen_platform_register_types(void)
-{
-    type_register_static(&xen_platform_info);
-}
-
-type_init(xen_platform_register_types)
diff --git a/hw/xen/xen_pvdevice.c b/hw/xen/xen_pvdevice.c
deleted file mode 100644
index c218947..0000000
--- a/hw/xen/xen_pvdevice.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms,
- * with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * *   Redistributions of source code must retain the above
- *     copyright notice, this list of conditions and the
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the
- *     following disclaimer in the documentation and/or other
- *     materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "hw/hw.h"
-#include "hw/pci/pci.h"
-#include "trace.h"
-
-#define TYPE_XEN_PV_DEVICE  "xen-pvdevice"
-
-#define XEN_PV_DEVICE(obj) \
-     OBJECT_CHECK(XenPVDevice, (obj), TYPE_XEN_PV_DEVICE)
-
-typedef struct XenPVDevice {
-    /*< private >*/
-    PCIDevice       parent_obj;
-    /*< public >*/
-    uint16_t        vendor_id;
-    uint16_t        device_id;
-    uint8_t         revision;
-    uint32_t        size;
-    MemoryRegion    mmio;
-} XenPVDevice;
-
-static uint64_t xen_pv_mmio_read(void *opaque, hwaddr addr,
-                                 unsigned size)
-{
-    trace_xen_pv_mmio_read(addr);
-
-    return ~(uint64_t)0;
-}
-
-static void xen_pv_mmio_write(void *opaque, hwaddr addr,
-                              uint64_t val, unsigned size)
-{
-    trace_xen_pv_mmio_write(addr);
-}
-
-static const MemoryRegionOps xen_pv_mmio_ops = {
-    .read = &xen_pv_mmio_read,
-    .write = &xen_pv_mmio_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static int xen_pv_init(PCIDevice *pci_dev)
-{
-    XenPVDevice *d = XEN_PV_DEVICE(pci_dev);
-    uint8_t *pci_conf;
-
-    /* device-id property must always be supplied */
-    if (d->device_id == 0xffff)
-	    return -1;
-
-    pci_conf = pci_dev->config;
-
-    pci_set_word(pci_conf + PCI_VENDOR_ID, d->vendor_id);
-    pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, d->vendor_id);
-    pci_set_word(pci_conf + PCI_DEVICE_ID, d->device_id);
-    pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, d->device_id);
-    pci_set_byte(pci_conf + PCI_REVISION_ID, d->revision);
-
-    pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_MEMORY);
-
-    pci_config_set_prog_interface(pci_conf, 0);
-
-    pci_conf[PCI_INTERRUPT_PIN] = 1;
-
-    memory_region_init_io(&d->mmio, NULL, &xen_pv_mmio_ops, d,
-                          "mmio", d->size);
-
-    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
-                     &d->mmio);
-
-    return 0;
-}
-
-static Property xen_pv_props[] = {
-    DEFINE_PROP_UINT16("vendor-id", XenPVDevice, vendor_id, PCI_VENDOR_ID_XEN),
-    DEFINE_PROP_UINT16("device-id", XenPVDevice, device_id, 0xffff),
-    DEFINE_PROP_UINT8("revision", XenPVDevice, revision, 0x01),
-    DEFINE_PROP_UINT32("size", XenPVDevice, size, 0x400000),
-    DEFINE_PROP_END_OF_LIST()
-};
-
-static void xen_pv_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = xen_pv_init;
-    k->class_id = PCI_CLASS_SYSTEM_OTHER;
-    dc->desc = "Xen PV Device";
-    dc->props = xen_pv_props;
-}
-
-static const TypeInfo xen_pv_type_info = {
-    .name          = TYPE_XEN_PV_DEVICE,
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(XenPVDevice),
-    .class_init    = xen_pv_class_init,
-};
-
-static void xen_pv_register_types(void)
-{
-    type_register_static(&xen_pv_type_info);
-}
-
-type_init(xen_pv_register_types)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH resend 2/3] xen: move Xen HVM files under hw/i386/xen
@ 2014-03-25 15:59   ` Wei Liu
  0 siblings, 0 replies; 18+ messages in thread
From: Wei Liu @ 2014-03-25 15:59 UTC (permalink / raw)
  To: xen-devel, qemu-devel; +Cc: anthony.perard, Wei Liu, stefano.stabellini

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 hw/i386/Makefile.objs      |    2 +-
 hw/i386/xen/Makefile.objs  |    1 +
 hw/i386/xen/xen_apic.c     |   97 ++++++++++
 hw/i386/xen/xen_platform.c |  450 ++++++++++++++++++++++++++++++++++++++++++++
 hw/i386/xen/xen_pvdevice.c |  135 +++++++++++++
 hw/xen/Makefile.objs       |    1 -
 hw/xen/xen_apic.c          |   97 ----------
 hw/xen/xen_platform.c      |  450 --------------------------------------------
 hw/xen/xen_pvdevice.c      |  135 -------------
 9 files changed, 684 insertions(+), 684 deletions(-)
 create mode 100644 hw/i386/xen/Makefile.objs
 create mode 100644 hw/i386/xen/xen_apic.c
 create mode 100644 hw/i386/xen/xen_platform.c
 create mode 100644 hw/i386/xen/xen_pvdevice.c
 delete mode 100644 hw/xen/xen_apic.c
 delete mode 100644 hw/xen/xen_platform.c
 delete mode 100644 hw/xen/xen_pvdevice.c

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index f9899a3..f66c349 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -2,7 +2,7 @@ obj-$(CONFIG_KVM) += kvm/
 obj-y += multiboot.o smbios.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
-obj-$(CONFIG_XEN) += ../xenpv/
+obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
 obj-y += acpi-build.o
diff --git a/hw/i386/xen/Makefile.objs b/hw/i386/xen/Makefile.objs
new file mode 100644
index 0000000..801a68d
--- /dev/null
+++ b/hw/i386/xen/Makefile.objs
@@ -0,0 +1 @@
+obj-y += xen_platform.o xen_apic.o xen_pvdevice.o
diff --git a/hw/i386/xen/xen_apic.c b/hw/i386/xen/xen_apic.c
new file mode 100644
index 0000000..63bb7f7
--- /dev/null
+++ b/hw/i386/xen/xen_apic.c
@@ -0,0 +1,97 @@
+/*
+ * Xen basic APIC support
+ *
+ * Copyright (c) 2012 Citrix
+ *
+ * Authors:
+ *  Wei Liu <wei.liu2@citrix.com>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+#include "hw/i386/apic_internal.h"
+#include "hw/pci/msi.h"
+#include "hw/xen/xen.h"
+
+static uint64_t xen_apic_mem_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    return ~(uint64_t)0;
+}
+
+static void xen_apic_mem_write(void *opaque, hwaddr addr,
+                               uint64_t data, unsigned size)
+{
+    if (size != sizeof(uint32_t)) {
+        fprintf(stderr, "Xen: APIC write data size = %d, invalid\n", size);
+        return;
+    }
+
+    xen_hvm_inject_msi(addr, data);
+}
+
+static const MemoryRegionOps xen_apic_io_ops = {
+    .read = xen_apic_mem_read,
+    .write = xen_apic_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void xen_apic_realize(DeviceState *dev, Error **errp)
+{
+    APICCommonState *s = APIC_COMMON(dev);
+
+    memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s,
+                          "xen-apic-msi", APIC_SPACE_SIZE);
+
+#if defined(CONFIG_XEN_CTRL_INTERFACE_VERSION) \
+    && CONFIG_XEN_CTRL_INTERFACE_VERSION >= 420
+    msi_supported = true;
+#endif
+}
+
+static void xen_apic_set_base(APICCommonState *s, uint64_t val)
+{
+}
+
+static void xen_apic_set_tpr(APICCommonState *s, uint8_t val)
+{
+}
+
+static uint8_t xen_apic_get_tpr(APICCommonState *s)
+{
+    return 0;
+}
+
+static void xen_apic_vapic_base_update(APICCommonState *s)
+{
+}
+
+static void xen_apic_external_nmi(APICCommonState *s)
+{
+}
+
+static void xen_apic_class_init(ObjectClass *klass, void *data)
+{
+    APICCommonClass *k = APIC_COMMON_CLASS(klass);
+
+    k->realize = xen_apic_realize;
+    k->set_base = xen_apic_set_base;
+    k->set_tpr = xen_apic_set_tpr;
+    k->get_tpr = xen_apic_get_tpr;
+    k->vapic_base_update = xen_apic_vapic_base_update;
+    k->external_nmi = xen_apic_external_nmi;
+}
+
+static const TypeInfo xen_apic_info = {
+    .name = "xen-apic",
+    .parent = TYPE_APIC_COMMON,
+    .instance_size = sizeof(APICCommonState),
+    .class_init = xen_apic_class_init,
+};
+
+static void xen_apic_register_types(void)
+{
+    type_register_static(&xen_apic_info);
+}
+
+type_init(xen_apic_register_types)
diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
new file mode 100644
index 0000000..1d9d0e9
--- /dev/null
+++ b/hw/i386/xen/xen_platform.c
@@ -0,0 +1,450 @@
+/*
+ * XEN platform pci device, formerly known as the event channel device
+ *
+ * Copyright (c) 2003-2004 Intel Corp.
+ * Copyright (c) 2006 XenSource
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <assert.h>
+
+#include "hw/hw.h"
+#include "hw/i386/pc.h"
+#include "hw/ide.h"
+#include "hw/pci/pci.h"
+#include "hw/irq.h"
+#include "hw/xen/xen_common.h"
+#include "hw/xen/xen_backend.h"
+#include "trace.h"
+#include "exec/address-spaces.h"
+
+#include <xenguest.h>
+
+//#define DEBUG_PLATFORM
+
+#ifdef DEBUG_PLATFORM
+#define DPRINTF(fmt, ...) do { \
+    fprintf(stderr, "xen_platform: " fmt, ## __VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+#define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
+
+typedef struct PCIXenPlatformState {
+    /*< private >*/
+    PCIDevice parent_obj;
+    /*< public >*/
+
+    MemoryRegion fixed_io;
+    MemoryRegion bar;
+    MemoryRegion mmio_bar;
+    uint8_t flags; /* used only for version_id == 2 */
+    int drivers_blacklisted;
+    uint16_t driver_product_version;
+
+    /* Log from guest drivers */
+    char log_buffer[4096];
+    int log_buffer_off;
+} PCIXenPlatformState;
+
+#define TYPE_XEN_PLATFORM "xen-platform"
+#define XEN_PLATFORM(obj) \
+    OBJECT_CHECK(PCIXenPlatformState, (obj), TYPE_XEN_PLATFORM)
+
+#define XEN_PLATFORM_IOPORT 0x10
+
+/* Send bytes to syslog */
+static void log_writeb(PCIXenPlatformState *s, char val)
+{
+    if (val == '\n' || s->log_buffer_off == sizeof(s->log_buffer) - 1) {
+        /* Flush buffer */
+        s->log_buffer[s->log_buffer_off] = 0;
+        trace_xen_platform_log(s->log_buffer);
+        s->log_buffer_off = 0;
+    } else {
+        s->log_buffer[s->log_buffer_off++] = val;
+    }
+}
+
+/* Xen Platform, Fixed IOPort */
+#define UNPLUG_ALL_IDE_DISKS 1
+#define UNPLUG_ALL_NICS 2
+#define UNPLUG_AUX_IDE_DISKS 4
+
+static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
+{
+    /* We have to ignore passthrough devices */
+    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
+            PCI_CLASS_NETWORK_ETHERNET
+            && strcmp(d->name, "xen-pci-passthrough") != 0) {
+        object_unparent(OBJECT(d));
+    }
+}
+
+static void pci_unplug_nics(PCIBus *bus)
+{
+    pci_for_each_device(bus, 0, unplug_nic, NULL);
+}
+
+static void unplug_disks(PCIBus *b, PCIDevice *d, void *o)
+{
+    /* We have to ignore passthrough devices */
+    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
+            PCI_CLASS_STORAGE_IDE
+            && strcmp(d->name, "xen-pci-passthrough") != 0) {
+        pci_piix3_xen_ide_unplug(DEVICE(d));
+    }
+}
+
+static void pci_unplug_disks(PCIBus *bus)
+{
+    pci_for_each_device(bus, 0, unplug_disks, NULL);
+}
+
+static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCIXenPlatformState *s = opaque;
+
+    switch (addr) {
+    case 0: {
+        PCIDevice *pci_dev = PCI_DEVICE(s);
+        /* Unplug devices.  Value is a bitmask of which devices to
+           unplug, with bit 0 the IDE devices, bit 1 the network
+           devices, and bit 2 the non-primary-master IDE devices. */
+        if (val & UNPLUG_ALL_IDE_DISKS) {
+            DPRINTF("unplug disks\n");
+            bdrv_drain_all();
+            bdrv_flush_all();
+            pci_unplug_disks(pci_dev->bus);
+        }
+        if (val & UNPLUG_ALL_NICS) {
+            DPRINTF("unplug nics\n");
+            pci_unplug_nics(pci_dev->bus);
+        }
+        if (val & UNPLUG_AUX_IDE_DISKS) {
+            DPRINTF("unplug auxiliary disks not supported\n");
+        }
+        break;
+    }
+    case 2:
+        switch (val) {
+        case 1:
+            DPRINTF("Citrix Windows PV drivers loaded in guest\n");
+            break;
+        case 0:
+            DPRINTF("Guest claimed to be running PV product 0?\n");
+            break;
+        default:
+            DPRINTF("Unknown PV product %d loaded in guest\n", val);
+            break;
+        }
+        s->driver_product_version = val;
+        break;
+    }
+}
+
+static void platform_fixed_ioport_writel(void *opaque, uint32_t addr,
+                                         uint32_t val)
+{
+    switch (addr) {
+    case 0:
+        /* PV driver version */
+        break;
+    }
+}
+
+static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCIXenPlatformState *s = opaque;
+
+    switch (addr) {
+    case 0: /* Platform flags */ {
+        hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
+            HVMMEM_ram_ro : HVMMEM_ram_rw;
+        if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type, 0xc0, 0x40)) {
+            DPRINTF("unable to change ro/rw state of ROM memory area!\n");
+        } else {
+            s->flags = val & PFFLAG_ROM_LOCK;
+            DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n",
+                    (mem_type == HVMMEM_ram_ro ? "ro":"rw"));
+        }
+        break;
+    }
+    case 2:
+        log_writeb(s, val);
+        break;
+    }
+}
+
+static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr)
+{
+    PCIXenPlatformState *s = opaque;
+
+    switch (addr) {
+    case 0:
+        if (s->drivers_blacklisted) {
+            /* The drivers will recognise this magic number and refuse
+             * to do anything. */
+            return 0xd249;
+        } else {
+            /* Magic value so that you can identify the interface. */
+            return 0x49d2;
+        }
+    default:
+        return 0xffff;
+    }
+}
+
+static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr)
+{
+    PCIXenPlatformState *s = opaque;
+
+    switch (addr) {
+    case 0:
+        /* Platform flags */
+        return s->flags;
+    case 2:
+        /* Version number */
+        return 1;
+    default:
+        return 0xff;
+    }
+}
+
+static void platform_fixed_ioport_reset(void *opaque)
+{
+    PCIXenPlatformState *s = opaque;
+
+    platform_fixed_ioport_writeb(s, 0, 0);
+}
+
+static uint64_t platform_fixed_ioport_read(void *opaque,
+                                           hwaddr addr,
+                                           unsigned size)
+{
+    switch (size) {
+    case 1:
+        return platform_fixed_ioport_readb(opaque, addr);
+    case 2:
+        return platform_fixed_ioport_readw(opaque, addr);
+    default:
+        return -1;
+    }
+}
+
+static void platform_fixed_ioport_write(void *opaque, hwaddr addr,
+
+                                        uint64_t val, unsigned size)
+{
+    switch (size) {
+    case 1:
+        platform_fixed_ioport_writeb(opaque, addr, val);
+        break;
+    case 2:
+        platform_fixed_ioport_writew(opaque, addr, val);
+        break;
+    case 4:
+        platform_fixed_ioport_writel(opaque, addr, val);
+        break;
+    }
+}
+
+
+static const MemoryRegionOps platform_fixed_io_ops = {
+    .read = platform_fixed_ioport_read,
+    .write = platform_fixed_ioport_write,
+    .valid = {
+        .unaligned = true,
+    },
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+        .unaligned = true,
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void platform_fixed_ioport_init(PCIXenPlatformState* s)
+{
+    memory_region_init_io(&s->fixed_io, OBJECT(s), &platform_fixed_io_ops, s,
+                          "xen-fixed", 16);
+    memory_region_add_subregion(get_system_io(), XEN_PLATFORM_IOPORT,
+                                &s->fixed_io);
+}
+
+/* Xen Platform PCI Device */
+
+static uint64_t xen_platform_ioport_readb(void *opaque, hwaddr addr,
+                                          unsigned int size)
+{
+    if (addr == 0) {
+        return platform_fixed_ioport_readb(opaque, 0);
+    } else {
+        return ~0u;
+    }
+}
+
+static void xen_platform_ioport_writeb(void *opaque, hwaddr addr,
+                                       uint64_t val, unsigned int size)
+{
+    PCIXenPlatformState *s = opaque;
+
+    switch (addr) {
+    case 0: /* Platform flags */
+        platform_fixed_ioport_writeb(opaque, 0, (uint32_t)val);
+        break;
+    case 8:
+        log_writeb(s, (uint32_t)val);
+        break;
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps xen_pci_io_ops = {
+    .read  = xen_platform_ioport_readb,
+    .write = xen_platform_ioport_writeb,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 1,
+};
+
+static void platform_ioport_bar_setup(PCIXenPlatformState *d)
+{
+    memory_region_init_io(&d->bar, OBJECT(d), &xen_pci_io_ops, d,
+                          "xen-pci", 0x100);
+}
+
+static uint64_t platform_mmio_read(void *opaque, hwaddr addr,
+                                   unsigned size)
+{
+    DPRINTF("Warning: attempted read from physical address "
+            "0x" TARGET_FMT_plx " in xen platform mmio space\n", addr);
+
+    return 0;
+}
+
+static void platform_mmio_write(void *opaque, hwaddr addr,
+                                uint64_t val, unsigned size)
+{
+    DPRINTF("Warning: attempted write of 0x%"PRIx64" to physical "
+            "address 0x" TARGET_FMT_plx " in xen platform mmio space\n",
+            val, addr);
+}
+
+static const MemoryRegionOps platform_mmio_handler = {
+    .read = &platform_mmio_read,
+    .write = &platform_mmio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void platform_mmio_setup(PCIXenPlatformState *d)
+{
+    memory_region_init_io(&d->mmio_bar, OBJECT(d), &platform_mmio_handler, d,
+                          "xen-mmio", 0x1000000);
+}
+
+static int xen_platform_post_load(void *opaque, int version_id)
+{
+    PCIXenPlatformState *s = opaque;
+
+    platform_fixed_ioport_writeb(s, 0, s->flags);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_xen_platform = {
+    .name = "platform",
+    .version_id = 4,
+    .minimum_version_id = 4,
+    .minimum_version_id_old = 4,
+    .post_load = xen_platform_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_PCI_DEVICE(parent_obj, PCIXenPlatformState),
+        VMSTATE_UINT8(flags, PCIXenPlatformState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int xen_platform_initfn(PCIDevice *dev)
+{
+    PCIXenPlatformState *d = XEN_PLATFORM(dev);
+    uint8_t *pci_conf;
+
+    pci_conf = dev->config;
+
+    pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+
+    pci_config_set_prog_interface(pci_conf, 0);
+
+    pci_conf[PCI_INTERRUPT_PIN] = 1;
+
+    platform_ioport_bar_setup(d);
+    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->bar);
+
+    /* reserve 16MB mmio address for share memory*/
+    platform_mmio_setup(d);
+    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                     &d->mmio_bar);
+
+    platform_fixed_ioport_init(d);
+
+    return 0;
+}
+
+static void platform_reset(DeviceState *dev)
+{
+    PCIXenPlatformState *s = XEN_PLATFORM(dev);
+
+    platform_fixed_ioport_reset(s);
+}
+
+static void xen_platform_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = xen_platform_initfn;
+    k->vendor_id = PCI_VENDOR_ID_XEN;
+    k->device_id = PCI_DEVICE_ID_XEN_PLATFORM;
+    k->class_id = PCI_CLASS_OTHERS << 8 | 0x80;
+    k->subsystem_vendor_id = PCI_VENDOR_ID_XEN;
+    k->subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM;
+    k->revision = 1;
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    dc->desc = "XEN platform pci device";
+    dc->reset = platform_reset;
+    dc->vmsd = &vmstate_xen_platform;
+}
+
+static const TypeInfo xen_platform_info = {
+    .name          = TYPE_XEN_PLATFORM,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(PCIXenPlatformState),
+    .class_init    = xen_platform_class_init,
+};
+
+static void xen_platform_register_types(void)
+{
+    type_register_static(&xen_platform_info);
+}
+
+type_init(xen_platform_register_types)
diff --git a/hw/i386/xen/xen_pvdevice.c b/hw/i386/xen/xen_pvdevice.c
new file mode 100644
index 0000000..c218947
--- /dev/null
+++ b/hw/i386/xen/xen_pvdevice.c
@@ -0,0 +1,135 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "trace.h"
+
+#define TYPE_XEN_PV_DEVICE  "xen-pvdevice"
+
+#define XEN_PV_DEVICE(obj) \
+     OBJECT_CHECK(XenPVDevice, (obj), TYPE_XEN_PV_DEVICE)
+
+typedef struct XenPVDevice {
+    /*< private >*/
+    PCIDevice       parent_obj;
+    /*< public >*/
+    uint16_t        vendor_id;
+    uint16_t        device_id;
+    uint8_t         revision;
+    uint32_t        size;
+    MemoryRegion    mmio;
+} XenPVDevice;
+
+static uint64_t xen_pv_mmio_read(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    trace_xen_pv_mmio_read(addr);
+
+    return ~(uint64_t)0;
+}
+
+static void xen_pv_mmio_write(void *opaque, hwaddr addr,
+                              uint64_t val, unsigned size)
+{
+    trace_xen_pv_mmio_write(addr);
+}
+
+static const MemoryRegionOps xen_pv_mmio_ops = {
+    .read = &xen_pv_mmio_read,
+    .write = &xen_pv_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int xen_pv_init(PCIDevice *pci_dev)
+{
+    XenPVDevice *d = XEN_PV_DEVICE(pci_dev);
+    uint8_t *pci_conf;
+
+    /* device-id property must always be supplied */
+    if (d->device_id == 0xffff)
+	    return -1;
+
+    pci_conf = pci_dev->config;
+
+    pci_set_word(pci_conf + PCI_VENDOR_ID, d->vendor_id);
+    pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, d->vendor_id);
+    pci_set_word(pci_conf + PCI_DEVICE_ID, d->device_id);
+    pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, d->device_id);
+    pci_set_byte(pci_conf + PCI_REVISION_ID, d->revision);
+
+    pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_MEMORY);
+
+    pci_config_set_prog_interface(pci_conf, 0);
+
+    pci_conf[PCI_INTERRUPT_PIN] = 1;
+
+    memory_region_init_io(&d->mmio, NULL, &xen_pv_mmio_ops, d,
+                          "mmio", d->size);
+
+    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                     &d->mmio);
+
+    return 0;
+}
+
+static Property xen_pv_props[] = {
+    DEFINE_PROP_UINT16("vendor-id", XenPVDevice, vendor_id, PCI_VENDOR_ID_XEN),
+    DEFINE_PROP_UINT16("device-id", XenPVDevice, device_id, 0xffff),
+    DEFINE_PROP_UINT8("revision", XenPVDevice, revision, 0x01),
+    DEFINE_PROP_UINT32("size", XenPVDevice, size, 0x400000),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void xen_pv_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = xen_pv_init;
+    k->class_id = PCI_CLASS_SYSTEM_OTHER;
+    dc->desc = "Xen PV Device";
+    dc->props = xen_pv_props;
+}
+
+static const TypeInfo xen_pv_type_info = {
+    .name          = TYPE_XEN_PV_DEVICE,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(XenPVDevice),
+    .class_init    = xen_pv_class_init,
+};
+
+static void xen_pv_register_types(void)
+{
+    type_register_static(&xen_pv_type_info);
+}
+
+type_init(xen_pv_register_types)
diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs
index ce640c6..a0ca0aa 100644
--- a/hw/xen/Makefile.objs
+++ b/hw/xen/Makefile.objs
@@ -1,6 +1,5 @@
 # xen backend driver support
 common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
 
-obj-$(CONFIG_XEN_I386) += xen_platform.o xen_apic.o xen_pvdevice.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
 obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
diff --git a/hw/xen/xen_apic.c b/hw/xen/xen_apic.c
deleted file mode 100644
index 63bb7f7..0000000
--- a/hw/xen/xen_apic.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Xen basic APIC support
- *
- * Copyright (c) 2012 Citrix
- *
- * Authors:
- *  Wei Liu <wei.liu2@citrix.com>
- *
- * This work is licensed under the terms of the GNU GPL version 2 or
- * later. See the COPYING file in the top-level directory.
- */
-#include "hw/i386/apic_internal.h"
-#include "hw/pci/msi.h"
-#include "hw/xen/xen.h"
-
-static uint64_t xen_apic_mem_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    return ~(uint64_t)0;
-}
-
-static void xen_apic_mem_write(void *opaque, hwaddr addr,
-                               uint64_t data, unsigned size)
-{
-    if (size != sizeof(uint32_t)) {
-        fprintf(stderr, "Xen: APIC write data size = %d, invalid\n", size);
-        return;
-    }
-
-    xen_hvm_inject_msi(addr, data);
-}
-
-static const MemoryRegionOps xen_apic_io_ops = {
-    .read = xen_apic_mem_read,
-    .write = xen_apic_mem_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void xen_apic_realize(DeviceState *dev, Error **errp)
-{
-    APICCommonState *s = APIC_COMMON(dev);
-
-    memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s,
-                          "xen-apic-msi", APIC_SPACE_SIZE);
-
-#if defined(CONFIG_XEN_CTRL_INTERFACE_VERSION) \
-    && CONFIG_XEN_CTRL_INTERFACE_VERSION >= 420
-    msi_supported = true;
-#endif
-}
-
-static void xen_apic_set_base(APICCommonState *s, uint64_t val)
-{
-}
-
-static void xen_apic_set_tpr(APICCommonState *s, uint8_t val)
-{
-}
-
-static uint8_t xen_apic_get_tpr(APICCommonState *s)
-{
-    return 0;
-}
-
-static void xen_apic_vapic_base_update(APICCommonState *s)
-{
-}
-
-static void xen_apic_external_nmi(APICCommonState *s)
-{
-}
-
-static void xen_apic_class_init(ObjectClass *klass, void *data)
-{
-    APICCommonClass *k = APIC_COMMON_CLASS(klass);
-
-    k->realize = xen_apic_realize;
-    k->set_base = xen_apic_set_base;
-    k->set_tpr = xen_apic_set_tpr;
-    k->get_tpr = xen_apic_get_tpr;
-    k->vapic_base_update = xen_apic_vapic_base_update;
-    k->external_nmi = xen_apic_external_nmi;
-}
-
-static const TypeInfo xen_apic_info = {
-    .name = "xen-apic",
-    .parent = TYPE_APIC_COMMON,
-    .instance_size = sizeof(APICCommonState),
-    .class_init = xen_apic_class_init,
-};
-
-static void xen_apic_register_types(void)
-{
-    type_register_static(&xen_apic_info);
-}
-
-type_init(xen_apic_register_types)
diff --git a/hw/xen/xen_platform.c b/hw/xen/xen_platform.c
deleted file mode 100644
index 1d9d0e9..0000000
--- a/hw/xen/xen_platform.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * XEN platform pci device, formerly known as the event channel device
- *
- * Copyright (c) 2003-2004 Intel Corp.
- * Copyright (c) 2006 XenSource
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <assert.h>
-
-#include "hw/hw.h"
-#include "hw/i386/pc.h"
-#include "hw/ide.h"
-#include "hw/pci/pci.h"
-#include "hw/irq.h"
-#include "hw/xen/xen_common.h"
-#include "hw/xen/xen_backend.h"
-#include "trace.h"
-#include "exec/address-spaces.h"
-
-#include <xenguest.h>
-
-//#define DEBUG_PLATFORM
-
-#ifdef DEBUG_PLATFORM
-#define DPRINTF(fmt, ...) do { \
-    fprintf(stderr, "xen_platform: " fmt, ## __VA_ARGS__); \
-} while (0)
-#else
-#define DPRINTF(fmt, ...) do { } while (0)
-#endif
-
-#define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
-
-typedef struct PCIXenPlatformState {
-    /*< private >*/
-    PCIDevice parent_obj;
-    /*< public >*/
-
-    MemoryRegion fixed_io;
-    MemoryRegion bar;
-    MemoryRegion mmio_bar;
-    uint8_t flags; /* used only for version_id == 2 */
-    int drivers_blacklisted;
-    uint16_t driver_product_version;
-
-    /* Log from guest drivers */
-    char log_buffer[4096];
-    int log_buffer_off;
-} PCIXenPlatformState;
-
-#define TYPE_XEN_PLATFORM "xen-platform"
-#define XEN_PLATFORM(obj) \
-    OBJECT_CHECK(PCIXenPlatformState, (obj), TYPE_XEN_PLATFORM)
-
-#define XEN_PLATFORM_IOPORT 0x10
-
-/* Send bytes to syslog */
-static void log_writeb(PCIXenPlatformState *s, char val)
-{
-    if (val == '\n' || s->log_buffer_off == sizeof(s->log_buffer) - 1) {
-        /* Flush buffer */
-        s->log_buffer[s->log_buffer_off] = 0;
-        trace_xen_platform_log(s->log_buffer);
-        s->log_buffer_off = 0;
-    } else {
-        s->log_buffer[s->log_buffer_off++] = val;
-    }
-}
-
-/* Xen Platform, Fixed IOPort */
-#define UNPLUG_ALL_IDE_DISKS 1
-#define UNPLUG_ALL_NICS 2
-#define UNPLUG_AUX_IDE_DISKS 4
-
-static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
-{
-    /* We have to ignore passthrough devices */
-    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
-            PCI_CLASS_NETWORK_ETHERNET
-            && strcmp(d->name, "xen-pci-passthrough") != 0) {
-        object_unparent(OBJECT(d));
-    }
-}
-
-static void pci_unplug_nics(PCIBus *bus)
-{
-    pci_for_each_device(bus, 0, unplug_nic, NULL);
-}
-
-static void unplug_disks(PCIBus *b, PCIDevice *d, void *o)
-{
-    /* We have to ignore passthrough devices */
-    if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
-            PCI_CLASS_STORAGE_IDE
-            && strcmp(d->name, "xen-pci-passthrough") != 0) {
-        pci_piix3_xen_ide_unplug(DEVICE(d));
-    }
-}
-
-static void pci_unplug_disks(PCIBus *bus)
-{
-    pci_for_each_device(bus, 0, unplug_disks, NULL);
-}
-
-static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
-{
-    PCIXenPlatformState *s = opaque;
-
-    switch (addr) {
-    case 0: {
-        PCIDevice *pci_dev = PCI_DEVICE(s);
-        /* Unplug devices.  Value is a bitmask of which devices to
-           unplug, with bit 0 the IDE devices, bit 1 the network
-           devices, and bit 2 the non-primary-master IDE devices. */
-        if (val & UNPLUG_ALL_IDE_DISKS) {
-            DPRINTF("unplug disks\n");
-            bdrv_drain_all();
-            bdrv_flush_all();
-            pci_unplug_disks(pci_dev->bus);
-        }
-        if (val & UNPLUG_ALL_NICS) {
-            DPRINTF("unplug nics\n");
-            pci_unplug_nics(pci_dev->bus);
-        }
-        if (val & UNPLUG_AUX_IDE_DISKS) {
-            DPRINTF("unplug auxiliary disks not supported\n");
-        }
-        break;
-    }
-    case 2:
-        switch (val) {
-        case 1:
-            DPRINTF("Citrix Windows PV drivers loaded in guest\n");
-            break;
-        case 0:
-            DPRINTF("Guest claimed to be running PV product 0?\n");
-            break;
-        default:
-            DPRINTF("Unknown PV product %d loaded in guest\n", val);
-            break;
-        }
-        s->driver_product_version = val;
-        break;
-    }
-}
-
-static void platform_fixed_ioport_writel(void *opaque, uint32_t addr,
-                                         uint32_t val)
-{
-    switch (addr) {
-    case 0:
-        /* PV driver version */
-        break;
-    }
-}
-
-static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
-{
-    PCIXenPlatformState *s = opaque;
-
-    switch (addr) {
-    case 0: /* Platform flags */ {
-        hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
-            HVMMEM_ram_ro : HVMMEM_ram_rw;
-        if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type, 0xc0, 0x40)) {
-            DPRINTF("unable to change ro/rw state of ROM memory area!\n");
-        } else {
-            s->flags = val & PFFLAG_ROM_LOCK;
-            DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n",
-                    (mem_type == HVMMEM_ram_ro ? "ro":"rw"));
-        }
-        break;
-    }
-    case 2:
-        log_writeb(s, val);
-        break;
-    }
-}
-
-static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr)
-{
-    PCIXenPlatformState *s = opaque;
-
-    switch (addr) {
-    case 0:
-        if (s->drivers_blacklisted) {
-            /* The drivers will recognise this magic number and refuse
-             * to do anything. */
-            return 0xd249;
-        } else {
-            /* Magic value so that you can identify the interface. */
-            return 0x49d2;
-        }
-    default:
-        return 0xffff;
-    }
-}
-
-static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr)
-{
-    PCIXenPlatformState *s = opaque;
-
-    switch (addr) {
-    case 0:
-        /* Platform flags */
-        return s->flags;
-    case 2:
-        /* Version number */
-        return 1;
-    default:
-        return 0xff;
-    }
-}
-
-static void platform_fixed_ioport_reset(void *opaque)
-{
-    PCIXenPlatformState *s = opaque;
-
-    platform_fixed_ioport_writeb(s, 0, 0);
-}
-
-static uint64_t platform_fixed_ioport_read(void *opaque,
-                                           hwaddr addr,
-                                           unsigned size)
-{
-    switch (size) {
-    case 1:
-        return platform_fixed_ioport_readb(opaque, addr);
-    case 2:
-        return platform_fixed_ioport_readw(opaque, addr);
-    default:
-        return -1;
-    }
-}
-
-static void platform_fixed_ioport_write(void *opaque, hwaddr addr,
-
-                                        uint64_t val, unsigned size)
-{
-    switch (size) {
-    case 1:
-        platform_fixed_ioport_writeb(opaque, addr, val);
-        break;
-    case 2:
-        platform_fixed_ioport_writew(opaque, addr, val);
-        break;
-    case 4:
-        platform_fixed_ioport_writel(opaque, addr, val);
-        break;
-    }
-}
-
-
-static const MemoryRegionOps platform_fixed_io_ops = {
-    .read = platform_fixed_ioport_read,
-    .write = platform_fixed_ioport_write,
-    .valid = {
-        .unaligned = true,
-    },
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 4,
-        .unaligned = true,
-    },
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void platform_fixed_ioport_init(PCIXenPlatformState* s)
-{
-    memory_region_init_io(&s->fixed_io, OBJECT(s), &platform_fixed_io_ops, s,
-                          "xen-fixed", 16);
-    memory_region_add_subregion(get_system_io(), XEN_PLATFORM_IOPORT,
-                                &s->fixed_io);
-}
-
-/* Xen Platform PCI Device */
-
-static uint64_t xen_platform_ioport_readb(void *opaque, hwaddr addr,
-                                          unsigned int size)
-{
-    if (addr == 0) {
-        return platform_fixed_ioport_readb(opaque, 0);
-    } else {
-        return ~0u;
-    }
-}
-
-static void xen_platform_ioport_writeb(void *opaque, hwaddr addr,
-                                       uint64_t val, unsigned int size)
-{
-    PCIXenPlatformState *s = opaque;
-
-    switch (addr) {
-    case 0: /* Platform flags */
-        platform_fixed_ioport_writeb(opaque, 0, (uint32_t)val);
-        break;
-    case 8:
-        log_writeb(s, (uint32_t)val);
-        break;
-    default:
-        break;
-    }
-}
-
-static const MemoryRegionOps xen_pci_io_ops = {
-    .read  = xen_platform_ioport_readb,
-    .write = xen_platform_ioport_writeb,
-    .impl.min_access_size = 1,
-    .impl.max_access_size = 1,
-};
-
-static void platform_ioport_bar_setup(PCIXenPlatformState *d)
-{
-    memory_region_init_io(&d->bar, OBJECT(d), &xen_pci_io_ops, d,
-                          "xen-pci", 0x100);
-}
-
-static uint64_t platform_mmio_read(void *opaque, hwaddr addr,
-                                   unsigned size)
-{
-    DPRINTF("Warning: attempted read from physical address "
-            "0x" TARGET_FMT_plx " in xen platform mmio space\n", addr);
-
-    return 0;
-}
-
-static void platform_mmio_write(void *opaque, hwaddr addr,
-                                uint64_t val, unsigned size)
-{
-    DPRINTF("Warning: attempted write of 0x%"PRIx64" to physical "
-            "address 0x" TARGET_FMT_plx " in xen platform mmio space\n",
-            val, addr);
-}
-
-static const MemoryRegionOps platform_mmio_handler = {
-    .read = &platform_mmio_read,
-    .write = &platform_mmio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void platform_mmio_setup(PCIXenPlatformState *d)
-{
-    memory_region_init_io(&d->mmio_bar, OBJECT(d), &platform_mmio_handler, d,
-                          "xen-mmio", 0x1000000);
-}
-
-static int xen_platform_post_load(void *opaque, int version_id)
-{
-    PCIXenPlatformState *s = opaque;
-
-    platform_fixed_ioport_writeb(s, 0, s->flags);
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_xen_platform = {
-    .name = "platform",
-    .version_id = 4,
-    .minimum_version_id = 4,
-    .minimum_version_id_old = 4,
-    .post_load = xen_platform_post_load,
-    .fields = (VMStateField []) {
-        VMSTATE_PCI_DEVICE(parent_obj, PCIXenPlatformState),
-        VMSTATE_UINT8(flags, PCIXenPlatformState),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int xen_platform_initfn(PCIDevice *dev)
-{
-    PCIXenPlatformState *d = XEN_PLATFORM(dev);
-    uint8_t *pci_conf;
-
-    pci_conf = dev->config;
-
-    pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-
-    pci_config_set_prog_interface(pci_conf, 0);
-
-    pci_conf[PCI_INTERRUPT_PIN] = 1;
-
-    platform_ioport_bar_setup(d);
-    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->bar);
-
-    /* reserve 16MB mmio address for share memory*/
-    platform_mmio_setup(d);
-    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
-                     &d->mmio_bar);
-
-    platform_fixed_ioport_init(d);
-
-    return 0;
-}
-
-static void platform_reset(DeviceState *dev)
-{
-    PCIXenPlatformState *s = XEN_PLATFORM(dev);
-
-    platform_fixed_ioport_reset(s);
-}
-
-static void xen_platform_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = xen_platform_initfn;
-    k->vendor_id = PCI_VENDOR_ID_XEN;
-    k->device_id = PCI_DEVICE_ID_XEN_PLATFORM;
-    k->class_id = PCI_CLASS_OTHERS << 8 | 0x80;
-    k->subsystem_vendor_id = PCI_VENDOR_ID_XEN;
-    k->subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM;
-    k->revision = 1;
-    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-    dc->desc = "XEN platform pci device";
-    dc->reset = platform_reset;
-    dc->vmsd = &vmstate_xen_platform;
-}
-
-static const TypeInfo xen_platform_info = {
-    .name          = TYPE_XEN_PLATFORM,
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(PCIXenPlatformState),
-    .class_init    = xen_platform_class_init,
-};
-
-static void xen_platform_register_types(void)
-{
-    type_register_static(&xen_platform_info);
-}
-
-type_init(xen_platform_register_types)
diff --git a/hw/xen/xen_pvdevice.c b/hw/xen/xen_pvdevice.c
deleted file mode 100644
index c218947..0000000
--- a/hw/xen/xen_pvdevice.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms,
- * with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * *   Redistributions of source code must retain the above
- *     copyright notice, this list of conditions and the
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the
- *     following disclaimer in the documentation and/or other
- *     materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "hw/hw.h"
-#include "hw/pci/pci.h"
-#include "trace.h"
-
-#define TYPE_XEN_PV_DEVICE  "xen-pvdevice"
-
-#define XEN_PV_DEVICE(obj) \
-     OBJECT_CHECK(XenPVDevice, (obj), TYPE_XEN_PV_DEVICE)
-
-typedef struct XenPVDevice {
-    /*< private >*/
-    PCIDevice       parent_obj;
-    /*< public >*/
-    uint16_t        vendor_id;
-    uint16_t        device_id;
-    uint8_t         revision;
-    uint32_t        size;
-    MemoryRegion    mmio;
-} XenPVDevice;
-
-static uint64_t xen_pv_mmio_read(void *opaque, hwaddr addr,
-                                 unsigned size)
-{
-    trace_xen_pv_mmio_read(addr);
-
-    return ~(uint64_t)0;
-}
-
-static void xen_pv_mmio_write(void *opaque, hwaddr addr,
-                              uint64_t val, unsigned size)
-{
-    trace_xen_pv_mmio_write(addr);
-}
-
-static const MemoryRegionOps xen_pv_mmio_ops = {
-    .read = &xen_pv_mmio_read,
-    .write = &xen_pv_mmio_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static int xen_pv_init(PCIDevice *pci_dev)
-{
-    XenPVDevice *d = XEN_PV_DEVICE(pci_dev);
-    uint8_t *pci_conf;
-
-    /* device-id property must always be supplied */
-    if (d->device_id == 0xffff)
-	    return -1;
-
-    pci_conf = pci_dev->config;
-
-    pci_set_word(pci_conf + PCI_VENDOR_ID, d->vendor_id);
-    pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, d->vendor_id);
-    pci_set_word(pci_conf + PCI_DEVICE_ID, d->device_id);
-    pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, d->device_id);
-    pci_set_byte(pci_conf + PCI_REVISION_ID, d->revision);
-
-    pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_MEMORY);
-
-    pci_config_set_prog_interface(pci_conf, 0);
-
-    pci_conf[PCI_INTERRUPT_PIN] = 1;
-
-    memory_region_init_io(&d->mmio, NULL, &xen_pv_mmio_ops, d,
-                          "mmio", d->size);
-
-    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
-                     &d->mmio);
-
-    return 0;
-}
-
-static Property xen_pv_props[] = {
-    DEFINE_PROP_UINT16("vendor-id", XenPVDevice, vendor_id, PCI_VENDOR_ID_XEN),
-    DEFINE_PROP_UINT16("device-id", XenPVDevice, device_id, 0xffff),
-    DEFINE_PROP_UINT8("revision", XenPVDevice, revision, 0x01),
-    DEFINE_PROP_UINT32("size", XenPVDevice, size, 0x400000),
-    DEFINE_PROP_END_OF_LIST()
-};
-
-static void xen_pv_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = xen_pv_init;
-    k->class_id = PCI_CLASS_SYSTEM_OTHER;
-    dc->desc = "Xen PV Device";
-    dc->props = xen_pv_props;
-}
-
-static const TypeInfo xen_pv_type_info = {
-    .name          = TYPE_XEN_PV_DEVICE,
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(XenPVDevice),
-    .class_init    = xen_pv_class_init,
-};
-
-static void xen_pv_register_types(void)
-{
-    type_register_static(&xen_pv_type_info);
-}
-
-type_init(xen_pv_register_types)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH resend 3/3] xen: factor out common functions
  2014-03-25 15:59 ` Wei Liu
@ 2014-03-25 15:59   ` Wei Liu
  -1 siblings, 0 replies; 18+ messages in thread
From: Wei Liu @ 2014-03-25 15:59 UTC (permalink / raw)
  To: xen-devel, qemu-devel; +Cc: anthony.perard, Wei Liu, stefano.stabellini

So common functions used by both HVM and PV are factored out from
xen-all.c to xen-common.c.

Finally rename xen-all.c to xen-hvm.c, as those functions are only
useful to HVM guest.

Create *-stub files and modify Makefile.target to reflect the changes.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 Makefile.target     |    6 +-
 xen-all.c           | 1228 ---------------------------------------------------
 xen-common-stub.c   |   19 +
 xen-common.c        |  123 ++++++
 xen-hvm-stub.c      |   66 +++
 xen-hvm.c           | 1129 ++++++++++++++++++++++++++++++++++++++++++++++
 xen-mapcache-stub.c |   39 ++
 xen-stub.c          |   70 ---
 8 files changed, 1380 insertions(+), 1300 deletions(-)
 delete mode 100644 xen-all.c
 create mode 100644 xen-common-stub.c
 create mode 100644 xen-common.c
 create mode 100644 xen-hvm-stub.c
 create mode 100644 xen-hvm.c
 create mode 100644 xen-mapcache-stub.c
 delete mode 100644 xen-stub.c

diff --git a/Makefile.target b/Makefile.target
index ba12340..02090aa 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -120,8 +120,10 @@ obj-y += dump.o
 LIBS+=$(libs_softmmu)
 
 # xen support
-obj-$(CONFIG_XEN) += xen-all.o xen-mapcache.o
-obj-$(call lnot,$(CONFIG_XEN)) += xen-stub.o
+obj-$(CONFIG_XEN) += xen-common.o
+obj-$(CONFIG_XEN_I386) += xen-hvm.o xen-mapcache.o
+obj-$(call lnot,$(CONFIG_XEN)) += xen-common-stub.o
+obj-$(call lnot,$(CONFIG_XEN_I386)) += xen-hvm-stub.o xen-mapcache-stub.o
 
 # Hardware support
 ifeq ($(TARGET_NAME), sparc64)
diff --git a/xen-all.c b/xen-all.c
deleted file mode 100644
index ba34739..0000000
--- a/xen-all.c
+++ /dev/null
@@ -1,1228 +0,0 @@
-/*
- * Copyright (C) 2010       Citrix Ltd.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include <sys/mman.h>
-
-#include "hw/pci/pci.h"
-#include "hw/i386/pc.h"
-#include "hw/xen/xen_common.h"
-#include "hw/xen/xen_backend.h"
-#include "qmp-commands.h"
-
-#include "sysemu/char.h"
-#include "qemu/range.h"
-#include "sysemu/xen-mapcache.h"
-#include "trace.h"
-#include "exec/address-spaces.h"
-
-#include <xen/hvm/ioreq.h>
-#include <xen/hvm/params.h>
-#include <xen/hvm/e820.h>
-
-//#define DEBUG_XEN
-
-#ifdef DEBUG_XEN
-#define DPRINTF(fmt, ...) \
-    do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
-    do { } while (0)
-#endif
-
-static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi;
-static MemoryRegion *framebuffer;
-static bool xen_in_migration;
-
-/* Compatibility with older version */
-#if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a
-static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
-{
-    return shared_page->vcpu_iodata[i].vp_eport;
-}
-static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
-{
-    return &shared_page->vcpu_iodata[vcpu].vp_ioreq;
-}
-#  define FMT_ioreq_size PRIx64
-#else
-static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
-{
-    return shared_page->vcpu_ioreq[i].vp_eport;
-}
-static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
-{
-    return &shared_page->vcpu_ioreq[vcpu];
-}
-#  define FMT_ioreq_size "u"
-#endif
-#ifndef HVM_PARAM_BUFIOREQ_EVTCHN
-#define HVM_PARAM_BUFIOREQ_EVTCHN 26
-#endif
-
-#define BUFFER_IO_MAX_DELAY  100
-
-typedef struct XenPhysmap {
-    hwaddr start_addr;
-    ram_addr_t size;
-    char *name;
-    hwaddr phys_offset;
-
-    QLIST_ENTRY(XenPhysmap) list;
-} XenPhysmap;
-
-typedef struct XenIOState {
-    shared_iopage_t *shared_page;
-    buffered_iopage_t *buffered_io_page;
-    QEMUTimer *buffered_io_timer;
-    /* the evtchn port for polling the notification, */
-    evtchn_port_t *ioreq_local_port;
-    /* evtchn local port for buffered io */
-    evtchn_port_t bufioreq_local_port;
-    /* the evtchn fd for polling */
-    XenEvtchn xce_handle;
-    /* which vcpu we are serving */
-    int send_vcpu;
-
-    struct xs_handle *xenstore;
-    MemoryListener memory_listener;
-    QLIST_HEAD(, XenPhysmap) physmap;
-    hwaddr free_phys_offset;
-    const XenPhysmap *log_for_dirtybit;
-
-    Notifier exit;
-    Notifier suspend;
-    Notifier wakeup;
-} XenIOState;
-
-/* Xen specific function for piix pci */
-
-int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
-{
-    return irq_num + ((pci_dev->devfn >> 3) << 2);
-}
-
-void xen_piix3_set_irq(void *opaque, int irq_num, int level)
-{
-    xc_hvm_set_pci_intx_level(xen_xc, xen_domid, 0, 0, irq_num >> 2,
-                              irq_num & 3, level);
-}
-
-void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
-{
-    int i;
-
-    /* Scan for updates to PCI link routes (0x60-0x63). */
-    for (i = 0; i < len; i++) {
-        uint8_t v = (val >> (8 * i)) & 0xff;
-        if (v & 0x80) {
-            v = 0;
-        }
-        v &= 0xf;
-        if (((address + i) >= 0x60) && ((address + i) <= 0x63)) {
-            xc_hvm_set_pci_link_route(xen_xc, xen_domid, address + i - 0x60, v);
-        }
-    }
-}
-
-void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
-{
-    xen_xc_hvm_inject_msi(xen_xc, xen_domid, addr, data);
-}
-
-static void xen_suspend_notifier(Notifier *notifier, void *data)
-{
-    xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
-}
-
-/* Xen Interrupt Controller */
-
-static void xen_set_irq(void *opaque, int irq, int level)
-{
-    xc_hvm_set_isa_irq_level(xen_xc, xen_domid, irq, level);
-}
-
-qemu_irq *xen_interrupt_controller_init(void)
-{
-    return qemu_allocate_irqs(xen_set_irq, NULL, 16);
-}
-
-/* Memory Ops */
-
-static void xen_ram_init(ram_addr_t ram_size, MemoryRegion **ram_memory_p)
-{
-    MemoryRegion *sysmem = get_system_memory();
-    ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
-    ram_addr_t block_len;
-
-    block_len = ram_size;
-    if (ram_size >= HVM_BELOW_4G_RAM_END) {
-        /* Xen does not allocate the memory continuously, and keep a hole at
-         * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH
-         */
-        block_len += HVM_BELOW_4G_MMIO_LENGTH;
-    }
-    memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len);
-    *ram_memory_p = &ram_memory;
-    vmstate_register_ram_global(&ram_memory);
-
-    if (ram_size >= HVM_BELOW_4G_RAM_END) {
-        above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
-        below_4g_mem_size = HVM_BELOW_4G_RAM_END;
-    } else {
-        below_4g_mem_size = ram_size;
-    }
-
-    memory_region_init_alias(&ram_640k, NULL, "xen.ram.640k",
-                             &ram_memory, 0, 0xa0000);
-    memory_region_add_subregion(sysmem, 0, &ram_640k);
-    /* Skip of the VGA IO memory space, it will be registered later by the VGA
-     * emulated device.
-     *
-     * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load
-     * the Options ROM, so it is registered here as RAM.
-     */
-    memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo",
-                             &ram_memory, 0xc0000, below_4g_mem_size - 0xc0000);
-    memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
-    if (above_4g_mem_size > 0) {
-        memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi",
-                                 &ram_memory, 0x100000000ULL,
-                                 above_4g_mem_size);
-        memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
-    }
-}
-
-void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
-{
-    unsigned long nr_pfn;
-    xen_pfn_t *pfn_list;
-    int i;
-
-    if (runstate_check(RUN_STATE_INMIGRATE)) {
-        /* RAM already populated in Xen */
-        fprintf(stderr, "%s: do not alloc "RAM_ADDR_FMT
-                " bytes of ram at "RAM_ADDR_FMT" when runstate is INMIGRATE\n",
-                __func__, size, ram_addr); 
-        return;
-    }
-
-    if (mr == &ram_memory) {
-        return;
-    }
-
-    trace_xen_ram_alloc(ram_addr, size);
-
-    nr_pfn = size >> TARGET_PAGE_BITS;
-    pfn_list = g_malloc(sizeof (*pfn_list) * nr_pfn);
-
-    for (i = 0; i < nr_pfn; i++) {
-        pfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i;
-    }
-
-    if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
-        hw_error("xen: failed to populate ram at " RAM_ADDR_FMT, ram_addr);
-    }
-
-    g_free(pfn_list);
-}
-
-static XenPhysmap *get_physmapping(XenIOState *state,
-                                   hwaddr start_addr, ram_addr_t size)
-{
-    XenPhysmap *physmap = NULL;
-
-    start_addr &= TARGET_PAGE_MASK;
-
-    QLIST_FOREACH(physmap, &state->physmap, list) {
-        if (range_covers_byte(physmap->start_addr, physmap->size, start_addr)) {
-            return physmap;
-        }
-    }
-    return NULL;
-}
-
-static hwaddr xen_phys_offset_to_gaddr(hwaddr start_addr,
-                                                   ram_addr_t size, void *opaque)
-{
-    hwaddr addr = start_addr & TARGET_PAGE_MASK;
-    XenIOState *xen_io_state = opaque;
-    XenPhysmap *physmap = NULL;
-
-    QLIST_FOREACH(physmap, &xen_io_state->physmap, list) {
-        if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
-            return physmap->start_addr;
-        }
-    }
-
-    return start_addr;
-}
-
-#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340
-static int xen_add_to_physmap(XenIOState *state,
-                              hwaddr start_addr,
-                              ram_addr_t size,
-                              MemoryRegion *mr,
-                              hwaddr offset_within_region)
-{
-    unsigned long i = 0;
-    int rc = 0;
-    XenPhysmap *physmap = NULL;
-    hwaddr pfn, start_gpfn;
-    hwaddr phys_offset = memory_region_get_ram_addr(mr);
-    char path[80], value[17];
-
-    if (get_physmapping(state, start_addr, size)) {
-        return 0;
-    }
-    if (size <= 0) {
-        return -1;
-    }
-
-    /* Xen can only handle a single dirty log region for now and we want
-     * the linear framebuffer to be that region.
-     * Avoid tracking any regions that is not videoram and avoid tracking
-     * the legacy vga region. */
-    if (mr == framebuffer && start_addr > 0xbffff) {
-        goto go_physmap;
-    }
-    return -1;
-
-go_physmap:
-    DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
-            start_addr, start_addr + size);
-
-    pfn = phys_offset >> TARGET_PAGE_BITS;
-    start_gpfn = start_addr >> TARGET_PAGE_BITS;
-    for (i = 0; i < size >> TARGET_PAGE_BITS; i++) {
-        unsigned long idx = pfn + i;
-        xen_pfn_t gpfn = start_gpfn + i;
-
-        rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
-        if (rc) {
-            DPRINTF("add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
-                    PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
-            return -rc;
-        }
-    }
-
-    physmap = g_malloc(sizeof (XenPhysmap));
-
-    physmap->start_addr = start_addr;
-    physmap->size = size;
-    physmap->name = (char *)mr->name;
-    physmap->phys_offset = phys_offset;
-
-    QLIST_INSERT_HEAD(&state->physmap, physmap, list);
-
-    xc_domain_pin_memory_cacheattr(xen_xc, xen_domid,
-                                   start_addr >> TARGET_PAGE_BITS,
-                                   (start_addr + size) >> TARGET_PAGE_BITS,
-                                   XEN_DOMCTL_MEM_CACHEATTR_WB);
-
-    snprintf(path, sizeof(path),
-            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
-            xen_domid, (uint64_t)phys_offset);
-    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)start_addr);
-    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
-        return -1;
-    }
-    snprintf(path, sizeof(path),
-            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
-            xen_domid, (uint64_t)phys_offset);
-    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)size);
-    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
-        return -1;
-    }
-    if (mr->name) {
-        snprintf(path, sizeof(path),
-                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
-                xen_domid, (uint64_t)phys_offset);
-        if (!xs_write(state->xenstore, 0, path, mr->name, strlen(mr->name))) {
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-static int xen_remove_from_physmap(XenIOState *state,
-                                   hwaddr start_addr,
-                                   ram_addr_t size)
-{
-    unsigned long i = 0;
-    int rc = 0;
-    XenPhysmap *physmap = NULL;
-    hwaddr phys_offset = 0;
-
-    physmap = get_physmapping(state, start_addr, size);
-    if (physmap == NULL) {
-        return -1;
-    }
-
-    phys_offset = physmap->phys_offset;
-    size = physmap->size;
-
-    DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", at "
-            "%"HWADDR_PRIx"\n", start_addr, start_addr + size, phys_offset);
-
-    size >>= TARGET_PAGE_BITS;
-    start_addr >>= TARGET_PAGE_BITS;
-    phys_offset >>= TARGET_PAGE_BITS;
-    for (i = 0; i < size; i++) {
-        unsigned long idx = start_addr + i;
-        xen_pfn_t gpfn = phys_offset + i;
-
-        rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
-        if (rc) {
-            fprintf(stderr, "add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
-                    PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
-            return -rc;
-        }
-    }
-
-    QLIST_REMOVE(physmap, list);
-    if (state->log_for_dirtybit == physmap) {
-        state->log_for_dirtybit = NULL;
-    }
-    g_free(physmap);
-
-    return 0;
-}
-
-#else
-static int xen_add_to_physmap(XenIOState *state,
-                              hwaddr start_addr,
-                              ram_addr_t size,
-                              MemoryRegion *mr,
-                              hwaddr offset_within_region)
-{
-    return -ENOSYS;
-}
-
-static int xen_remove_from_physmap(XenIOState *state,
-                                   hwaddr start_addr,
-                                   ram_addr_t size)
-{
-    return -ENOSYS;
-}
-#endif
-
-static void xen_set_memory(struct MemoryListener *listener,
-                           MemoryRegionSection *section,
-                           bool add)
-{
-    XenIOState *state = container_of(listener, XenIOState, memory_listener);
-    hwaddr start_addr = section->offset_within_address_space;
-    ram_addr_t size = int128_get64(section->size);
-    bool log_dirty = memory_region_is_logging(section->mr);
-    hvmmem_type_t mem_type;
-
-    if (!memory_region_is_ram(section->mr)) {
-        return;
-    }
-
-    if (!(section->mr != &ram_memory
-          && ( (log_dirty && add) || (!log_dirty && !add)))) {
-        return;
-    }
-
-    trace_xen_client_set_memory(start_addr, size, log_dirty);
-
-    start_addr &= TARGET_PAGE_MASK;
-    size = TARGET_PAGE_ALIGN(size);
-
-    if (add) {
-        if (!memory_region_is_rom(section->mr)) {
-            xen_add_to_physmap(state, start_addr, size,
-                               section->mr, section->offset_within_region);
-        } else {
-            mem_type = HVMMEM_ram_ro;
-            if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,
-                                    start_addr >> TARGET_PAGE_BITS,
-                                    size >> TARGET_PAGE_BITS)) {
-                DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",
-                        start_addr);
-            }
-        }
-    } else {
-        if (xen_remove_from_physmap(state, start_addr, size) < 0) {
-            DPRINTF("physmapping does not exist at "TARGET_FMT_plx"\n", start_addr);
-        }
-    }
-}
-
-static void xen_region_add(MemoryListener *listener,
-                           MemoryRegionSection *section)
-{
-    memory_region_ref(section->mr);
-    xen_set_memory(listener, section, true);
-}
-
-static void xen_region_del(MemoryListener *listener,
-                           MemoryRegionSection *section)
-{
-    xen_set_memory(listener, section, false);
-    memory_region_unref(section->mr);
-}
-
-static void xen_sync_dirty_bitmap(XenIOState *state,
-                                  hwaddr start_addr,
-                                  ram_addr_t size)
-{
-    hwaddr npages = size >> TARGET_PAGE_BITS;
-    const int width = sizeof(unsigned long) * 8;
-    unsigned long bitmap[(npages + width - 1) / width];
-    int rc, i, j;
-    const XenPhysmap *physmap = NULL;
-
-    physmap = get_physmapping(state, start_addr, size);
-    if (physmap == NULL) {
-        /* not handled */
-        return;
-    }
-
-    if (state->log_for_dirtybit == NULL) {
-        state->log_for_dirtybit = physmap;
-    } else if (state->log_for_dirtybit != physmap) {
-        /* Only one range for dirty bitmap can be tracked. */
-        return;
-    }
-
-    rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid,
-                                 start_addr >> TARGET_PAGE_BITS, npages,
-                                 bitmap);
-    if (rc < 0) {
-        if (rc != -ENODATA) {
-            memory_region_set_dirty(framebuffer, 0, size);
-            DPRINTF("xen: track_dirty_vram failed (0x" TARGET_FMT_plx
-                    ", 0x" TARGET_FMT_plx "): %s\n",
-                    start_addr, start_addr + size, strerror(-rc));
-        }
-        return;
-    }
-
-    for (i = 0; i < ARRAY_SIZE(bitmap); i++) {
-        unsigned long map = bitmap[i];
-        while (map != 0) {
-            j = ffsl(map) - 1;
-            map &= ~(1ul << j);
-            memory_region_set_dirty(framebuffer,
-                                    (i * width + j) * TARGET_PAGE_SIZE,
-                                    TARGET_PAGE_SIZE);
-        };
-    }
-}
-
-static void xen_log_start(MemoryListener *listener,
-                          MemoryRegionSection *section)
-{
-    XenIOState *state = container_of(listener, XenIOState, memory_listener);
-
-    xen_sync_dirty_bitmap(state, section->offset_within_address_space,
-                          int128_get64(section->size));
-}
-
-static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section)
-{
-    XenIOState *state = container_of(listener, XenIOState, memory_listener);
-
-    state->log_for_dirtybit = NULL;
-    /* Disable dirty bit tracking */
-    xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
-}
-
-static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *section)
-{
-    XenIOState *state = container_of(listener, XenIOState, memory_listener);
-
-    xen_sync_dirty_bitmap(state, section->offset_within_address_space,
-                          int128_get64(section->size));
-}
-
-static void xen_log_global_start(MemoryListener *listener)
-{
-    if (xen_enabled()) {
-        xen_in_migration = true;
-    }
-}
-
-static void xen_log_global_stop(MemoryListener *listener)
-{
-    xen_in_migration = false;
-}
-
-static MemoryListener xen_memory_listener = {
-    .region_add = xen_region_add,
-    .region_del = xen_region_del,
-    .log_start = xen_log_start,
-    .log_stop = xen_log_stop,
-    .log_sync = xen_log_sync,
-    .log_global_start = xen_log_global_start,
-    .log_global_stop = xen_log_global_stop,
-    .priority = 10,
-};
-
-void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
-{
-    if (enable) {
-        memory_global_dirty_log_start();
-    } else {
-        memory_global_dirty_log_stop();
-    }
-}
-
-/* get the ioreq packets from share mem */
-static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu)
-{
-    ioreq_t *req = xen_vcpu_ioreq(state->shared_page, vcpu);
-
-    if (req->state != STATE_IOREQ_READY) {
-        DPRINTF("I/O request not ready: "
-                "%x, ptr: %x, port: %"PRIx64", "
-                "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
-                req->state, req->data_is_ptr, req->addr,
-                req->data, req->count, req->size);
-        return NULL;
-    }
-
-    xen_rmb(); /* see IOREQ_READY /then/ read contents of ioreq */
-
-    req->state = STATE_IOREQ_INPROCESS;
-    return req;
-}
-
-/* use poll to get the port notification */
-/* ioreq_vec--out,the */
-/* retval--the number of ioreq packet */
-static ioreq_t *cpu_get_ioreq(XenIOState *state)
-{
-    int i;
-    evtchn_port_t port;
-
-    port = xc_evtchn_pending(state->xce_handle);
-    if (port == state->bufioreq_local_port) {
-        timer_mod(state->buffered_io_timer,
-                BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
-        return NULL;
-    }
-
-    if (port != -1) {
-        for (i = 0; i < max_cpus; i++) {
-            if (state->ioreq_local_port[i] == port) {
-                break;
-            }
-        }
-
-        if (i == max_cpus) {
-            hw_error("Fatal error while trying to get io event!\n");
-        }
-
-        /* unmask the wanted port again */
-        xc_evtchn_unmask(state->xce_handle, port);
-
-        /* get the io packet from shared memory */
-        state->send_vcpu = i;
-        return cpu_get_ioreq_from_shared_memory(state, i);
-    }
-
-    /* read error or read nothing */
-    return NULL;
-}
-
-static uint32_t do_inp(pio_addr_t addr, unsigned long size)
-{
-    switch (size) {
-        case 1:
-            return cpu_inb(addr);
-        case 2:
-            return cpu_inw(addr);
-        case 4:
-            return cpu_inl(addr);
-        default:
-            hw_error("inp: bad size: %04"FMT_pioaddr" %lx", addr, size);
-    }
-}
-
-static void do_outp(pio_addr_t addr,
-        unsigned long size, uint32_t val)
-{
-    switch (size) {
-        case 1:
-            return cpu_outb(addr, val);
-        case 2:
-            return cpu_outw(addr, val);
-        case 4:
-            return cpu_outl(addr, val);
-        default:
-            hw_error("outp: bad size: %04"FMT_pioaddr" %lx", addr, size);
-    }
-}
-
-/*
- * Helper functions which read/write an object from/to physical guest
- * memory, as part of the implementation of an ioreq.
- *
- * Equivalent to
- *   cpu_physical_memory_rw(addr + (req->df ? -1 : +1) * req->size * i,
- *                          val, req->size, 0/1)
- * except without the integer overflow problems.
- */
-static void rw_phys_req_item(hwaddr addr,
-                             ioreq_t *req, uint32_t i, void *val, int rw)
-{
-    /* Do everything unsigned so overflow just results in a truncated result
-     * and accesses to undesired parts of guest memory, which is up
-     * to the guest */
-    hwaddr offset = (hwaddr)req->size * i;
-    if (req->df) {
-        addr -= offset;
-    } else {
-        addr += offset;
-    }
-    cpu_physical_memory_rw(addr, val, req->size, rw);
-}
-
-static inline void read_phys_req_item(hwaddr addr,
-                                      ioreq_t *req, uint32_t i, void *val)
-{
-    rw_phys_req_item(addr, req, i, val, 0);
-}
-static inline void write_phys_req_item(hwaddr addr,
-                                       ioreq_t *req, uint32_t i, void *val)
-{
-    rw_phys_req_item(addr, req, i, val, 1);
-}
-
-
-static void cpu_ioreq_pio(ioreq_t *req)
-{
-    uint32_t i;
-
-    if (req->dir == IOREQ_READ) {
-        if (!req->data_is_ptr) {
-            req->data = do_inp(req->addr, req->size);
-        } else {
-            uint32_t tmp;
-
-            for (i = 0; i < req->count; i++) {
-                tmp = do_inp(req->addr, req->size);
-                write_phys_req_item(req->data, req, i, &tmp);
-            }
-        }
-    } else if (req->dir == IOREQ_WRITE) {
-        if (!req->data_is_ptr) {
-            do_outp(req->addr, req->size, req->data);
-        } else {
-            for (i = 0; i < req->count; i++) {
-                uint32_t tmp = 0;
-
-                read_phys_req_item(req->data, req, i, &tmp);
-                do_outp(req->addr, req->size, tmp);
-            }
-        }
-    }
-}
-
-static void cpu_ioreq_move(ioreq_t *req)
-{
-    uint32_t i;
-
-    if (!req->data_is_ptr) {
-        if (req->dir == IOREQ_READ) {
-            for (i = 0; i < req->count; i++) {
-                read_phys_req_item(req->addr, req, i, &req->data);
-            }
-        } else if (req->dir == IOREQ_WRITE) {
-            for (i = 0; i < req->count; i++) {
-                write_phys_req_item(req->addr, req, i, &req->data);
-            }
-        }
-    } else {
-        uint64_t tmp;
-
-        if (req->dir == IOREQ_READ) {
-            for (i = 0; i < req->count; i++) {
-                read_phys_req_item(req->addr, req, i, &tmp);
-                write_phys_req_item(req->data, req, i, &tmp);
-            }
-        } else if (req->dir == IOREQ_WRITE) {
-            for (i = 0; i < req->count; i++) {
-                read_phys_req_item(req->data, req, i, &tmp);
-                write_phys_req_item(req->addr, req, i, &tmp);
-            }
-        }
-    }
-}
-
-static void handle_ioreq(ioreq_t *req)
-{
-    if (!req->data_is_ptr && (req->dir == IOREQ_WRITE) &&
-            (req->size < sizeof (target_ulong))) {
-        req->data &= ((target_ulong) 1 << (8 * req->size)) - 1;
-    }
-
-    switch (req->type) {
-        case IOREQ_TYPE_PIO:
-            cpu_ioreq_pio(req);
-            break;
-        case IOREQ_TYPE_COPY:
-            cpu_ioreq_move(req);
-            break;
-        case IOREQ_TYPE_TIMEOFFSET:
-            break;
-        case IOREQ_TYPE_INVALIDATE:
-            xen_invalidate_map_cache();
-            break;
-        default:
-            hw_error("Invalid ioreq type 0x%x\n", req->type);
-    }
-}
-
-static int handle_buffered_iopage(XenIOState *state)
-{
-    buf_ioreq_t *buf_req = NULL;
-    ioreq_t req;
-    int qw;
-
-    if (!state->buffered_io_page) {
-        return 0;
-    }
-
-    memset(&req, 0x00, sizeof(req));
-
-    while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {
-        buf_req = &state->buffered_io_page->buf_ioreq[
-            state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
-        req.size = 1UL << buf_req->size;
-        req.count = 1;
-        req.addr = buf_req->addr;
-        req.data = buf_req->data;
-        req.state = STATE_IOREQ_READY;
-        req.dir = buf_req->dir;
-        req.df = 1;
-        req.type = buf_req->type;
-        req.data_is_ptr = 0;
-        qw = (req.size == 8);
-        if (qw) {
-            buf_req = &state->buffered_io_page->buf_ioreq[
-                (state->buffered_io_page->read_pointer + 1) % IOREQ_BUFFER_SLOT_NUM];
-            req.data |= ((uint64_t)buf_req->data) << 32;
-        }
-
-        handle_ioreq(&req);
-
-        xen_mb();
-        state->buffered_io_page->read_pointer += qw ? 2 : 1;
-    }
-
-    return req.count;
-}
-
-static void handle_buffered_io(void *opaque)
-{
-    XenIOState *state = opaque;
-
-    if (handle_buffered_iopage(state)) {
-        timer_mod(state->buffered_io_timer,
-                BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
-    } else {
-        timer_del(state->buffered_io_timer);
-        xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
-    }
-}
-
-static void cpu_handle_ioreq(void *opaque)
-{
-    XenIOState *state = opaque;
-    ioreq_t *req = cpu_get_ioreq(state);
-
-    handle_buffered_iopage(state);
-    if (req) {
-        handle_ioreq(req);
-
-        if (req->state != STATE_IOREQ_INPROCESS) {
-            fprintf(stderr, "Badness in I/O request ... not in service?!: "
-                    "%x, ptr: %x, port: %"PRIx64", "
-                    "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
-                    req->state, req->data_is_ptr, req->addr,
-                    req->data, req->count, req->size);
-            destroy_hvm_domain(false);
-            return;
-        }
-
-        xen_wmb(); /* Update ioreq contents /then/ update state. */
-
-        /*
-         * We do this before we send the response so that the tools
-         * have the opportunity to pick up on the reset before the
-         * guest resumes and does a hlt with interrupts disabled which
-         * causes Xen to powerdown the domain.
-         */
-        if (runstate_is_running()) {
-            if (qemu_shutdown_requested_get()) {
-                destroy_hvm_domain(false);
-            }
-            if (qemu_reset_requested_get()) {
-                qemu_system_reset(VMRESET_REPORT);
-                destroy_hvm_domain(true);
-            }
-        }
-
-        req->state = STATE_IORESP_READY;
-        xc_evtchn_notify(state->xce_handle, state->ioreq_local_port[state->send_vcpu]);
-    }
-}
-
-static int store_dev_info(int domid, CharDriverState *cs, const char *string)
-{
-    struct xs_handle *xs = NULL;
-    char *path = NULL;
-    char *newpath = NULL;
-    char *pts = NULL;
-    int ret = -1;
-
-    /* Only continue if we're talking to a pty. */
-    if (strncmp(cs->filename, "pty:", 4)) {
-        return 0;
-    }
-    pts = cs->filename + 4;
-
-    /* We now have everything we need to set the xenstore entry. */
-    xs = xs_open(0);
-    if (xs == NULL) {
-        fprintf(stderr, "Could not contact XenStore\n");
-        goto out;
-    }
-
-    path = xs_get_domain_path(xs, domid);
-    if (path == NULL) {
-        fprintf(stderr, "xs_get_domain_path() error\n");
-        goto out;
-    }
-    newpath = realloc(path, (strlen(path) + strlen(string) +
-                strlen("/tty") + 1));
-    if (newpath == NULL) {
-        fprintf(stderr, "realloc error\n");
-        goto out;
-    }
-    path = newpath;
-
-    strcat(path, string);
-    strcat(path, "/tty");
-    if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
-        fprintf(stderr, "xs_write for '%s' fail", string);
-        goto out;
-    }
-    ret = 0;
-
-out:
-    free(path);
-    xs_close(xs);
-
-    return ret;
-}
-
-void xenstore_store_pv_console_info(int i, CharDriverState *chr)
-{
-    if (i == 0) {
-        store_dev_info(xen_domid, chr, "/console");
-    } else {
-        char buf[32];
-        snprintf(buf, sizeof(buf), "/device/console/%d", i);
-        store_dev_info(xen_domid, chr, buf);
-    }
-}
-
-static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
-{
-    char path[50];
-
-    if (xs == NULL) {
-        fprintf(stderr, "xenstore connection not initialized\n");
-        exit(1);
-    }
-
-    snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
-    if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) {
-        fprintf(stderr, "error recording dm state\n");
-        exit(1);
-    }
-}
-
-static void xen_main_loop_prepare(XenIOState *state)
-{
-    int evtchn_fd = -1;
-
-    if (state->xce_handle != XC_HANDLER_INITIAL_VALUE) {
-        evtchn_fd = xc_evtchn_fd(state->xce_handle);
-    }
-
-    state->buffered_io_timer = timer_new_ms(QEMU_CLOCK_REALTIME, handle_buffered_io,
-                                                 state);
-
-    if (evtchn_fd != -1) {
-        qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
-    }
-}
-
-
-/* Initialise Xen */
-
-static void xen_change_state_handler(void *opaque, int running,
-                                     RunState state)
-{
-    if (running) {
-        /* record state running */
-        xenstore_record_dm_state(xenstore, "running");
-    }
-}
-
-static void xen_hvm_change_state_handler(void *opaque, int running,
-                                         RunState rstate)
-{
-    XenIOState *xstate = opaque;
-    if (running) {
-        xen_main_loop_prepare(xstate);
-    }
-}
-
-static void xen_exit_notifier(Notifier *n, void *data)
-{
-    XenIOState *state = container_of(n, XenIOState, exit);
-
-    xc_evtchn_close(state->xce_handle);
-    xs_daemon_close(state->xenstore);
-}
-
-int xen_init(QEMUMachine *machine)
-{
-    xen_xc = xen_xc_interface_open(0, 0, 0);
-    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
-        xen_be_printf(NULL, 0, "can't open xen interface\n");
-        return -1;
-    }
-    qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
-
-    return 0;
-}
-
-static void xen_read_physmap(XenIOState *state)
-{
-    XenPhysmap *physmap = NULL;
-    unsigned int len, num, i;
-    char path[80], *value = NULL;
-    char **entries = NULL;
-
-    snprintf(path, sizeof(path),
-            "/local/domain/0/device-model/%d/physmap", xen_domid);
-    entries = xs_directory(state->xenstore, 0, path, &num);
-    if (entries == NULL)
-        return;
-
-    for (i = 0; i < num; i++) {
-        physmap = g_malloc(sizeof (XenPhysmap));
-        physmap->phys_offset = strtoull(entries[i], NULL, 16);
-        snprintf(path, sizeof(path),
-                "/local/domain/0/device-model/%d/physmap/%s/start_addr",
-                xen_domid, entries[i]);
-        value = xs_read(state->xenstore, 0, path, &len);
-        if (value == NULL) {
-            g_free(physmap);
-            continue;
-        }
-        physmap->start_addr = strtoull(value, NULL, 16);
-        free(value);
-
-        snprintf(path, sizeof(path),
-                "/local/domain/0/device-model/%d/physmap/%s/size",
-                xen_domid, entries[i]);
-        value = xs_read(state->xenstore, 0, path, &len);
-        if (value == NULL) {
-            g_free(physmap);
-            continue;
-        }
-        physmap->size = strtoull(value, NULL, 16);
-        free(value);
-
-        snprintf(path, sizeof(path),
-                "/local/domain/0/device-model/%d/physmap/%s/name",
-                xen_domid, entries[i]);
-        physmap->name = xs_read(state->xenstore, 0, path, &len);
-
-        QLIST_INSERT_HEAD(&state->physmap, physmap, list);
-    }
-    free(entries);
-}
-
-static void xen_wakeup_notifier(Notifier *notifier, void *data)
-{
-    xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
-}
-
-int xen_hvm_init(MemoryRegion **ram_memory)
-{
-    int i, rc;
-    unsigned long ioreq_pfn;
-    unsigned long bufioreq_evtchn;
-    XenIOState *state;
-
-    state = g_malloc0(sizeof (XenIOState));
-
-    state->xce_handle = xen_xc_evtchn_open(NULL, 0);
-    if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
-        perror("xen: event channel open");
-        g_free(state);
-        return -errno;
-    }
-
-    state->xenstore = xs_daemon_open();
-    if (state->xenstore == NULL) {
-        perror("xen: xenstore open");
-        g_free(state);
-        return -errno;
-    }
-
-    state->exit.notify = xen_exit_notifier;
-    qemu_add_exit_notifier(&state->exit);
-
-    state->suspend.notify = xen_suspend_notifier;
-    qemu_register_suspend_notifier(&state->suspend);
-
-    state->wakeup.notify = xen_wakeup_notifier;
-    qemu_register_wakeup_notifier(&state->wakeup);
-
-    xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
-    DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
-    state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
-                                              PROT_READ|PROT_WRITE, ioreq_pfn);
-    if (state->shared_page == NULL) {
-        hw_error("map shared IO page returned error %d handle=" XC_INTERFACE_FMT,
-                 errno, xen_xc);
-    }
-
-    xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
-    DPRINTF("buffered io page at pfn %lx\n", ioreq_pfn);
-    state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
-                                                   PROT_READ|PROT_WRITE, ioreq_pfn);
-    if (state->buffered_io_page == NULL) {
-        hw_error("map buffered IO page returned error %d", errno);
-    }
-
-    state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));
-
-    /* FIXME: how about if we overflow the page here? */
-    for (i = 0; i < max_cpus; i++) {
-        rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
-                                        xen_vcpu_eport(state->shared_page, i));
-        if (rc == -1) {
-            fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
-            return -1;
-        }
-        state->ioreq_local_port[i] = rc;
-    }
-
-    rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN,
-            &bufioreq_evtchn);
-    if (rc < 0) {
-        fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");
-        return -1;
-    }
-    rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
-            (uint32_t)bufioreq_evtchn);
-    if (rc == -1) {
-        fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
-        return -1;
-    }
-    state->bufioreq_local_port = rc;
-
-    /* Init RAM management */
-    xen_map_cache_init(xen_phys_offset_to_gaddr, state);
-    xen_ram_init(ram_size, ram_memory);
-
-    qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
-
-    state->memory_listener = xen_memory_listener;
-    QLIST_INIT(&state->physmap);
-    memory_listener_register(&state->memory_listener, &address_space_memory);
-    state->log_for_dirtybit = NULL;
-
-    /* Initialize backend core & drivers */
-    if (xen_be_init() != 0) {
-        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
-        exit(1);
-    }
-    xen_be_register("console", &xen_console_ops);
-    xen_be_register("vkbd", &xen_kbdmouse_ops);
-    xen_be_register("qdisk", &xen_blkdev_ops);
-    xen_read_physmap(state);
-
-    return 0;
-}
-
-void destroy_hvm_domain(bool reboot)
-{
-    XenXC xc_handle;
-    int sts;
-
-    xc_handle = xen_xc_interface_open(0, 0, 0);
-    if (xc_handle == XC_HANDLER_INITIAL_VALUE) {
-        fprintf(stderr, "Cannot acquire xenctrl handle\n");
-    } else {
-        sts = xc_domain_shutdown(xc_handle, xen_domid,
-                                 reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff);
-        if (sts != 0) {
-            fprintf(stderr, "xc_domain_shutdown failed to issue %s, "
-                    "sts %d, %s\n", reboot ? "reboot" : "poweroff",
-                    sts, strerror(errno));
-        } else {
-            fprintf(stderr, "Issued domain %d %s\n", xen_domid,
-                    reboot ? "reboot" : "poweroff");
-        }
-        xc_interface_close(xc_handle);
-    }
-}
-
-void xen_register_framebuffer(MemoryRegion *mr)
-{
-    framebuffer = mr;
-}
-
-void xen_shutdown_fatal_error(const char *fmt, ...)
-{
-    va_list ap;
-
-    va_start(ap, fmt);
-    vfprintf(stderr, fmt, ap);
-    va_end(ap);
-    fprintf(stderr, "Will destroy the domain.\n");
-    /* destroy the domain */
-    qemu_system_shutdown_request();
-}
-
-void xen_modified_memory(ram_addr_t start, ram_addr_t length)
-{
-    if (unlikely(xen_in_migration)) {
-        int rc;
-        ram_addr_t start_pfn, nb_pages;
-
-        if (length == 0) {
-            length = TARGET_PAGE_SIZE;
-        }
-        start_pfn = start >> TARGET_PAGE_BITS;
-        nb_pages = ((start + length + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
-            - start_pfn;
-        rc = xc_hvm_modified_memory(xen_xc, xen_domid, start_pfn, nb_pages);
-        if (rc) {
-            fprintf(stderr,
-                    "%s failed for "RAM_ADDR_FMT" ("RAM_ADDR_FMT"): %i, %s\n",
-                    __func__, start, nb_pages, rc, strerror(-rc));
-        }
-    }
-}
diff --git a/xen-common-stub.c b/xen-common-stub.c
new file mode 100644
index 0000000..0bba290
--- /dev/null
+++ b/xen-common-stub.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014       Citrix Systems UK Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+#include "hw/xen/xen.h"
+
+void xenstore_store_pv_console_info(int i, CharDriverState *chr)
+{
+}
+
+int xen_init(QEMUMachine *machine)
+{
+    return -ENOSYS;
+}
+
diff --git a/xen-common.c b/xen-common.c
new file mode 100644
index 0000000..aa71b1a
--- /dev/null
+++ b/xen-common.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2014       Citrix Systems UK Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/xen/xen_backend.h"
+#include "qmp-commands.h"
+#include "sysemu/char.h"
+
+//#define DEBUG_XEN
+
+#ifdef DEBUG_XEN
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+static int store_dev_info(int domid, CharDriverState *cs, const char *string)
+{
+    struct xs_handle *xs = NULL;
+    char *path = NULL;
+    char *newpath = NULL;
+    char *pts = NULL;
+    int ret = -1;
+
+    /* Only continue if we're talking to a pty. */
+    if (strncmp(cs->filename, "pty:", 4)) {
+        return 0;
+    }
+    pts = cs->filename + 4;
+
+    /* We now have everything we need to set the xenstore entry. */
+    xs = xs_open(0);
+    if (xs == NULL) {
+        fprintf(stderr, "Could not contact XenStore\n");
+        goto out;
+    }
+
+    path = xs_get_domain_path(xs, domid);
+    if (path == NULL) {
+        fprintf(stderr, "xs_get_domain_path() error\n");
+        goto out;
+    }
+    newpath = realloc(path, (strlen(path) + strlen(string) +
+                strlen("/tty") + 1));
+    if (newpath == NULL) {
+        fprintf(stderr, "realloc error\n");
+        goto out;
+    }
+    path = newpath;
+
+    strcat(path, string);
+    strcat(path, "/tty");
+    if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
+        fprintf(stderr, "xs_write for '%s' fail", string);
+        goto out;
+    }
+    ret = 0;
+
+out:
+    free(path);
+    xs_close(xs);
+
+    return ret;
+}
+
+void xenstore_store_pv_console_info(int i, CharDriverState *chr)
+{
+    if (i == 0) {
+        store_dev_info(xen_domid, chr, "/console");
+    } else {
+        char buf[32];
+        snprintf(buf, sizeof(buf), "/device/console/%d", i);
+        store_dev_info(xen_domid, chr, buf);
+    }
+}
+
+
+static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
+{
+    char path[50];
+
+    if (xs == NULL) {
+        fprintf(stderr, "xenstore connection not initialized\n");
+        exit(1);
+    }
+
+    snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
+    if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) {
+        fprintf(stderr, "error recording dm state\n");
+        exit(1);
+    }
+}
+
+
+static void xen_change_state_handler(void *opaque, int running,
+                                     RunState state)
+{
+    if (running) {
+        /* record state running */
+        xenstore_record_dm_state(xenstore, "running");
+    }
+}
+
+int xen_init(QEMUMachine *machine)
+{
+    xen_xc = xen_xc_interface_open(0, 0, 0);
+    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
+        xen_be_printf(NULL, 0, "can't open xen interface\n");
+        return -1;
+    }
+    qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
+
+    return 0;
+}
+
diff --git a/xen-hvm-stub.c b/xen-hvm-stub.c
new file mode 100644
index 0000000..00fa9b3
--- /dev/null
+++ b/xen-hvm-stub.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010       Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "qemu-common.h"
+#include "hw/xen/xen.h"
+#include "exec/memory.h"
+#include "qmp-commands.h"
+#include "hw/xen/xen_common.h"
+
+int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+    return -1;
+}
+
+void xen_piix3_set_irq(void *opaque, int irq_num, int level)
+{
+}
+
+void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
+{
+}
+
+void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
+{
+}
+
+void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
+{
+}
+
+void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
+{
+}
+
+qemu_irq *xen_interrupt_controller_init(void)
+{
+    return NULL;
+}
+
+void xen_register_framebuffer(MemoryRegion *mr)
+{
+}
+
+void xen_modified_memory(ram_addr_t start, ram_addr_t length)
+{
+}
+
+int xen_hvm_init(MemoryRegion **ram_memory)
+{
+    return 0;
+}
+
+void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
+{
+}
+
+void xen_shutdown_fatal_error(const char *fmt, ...)
+{
+}
diff --git a/xen-hvm.c b/xen-hvm.c
new file mode 100644
index 0000000..0a49055
--- /dev/null
+++ b/xen-hvm.c
@@ -0,0 +1,1129 @@
+/*
+ * Copyright (C) 2010       Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include <sys/mman.h>
+
+#include "hw/pci/pci.h"
+#include "hw/i386/pc.h"
+#include "hw/xen/xen_common.h"
+#include "hw/xen/xen_backend.h"
+#include "qmp-commands.h"
+
+#include "sysemu/char.h"
+#include "qemu/range.h"
+#include "sysemu/xen-mapcache.h"
+#include "trace.h"
+#include "exec/address-spaces.h"
+
+#include <xen/hvm/ioreq.h>
+#include <xen/hvm/params.h>
+#include <xen/hvm/e820.h>
+
+//#define DEBUG_XEN_HVM
+
+#ifdef DEBUG_XEN_HVM
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi;
+static MemoryRegion *framebuffer;
+static bool xen_in_migration;
+
+/* Compatibility with older version */
+#if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a
+static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
+{
+    return shared_page->vcpu_iodata[i].vp_eport;
+}
+static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
+{
+    return &shared_page->vcpu_iodata[vcpu].vp_ioreq;
+}
+#  define FMT_ioreq_size PRIx64
+#else
+static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
+{
+    return shared_page->vcpu_ioreq[i].vp_eport;
+}
+static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
+{
+    return &shared_page->vcpu_ioreq[vcpu];
+}
+#  define FMT_ioreq_size "u"
+#endif
+#ifndef HVM_PARAM_BUFIOREQ_EVTCHN
+#define HVM_PARAM_BUFIOREQ_EVTCHN 26
+#endif
+
+#define BUFFER_IO_MAX_DELAY  100
+
+typedef struct XenPhysmap {
+    hwaddr start_addr;
+    ram_addr_t size;
+    char *name;
+    hwaddr phys_offset;
+
+    QLIST_ENTRY(XenPhysmap) list;
+} XenPhysmap;
+
+typedef struct XenIOState {
+    shared_iopage_t *shared_page;
+    buffered_iopage_t *buffered_io_page;
+    QEMUTimer *buffered_io_timer;
+    /* the evtchn port for polling the notification, */
+    evtchn_port_t *ioreq_local_port;
+    /* evtchn local port for buffered io */
+    evtchn_port_t bufioreq_local_port;
+    /* the evtchn fd for polling */
+    XenEvtchn xce_handle;
+    /* which vcpu we are serving */
+    int send_vcpu;
+
+    struct xs_handle *xenstore;
+    MemoryListener memory_listener;
+    QLIST_HEAD(, XenPhysmap) physmap;
+    hwaddr free_phys_offset;
+    const XenPhysmap *log_for_dirtybit;
+
+    Notifier exit;
+    Notifier suspend;
+    Notifier wakeup;
+} XenIOState;
+
+/* Xen specific function for piix pci */
+
+int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+    return irq_num + ((pci_dev->devfn >> 3) << 2);
+}
+
+void xen_piix3_set_irq(void *opaque, int irq_num, int level)
+{
+    xc_hvm_set_pci_intx_level(xen_xc, xen_domid, 0, 0, irq_num >> 2,
+                              irq_num & 3, level);
+}
+
+void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
+{
+    int i;
+
+    /* Scan for updates to PCI link routes (0x60-0x63). */
+    for (i = 0; i < len; i++) {
+        uint8_t v = (val >> (8 * i)) & 0xff;
+        if (v & 0x80) {
+            v = 0;
+        }
+        v &= 0xf;
+        if (((address + i) >= 0x60) && ((address + i) <= 0x63)) {
+            xc_hvm_set_pci_link_route(xen_xc, xen_domid, address + i - 0x60, v);
+        }
+    }
+}
+
+void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
+{
+    xen_xc_hvm_inject_msi(xen_xc, xen_domid, addr, data);
+}
+
+static void xen_suspend_notifier(Notifier *notifier, void *data)
+{
+    xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
+}
+
+/* Xen Interrupt Controller */
+
+static void xen_set_irq(void *opaque, int irq, int level)
+{
+    xc_hvm_set_isa_irq_level(xen_xc, xen_domid, irq, level);
+}
+
+qemu_irq *xen_interrupt_controller_init(void)
+{
+    return qemu_allocate_irqs(xen_set_irq, NULL, 16);
+}
+
+/* Memory Ops */
+
+static void xen_ram_init(ram_addr_t ram_size, MemoryRegion **ram_memory_p)
+{
+    MemoryRegion *sysmem = get_system_memory();
+    ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
+    ram_addr_t block_len;
+
+    block_len = ram_size;
+    if (ram_size >= HVM_BELOW_4G_RAM_END) {
+        /* Xen does not allocate the memory continuously, and keep a hole at
+         * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH
+         */
+        block_len += HVM_BELOW_4G_MMIO_LENGTH;
+    }
+    memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len);
+    *ram_memory_p = &ram_memory;
+    vmstate_register_ram_global(&ram_memory);
+
+    if (ram_size >= HVM_BELOW_4G_RAM_END) {
+        above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
+        below_4g_mem_size = HVM_BELOW_4G_RAM_END;
+    } else {
+        below_4g_mem_size = ram_size;
+    }
+
+    memory_region_init_alias(&ram_640k, NULL, "xen.ram.640k",
+                             &ram_memory, 0, 0xa0000);
+    memory_region_add_subregion(sysmem, 0, &ram_640k);
+    /* Skip of the VGA IO memory space, it will be registered later by the VGA
+     * emulated device.
+     *
+     * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load
+     * the Options ROM, so it is registered here as RAM.
+     */
+    memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo",
+                             &ram_memory, 0xc0000, below_4g_mem_size - 0xc0000);
+    memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
+    if (above_4g_mem_size > 0) {
+        memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi",
+                                 &ram_memory, 0x100000000ULL,
+                                 above_4g_mem_size);
+        memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
+    }
+}
+
+void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
+{
+    unsigned long nr_pfn;
+    xen_pfn_t *pfn_list;
+    int i;
+
+    if (runstate_check(RUN_STATE_INMIGRATE)) {
+        /* RAM already populated in Xen */
+        fprintf(stderr, "%s: do not alloc "RAM_ADDR_FMT
+                " bytes of ram at "RAM_ADDR_FMT" when runstate is INMIGRATE\n",
+                __func__, size, ram_addr); 
+        return;
+    }
+
+    if (mr == &ram_memory) {
+        return;
+    }
+
+    trace_xen_ram_alloc(ram_addr, size);
+
+    nr_pfn = size >> TARGET_PAGE_BITS;
+    pfn_list = g_malloc(sizeof (*pfn_list) * nr_pfn);
+
+    for (i = 0; i < nr_pfn; i++) {
+        pfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i;
+    }
+
+    if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
+        hw_error("xen: failed to populate ram at " RAM_ADDR_FMT, ram_addr);
+    }
+
+    g_free(pfn_list);
+}
+
+static XenPhysmap *get_physmapping(XenIOState *state,
+                                   hwaddr start_addr, ram_addr_t size)
+{
+    XenPhysmap *physmap = NULL;
+
+    start_addr &= TARGET_PAGE_MASK;
+
+    QLIST_FOREACH(physmap, &state->physmap, list) {
+        if (range_covers_byte(physmap->start_addr, physmap->size, start_addr)) {
+            return physmap;
+        }
+    }
+    return NULL;
+}
+
+static hwaddr xen_phys_offset_to_gaddr(hwaddr start_addr,
+                                                   ram_addr_t size, void *opaque)
+{
+    hwaddr addr = start_addr & TARGET_PAGE_MASK;
+    XenIOState *xen_io_state = opaque;
+    XenPhysmap *physmap = NULL;
+
+    QLIST_FOREACH(physmap, &xen_io_state->physmap, list) {
+        if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
+            return physmap->start_addr;
+        }
+    }
+
+    return start_addr;
+}
+
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340
+static int xen_add_to_physmap(XenIOState *state,
+                              hwaddr start_addr,
+                              ram_addr_t size,
+                              MemoryRegion *mr,
+                              hwaddr offset_within_region)
+{
+    unsigned long i = 0;
+    int rc = 0;
+    XenPhysmap *physmap = NULL;
+    hwaddr pfn, start_gpfn;
+    hwaddr phys_offset = memory_region_get_ram_addr(mr);
+    char path[80], value[17];
+
+    if (get_physmapping(state, start_addr, size)) {
+        return 0;
+    }
+    if (size <= 0) {
+        return -1;
+    }
+
+    /* Xen can only handle a single dirty log region for now and we want
+     * the linear framebuffer to be that region.
+     * Avoid tracking any regions that is not videoram and avoid tracking
+     * the legacy vga region. */
+    if (mr == framebuffer && start_addr > 0xbffff) {
+        goto go_physmap;
+    }
+    return -1;
+
+go_physmap:
+    DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
+            start_addr, start_addr + size);
+
+    pfn = phys_offset >> TARGET_PAGE_BITS;
+    start_gpfn = start_addr >> TARGET_PAGE_BITS;
+    for (i = 0; i < size >> TARGET_PAGE_BITS; i++) {
+        unsigned long idx = pfn + i;
+        xen_pfn_t gpfn = start_gpfn + i;
+
+        rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
+        if (rc) {
+            DPRINTF("add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
+                    PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
+            return -rc;
+        }
+    }
+
+    physmap = g_malloc(sizeof (XenPhysmap));
+
+    physmap->start_addr = start_addr;
+    physmap->size = size;
+    physmap->name = (char *)mr->name;
+    physmap->phys_offset = phys_offset;
+
+    QLIST_INSERT_HEAD(&state->physmap, physmap, list);
+
+    xc_domain_pin_memory_cacheattr(xen_xc, xen_domid,
+                                   start_addr >> TARGET_PAGE_BITS,
+                                   (start_addr + size) >> TARGET_PAGE_BITS,
+                                   XEN_DOMCTL_MEM_CACHEATTR_WB);
+
+    snprintf(path, sizeof(path),
+            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
+            xen_domid, (uint64_t)phys_offset);
+    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)start_addr);
+    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
+        return -1;
+    }
+    snprintf(path, sizeof(path),
+            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
+            xen_domid, (uint64_t)phys_offset);
+    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)size);
+    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
+        return -1;
+    }
+    if (mr->name) {
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
+                xen_domid, (uint64_t)phys_offset);
+        if (!xs_write(state->xenstore, 0, path, mr->name, strlen(mr->name))) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int xen_remove_from_physmap(XenIOState *state,
+                                   hwaddr start_addr,
+                                   ram_addr_t size)
+{
+    unsigned long i = 0;
+    int rc = 0;
+    XenPhysmap *physmap = NULL;
+    hwaddr phys_offset = 0;
+
+    physmap = get_physmapping(state, start_addr, size);
+    if (physmap == NULL) {
+        return -1;
+    }
+
+    phys_offset = physmap->phys_offset;
+    size = physmap->size;
+
+    DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", at "
+            "%"HWADDR_PRIx"\n", start_addr, start_addr + size, phys_offset);
+
+    size >>= TARGET_PAGE_BITS;
+    start_addr >>= TARGET_PAGE_BITS;
+    phys_offset >>= TARGET_PAGE_BITS;
+    for (i = 0; i < size; i++) {
+        unsigned long idx = start_addr + i;
+        xen_pfn_t gpfn = phys_offset + i;
+
+        rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
+        if (rc) {
+            fprintf(stderr, "add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
+                    PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
+            return -rc;
+        }
+    }
+
+    QLIST_REMOVE(physmap, list);
+    if (state->log_for_dirtybit == physmap) {
+        state->log_for_dirtybit = NULL;
+    }
+    g_free(physmap);
+
+    return 0;
+}
+
+#else
+static int xen_add_to_physmap(XenIOState *state,
+                              hwaddr start_addr,
+                              ram_addr_t size,
+                              MemoryRegion *mr,
+                              hwaddr offset_within_region)
+{
+    return -ENOSYS;
+}
+
+static int xen_remove_from_physmap(XenIOState *state,
+                                   hwaddr start_addr,
+                                   ram_addr_t size)
+{
+    return -ENOSYS;
+}
+#endif
+
+static void xen_set_memory(struct MemoryListener *listener,
+                           MemoryRegionSection *section,
+                           bool add)
+{
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+    hwaddr start_addr = section->offset_within_address_space;
+    ram_addr_t size = int128_get64(section->size);
+    bool log_dirty = memory_region_is_logging(section->mr);
+    hvmmem_type_t mem_type;
+
+    if (!memory_region_is_ram(section->mr)) {
+        return;
+    }
+
+    if (!(section->mr != &ram_memory
+          && ( (log_dirty && add) || (!log_dirty && !add)))) {
+        return;
+    }
+
+    trace_xen_client_set_memory(start_addr, size, log_dirty);
+
+    start_addr &= TARGET_PAGE_MASK;
+    size = TARGET_PAGE_ALIGN(size);
+
+    if (add) {
+        if (!memory_region_is_rom(section->mr)) {
+            xen_add_to_physmap(state, start_addr, size,
+                               section->mr, section->offset_within_region);
+        } else {
+            mem_type = HVMMEM_ram_ro;
+            if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,
+                                    start_addr >> TARGET_PAGE_BITS,
+                                    size >> TARGET_PAGE_BITS)) {
+                DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",
+                        start_addr);
+            }
+        }
+    } else {
+        if (xen_remove_from_physmap(state, start_addr, size) < 0) {
+            DPRINTF("physmapping does not exist at "TARGET_FMT_plx"\n", start_addr);
+        }
+    }
+}
+
+static void xen_region_add(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+    memory_region_ref(section->mr);
+    xen_set_memory(listener, section, true);
+}
+
+static void xen_region_del(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+    xen_set_memory(listener, section, false);
+    memory_region_unref(section->mr);
+}
+
+static void xen_sync_dirty_bitmap(XenIOState *state,
+                                  hwaddr start_addr,
+                                  ram_addr_t size)
+{
+    hwaddr npages = size >> TARGET_PAGE_BITS;
+    const int width = sizeof(unsigned long) * 8;
+    unsigned long bitmap[(npages + width - 1) / width];
+    int rc, i, j;
+    const XenPhysmap *physmap = NULL;
+
+    physmap = get_physmapping(state, start_addr, size);
+    if (physmap == NULL) {
+        /* not handled */
+        return;
+    }
+
+    if (state->log_for_dirtybit == NULL) {
+        state->log_for_dirtybit = physmap;
+    } else if (state->log_for_dirtybit != physmap) {
+        /* Only one range for dirty bitmap can be tracked. */
+        return;
+    }
+
+    rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid,
+                                 start_addr >> TARGET_PAGE_BITS, npages,
+                                 bitmap);
+    if (rc < 0) {
+        if (rc != -ENODATA) {
+            memory_region_set_dirty(framebuffer, 0, size);
+            DPRINTF("xen: track_dirty_vram failed (0x" TARGET_FMT_plx
+                    ", 0x" TARGET_FMT_plx "): %s\n",
+                    start_addr, start_addr + size, strerror(-rc));
+        }
+        return;
+    }
+
+    for (i = 0; i < ARRAY_SIZE(bitmap); i++) {
+        unsigned long map = bitmap[i];
+        while (map != 0) {
+            j = ffsl(map) - 1;
+            map &= ~(1ul << j);
+            memory_region_set_dirty(framebuffer,
+                                    (i * width + j) * TARGET_PAGE_SIZE,
+                                    TARGET_PAGE_SIZE);
+        };
+    }
+}
+
+static void xen_log_start(MemoryListener *listener,
+                          MemoryRegionSection *section)
+{
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+
+    xen_sync_dirty_bitmap(state, section->offset_within_address_space,
+                          int128_get64(section->size));
+}
+
+static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section)
+{
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+
+    state->log_for_dirtybit = NULL;
+    /* Disable dirty bit tracking */
+    xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
+}
+
+static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *section)
+{
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+
+    xen_sync_dirty_bitmap(state, section->offset_within_address_space,
+                          int128_get64(section->size));
+}
+
+static void xen_log_global_start(MemoryListener *listener)
+{
+    if (xen_enabled()) {
+        xen_in_migration = true;
+    }
+}
+
+static void xen_log_global_stop(MemoryListener *listener)
+{
+    xen_in_migration = false;
+}
+
+static MemoryListener xen_memory_listener = {
+    .region_add = xen_region_add,
+    .region_del = xen_region_del,
+    .log_start = xen_log_start,
+    .log_stop = xen_log_stop,
+    .log_sync = xen_log_sync,
+    .log_global_start = xen_log_global_start,
+    .log_global_stop = xen_log_global_stop,
+    .priority = 10,
+};
+
+/* get the ioreq packets from share mem */
+static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu)
+{
+    ioreq_t *req = xen_vcpu_ioreq(state->shared_page, vcpu);
+
+    if (req->state != STATE_IOREQ_READY) {
+        DPRINTF("I/O request not ready: "
+                "%x, ptr: %x, port: %"PRIx64", "
+                "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
+                req->state, req->data_is_ptr, req->addr,
+                req->data, req->count, req->size);
+        return NULL;
+    }
+
+    xen_rmb(); /* see IOREQ_READY /then/ read contents of ioreq */
+
+    req->state = STATE_IOREQ_INPROCESS;
+    return req;
+}
+
+/* use poll to get the port notification */
+/* ioreq_vec--out,the */
+/* retval--the number of ioreq packet */
+static ioreq_t *cpu_get_ioreq(XenIOState *state)
+{
+    int i;
+    evtchn_port_t port;
+
+    port = xc_evtchn_pending(state->xce_handle);
+    if (port == state->bufioreq_local_port) {
+        timer_mod(state->buffered_io_timer,
+                BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
+        return NULL;
+    }
+
+    if (port != -1) {
+        for (i = 0; i < max_cpus; i++) {
+            if (state->ioreq_local_port[i] == port) {
+                break;
+            }
+        }
+
+        if (i == max_cpus) {
+            hw_error("Fatal error while trying to get io event!\n");
+        }
+
+        /* unmask the wanted port again */
+        xc_evtchn_unmask(state->xce_handle, port);
+
+        /* get the io packet from shared memory */
+        state->send_vcpu = i;
+        return cpu_get_ioreq_from_shared_memory(state, i);
+    }
+
+    /* read error or read nothing */
+    return NULL;
+}
+
+static uint32_t do_inp(pio_addr_t addr, unsigned long size)
+{
+    switch (size) {
+        case 1:
+            return cpu_inb(addr);
+        case 2:
+            return cpu_inw(addr);
+        case 4:
+            return cpu_inl(addr);
+        default:
+            hw_error("inp: bad size: %04"FMT_pioaddr" %lx", addr, size);
+    }
+}
+
+static void do_outp(pio_addr_t addr,
+        unsigned long size, uint32_t val)
+{
+    switch (size) {
+        case 1:
+            return cpu_outb(addr, val);
+        case 2:
+            return cpu_outw(addr, val);
+        case 4:
+            return cpu_outl(addr, val);
+        default:
+            hw_error("outp: bad size: %04"FMT_pioaddr" %lx", addr, size);
+    }
+}
+
+/*
+ * Helper functions which read/write an object from/to physical guest
+ * memory, as part of the implementation of an ioreq.
+ *
+ * Equivalent to
+ *   cpu_physical_memory_rw(addr + (req->df ? -1 : +1) * req->size * i,
+ *                          val, req->size, 0/1)
+ * except without the integer overflow problems.
+ */
+static void rw_phys_req_item(hwaddr addr,
+                             ioreq_t *req, uint32_t i, void *val, int rw)
+{
+    /* Do everything unsigned so overflow just results in a truncated result
+     * and accesses to undesired parts of guest memory, which is up
+     * to the guest */
+    hwaddr offset = (hwaddr)req->size * i;
+    if (req->df) {
+        addr -= offset;
+    } else {
+        addr += offset;
+    }
+    cpu_physical_memory_rw(addr, val, req->size, rw);
+}
+
+static inline void read_phys_req_item(hwaddr addr,
+                                      ioreq_t *req, uint32_t i, void *val)
+{
+    rw_phys_req_item(addr, req, i, val, 0);
+}
+static inline void write_phys_req_item(hwaddr addr,
+                                       ioreq_t *req, uint32_t i, void *val)
+{
+    rw_phys_req_item(addr, req, i, val, 1);
+}
+
+
+static void cpu_ioreq_pio(ioreq_t *req)
+{
+    uint32_t i;
+
+    if (req->dir == IOREQ_READ) {
+        if (!req->data_is_ptr) {
+            req->data = do_inp(req->addr, req->size);
+        } else {
+            uint32_t tmp;
+
+            for (i = 0; i < req->count; i++) {
+                tmp = do_inp(req->addr, req->size);
+                write_phys_req_item(req->data, req, i, &tmp);
+            }
+        }
+    } else if (req->dir == IOREQ_WRITE) {
+        if (!req->data_is_ptr) {
+            do_outp(req->addr, req->size, req->data);
+        } else {
+            for (i = 0; i < req->count; i++) {
+                uint32_t tmp = 0;
+
+                read_phys_req_item(req->data, req, i, &tmp);
+                do_outp(req->addr, req->size, tmp);
+            }
+        }
+    }
+}
+
+static void cpu_ioreq_move(ioreq_t *req)
+{
+    uint32_t i;
+
+    if (!req->data_is_ptr) {
+        if (req->dir == IOREQ_READ) {
+            for (i = 0; i < req->count; i++) {
+                read_phys_req_item(req->addr, req, i, &req->data);
+            }
+        } else if (req->dir == IOREQ_WRITE) {
+            for (i = 0; i < req->count; i++) {
+                write_phys_req_item(req->addr, req, i, &req->data);
+            }
+        }
+    } else {
+        uint64_t tmp;
+
+        if (req->dir == IOREQ_READ) {
+            for (i = 0; i < req->count; i++) {
+                read_phys_req_item(req->addr, req, i, &tmp);
+                write_phys_req_item(req->data, req, i, &tmp);
+            }
+        } else if (req->dir == IOREQ_WRITE) {
+            for (i = 0; i < req->count; i++) {
+                read_phys_req_item(req->data, req, i, &tmp);
+                write_phys_req_item(req->addr, req, i, &tmp);
+            }
+        }
+    }
+}
+
+static void handle_ioreq(ioreq_t *req)
+{
+    if (!req->data_is_ptr && (req->dir == IOREQ_WRITE) &&
+            (req->size < sizeof (target_ulong))) {
+        req->data &= ((target_ulong) 1 << (8 * req->size)) - 1;
+    }
+
+    switch (req->type) {
+        case IOREQ_TYPE_PIO:
+            cpu_ioreq_pio(req);
+            break;
+        case IOREQ_TYPE_COPY:
+            cpu_ioreq_move(req);
+            break;
+        case IOREQ_TYPE_TIMEOFFSET:
+            break;
+        case IOREQ_TYPE_INVALIDATE:
+            xen_invalidate_map_cache();
+            break;
+        default:
+            hw_error("Invalid ioreq type 0x%x\n", req->type);
+    }
+}
+
+static int handle_buffered_iopage(XenIOState *state)
+{
+    buf_ioreq_t *buf_req = NULL;
+    ioreq_t req;
+    int qw;
+
+    if (!state->buffered_io_page) {
+        return 0;
+    }
+
+    memset(&req, 0x00, sizeof(req));
+
+    while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {
+        buf_req = &state->buffered_io_page->buf_ioreq[
+            state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
+        req.size = 1UL << buf_req->size;
+        req.count = 1;
+        req.addr = buf_req->addr;
+        req.data = buf_req->data;
+        req.state = STATE_IOREQ_READY;
+        req.dir = buf_req->dir;
+        req.df = 1;
+        req.type = buf_req->type;
+        req.data_is_ptr = 0;
+        qw = (req.size == 8);
+        if (qw) {
+            buf_req = &state->buffered_io_page->buf_ioreq[
+                (state->buffered_io_page->read_pointer + 1) % IOREQ_BUFFER_SLOT_NUM];
+            req.data |= ((uint64_t)buf_req->data) << 32;
+        }
+
+        handle_ioreq(&req);
+
+        xen_mb();
+        state->buffered_io_page->read_pointer += qw ? 2 : 1;
+    }
+
+    return req.count;
+}
+
+static void handle_buffered_io(void *opaque)
+{
+    XenIOState *state = opaque;
+
+    if (handle_buffered_iopage(state)) {
+        timer_mod(state->buffered_io_timer,
+                BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
+    } else {
+        timer_del(state->buffered_io_timer);
+        xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
+    }
+}
+
+static void cpu_handle_ioreq(void *opaque)
+{
+    XenIOState *state = opaque;
+    ioreq_t *req = cpu_get_ioreq(state);
+
+    handle_buffered_iopage(state);
+    if (req) {
+        handle_ioreq(req);
+
+        if (req->state != STATE_IOREQ_INPROCESS) {
+            fprintf(stderr, "Badness in I/O request ... not in service?!: "
+                    "%x, ptr: %x, port: %"PRIx64", "
+                    "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
+                    req->state, req->data_is_ptr, req->addr,
+                    req->data, req->count, req->size);
+            destroy_hvm_domain(false);
+            return;
+        }
+
+        xen_wmb(); /* Update ioreq contents /then/ update state. */
+
+        /*
+         * We do this before we send the response so that the tools
+         * have the opportunity to pick up on the reset before the
+         * guest resumes and does a hlt with interrupts disabled which
+         * causes Xen to powerdown the domain.
+         */
+        if (runstate_is_running()) {
+            if (qemu_shutdown_requested_get()) {
+                destroy_hvm_domain(false);
+            }
+            if (qemu_reset_requested_get()) {
+                qemu_system_reset(VMRESET_REPORT);
+                destroy_hvm_domain(true);
+            }
+        }
+
+        req->state = STATE_IORESP_READY;
+        xc_evtchn_notify(state->xce_handle, state->ioreq_local_port[state->send_vcpu]);
+    }
+}
+
+static void xen_main_loop_prepare(XenIOState *state)
+{
+    int evtchn_fd = -1;
+
+    if (state->xce_handle != XC_HANDLER_INITIAL_VALUE) {
+        evtchn_fd = xc_evtchn_fd(state->xce_handle);
+    }
+
+    state->buffered_io_timer = timer_new_ms(QEMU_CLOCK_REALTIME, handle_buffered_io,
+                                                 state);
+
+    if (evtchn_fd != -1) {
+        qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
+    }
+}
+
+
+static void xen_hvm_change_state_handler(void *opaque, int running,
+                                         RunState rstate)
+{
+    XenIOState *xstate = opaque;
+    if (running) {
+        xen_main_loop_prepare(xstate);
+    }
+}
+
+static void xen_exit_notifier(Notifier *n, void *data)
+{
+    XenIOState *state = container_of(n, XenIOState, exit);
+
+    xc_evtchn_close(state->xce_handle);
+    xs_daemon_close(state->xenstore);
+}
+
+static void xen_read_physmap(XenIOState *state)
+{
+    XenPhysmap *physmap = NULL;
+    unsigned int len, num, i;
+    char path[80], *value = NULL;
+    char **entries = NULL;
+
+    snprintf(path, sizeof(path),
+            "/local/domain/0/device-model/%d/physmap", xen_domid);
+    entries = xs_directory(state->xenstore, 0, path, &num);
+    if (entries == NULL)
+        return;
+
+    for (i = 0; i < num; i++) {
+        physmap = g_malloc(sizeof (XenPhysmap));
+        physmap->phys_offset = strtoull(entries[i], NULL, 16);
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%s/start_addr",
+                xen_domid, entries[i]);
+        value = xs_read(state->xenstore, 0, path, &len);
+        if (value == NULL) {
+            g_free(physmap);
+            continue;
+        }
+        physmap->start_addr = strtoull(value, NULL, 16);
+        free(value);
+
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%s/size",
+                xen_domid, entries[i]);
+        value = xs_read(state->xenstore, 0, path, &len);
+        if (value == NULL) {
+            g_free(physmap);
+            continue;
+        }
+        physmap->size = strtoull(value, NULL, 16);
+        free(value);
+
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%s/name",
+                xen_domid, entries[i]);
+        physmap->name = xs_read(state->xenstore, 0, path, &len);
+
+        QLIST_INSERT_HEAD(&state->physmap, physmap, list);
+    }
+    free(entries);
+}
+
+static void xen_wakeup_notifier(Notifier *notifier, void *data)
+{
+    xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
+}
+
+int xen_hvm_init(MemoryRegion **ram_memory)
+{
+    int i, rc;
+    unsigned long ioreq_pfn;
+    unsigned long bufioreq_evtchn;
+    XenIOState *state;
+
+    state = g_malloc0(sizeof (XenIOState));
+
+    state->xce_handle = xen_xc_evtchn_open(NULL, 0);
+    if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
+        perror("xen: event channel open");
+        g_free(state);
+        return -errno;
+    }
+
+    state->xenstore = xs_daemon_open();
+    if (state->xenstore == NULL) {
+        perror("xen: xenstore open");
+        g_free(state);
+        return -errno;
+    }
+
+    state->exit.notify = xen_exit_notifier;
+    qemu_add_exit_notifier(&state->exit);
+
+    state->suspend.notify = xen_suspend_notifier;
+    qemu_register_suspend_notifier(&state->suspend);
+
+    state->wakeup.notify = xen_wakeup_notifier;
+    qemu_register_wakeup_notifier(&state->wakeup);
+
+    xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
+    DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
+    state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
+                                              PROT_READ|PROT_WRITE, ioreq_pfn);
+    if (state->shared_page == NULL) {
+        hw_error("map shared IO page returned error %d handle=" XC_INTERFACE_FMT,
+                 errno, xen_xc);
+    }
+
+    xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
+    DPRINTF("buffered io page at pfn %lx\n", ioreq_pfn);
+    state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
+                                                   PROT_READ|PROT_WRITE, ioreq_pfn);
+    if (state->buffered_io_page == NULL) {
+        hw_error("map buffered IO page returned error %d", errno);
+    }
+
+    state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));
+
+    /* FIXME: how about if we overflow the page here? */
+    for (i = 0; i < max_cpus; i++) {
+        rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
+                                        xen_vcpu_eport(state->shared_page, i));
+        if (rc == -1) {
+            fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
+            return -1;
+        }
+        state->ioreq_local_port[i] = rc;
+    }
+
+    rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN,
+            &bufioreq_evtchn);
+    if (rc < 0) {
+        fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");
+        return -1;
+    }
+    rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
+            (uint32_t)bufioreq_evtchn);
+    if (rc == -1) {
+        fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
+        return -1;
+    }
+    state->bufioreq_local_port = rc;
+
+    /* Init RAM management */
+    xen_map_cache_init(xen_phys_offset_to_gaddr, state);
+    xen_ram_init(ram_size, ram_memory);
+
+    qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
+
+    state->memory_listener = xen_memory_listener;
+    QLIST_INIT(&state->physmap);
+    memory_listener_register(&state->memory_listener, &address_space_memory);
+    state->log_for_dirtybit = NULL;
+
+    /* Initialize backend core & drivers */
+    if (xen_be_init() != 0) {
+        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
+        exit(1);
+    }
+    xen_be_register("console", &xen_console_ops);
+    xen_be_register("vkbd", &xen_kbdmouse_ops);
+    xen_be_register("qdisk", &xen_blkdev_ops);
+    xen_read_physmap(state);
+
+    return 0;
+}
+
+void destroy_hvm_domain(bool reboot)
+{
+    XenXC xc_handle;
+    int sts;
+
+    xc_handle = xen_xc_interface_open(0, 0, 0);
+    if (xc_handle == XC_HANDLER_INITIAL_VALUE) {
+        fprintf(stderr, "Cannot acquire xenctrl handle\n");
+    } else {
+        sts = xc_domain_shutdown(xc_handle, xen_domid,
+                                 reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff);
+        if (sts != 0) {
+            fprintf(stderr, "xc_domain_shutdown failed to issue %s, "
+                    "sts %d, %s\n", reboot ? "reboot" : "poweroff",
+                    sts, strerror(errno));
+        } else {
+            fprintf(stderr, "Issued domain %d %s\n", xen_domid,
+                    reboot ? "reboot" : "poweroff");
+        }
+        xc_interface_close(xc_handle);
+    }
+}
+
+void xen_register_framebuffer(MemoryRegion *mr)
+{
+    framebuffer = mr;
+}
+
+void xen_shutdown_fatal_error(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    fprintf(stderr, "Will destroy the domain.\n");
+    /* destroy the domain */
+    qemu_system_shutdown_request();
+}
+
+void xen_modified_memory(ram_addr_t start, ram_addr_t length)
+{
+    if (unlikely(xen_in_migration)) {
+        int rc;
+        ram_addr_t start_pfn, nb_pages;
+
+        if (length == 0) {
+            length = TARGET_PAGE_SIZE;
+        }
+        start_pfn = start >> TARGET_PAGE_BITS;
+        nb_pages = ((start + length + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
+            - start_pfn;
+        rc = xc_hvm_modified_memory(xen_xc, xen_domid, start_pfn, nb_pages);
+        if (rc) {
+            fprintf(stderr,
+                    "%s failed for "RAM_ADDR_FMT" ("RAM_ADDR_FMT"): %i, %s\n",
+                    __func__, start, nb_pages, rc, strerror(-rc));
+        }
+    }
+}
+
+void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
+{
+    if (enable) {
+        memory_global_dirty_log_start();
+    } else {
+        memory_global_dirty_log_stop();
+    }
+}
diff --git a/xen-mapcache-stub.c b/xen-mapcache-stub.c
new file mode 100644
index 0000000..f4ddf53
--- /dev/null
+++ b/xen-mapcache-stub.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014       Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "config.h"
+
+#include <sys/resource.h>
+
+#include "hw/xen/xen_backend.h"
+
+#include <xen/hvm/params.h>
+
+#include "sysemu/xen-mapcache.h"
+#include "trace.h"
+
+uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
+                       uint8_t lock)
+{
+    abort();
+    return NULL;
+}
+
+ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
+{
+    abort();
+    return 0;
+}
+
+void xen_invalidate_map_cache_entry(uint8_t *buffer)
+{
+    abort();
+}
+
diff --git a/xen-stub.c b/xen-stub.c
deleted file mode 100644
index 59927cb..0000000
--- a/xen-stub.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010       Citrix Ltd.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu-common.h"
-#include "hw/xen/xen.h"
-#include "exec/memory.h"
-#include "qmp-commands.h"
-
-void xenstore_store_pv_console_info(int i, CharDriverState *chr)
-{
-}
-
-int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
-{
-    return -1;
-}
-
-void xen_piix3_set_irq(void *opaque, int irq_num, int level)
-{
-}
-
-void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
-{
-}
-
-void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
-{
-}
-
-void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
-{
-}
-
-void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
-{
-}
-
-qemu_irq *xen_interrupt_controller_init(void)
-{
-    return NULL;
-}
-
-int xen_init(QEMUMachine *machine)
-{
-    return -ENOSYS;
-}
-
-void xen_register_framebuffer(MemoryRegion *mr)
-{
-}
-
-void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
-{
-}
-
-void xen_modified_memory(ram_addr_t start, ram_addr_t length)
-{
-}
-
-int xen_hvm_init(MemoryRegion **ram_memory)
-{
-    return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH resend 3/3] xen: factor out common functions
@ 2014-03-25 15:59   ` Wei Liu
  0 siblings, 0 replies; 18+ messages in thread
From: Wei Liu @ 2014-03-25 15:59 UTC (permalink / raw)
  To: xen-devel, qemu-devel; +Cc: anthony.perard, Wei Liu, stefano.stabellini

So common functions used by both HVM and PV are factored out from
xen-all.c to xen-common.c.

Finally rename xen-all.c to xen-hvm.c, as those functions are only
useful to HVM guest.

Create *-stub files and modify Makefile.target to reflect the changes.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 Makefile.target     |    6 +-
 xen-all.c           | 1228 ---------------------------------------------------
 xen-common-stub.c   |   19 +
 xen-common.c        |  123 ++++++
 xen-hvm-stub.c      |   66 +++
 xen-hvm.c           | 1129 ++++++++++++++++++++++++++++++++++++++++++++++
 xen-mapcache-stub.c |   39 ++
 xen-stub.c          |   70 ---
 8 files changed, 1380 insertions(+), 1300 deletions(-)
 delete mode 100644 xen-all.c
 create mode 100644 xen-common-stub.c
 create mode 100644 xen-common.c
 create mode 100644 xen-hvm-stub.c
 create mode 100644 xen-hvm.c
 create mode 100644 xen-mapcache-stub.c
 delete mode 100644 xen-stub.c

diff --git a/Makefile.target b/Makefile.target
index ba12340..02090aa 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -120,8 +120,10 @@ obj-y += dump.o
 LIBS+=$(libs_softmmu)
 
 # xen support
-obj-$(CONFIG_XEN) += xen-all.o xen-mapcache.o
-obj-$(call lnot,$(CONFIG_XEN)) += xen-stub.o
+obj-$(CONFIG_XEN) += xen-common.o
+obj-$(CONFIG_XEN_I386) += xen-hvm.o xen-mapcache.o
+obj-$(call lnot,$(CONFIG_XEN)) += xen-common-stub.o
+obj-$(call lnot,$(CONFIG_XEN_I386)) += xen-hvm-stub.o xen-mapcache-stub.o
 
 # Hardware support
 ifeq ($(TARGET_NAME), sparc64)
diff --git a/xen-all.c b/xen-all.c
deleted file mode 100644
index ba34739..0000000
--- a/xen-all.c
+++ /dev/null
@@ -1,1228 +0,0 @@
-/*
- * Copyright (C) 2010       Citrix Ltd.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include <sys/mman.h>
-
-#include "hw/pci/pci.h"
-#include "hw/i386/pc.h"
-#include "hw/xen/xen_common.h"
-#include "hw/xen/xen_backend.h"
-#include "qmp-commands.h"
-
-#include "sysemu/char.h"
-#include "qemu/range.h"
-#include "sysemu/xen-mapcache.h"
-#include "trace.h"
-#include "exec/address-spaces.h"
-
-#include <xen/hvm/ioreq.h>
-#include <xen/hvm/params.h>
-#include <xen/hvm/e820.h>
-
-//#define DEBUG_XEN
-
-#ifdef DEBUG_XEN
-#define DPRINTF(fmt, ...) \
-    do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
-    do { } while (0)
-#endif
-
-static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi;
-static MemoryRegion *framebuffer;
-static bool xen_in_migration;
-
-/* Compatibility with older version */
-#if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a
-static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
-{
-    return shared_page->vcpu_iodata[i].vp_eport;
-}
-static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
-{
-    return &shared_page->vcpu_iodata[vcpu].vp_ioreq;
-}
-#  define FMT_ioreq_size PRIx64
-#else
-static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
-{
-    return shared_page->vcpu_ioreq[i].vp_eport;
-}
-static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
-{
-    return &shared_page->vcpu_ioreq[vcpu];
-}
-#  define FMT_ioreq_size "u"
-#endif
-#ifndef HVM_PARAM_BUFIOREQ_EVTCHN
-#define HVM_PARAM_BUFIOREQ_EVTCHN 26
-#endif
-
-#define BUFFER_IO_MAX_DELAY  100
-
-typedef struct XenPhysmap {
-    hwaddr start_addr;
-    ram_addr_t size;
-    char *name;
-    hwaddr phys_offset;
-
-    QLIST_ENTRY(XenPhysmap) list;
-} XenPhysmap;
-
-typedef struct XenIOState {
-    shared_iopage_t *shared_page;
-    buffered_iopage_t *buffered_io_page;
-    QEMUTimer *buffered_io_timer;
-    /* the evtchn port for polling the notification, */
-    evtchn_port_t *ioreq_local_port;
-    /* evtchn local port for buffered io */
-    evtchn_port_t bufioreq_local_port;
-    /* the evtchn fd for polling */
-    XenEvtchn xce_handle;
-    /* which vcpu we are serving */
-    int send_vcpu;
-
-    struct xs_handle *xenstore;
-    MemoryListener memory_listener;
-    QLIST_HEAD(, XenPhysmap) physmap;
-    hwaddr free_phys_offset;
-    const XenPhysmap *log_for_dirtybit;
-
-    Notifier exit;
-    Notifier suspend;
-    Notifier wakeup;
-} XenIOState;
-
-/* Xen specific function for piix pci */
-
-int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
-{
-    return irq_num + ((pci_dev->devfn >> 3) << 2);
-}
-
-void xen_piix3_set_irq(void *opaque, int irq_num, int level)
-{
-    xc_hvm_set_pci_intx_level(xen_xc, xen_domid, 0, 0, irq_num >> 2,
-                              irq_num & 3, level);
-}
-
-void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
-{
-    int i;
-
-    /* Scan for updates to PCI link routes (0x60-0x63). */
-    for (i = 0; i < len; i++) {
-        uint8_t v = (val >> (8 * i)) & 0xff;
-        if (v & 0x80) {
-            v = 0;
-        }
-        v &= 0xf;
-        if (((address + i) >= 0x60) && ((address + i) <= 0x63)) {
-            xc_hvm_set_pci_link_route(xen_xc, xen_domid, address + i - 0x60, v);
-        }
-    }
-}
-
-void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
-{
-    xen_xc_hvm_inject_msi(xen_xc, xen_domid, addr, data);
-}
-
-static void xen_suspend_notifier(Notifier *notifier, void *data)
-{
-    xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
-}
-
-/* Xen Interrupt Controller */
-
-static void xen_set_irq(void *opaque, int irq, int level)
-{
-    xc_hvm_set_isa_irq_level(xen_xc, xen_domid, irq, level);
-}
-
-qemu_irq *xen_interrupt_controller_init(void)
-{
-    return qemu_allocate_irqs(xen_set_irq, NULL, 16);
-}
-
-/* Memory Ops */
-
-static void xen_ram_init(ram_addr_t ram_size, MemoryRegion **ram_memory_p)
-{
-    MemoryRegion *sysmem = get_system_memory();
-    ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
-    ram_addr_t block_len;
-
-    block_len = ram_size;
-    if (ram_size >= HVM_BELOW_4G_RAM_END) {
-        /* Xen does not allocate the memory continuously, and keep a hole at
-         * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH
-         */
-        block_len += HVM_BELOW_4G_MMIO_LENGTH;
-    }
-    memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len);
-    *ram_memory_p = &ram_memory;
-    vmstate_register_ram_global(&ram_memory);
-
-    if (ram_size >= HVM_BELOW_4G_RAM_END) {
-        above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
-        below_4g_mem_size = HVM_BELOW_4G_RAM_END;
-    } else {
-        below_4g_mem_size = ram_size;
-    }
-
-    memory_region_init_alias(&ram_640k, NULL, "xen.ram.640k",
-                             &ram_memory, 0, 0xa0000);
-    memory_region_add_subregion(sysmem, 0, &ram_640k);
-    /* Skip of the VGA IO memory space, it will be registered later by the VGA
-     * emulated device.
-     *
-     * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load
-     * the Options ROM, so it is registered here as RAM.
-     */
-    memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo",
-                             &ram_memory, 0xc0000, below_4g_mem_size - 0xc0000);
-    memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
-    if (above_4g_mem_size > 0) {
-        memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi",
-                                 &ram_memory, 0x100000000ULL,
-                                 above_4g_mem_size);
-        memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
-    }
-}
-
-void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
-{
-    unsigned long nr_pfn;
-    xen_pfn_t *pfn_list;
-    int i;
-
-    if (runstate_check(RUN_STATE_INMIGRATE)) {
-        /* RAM already populated in Xen */
-        fprintf(stderr, "%s: do not alloc "RAM_ADDR_FMT
-                " bytes of ram at "RAM_ADDR_FMT" when runstate is INMIGRATE\n",
-                __func__, size, ram_addr); 
-        return;
-    }
-
-    if (mr == &ram_memory) {
-        return;
-    }
-
-    trace_xen_ram_alloc(ram_addr, size);
-
-    nr_pfn = size >> TARGET_PAGE_BITS;
-    pfn_list = g_malloc(sizeof (*pfn_list) * nr_pfn);
-
-    for (i = 0; i < nr_pfn; i++) {
-        pfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i;
-    }
-
-    if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
-        hw_error("xen: failed to populate ram at " RAM_ADDR_FMT, ram_addr);
-    }
-
-    g_free(pfn_list);
-}
-
-static XenPhysmap *get_physmapping(XenIOState *state,
-                                   hwaddr start_addr, ram_addr_t size)
-{
-    XenPhysmap *physmap = NULL;
-
-    start_addr &= TARGET_PAGE_MASK;
-
-    QLIST_FOREACH(physmap, &state->physmap, list) {
-        if (range_covers_byte(physmap->start_addr, physmap->size, start_addr)) {
-            return physmap;
-        }
-    }
-    return NULL;
-}
-
-static hwaddr xen_phys_offset_to_gaddr(hwaddr start_addr,
-                                                   ram_addr_t size, void *opaque)
-{
-    hwaddr addr = start_addr & TARGET_PAGE_MASK;
-    XenIOState *xen_io_state = opaque;
-    XenPhysmap *physmap = NULL;
-
-    QLIST_FOREACH(physmap, &xen_io_state->physmap, list) {
-        if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
-            return physmap->start_addr;
-        }
-    }
-
-    return start_addr;
-}
-
-#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340
-static int xen_add_to_physmap(XenIOState *state,
-                              hwaddr start_addr,
-                              ram_addr_t size,
-                              MemoryRegion *mr,
-                              hwaddr offset_within_region)
-{
-    unsigned long i = 0;
-    int rc = 0;
-    XenPhysmap *physmap = NULL;
-    hwaddr pfn, start_gpfn;
-    hwaddr phys_offset = memory_region_get_ram_addr(mr);
-    char path[80], value[17];
-
-    if (get_physmapping(state, start_addr, size)) {
-        return 0;
-    }
-    if (size <= 0) {
-        return -1;
-    }
-
-    /* Xen can only handle a single dirty log region for now and we want
-     * the linear framebuffer to be that region.
-     * Avoid tracking any regions that is not videoram and avoid tracking
-     * the legacy vga region. */
-    if (mr == framebuffer && start_addr > 0xbffff) {
-        goto go_physmap;
-    }
-    return -1;
-
-go_physmap:
-    DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
-            start_addr, start_addr + size);
-
-    pfn = phys_offset >> TARGET_PAGE_BITS;
-    start_gpfn = start_addr >> TARGET_PAGE_BITS;
-    for (i = 0; i < size >> TARGET_PAGE_BITS; i++) {
-        unsigned long idx = pfn + i;
-        xen_pfn_t gpfn = start_gpfn + i;
-
-        rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
-        if (rc) {
-            DPRINTF("add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
-                    PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
-            return -rc;
-        }
-    }
-
-    physmap = g_malloc(sizeof (XenPhysmap));
-
-    physmap->start_addr = start_addr;
-    physmap->size = size;
-    physmap->name = (char *)mr->name;
-    physmap->phys_offset = phys_offset;
-
-    QLIST_INSERT_HEAD(&state->physmap, physmap, list);
-
-    xc_domain_pin_memory_cacheattr(xen_xc, xen_domid,
-                                   start_addr >> TARGET_PAGE_BITS,
-                                   (start_addr + size) >> TARGET_PAGE_BITS,
-                                   XEN_DOMCTL_MEM_CACHEATTR_WB);
-
-    snprintf(path, sizeof(path),
-            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
-            xen_domid, (uint64_t)phys_offset);
-    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)start_addr);
-    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
-        return -1;
-    }
-    snprintf(path, sizeof(path),
-            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
-            xen_domid, (uint64_t)phys_offset);
-    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)size);
-    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
-        return -1;
-    }
-    if (mr->name) {
-        snprintf(path, sizeof(path),
-                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
-                xen_domid, (uint64_t)phys_offset);
-        if (!xs_write(state->xenstore, 0, path, mr->name, strlen(mr->name))) {
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-static int xen_remove_from_physmap(XenIOState *state,
-                                   hwaddr start_addr,
-                                   ram_addr_t size)
-{
-    unsigned long i = 0;
-    int rc = 0;
-    XenPhysmap *physmap = NULL;
-    hwaddr phys_offset = 0;
-
-    physmap = get_physmapping(state, start_addr, size);
-    if (physmap == NULL) {
-        return -1;
-    }
-
-    phys_offset = physmap->phys_offset;
-    size = physmap->size;
-
-    DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", at "
-            "%"HWADDR_PRIx"\n", start_addr, start_addr + size, phys_offset);
-
-    size >>= TARGET_PAGE_BITS;
-    start_addr >>= TARGET_PAGE_BITS;
-    phys_offset >>= TARGET_PAGE_BITS;
-    for (i = 0; i < size; i++) {
-        unsigned long idx = start_addr + i;
-        xen_pfn_t gpfn = phys_offset + i;
-
-        rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
-        if (rc) {
-            fprintf(stderr, "add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
-                    PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
-            return -rc;
-        }
-    }
-
-    QLIST_REMOVE(physmap, list);
-    if (state->log_for_dirtybit == physmap) {
-        state->log_for_dirtybit = NULL;
-    }
-    g_free(physmap);
-
-    return 0;
-}
-
-#else
-static int xen_add_to_physmap(XenIOState *state,
-                              hwaddr start_addr,
-                              ram_addr_t size,
-                              MemoryRegion *mr,
-                              hwaddr offset_within_region)
-{
-    return -ENOSYS;
-}
-
-static int xen_remove_from_physmap(XenIOState *state,
-                                   hwaddr start_addr,
-                                   ram_addr_t size)
-{
-    return -ENOSYS;
-}
-#endif
-
-static void xen_set_memory(struct MemoryListener *listener,
-                           MemoryRegionSection *section,
-                           bool add)
-{
-    XenIOState *state = container_of(listener, XenIOState, memory_listener);
-    hwaddr start_addr = section->offset_within_address_space;
-    ram_addr_t size = int128_get64(section->size);
-    bool log_dirty = memory_region_is_logging(section->mr);
-    hvmmem_type_t mem_type;
-
-    if (!memory_region_is_ram(section->mr)) {
-        return;
-    }
-
-    if (!(section->mr != &ram_memory
-          && ( (log_dirty && add) || (!log_dirty && !add)))) {
-        return;
-    }
-
-    trace_xen_client_set_memory(start_addr, size, log_dirty);
-
-    start_addr &= TARGET_PAGE_MASK;
-    size = TARGET_PAGE_ALIGN(size);
-
-    if (add) {
-        if (!memory_region_is_rom(section->mr)) {
-            xen_add_to_physmap(state, start_addr, size,
-                               section->mr, section->offset_within_region);
-        } else {
-            mem_type = HVMMEM_ram_ro;
-            if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,
-                                    start_addr >> TARGET_PAGE_BITS,
-                                    size >> TARGET_PAGE_BITS)) {
-                DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",
-                        start_addr);
-            }
-        }
-    } else {
-        if (xen_remove_from_physmap(state, start_addr, size) < 0) {
-            DPRINTF("physmapping does not exist at "TARGET_FMT_plx"\n", start_addr);
-        }
-    }
-}
-
-static void xen_region_add(MemoryListener *listener,
-                           MemoryRegionSection *section)
-{
-    memory_region_ref(section->mr);
-    xen_set_memory(listener, section, true);
-}
-
-static void xen_region_del(MemoryListener *listener,
-                           MemoryRegionSection *section)
-{
-    xen_set_memory(listener, section, false);
-    memory_region_unref(section->mr);
-}
-
-static void xen_sync_dirty_bitmap(XenIOState *state,
-                                  hwaddr start_addr,
-                                  ram_addr_t size)
-{
-    hwaddr npages = size >> TARGET_PAGE_BITS;
-    const int width = sizeof(unsigned long) * 8;
-    unsigned long bitmap[(npages + width - 1) / width];
-    int rc, i, j;
-    const XenPhysmap *physmap = NULL;
-
-    physmap = get_physmapping(state, start_addr, size);
-    if (physmap == NULL) {
-        /* not handled */
-        return;
-    }
-
-    if (state->log_for_dirtybit == NULL) {
-        state->log_for_dirtybit = physmap;
-    } else if (state->log_for_dirtybit != physmap) {
-        /* Only one range for dirty bitmap can be tracked. */
-        return;
-    }
-
-    rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid,
-                                 start_addr >> TARGET_PAGE_BITS, npages,
-                                 bitmap);
-    if (rc < 0) {
-        if (rc != -ENODATA) {
-            memory_region_set_dirty(framebuffer, 0, size);
-            DPRINTF("xen: track_dirty_vram failed (0x" TARGET_FMT_plx
-                    ", 0x" TARGET_FMT_plx "): %s\n",
-                    start_addr, start_addr + size, strerror(-rc));
-        }
-        return;
-    }
-
-    for (i = 0; i < ARRAY_SIZE(bitmap); i++) {
-        unsigned long map = bitmap[i];
-        while (map != 0) {
-            j = ffsl(map) - 1;
-            map &= ~(1ul << j);
-            memory_region_set_dirty(framebuffer,
-                                    (i * width + j) * TARGET_PAGE_SIZE,
-                                    TARGET_PAGE_SIZE);
-        };
-    }
-}
-
-static void xen_log_start(MemoryListener *listener,
-                          MemoryRegionSection *section)
-{
-    XenIOState *state = container_of(listener, XenIOState, memory_listener);
-
-    xen_sync_dirty_bitmap(state, section->offset_within_address_space,
-                          int128_get64(section->size));
-}
-
-static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section)
-{
-    XenIOState *state = container_of(listener, XenIOState, memory_listener);
-
-    state->log_for_dirtybit = NULL;
-    /* Disable dirty bit tracking */
-    xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
-}
-
-static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *section)
-{
-    XenIOState *state = container_of(listener, XenIOState, memory_listener);
-
-    xen_sync_dirty_bitmap(state, section->offset_within_address_space,
-                          int128_get64(section->size));
-}
-
-static void xen_log_global_start(MemoryListener *listener)
-{
-    if (xen_enabled()) {
-        xen_in_migration = true;
-    }
-}
-
-static void xen_log_global_stop(MemoryListener *listener)
-{
-    xen_in_migration = false;
-}
-
-static MemoryListener xen_memory_listener = {
-    .region_add = xen_region_add,
-    .region_del = xen_region_del,
-    .log_start = xen_log_start,
-    .log_stop = xen_log_stop,
-    .log_sync = xen_log_sync,
-    .log_global_start = xen_log_global_start,
-    .log_global_stop = xen_log_global_stop,
-    .priority = 10,
-};
-
-void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
-{
-    if (enable) {
-        memory_global_dirty_log_start();
-    } else {
-        memory_global_dirty_log_stop();
-    }
-}
-
-/* get the ioreq packets from share mem */
-static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu)
-{
-    ioreq_t *req = xen_vcpu_ioreq(state->shared_page, vcpu);
-
-    if (req->state != STATE_IOREQ_READY) {
-        DPRINTF("I/O request not ready: "
-                "%x, ptr: %x, port: %"PRIx64", "
-                "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
-                req->state, req->data_is_ptr, req->addr,
-                req->data, req->count, req->size);
-        return NULL;
-    }
-
-    xen_rmb(); /* see IOREQ_READY /then/ read contents of ioreq */
-
-    req->state = STATE_IOREQ_INPROCESS;
-    return req;
-}
-
-/* use poll to get the port notification */
-/* ioreq_vec--out,the */
-/* retval--the number of ioreq packet */
-static ioreq_t *cpu_get_ioreq(XenIOState *state)
-{
-    int i;
-    evtchn_port_t port;
-
-    port = xc_evtchn_pending(state->xce_handle);
-    if (port == state->bufioreq_local_port) {
-        timer_mod(state->buffered_io_timer,
-                BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
-        return NULL;
-    }
-
-    if (port != -1) {
-        for (i = 0; i < max_cpus; i++) {
-            if (state->ioreq_local_port[i] == port) {
-                break;
-            }
-        }
-
-        if (i == max_cpus) {
-            hw_error("Fatal error while trying to get io event!\n");
-        }
-
-        /* unmask the wanted port again */
-        xc_evtchn_unmask(state->xce_handle, port);
-
-        /* get the io packet from shared memory */
-        state->send_vcpu = i;
-        return cpu_get_ioreq_from_shared_memory(state, i);
-    }
-
-    /* read error or read nothing */
-    return NULL;
-}
-
-static uint32_t do_inp(pio_addr_t addr, unsigned long size)
-{
-    switch (size) {
-        case 1:
-            return cpu_inb(addr);
-        case 2:
-            return cpu_inw(addr);
-        case 4:
-            return cpu_inl(addr);
-        default:
-            hw_error("inp: bad size: %04"FMT_pioaddr" %lx", addr, size);
-    }
-}
-
-static void do_outp(pio_addr_t addr,
-        unsigned long size, uint32_t val)
-{
-    switch (size) {
-        case 1:
-            return cpu_outb(addr, val);
-        case 2:
-            return cpu_outw(addr, val);
-        case 4:
-            return cpu_outl(addr, val);
-        default:
-            hw_error("outp: bad size: %04"FMT_pioaddr" %lx", addr, size);
-    }
-}
-
-/*
- * Helper functions which read/write an object from/to physical guest
- * memory, as part of the implementation of an ioreq.
- *
- * Equivalent to
- *   cpu_physical_memory_rw(addr + (req->df ? -1 : +1) * req->size * i,
- *                          val, req->size, 0/1)
- * except without the integer overflow problems.
- */
-static void rw_phys_req_item(hwaddr addr,
-                             ioreq_t *req, uint32_t i, void *val, int rw)
-{
-    /* Do everything unsigned so overflow just results in a truncated result
-     * and accesses to undesired parts of guest memory, which is up
-     * to the guest */
-    hwaddr offset = (hwaddr)req->size * i;
-    if (req->df) {
-        addr -= offset;
-    } else {
-        addr += offset;
-    }
-    cpu_physical_memory_rw(addr, val, req->size, rw);
-}
-
-static inline void read_phys_req_item(hwaddr addr,
-                                      ioreq_t *req, uint32_t i, void *val)
-{
-    rw_phys_req_item(addr, req, i, val, 0);
-}
-static inline void write_phys_req_item(hwaddr addr,
-                                       ioreq_t *req, uint32_t i, void *val)
-{
-    rw_phys_req_item(addr, req, i, val, 1);
-}
-
-
-static void cpu_ioreq_pio(ioreq_t *req)
-{
-    uint32_t i;
-
-    if (req->dir == IOREQ_READ) {
-        if (!req->data_is_ptr) {
-            req->data = do_inp(req->addr, req->size);
-        } else {
-            uint32_t tmp;
-
-            for (i = 0; i < req->count; i++) {
-                tmp = do_inp(req->addr, req->size);
-                write_phys_req_item(req->data, req, i, &tmp);
-            }
-        }
-    } else if (req->dir == IOREQ_WRITE) {
-        if (!req->data_is_ptr) {
-            do_outp(req->addr, req->size, req->data);
-        } else {
-            for (i = 0; i < req->count; i++) {
-                uint32_t tmp = 0;
-
-                read_phys_req_item(req->data, req, i, &tmp);
-                do_outp(req->addr, req->size, tmp);
-            }
-        }
-    }
-}
-
-static void cpu_ioreq_move(ioreq_t *req)
-{
-    uint32_t i;
-
-    if (!req->data_is_ptr) {
-        if (req->dir == IOREQ_READ) {
-            for (i = 0; i < req->count; i++) {
-                read_phys_req_item(req->addr, req, i, &req->data);
-            }
-        } else if (req->dir == IOREQ_WRITE) {
-            for (i = 0; i < req->count; i++) {
-                write_phys_req_item(req->addr, req, i, &req->data);
-            }
-        }
-    } else {
-        uint64_t tmp;
-
-        if (req->dir == IOREQ_READ) {
-            for (i = 0; i < req->count; i++) {
-                read_phys_req_item(req->addr, req, i, &tmp);
-                write_phys_req_item(req->data, req, i, &tmp);
-            }
-        } else if (req->dir == IOREQ_WRITE) {
-            for (i = 0; i < req->count; i++) {
-                read_phys_req_item(req->data, req, i, &tmp);
-                write_phys_req_item(req->addr, req, i, &tmp);
-            }
-        }
-    }
-}
-
-static void handle_ioreq(ioreq_t *req)
-{
-    if (!req->data_is_ptr && (req->dir == IOREQ_WRITE) &&
-            (req->size < sizeof (target_ulong))) {
-        req->data &= ((target_ulong) 1 << (8 * req->size)) - 1;
-    }
-
-    switch (req->type) {
-        case IOREQ_TYPE_PIO:
-            cpu_ioreq_pio(req);
-            break;
-        case IOREQ_TYPE_COPY:
-            cpu_ioreq_move(req);
-            break;
-        case IOREQ_TYPE_TIMEOFFSET:
-            break;
-        case IOREQ_TYPE_INVALIDATE:
-            xen_invalidate_map_cache();
-            break;
-        default:
-            hw_error("Invalid ioreq type 0x%x\n", req->type);
-    }
-}
-
-static int handle_buffered_iopage(XenIOState *state)
-{
-    buf_ioreq_t *buf_req = NULL;
-    ioreq_t req;
-    int qw;
-
-    if (!state->buffered_io_page) {
-        return 0;
-    }
-
-    memset(&req, 0x00, sizeof(req));
-
-    while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {
-        buf_req = &state->buffered_io_page->buf_ioreq[
-            state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
-        req.size = 1UL << buf_req->size;
-        req.count = 1;
-        req.addr = buf_req->addr;
-        req.data = buf_req->data;
-        req.state = STATE_IOREQ_READY;
-        req.dir = buf_req->dir;
-        req.df = 1;
-        req.type = buf_req->type;
-        req.data_is_ptr = 0;
-        qw = (req.size == 8);
-        if (qw) {
-            buf_req = &state->buffered_io_page->buf_ioreq[
-                (state->buffered_io_page->read_pointer + 1) % IOREQ_BUFFER_SLOT_NUM];
-            req.data |= ((uint64_t)buf_req->data) << 32;
-        }
-
-        handle_ioreq(&req);
-
-        xen_mb();
-        state->buffered_io_page->read_pointer += qw ? 2 : 1;
-    }
-
-    return req.count;
-}
-
-static void handle_buffered_io(void *opaque)
-{
-    XenIOState *state = opaque;
-
-    if (handle_buffered_iopage(state)) {
-        timer_mod(state->buffered_io_timer,
-                BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
-    } else {
-        timer_del(state->buffered_io_timer);
-        xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
-    }
-}
-
-static void cpu_handle_ioreq(void *opaque)
-{
-    XenIOState *state = opaque;
-    ioreq_t *req = cpu_get_ioreq(state);
-
-    handle_buffered_iopage(state);
-    if (req) {
-        handle_ioreq(req);
-
-        if (req->state != STATE_IOREQ_INPROCESS) {
-            fprintf(stderr, "Badness in I/O request ... not in service?!: "
-                    "%x, ptr: %x, port: %"PRIx64", "
-                    "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
-                    req->state, req->data_is_ptr, req->addr,
-                    req->data, req->count, req->size);
-            destroy_hvm_domain(false);
-            return;
-        }
-
-        xen_wmb(); /* Update ioreq contents /then/ update state. */
-
-        /*
-         * We do this before we send the response so that the tools
-         * have the opportunity to pick up on the reset before the
-         * guest resumes and does a hlt with interrupts disabled which
-         * causes Xen to powerdown the domain.
-         */
-        if (runstate_is_running()) {
-            if (qemu_shutdown_requested_get()) {
-                destroy_hvm_domain(false);
-            }
-            if (qemu_reset_requested_get()) {
-                qemu_system_reset(VMRESET_REPORT);
-                destroy_hvm_domain(true);
-            }
-        }
-
-        req->state = STATE_IORESP_READY;
-        xc_evtchn_notify(state->xce_handle, state->ioreq_local_port[state->send_vcpu]);
-    }
-}
-
-static int store_dev_info(int domid, CharDriverState *cs, const char *string)
-{
-    struct xs_handle *xs = NULL;
-    char *path = NULL;
-    char *newpath = NULL;
-    char *pts = NULL;
-    int ret = -1;
-
-    /* Only continue if we're talking to a pty. */
-    if (strncmp(cs->filename, "pty:", 4)) {
-        return 0;
-    }
-    pts = cs->filename + 4;
-
-    /* We now have everything we need to set the xenstore entry. */
-    xs = xs_open(0);
-    if (xs == NULL) {
-        fprintf(stderr, "Could not contact XenStore\n");
-        goto out;
-    }
-
-    path = xs_get_domain_path(xs, domid);
-    if (path == NULL) {
-        fprintf(stderr, "xs_get_domain_path() error\n");
-        goto out;
-    }
-    newpath = realloc(path, (strlen(path) + strlen(string) +
-                strlen("/tty") + 1));
-    if (newpath == NULL) {
-        fprintf(stderr, "realloc error\n");
-        goto out;
-    }
-    path = newpath;
-
-    strcat(path, string);
-    strcat(path, "/tty");
-    if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
-        fprintf(stderr, "xs_write for '%s' fail", string);
-        goto out;
-    }
-    ret = 0;
-
-out:
-    free(path);
-    xs_close(xs);
-
-    return ret;
-}
-
-void xenstore_store_pv_console_info(int i, CharDriverState *chr)
-{
-    if (i == 0) {
-        store_dev_info(xen_domid, chr, "/console");
-    } else {
-        char buf[32];
-        snprintf(buf, sizeof(buf), "/device/console/%d", i);
-        store_dev_info(xen_domid, chr, buf);
-    }
-}
-
-static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
-{
-    char path[50];
-
-    if (xs == NULL) {
-        fprintf(stderr, "xenstore connection not initialized\n");
-        exit(1);
-    }
-
-    snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
-    if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) {
-        fprintf(stderr, "error recording dm state\n");
-        exit(1);
-    }
-}
-
-static void xen_main_loop_prepare(XenIOState *state)
-{
-    int evtchn_fd = -1;
-
-    if (state->xce_handle != XC_HANDLER_INITIAL_VALUE) {
-        evtchn_fd = xc_evtchn_fd(state->xce_handle);
-    }
-
-    state->buffered_io_timer = timer_new_ms(QEMU_CLOCK_REALTIME, handle_buffered_io,
-                                                 state);
-
-    if (evtchn_fd != -1) {
-        qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
-    }
-}
-
-
-/* Initialise Xen */
-
-static void xen_change_state_handler(void *opaque, int running,
-                                     RunState state)
-{
-    if (running) {
-        /* record state running */
-        xenstore_record_dm_state(xenstore, "running");
-    }
-}
-
-static void xen_hvm_change_state_handler(void *opaque, int running,
-                                         RunState rstate)
-{
-    XenIOState *xstate = opaque;
-    if (running) {
-        xen_main_loop_prepare(xstate);
-    }
-}
-
-static void xen_exit_notifier(Notifier *n, void *data)
-{
-    XenIOState *state = container_of(n, XenIOState, exit);
-
-    xc_evtchn_close(state->xce_handle);
-    xs_daemon_close(state->xenstore);
-}
-
-int xen_init(QEMUMachine *machine)
-{
-    xen_xc = xen_xc_interface_open(0, 0, 0);
-    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
-        xen_be_printf(NULL, 0, "can't open xen interface\n");
-        return -1;
-    }
-    qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
-
-    return 0;
-}
-
-static void xen_read_physmap(XenIOState *state)
-{
-    XenPhysmap *physmap = NULL;
-    unsigned int len, num, i;
-    char path[80], *value = NULL;
-    char **entries = NULL;
-
-    snprintf(path, sizeof(path),
-            "/local/domain/0/device-model/%d/physmap", xen_domid);
-    entries = xs_directory(state->xenstore, 0, path, &num);
-    if (entries == NULL)
-        return;
-
-    for (i = 0; i < num; i++) {
-        physmap = g_malloc(sizeof (XenPhysmap));
-        physmap->phys_offset = strtoull(entries[i], NULL, 16);
-        snprintf(path, sizeof(path),
-                "/local/domain/0/device-model/%d/physmap/%s/start_addr",
-                xen_domid, entries[i]);
-        value = xs_read(state->xenstore, 0, path, &len);
-        if (value == NULL) {
-            g_free(physmap);
-            continue;
-        }
-        physmap->start_addr = strtoull(value, NULL, 16);
-        free(value);
-
-        snprintf(path, sizeof(path),
-                "/local/domain/0/device-model/%d/physmap/%s/size",
-                xen_domid, entries[i]);
-        value = xs_read(state->xenstore, 0, path, &len);
-        if (value == NULL) {
-            g_free(physmap);
-            continue;
-        }
-        physmap->size = strtoull(value, NULL, 16);
-        free(value);
-
-        snprintf(path, sizeof(path),
-                "/local/domain/0/device-model/%d/physmap/%s/name",
-                xen_domid, entries[i]);
-        physmap->name = xs_read(state->xenstore, 0, path, &len);
-
-        QLIST_INSERT_HEAD(&state->physmap, physmap, list);
-    }
-    free(entries);
-}
-
-static void xen_wakeup_notifier(Notifier *notifier, void *data)
-{
-    xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
-}
-
-int xen_hvm_init(MemoryRegion **ram_memory)
-{
-    int i, rc;
-    unsigned long ioreq_pfn;
-    unsigned long bufioreq_evtchn;
-    XenIOState *state;
-
-    state = g_malloc0(sizeof (XenIOState));
-
-    state->xce_handle = xen_xc_evtchn_open(NULL, 0);
-    if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
-        perror("xen: event channel open");
-        g_free(state);
-        return -errno;
-    }
-
-    state->xenstore = xs_daemon_open();
-    if (state->xenstore == NULL) {
-        perror("xen: xenstore open");
-        g_free(state);
-        return -errno;
-    }
-
-    state->exit.notify = xen_exit_notifier;
-    qemu_add_exit_notifier(&state->exit);
-
-    state->suspend.notify = xen_suspend_notifier;
-    qemu_register_suspend_notifier(&state->suspend);
-
-    state->wakeup.notify = xen_wakeup_notifier;
-    qemu_register_wakeup_notifier(&state->wakeup);
-
-    xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
-    DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
-    state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
-                                              PROT_READ|PROT_WRITE, ioreq_pfn);
-    if (state->shared_page == NULL) {
-        hw_error("map shared IO page returned error %d handle=" XC_INTERFACE_FMT,
-                 errno, xen_xc);
-    }
-
-    xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
-    DPRINTF("buffered io page at pfn %lx\n", ioreq_pfn);
-    state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
-                                                   PROT_READ|PROT_WRITE, ioreq_pfn);
-    if (state->buffered_io_page == NULL) {
-        hw_error("map buffered IO page returned error %d", errno);
-    }
-
-    state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));
-
-    /* FIXME: how about if we overflow the page here? */
-    for (i = 0; i < max_cpus; i++) {
-        rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
-                                        xen_vcpu_eport(state->shared_page, i));
-        if (rc == -1) {
-            fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
-            return -1;
-        }
-        state->ioreq_local_port[i] = rc;
-    }
-
-    rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN,
-            &bufioreq_evtchn);
-    if (rc < 0) {
-        fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");
-        return -1;
-    }
-    rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
-            (uint32_t)bufioreq_evtchn);
-    if (rc == -1) {
-        fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
-        return -1;
-    }
-    state->bufioreq_local_port = rc;
-
-    /* Init RAM management */
-    xen_map_cache_init(xen_phys_offset_to_gaddr, state);
-    xen_ram_init(ram_size, ram_memory);
-
-    qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
-
-    state->memory_listener = xen_memory_listener;
-    QLIST_INIT(&state->physmap);
-    memory_listener_register(&state->memory_listener, &address_space_memory);
-    state->log_for_dirtybit = NULL;
-
-    /* Initialize backend core & drivers */
-    if (xen_be_init() != 0) {
-        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
-        exit(1);
-    }
-    xen_be_register("console", &xen_console_ops);
-    xen_be_register("vkbd", &xen_kbdmouse_ops);
-    xen_be_register("qdisk", &xen_blkdev_ops);
-    xen_read_physmap(state);
-
-    return 0;
-}
-
-void destroy_hvm_domain(bool reboot)
-{
-    XenXC xc_handle;
-    int sts;
-
-    xc_handle = xen_xc_interface_open(0, 0, 0);
-    if (xc_handle == XC_HANDLER_INITIAL_VALUE) {
-        fprintf(stderr, "Cannot acquire xenctrl handle\n");
-    } else {
-        sts = xc_domain_shutdown(xc_handle, xen_domid,
-                                 reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff);
-        if (sts != 0) {
-            fprintf(stderr, "xc_domain_shutdown failed to issue %s, "
-                    "sts %d, %s\n", reboot ? "reboot" : "poweroff",
-                    sts, strerror(errno));
-        } else {
-            fprintf(stderr, "Issued domain %d %s\n", xen_domid,
-                    reboot ? "reboot" : "poweroff");
-        }
-        xc_interface_close(xc_handle);
-    }
-}
-
-void xen_register_framebuffer(MemoryRegion *mr)
-{
-    framebuffer = mr;
-}
-
-void xen_shutdown_fatal_error(const char *fmt, ...)
-{
-    va_list ap;
-
-    va_start(ap, fmt);
-    vfprintf(stderr, fmt, ap);
-    va_end(ap);
-    fprintf(stderr, "Will destroy the domain.\n");
-    /* destroy the domain */
-    qemu_system_shutdown_request();
-}
-
-void xen_modified_memory(ram_addr_t start, ram_addr_t length)
-{
-    if (unlikely(xen_in_migration)) {
-        int rc;
-        ram_addr_t start_pfn, nb_pages;
-
-        if (length == 0) {
-            length = TARGET_PAGE_SIZE;
-        }
-        start_pfn = start >> TARGET_PAGE_BITS;
-        nb_pages = ((start + length + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
-            - start_pfn;
-        rc = xc_hvm_modified_memory(xen_xc, xen_domid, start_pfn, nb_pages);
-        if (rc) {
-            fprintf(stderr,
-                    "%s failed for "RAM_ADDR_FMT" ("RAM_ADDR_FMT"): %i, %s\n",
-                    __func__, start, nb_pages, rc, strerror(-rc));
-        }
-    }
-}
diff --git a/xen-common-stub.c b/xen-common-stub.c
new file mode 100644
index 0000000..0bba290
--- /dev/null
+++ b/xen-common-stub.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014       Citrix Systems UK Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+#include "hw/xen/xen.h"
+
+void xenstore_store_pv_console_info(int i, CharDriverState *chr)
+{
+}
+
+int xen_init(QEMUMachine *machine)
+{
+    return -ENOSYS;
+}
+
diff --git a/xen-common.c b/xen-common.c
new file mode 100644
index 0000000..aa71b1a
--- /dev/null
+++ b/xen-common.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2014       Citrix Systems UK Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "hw/xen/xen_backend.h"
+#include "qmp-commands.h"
+#include "sysemu/char.h"
+
+//#define DEBUG_XEN
+
+#ifdef DEBUG_XEN
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+static int store_dev_info(int domid, CharDriverState *cs, const char *string)
+{
+    struct xs_handle *xs = NULL;
+    char *path = NULL;
+    char *newpath = NULL;
+    char *pts = NULL;
+    int ret = -1;
+
+    /* Only continue if we're talking to a pty. */
+    if (strncmp(cs->filename, "pty:", 4)) {
+        return 0;
+    }
+    pts = cs->filename + 4;
+
+    /* We now have everything we need to set the xenstore entry. */
+    xs = xs_open(0);
+    if (xs == NULL) {
+        fprintf(stderr, "Could not contact XenStore\n");
+        goto out;
+    }
+
+    path = xs_get_domain_path(xs, domid);
+    if (path == NULL) {
+        fprintf(stderr, "xs_get_domain_path() error\n");
+        goto out;
+    }
+    newpath = realloc(path, (strlen(path) + strlen(string) +
+                strlen("/tty") + 1));
+    if (newpath == NULL) {
+        fprintf(stderr, "realloc error\n");
+        goto out;
+    }
+    path = newpath;
+
+    strcat(path, string);
+    strcat(path, "/tty");
+    if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
+        fprintf(stderr, "xs_write for '%s' fail", string);
+        goto out;
+    }
+    ret = 0;
+
+out:
+    free(path);
+    xs_close(xs);
+
+    return ret;
+}
+
+void xenstore_store_pv_console_info(int i, CharDriverState *chr)
+{
+    if (i == 0) {
+        store_dev_info(xen_domid, chr, "/console");
+    } else {
+        char buf[32];
+        snprintf(buf, sizeof(buf), "/device/console/%d", i);
+        store_dev_info(xen_domid, chr, buf);
+    }
+}
+
+
+static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
+{
+    char path[50];
+
+    if (xs == NULL) {
+        fprintf(stderr, "xenstore connection not initialized\n");
+        exit(1);
+    }
+
+    snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
+    if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) {
+        fprintf(stderr, "error recording dm state\n");
+        exit(1);
+    }
+}
+
+
+static void xen_change_state_handler(void *opaque, int running,
+                                     RunState state)
+{
+    if (running) {
+        /* record state running */
+        xenstore_record_dm_state(xenstore, "running");
+    }
+}
+
+int xen_init(QEMUMachine *machine)
+{
+    xen_xc = xen_xc_interface_open(0, 0, 0);
+    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
+        xen_be_printf(NULL, 0, "can't open xen interface\n");
+        return -1;
+    }
+    qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
+
+    return 0;
+}
+
diff --git a/xen-hvm-stub.c b/xen-hvm-stub.c
new file mode 100644
index 0000000..00fa9b3
--- /dev/null
+++ b/xen-hvm-stub.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010       Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "qemu-common.h"
+#include "hw/xen/xen.h"
+#include "exec/memory.h"
+#include "qmp-commands.h"
+#include "hw/xen/xen_common.h"
+
+int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+    return -1;
+}
+
+void xen_piix3_set_irq(void *opaque, int irq_num, int level)
+{
+}
+
+void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
+{
+}
+
+void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
+{
+}
+
+void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
+{
+}
+
+void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
+{
+}
+
+qemu_irq *xen_interrupt_controller_init(void)
+{
+    return NULL;
+}
+
+void xen_register_framebuffer(MemoryRegion *mr)
+{
+}
+
+void xen_modified_memory(ram_addr_t start, ram_addr_t length)
+{
+}
+
+int xen_hvm_init(MemoryRegion **ram_memory)
+{
+    return 0;
+}
+
+void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
+{
+}
+
+void xen_shutdown_fatal_error(const char *fmt, ...)
+{
+}
diff --git a/xen-hvm.c b/xen-hvm.c
new file mode 100644
index 0000000..0a49055
--- /dev/null
+++ b/xen-hvm.c
@@ -0,0 +1,1129 @@
+/*
+ * Copyright (C) 2010       Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include <sys/mman.h>
+
+#include "hw/pci/pci.h"
+#include "hw/i386/pc.h"
+#include "hw/xen/xen_common.h"
+#include "hw/xen/xen_backend.h"
+#include "qmp-commands.h"
+
+#include "sysemu/char.h"
+#include "qemu/range.h"
+#include "sysemu/xen-mapcache.h"
+#include "trace.h"
+#include "exec/address-spaces.h"
+
+#include <xen/hvm/ioreq.h>
+#include <xen/hvm/params.h>
+#include <xen/hvm/e820.h>
+
+//#define DEBUG_XEN_HVM
+
+#ifdef DEBUG_XEN_HVM
+#define DPRINTF(fmt, ...) \
+    do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#endif
+
+static MemoryRegion ram_memory, ram_640k, ram_lo, ram_hi;
+static MemoryRegion *framebuffer;
+static bool xen_in_migration;
+
+/* Compatibility with older version */
+#if __XEN_LATEST_INTERFACE_VERSION__ < 0x0003020a
+static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
+{
+    return shared_page->vcpu_iodata[i].vp_eport;
+}
+static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
+{
+    return &shared_page->vcpu_iodata[vcpu].vp_ioreq;
+}
+#  define FMT_ioreq_size PRIx64
+#else
+static inline uint32_t xen_vcpu_eport(shared_iopage_t *shared_page, int i)
+{
+    return shared_page->vcpu_ioreq[i].vp_eport;
+}
+static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
+{
+    return &shared_page->vcpu_ioreq[vcpu];
+}
+#  define FMT_ioreq_size "u"
+#endif
+#ifndef HVM_PARAM_BUFIOREQ_EVTCHN
+#define HVM_PARAM_BUFIOREQ_EVTCHN 26
+#endif
+
+#define BUFFER_IO_MAX_DELAY  100
+
+typedef struct XenPhysmap {
+    hwaddr start_addr;
+    ram_addr_t size;
+    char *name;
+    hwaddr phys_offset;
+
+    QLIST_ENTRY(XenPhysmap) list;
+} XenPhysmap;
+
+typedef struct XenIOState {
+    shared_iopage_t *shared_page;
+    buffered_iopage_t *buffered_io_page;
+    QEMUTimer *buffered_io_timer;
+    /* the evtchn port for polling the notification, */
+    evtchn_port_t *ioreq_local_port;
+    /* evtchn local port for buffered io */
+    evtchn_port_t bufioreq_local_port;
+    /* the evtchn fd for polling */
+    XenEvtchn xce_handle;
+    /* which vcpu we are serving */
+    int send_vcpu;
+
+    struct xs_handle *xenstore;
+    MemoryListener memory_listener;
+    QLIST_HEAD(, XenPhysmap) physmap;
+    hwaddr free_phys_offset;
+    const XenPhysmap *log_for_dirtybit;
+
+    Notifier exit;
+    Notifier suspend;
+    Notifier wakeup;
+} XenIOState;
+
+/* Xen specific function for piix pci */
+
+int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+    return irq_num + ((pci_dev->devfn >> 3) << 2);
+}
+
+void xen_piix3_set_irq(void *opaque, int irq_num, int level)
+{
+    xc_hvm_set_pci_intx_level(xen_xc, xen_domid, 0, 0, irq_num >> 2,
+                              irq_num & 3, level);
+}
+
+void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
+{
+    int i;
+
+    /* Scan for updates to PCI link routes (0x60-0x63). */
+    for (i = 0; i < len; i++) {
+        uint8_t v = (val >> (8 * i)) & 0xff;
+        if (v & 0x80) {
+            v = 0;
+        }
+        v &= 0xf;
+        if (((address + i) >= 0x60) && ((address + i) <= 0x63)) {
+            xc_hvm_set_pci_link_route(xen_xc, xen_domid, address + i - 0x60, v);
+        }
+    }
+}
+
+void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
+{
+    xen_xc_hvm_inject_msi(xen_xc, xen_domid, addr, data);
+}
+
+static void xen_suspend_notifier(Notifier *notifier, void *data)
+{
+    xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
+}
+
+/* Xen Interrupt Controller */
+
+static void xen_set_irq(void *opaque, int irq, int level)
+{
+    xc_hvm_set_isa_irq_level(xen_xc, xen_domid, irq, level);
+}
+
+qemu_irq *xen_interrupt_controller_init(void)
+{
+    return qemu_allocate_irqs(xen_set_irq, NULL, 16);
+}
+
+/* Memory Ops */
+
+static void xen_ram_init(ram_addr_t ram_size, MemoryRegion **ram_memory_p)
+{
+    MemoryRegion *sysmem = get_system_memory();
+    ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
+    ram_addr_t block_len;
+
+    block_len = ram_size;
+    if (ram_size >= HVM_BELOW_4G_RAM_END) {
+        /* Xen does not allocate the memory continuously, and keep a hole at
+         * HVM_BELOW_4G_MMIO_START of HVM_BELOW_4G_MMIO_LENGTH
+         */
+        block_len += HVM_BELOW_4G_MMIO_LENGTH;
+    }
+    memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len);
+    *ram_memory_p = &ram_memory;
+    vmstate_register_ram_global(&ram_memory);
+
+    if (ram_size >= HVM_BELOW_4G_RAM_END) {
+        above_4g_mem_size = ram_size - HVM_BELOW_4G_RAM_END;
+        below_4g_mem_size = HVM_BELOW_4G_RAM_END;
+    } else {
+        below_4g_mem_size = ram_size;
+    }
+
+    memory_region_init_alias(&ram_640k, NULL, "xen.ram.640k",
+                             &ram_memory, 0, 0xa0000);
+    memory_region_add_subregion(sysmem, 0, &ram_640k);
+    /* Skip of the VGA IO memory space, it will be registered later by the VGA
+     * emulated device.
+     *
+     * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load
+     * the Options ROM, so it is registered here as RAM.
+     */
+    memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo",
+                             &ram_memory, 0xc0000, below_4g_mem_size - 0xc0000);
+    memory_region_add_subregion(sysmem, 0xc0000, &ram_lo);
+    if (above_4g_mem_size > 0) {
+        memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi",
+                                 &ram_memory, 0x100000000ULL,
+                                 above_4g_mem_size);
+        memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi);
+    }
+}
+
+void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
+{
+    unsigned long nr_pfn;
+    xen_pfn_t *pfn_list;
+    int i;
+
+    if (runstate_check(RUN_STATE_INMIGRATE)) {
+        /* RAM already populated in Xen */
+        fprintf(stderr, "%s: do not alloc "RAM_ADDR_FMT
+                " bytes of ram at "RAM_ADDR_FMT" when runstate is INMIGRATE\n",
+                __func__, size, ram_addr); 
+        return;
+    }
+
+    if (mr == &ram_memory) {
+        return;
+    }
+
+    trace_xen_ram_alloc(ram_addr, size);
+
+    nr_pfn = size >> TARGET_PAGE_BITS;
+    pfn_list = g_malloc(sizeof (*pfn_list) * nr_pfn);
+
+    for (i = 0; i < nr_pfn; i++) {
+        pfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i;
+    }
+
+    if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
+        hw_error("xen: failed to populate ram at " RAM_ADDR_FMT, ram_addr);
+    }
+
+    g_free(pfn_list);
+}
+
+static XenPhysmap *get_physmapping(XenIOState *state,
+                                   hwaddr start_addr, ram_addr_t size)
+{
+    XenPhysmap *physmap = NULL;
+
+    start_addr &= TARGET_PAGE_MASK;
+
+    QLIST_FOREACH(physmap, &state->physmap, list) {
+        if (range_covers_byte(physmap->start_addr, physmap->size, start_addr)) {
+            return physmap;
+        }
+    }
+    return NULL;
+}
+
+static hwaddr xen_phys_offset_to_gaddr(hwaddr start_addr,
+                                                   ram_addr_t size, void *opaque)
+{
+    hwaddr addr = start_addr & TARGET_PAGE_MASK;
+    XenIOState *xen_io_state = opaque;
+    XenPhysmap *physmap = NULL;
+
+    QLIST_FOREACH(physmap, &xen_io_state->physmap, list) {
+        if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
+            return physmap->start_addr;
+        }
+    }
+
+    return start_addr;
+}
+
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340
+static int xen_add_to_physmap(XenIOState *state,
+                              hwaddr start_addr,
+                              ram_addr_t size,
+                              MemoryRegion *mr,
+                              hwaddr offset_within_region)
+{
+    unsigned long i = 0;
+    int rc = 0;
+    XenPhysmap *physmap = NULL;
+    hwaddr pfn, start_gpfn;
+    hwaddr phys_offset = memory_region_get_ram_addr(mr);
+    char path[80], value[17];
+
+    if (get_physmapping(state, start_addr, size)) {
+        return 0;
+    }
+    if (size <= 0) {
+        return -1;
+    }
+
+    /* Xen can only handle a single dirty log region for now and we want
+     * the linear framebuffer to be that region.
+     * Avoid tracking any regions that is not videoram and avoid tracking
+     * the legacy vga region. */
+    if (mr == framebuffer && start_addr > 0xbffff) {
+        goto go_physmap;
+    }
+    return -1;
+
+go_physmap:
+    DPRINTF("mapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
+            start_addr, start_addr + size);
+
+    pfn = phys_offset >> TARGET_PAGE_BITS;
+    start_gpfn = start_addr >> TARGET_PAGE_BITS;
+    for (i = 0; i < size >> TARGET_PAGE_BITS; i++) {
+        unsigned long idx = pfn + i;
+        xen_pfn_t gpfn = start_gpfn + i;
+
+        rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
+        if (rc) {
+            DPRINTF("add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
+                    PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
+            return -rc;
+        }
+    }
+
+    physmap = g_malloc(sizeof (XenPhysmap));
+
+    physmap->start_addr = start_addr;
+    physmap->size = size;
+    physmap->name = (char *)mr->name;
+    physmap->phys_offset = phys_offset;
+
+    QLIST_INSERT_HEAD(&state->physmap, physmap, list);
+
+    xc_domain_pin_memory_cacheattr(xen_xc, xen_domid,
+                                   start_addr >> TARGET_PAGE_BITS,
+                                   (start_addr + size) >> TARGET_PAGE_BITS,
+                                   XEN_DOMCTL_MEM_CACHEATTR_WB);
+
+    snprintf(path, sizeof(path),
+            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
+            xen_domid, (uint64_t)phys_offset);
+    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)start_addr);
+    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
+        return -1;
+    }
+    snprintf(path, sizeof(path),
+            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
+            xen_domid, (uint64_t)phys_offset);
+    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)size);
+    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
+        return -1;
+    }
+    if (mr->name) {
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
+                xen_domid, (uint64_t)phys_offset);
+        if (!xs_write(state->xenstore, 0, path, mr->name, strlen(mr->name))) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int xen_remove_from_physmap(XenIOState *state,
+                                   hwaddr start_addr,
+                                   ram_addr_t size)
+{
+    unsigned long i = 0;
+    int rc = 0;
+    XenPhysmap *physmap = NULL;
+    hwaddr phys_offset = 0;
+
+    physmap = get_physmapping(state, start_addr, size);
+    if (physmap == NULL) {
+        return -1;
+    }
+
+    phys_offset = physmap->phys_offset;
+    size = physmap->size;
+
+    DPRINTF("unmapping vram to %"HWADDR_PRIx" - %"HWADDR_PRIx", at "
+            "%"HWADDR_PRIx"\n", start_addr, start_addr + size, phys_offset);
+
+    size >>= TARGET_PAGE_BITS;
+    start_addr >>= TARGET_PAGE_BITS;
+    phys_offset >>= TARGET_PAGE_BITS;
+    for (i = 0; i < size; i++) {
+        unsigned long idx = start_addr + i;
+        xen_pfn_t gpfn = phys_offset + i;
+
+        rc = xc_domain_add_to_physmap(xen_xc, xen_domid, XENMAPSPACE_gmfn, idx, gpfn);
+        if (rc) {
+            fprintf(stderr, "add_to_physmap MFN %"PRI_xen_pfn" to PFN %"
+                    PRI_xen_pfn" failed: %d\n", idx, gpfn, rc);
+            return -rc;
+        }
+    }
+
+    QLIST_REMOVE(physmap, list);
+    if (state->log_for_dirtybit == physmap) {
+        state->log_for_dirtybit = NULL;
+    }
+    g_free(physmap);
+
+    return 0;
+}
+
+#else
+static int xen_add_to_physmap(XenIOState *state,
+                              hwaddr start_addr,
+                              ram_addr_t size,
+                              MemoryRegion *mr,
+                              hwaddr offset_within_region)
+{
+    return -ENOSYS;
+}
+
+static int xen_remove_from_physmap(XenIOState *state,
+                                   hwaddr start_addr,
+                                   ram_addr_t size)
+{
+    return -ENOSYS;
+}
+#endif
+
+static void xen_set_memory(struct MemoryListener *listener,
+                           MemoryRegionSection *section,
+                           bool add)
+{
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+    hwaddr start_addr = section->offset_within_address_space;
+    ram_addr_t size = int128_get64(section->size);
+    bool log_dirty = memory_region_is_logging(section->mr);
+    hvmmem_type_t mem_type;
+
+    if (!memory_region_is_ram(section->mr)) {
+        return;
+    }
+
+    if (!(section->mr != &ram_memory
+          && ( (log_dirty && add) || (!log_dirty && !add)))) {
+        return;
+    }
+
+    trace_xen_client_set_memory(start_addr, size, log_dirty);
+
+    start_addr &= TARGET_PAGE_MASK;
+    size = TARGET_PAGE_ALIGN(size);
+
+    if (add) {
+        if (!memory_region_is_rom(section->mr)) {
+            xen_add_to_physmap(state, start_addr, size,
+                               section->mr, section->offset_within_region);
+        } else {
+            mem_type = HVMMEM_ram_ro;
+            if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type,
+                                    start_addr >> TARGET_PAGE_BITS,
+                                    size >> TARGET_PAGE_BITS)) {
+                DPRINTF("xc_hvm_set_mem_type error, addr: "TARGET_FMT_plx"\n",
+                        start_addr);
+            }
+        }
+    } else {
+        if (xen_remove_from_physmap(state, start_addr, size) < 0) {
+            DPRINTF("physmapping does not exist at "TARGET_FMT_plx"\n", start_addr);
+        }
+    }
+}
+
+static void xen_region_add(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+    memory_region_ref(section->mr);
+    xen_set_memory(listener, section, true);
+}
+
+static void xen_region_del(MemoryListener *listener,
+                           MemoryRegionSection *section)
+{
+    xen_set_memory(listener, section, false);
+    memory_region_unref(section->mr);
+}
+
+static void xen_sync_dirty_bitmap(XenIOState *state,
+                                  hwaddr start_addr,
+                                  ram_addr_t size)
+{
+    hwaddr npages = size >> TARGET_PAGE_BITS;
+    const int width = sizeof(unsigned long) * 8;
+    unsigned long bitmap[(npages + width - 1) / width];
+    int rc, i, j;
+    const XenPhysmap *physmap = NULL;
+
+    physmap = get_physmapping(state, start_addr, size);
+    if (physmap == NULL) {
+        /* not handled */
+        return;
+    }
+
+    if (state->log_for_dirtybit == NULL) {
+        state->log_for_dirtybit = physmap;
+    } else if (state->log_for_dirtybit != physmap) {
+        /* Only one range for dirty bitmap can be tracked. */
+        return;
+    }
+
+    rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid,
+                                 start_addr >> TARGET_PAGE_BITS, npages,
+                                 bitmap);
+    if (rc < 0) {
+        if (rc != -ENODATA) {
+            memory_region_set_dirty(framebuffer, 0, size);
+            DPRINTF("xen: track_dirty_vram failed (0x" TARGET_FMT_plx
+                    ", 0x" TARGET_FMT_plx "): %s\n",
+                    start_addr, start_addr + size, strerror(-rc));
+        }
+        return;
+    }
+
+    for (i = 0; i < ARRAY_SIZE(bitmap); i++) {
+        unsigned long map = bitmap[i];
+        while (map != 0) {
+            j = ffsl(map) - 1;
+            map &= ~(1ul << j);
+            memory_region_set_dirty(framebuffer,
+                                    (i * width + j) * TARGET_PAGE_SIZE,
+                                    TARGET_PAGE_SIZE);
+        };
+    }
+}
+
+static void xen_log_start(MemoryListener *listener,
+                          MemoryRegionSection *section)
+{
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+
+    xen_sync_dirty_bitmap(state, section->offset_within_address_space,
+                          int128_get64(section->size));
+}
+
+static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section)
+{
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+
+    state->log_for_dirtybit = NULL;
+    /* Disable dirty bit tracking */
+    xc_hvm_track_dirty_vram(xen_xc, xen_domid, 0, 0, NULL);
+}
+
+static void xen_log_sync(MemoryListener *listener, MemoryRegionSection *section)
+{
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+
+    xen_sync_dirty_bitmap(state, section->offset_within_address_space,
+                          int128_get64(section->size));
+}
+
+static void xen_log_global_start(MemoryListener *listener)
+{
+    if (xen_enabled()) {
+        xen_in_migration = true;
+    }
+}
+
+static void xen_log_global_stop(MemoryListener *listener)
+{
+    xen_in_migration = false;
+}
+
+static MemoryListener xen_memory_listener = {
+    .region_add = xen_region_add,
+    .region_del = xen_region_del,
+    .log_start = xen_log_start,
+    .log_stop = xen_log_stop,
+    .log_sync = xen_log_sync,
+    .log_global_start = xen_log_global_start,
+    .log_global_stop = xen_log_global_stop,
+    .priority = 10,
+};
+
+/* get the ioreq packets from share mem */
+static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu)
+{
+    ioreq_t *req = xen_vcpu_ioreq(state->shared_page, vcpu);
+
+    if (req->state != STATE_IOREQ_READY) {
+        DPRINTF("I/O request not ready: "
+                "%x, ptr: %x, port: %"PRIx64", "
+                "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
+                req->state, req->data_is_ptr, req->addr,
+                req->data, req->count, req->size);
+        return NULL;
+    }
+
+    xen_rmb(); /* see IOREQ_READY /then/ read contents of ioreq */
+
+    req->state = STATE_IOREQ_INPROCESS;
+    return req;
+}
+
+/* use poll to get the port notification */
+/* ioreq_vec--out,the */
+/* retval--the number of ioreq packet */
+static ioreq_t *cpu_get_ioreq(XenIOState *state)
+{
+    int i;
+    evtchn_port_t port;
+
+    port = xc_evtchn_pending(state->xce_handle);
+    if (port == state->bufioreq_local_port) {
+        timer_mod(state->buffered_io_timer,
+                BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
+        return NULL;
+    }
+
+    if (port != -1) {
+        for (i = 0; i < max_cpus; i++) {
+            if (state->ioreq_local_port[i] == port) {
+                break;
+            }
+        }
+
+        if (i == max_cpus) {
+            hw_error("Fatal error while trying to get io event!\n");
+        }
+
+        /* unmask the wanted port again */
+        xc_evtchn_unmask(state->xce_handle, port);
+
+        /* get the io packet from shared memory */
+        state->send_vcpu = i;
+        return cpu_get_ioreq_from_shared_memory(state, i);
+    }
+
+    /* read error or read nothing */
+    return NULL;
+}
+
+static uint32_t do_inp(pio_addr_t addr, unsigned long size)
+{
+    switch (size) {
+        case 1:
+            return cpu_inb(addr);
+        case 2:
+            return cpu_inw(addr);
+        case 4:
+            return cpu_inl(addr);
+        default:
+            hw_error("inp: bad size: %04"FMT_pioaddr" %lx", addr, size);
+    }
+}
+
+static void do_outp(pio_addr_t addr,
+        unsigned long size, uint32_t val)
+{
+    switch (size) {
+        case 1:
+            return cpu_outb(addr, val);
+        case 2:
+            return cpu_outw(addr, val);
+        case 4:
+            return cpu_outl(addr, val);
+        default:
+            hw_error("outp: bad size: %04"FMT_pioaddr" %lx", addr, size);
+    }
+}
+
+/*
+ * Helper functions which read/write an object from/to physical guest
+ * memory, as part of the implementation of an ioreq.
+ *
+ * Equivalent to
+ *   cpu_physical_memory_rw(addr + (req->df ? -1 : +1) * req->size * i,
+ *                          val, req->size, 0/1)
+ * except without the integer overflow problems.
+ */
+static void rw_phys_req_item(hwaddr addr,
+                             ioreq_t *req, uint32_t i, void *val, int rw)
+{
+    /* Do everything unsigned so overflow just results in a truncated result
+     * and accesses to undesired parts of guest memory, which is up
+     * to the guest */
+    hwaddr offset = (hwaddr)req->size * i;
+    if (req->df) {
+        addr -= offset;
+    } else {
+        addr += offset;
+    }
+    cpu_physical_memory_rw(addr, val, req->size, rw);
+}
+
+static inline void read_phys_req_item(hwaddr addr,
+                                      ioreq_t *req, uint32_t i, void *val)
+{
+    rw_phys_req_item(addr, req, i, val, 0);
+}
+static inline void write_phys_req_item(hwaddr addr,
+                                       ioreq_t *req, uint32_t i, void *val)
+{
+    rw_phys_req_item(addr, req, i, val, 1);
+}
+
+
+static void cpu_ioreq_pio(ioreq_t *req)
+{
+    uint32_t i;
+
+    if (req->dir == IOREQ_READ) {
+        if (!req->data_is_ptr) {
+            req->data = do_inp(req->addr, req->size);
+        } else {
+            uint32_t tmp;
+
+            for (i = 0; i < req->count; i++) {
+                tmp = do_inp(req->addr, req->size);
+                write_phys_req_item(req->data, req, i, &tmp);
+            }
+        }
+    } else if (req->dir == IOREQ_WRITE) {
+        if (!req->data_is_ptr) {
+            do_outp(req->addr, req->size, req->data);
+        } else {
+            for (i = 0; i < req->count; i++) {
+                uint32_t tmp = 0;
+
+                read_phys_req_item(req->data, req, i, &tmp);
+                do_outp(req->addr, req->size, tmp);
+            }
+        }
+    }
+}
+
+static void cpu_ioreq_move(ioreq_t *req)
+{
+    uint32_t i;
+
+    if (!req->data_is_ptr) {
+        if (req->dir == IOREQ_READ) {
+            for (i = 0; i < req->count; i++) {
+                read_phys_req_item(req->addr, req, i, &req->data);
+            }
+        } else if (req->dir == IOREQ_WRITE) {
+            for (i = 0; i < req->count; i++) {
+                write_phys_req_item(req->addr, req, i, &req->data);
+            }
+        }
+    } else {
+        uint64_t tmp;
+
+        if (req->dir == IOREQ_READ) {
+            for (i = 0; i < req->count; i++) {
+                read_phys_req_item(req->addr, req, i, &tmp);
+                write_phys_req_item(req->data, req, i, &tmp);
+            }
+        } else if (req->dir == IOREQ_WRITE) {
+            for (i = 0; i < req->count; i++) {
+                read_phys_req_item(req->data, req, i, &tmp);
+                write_phys_req_item(req->addr, req, i, &tmp);
+            }
+        }
+    }
+}
+
+static void handle_ioreq(ioreq_t *req)
+{
+    if (!req->data_is_ptr && (req->dir == IOREQ_WRITE) &&
+            (req->size < sizeof (target_ulong))) {
+        req->data &= ((target_ulong) 1 << (8 * req->size)) - 1;
+    }
+
+    switch (req->type) {
+        case IOREQ_TYPE_PIO:
+            cpu_ioreq_pio(req);
+            break;
+        case IOREQ_TYPE_COPY:
+            cpu_ioreq_move(req);
+            break;
+        case IOREQ_TYPE_TIMEOFFSET:
+            break;
+        case IOREQ_TYPE_INVALIDATE:
+            xen_invalidate_map_cache();
+            break;
+        default:
+            hw_error("Invalid ioreq type 0x%x\n", req->type);
+    }
+}
+
+static int handle_buffered_iopage(XenIOState *state)
+{
+    buf_ioreq_t *buf_req = NULL;
+    ioreq_t req;
+    int qw;
+
+    if (!state->buffered_io_page) {
+        return 0;
+    }
+
+    memset(&req, 0x00, sizeof(req));
+
+    while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {
+        buf_req = &state->buffered_io_page->buf_ioreq[
+            state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
+        req.size = 1UL << buf_req->size;
+        req.count = 1;
+        req.addr = buf_req->addr;
+        req.data = buf_req->data;
+        req.state = STATE_IOREQ_READY;
+        req.dir = buf_req->dir;
+        req.df = 1;
+        req.type = buf_req->type;
+        req.data_is_ptr = 0;
+        qw = (req.size == 8);
+        if (qw) {
+            buf_req = &state->buffered_io_page->buf_ioreq[
+                (state->buffered_io_page->read_pointer + 1) % IOREQ_BUFFER_SLOT_NUM];
+            req.data |= ((uint64_t)buf_req->data) << 32;
+        }
+
+        handle_ioreq(&req);
+
+        xen_mb();
+        state->buffered_io_page->read_pointer += qw ? 2 : 1;
+    }
+
+    return req.count;
+}
+
+static void handle_buffered_io(void *opaque)
+{
+    XenIOState *state = opaque;
+
+    if (handle_buffered_iopage(state)) {
+        timer_mod(state->buffered_io_timer,
+                BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
+    } else {
+        timer_del(state->buffered_io_timer);
+        xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
+    }
+}
+
+static void cpu_handle_ioreq(void *opaque)
+{
+    XenIOState *state = opaque;
+    ioreq_t *req = cpu_get_ioreq(state);
+
+    handle_buffered_iopage(state);
+    if (req) {
+        handle_ioreq(req);
+
+        if (req->state != STATE_IOREQ_INPROCESS) {
+            fprintf(stderr, "Badness in I/O request ... not in service?!: "
+                    "%x, ptr: %x, port: %"PRIx64", "
+                    "data: %"PRIx64", count: %" FMT_ioreq_size ", size: %" FMT_ioreq_size "\n",
+                    req->state, req->data_is_ptr, req->addr,
+                    req->data, req->count, req->size);
+            destroy_hvm_domain(false);
+            return;
+        }
+
+        xen_wmb(); /* Update ioreq contents /then/ update state. */
+
+        /*
+         * We do this before we send the response so that the tools
+         * have the opportunity to pick up on the reset before the
+         * guest resumes and does a hlt with interrupts disabled which
+         * causes Xen to powerdown the domain.
+         */
+        if (runstate_is_running()) {
+            if (qemu_shutdown_requested_get()) {
+                destroy_hvm_domain(false);
+            }
+            if (qemu_reset_requested_get()) {
+                qemu_system_reset(VMRESET_REPORT);
+                destroy_hvm_domain(true);
+            }
+        }
+
+        req->state = STATE_IORESP_READY;
+        xc_evtchn_notify(state->xce_handle, state->ioreq_local_port[state->send_vcpu]);
+    }
+}
+
+static void xen_main_loop_prepare(XenIOState *state)
+{
+    int evtchn_fd = -1;
+
+    if (state->xce_handle != XC_HANDLER_INITIAL_VALUE) {
+        evtchn_fd = xc_evtchn_fd(state->xce_handle);
+    }
+
+    state->buffered_io_timer = timer_new_ms(QEMU_CLOCK_REALTIME, handle_buffered_io,
+                                                 state);
+
+    if (evtchn_fd != -1) {
+        qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
+    }
+}
+
+
+static void xen_hvm_change_state_handler(void *opaque, int running,
+                                         RunState rstate)
+{
+    XenIOState *xstate = opaque;
+    if (running) {
+        xen_main_loop_prepare(xstate);
+    }
+}
+
+static void xen_exit_notifier(Notifier *n, void *data)
+{
+    XenIOState *state = container_of(n, XenIOState, exit);
+
+    xc_evtchn_close(state->xce_handle);
+    xs_daemon_close(state->xenstore);
+}
+
+static void xen_read_physmap(XenIOState *state)
+{
+    XenPhysmap *physmap = NULL;
+    unsigned int len, num, i;
+    char path[80], *value = NULL;
+    char **entries = NULL;
+
+    snprintf(path, sizeof(path),
+            "/local/domain/0/device-model/%d/physmap", xen_domid);
+    entries = xs_directory(state->xenstore, 0, path, &num);
+    if (entries == NULL)
+        return;
+
+    for (i = 0; i < num; i++) {
+        physmap = g_malloc(sizeof (XenPhysmap));
+        physmap->phys_offset = strtoull(entries[i], NULL, 16);
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%s/start_addr",
+                xen_domid, entries[i]);
+        value = xs_read(state->xenstore, 0, path, &len);
+        if (value == NULL) {
+            g_free(physmap);
+            continue;
+        }
+        physmap->start_addr = strtoull(value, NULL, 16);
+        free(value);
+
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%s/size",
+                xen_domid, entries[i]);
+        value = xs_read(state->xenstore, 0, path, &len);
+        if (value == NULL) {
+            g_free(physmap);
+            continue;
+        }
+        physmap->size = strtoull(value, NULL, 16);
+        free(value);
+
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%s/name",
+                xen_domid, entries[i]);
+        physmap->name = xs_read(state->xenstore, 0, path, &len);
+
+        QLIST_INSERT_HEAD(&state->physmap, physmap, list);
+    }
+    free(entries);
+}
+
+static void xen_wakeup_notifier(Notifier *notifier, void *data)
+{
+    xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
+}
+
+int xen_hvm_init(MemoryRegion **ram_memory)
+{
+    int i, rc;
+    unsigned long ioreq_pfn;
+    unsigned long bufioreq_evtchn;
+    XenIOState *state;
+
+    state = g_malloc0(sizeof (XenIOState));
+
+    state->xce_handle = xen_xc_evtchn_open(NULL, 0);
+    if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
+        perror("xen: event channel open");
+        g_free(state);
+        return -errno;
+    }
+
+    state->xenstore = xs_daemon_open();
+    if (state->xenstore == NULL) {
+        perror("xen: xenstore open");
+        g_free(state);
+        return -errno;
+    }
+
+    state->exit.notify = xen_exit_notifier;
+    qemu_add_exit_notifier(&state->exit);
+
+    state->suspend.notify = xen_suspend_notifier;
+    qemu_register_suspend_notifier(&state->suspend);
+
+    state->wakeup.notify = xen_wakeup_notifier;
+    qemu_register_wakeup_notifier(&state->wakeup);
+
+    xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
+    DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
+    state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
+                                              PROT_READ|PROT_WRITE, ioreq_pfn);
+    if (state->shared_page == NULL) {
+        hw_error("map shared IO page returned error %d handle=" XC_INTERFACE_FMT,
+                 errno, xen_xc);
+    }
+
+    xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
+    DPRINTF("buffered io page at pfn %lx\n", ioreq_pfn);
+    state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
+                                                   PROT_READ|PROT_WRITE, ioreq_pfn);
+    if (state->buffered_io_page == NULL) {
+        hw_error("map buffered IO page returned error %d", errno);
+    }
+
+    state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));
+
+    /* FIXME: how about if we overflow the page here? */
+    for (i = 0; i < max_cpus; i++) {
+        rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
+                                        xen_vcpu_eport(state->shared_page, i));
+        if (rc == -1) {
+            fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
+            return -1;
+        }
+        state->ioreq_local_port[i] = rc;
+    }
+
+    rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN,
+            &bufioreq_evtchn);
+    if (rc < 0) {
+        fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");
+        return -1;
+    }
+    rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
+            (uint32_t)bufioreq_evtchn);
+    if (rc == -1) {
+        fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
+        return -1;
+    }
+    state->bufioreq_local_port = rc;
+
+    /* Init RAM management */
+    xen_map_cache_init(xen_phys_offset_to_gaddr, state);
+    xen_ram_init(ram_size, ram_memory);
+
+    qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
+
+    state->memory_listener = xen_memory_listener;
+    QLIST_INIT(&state->physmap);
+    memory_listener_register(&state->memory_listener, &address_space_memory);
+    state->log_for_dirtybit = NULL;
+
+    /* Initialize backend core & drivers */
+    if (xen_be_init() != 0) {
+        fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
+        exit(1);
+    }
+    xen_be_register("console", &xen_console_ops);
+    xen_be_register("vkbd", &xen_kbdmouse_ops);
+    xen_be_register("qdisk", &xen_blkdev_ops);
+    xen_read_physmap(state);
+
+    return 0;
+}
+
+void destroy_hvm_domain(bool reboot)
+{
+    XenXC xc_handle;
+    int sts;
+
+    xc_handle = xen_xc_interface_open(0, 0, 0);
+    if (xc_handle == XC_HANDLER_INITIAL_VALUE) {
+        fprintf(stderr, "Cannot acquire xenctrl handle\n");
+    } else {
+        sts = xc_domain_shutdown(xc_handle, xen_domid,
+                                 reboot ? SHUTDOWN_reboot : SHUTDOWN_poweroff);
+        if (sts != 0) {
+            fprintf(stderr, "xc_domain_shutdown failed to issue %s, "
+                    "sts %d, %s\n", reboot ? "reboot" : "poweroff",
+                    sts, strerror(errno));
+        } else {
+            fprintf(stderr, "Issued domain %d %s\n", xen_domid,
+                    reboot ? "reboot" : "poweroff");
+        }
+        xc_interface_close(xc_handle);
+    }
+}
+
+void xen_register_framebuffer(MemoryRegion *mr)
+{
+    framebuffer = mr;
+}
+
+void xen_shutdown_fatal_error(const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    fprintf(stderr, "Will destroy the domain.\n");
+    /* destroy the domain */
+    qemu_system_shutdown_request();
+}
+
+void xen_modified_memory(ram_addr_t start, ram_addr_t length)
+{
+    if (unlikely(xen_in_migration)) {
+        int rc;
+        ram_addr_t start_pfn, nb_pages;
+
+        if (length == 0) {
+            length = TARGET_PAGE_SIZE;
+        }
+        start_pfn = start >> TARGET_PAGE_BITS;
+        nb_pages = ((start + length + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
+            - start_pfn;
+        rc = xc_hvm_modified_memory(xen_xc, xen_domid, start_pfn, nb_pages);
+        if (rc) {
+            fprintf(stderr,
+                    "%s failed for "RAM_ADDR_FMT" ("RAM_ADDR_FMT"): %i, %s\n",
+                    __func__, start, nb_pages, rc, strerror(-rc));
+        }
+    }
+}
+
+void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
+{
+    if (enable) {
+        memory_global_dirty_log_start();
+    } else {
+        memory_global_dirty_log_stop();
+    }
+}
diff --git a/xen-mapcache-stub.c b/xen-mapcache-stub.c
new file mode 100644
index 0000000..f4ddf53
--- /dev/null
+++ b/xen-mapcache-stub.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014       Citrix Ltd.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+
+#include "config.h"
+
+#include <sys/resource.h>
+
+#include "hw/xen/xen_backend.h"
+
+#include <xen/hvm/params.h>
+
+#include "sysemu/xen-mapcache.h"
+#include "trace.h"
+
+uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
+                       uint8_t lock)
+{
+    abort();
+    return NULL;
+}
+
+ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
+{
+    abort();
+    return 0;
+}
+
+void xen_invalidate_map_cache_entry(uint8_t *buffer)
+{
+    abort();
+}
+
diff --git a/xen-stub.c b/xen-stub.c
deleted file mode 100644
index 59927cb..0000000
--- a/xen-stub.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010       Citrix Ltd.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-
-#include "qemu-common.h"
-#include "hw/xen/xen.h"
-#include "exec/memory.h"
-#include "qmp-commands.h"
-
-void xenstore_store_pv_console_info(int i, CharDriverState *chr)
-{
-}
-
-int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
-{
-    return -1;
-}
-
-void xen_piix3_set_irq(void *opaque, int irq_num, int level)
-{
-}
-
-void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
-{
-}
-
-void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
-{
-}
-
-void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
-{
-}
-
-void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
-{
-}
-
-qemu_irq *xen_interrupt_controller_init(void)
-{
-    return NULL;
-}
-
-int xen_init(QEMUMachine *machine)
-{
-    return -ENOSYS;
-}
-
-void xen_register_framebuffer(MemoryRegion *mr)
-{
-}
-
-void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
-{
-}
-
-void xen_modified_memory(ram_addr_t start, ram_addr_t length)
-{
-}
-
-int xen_hvm_init(MemoryRegion **ram_memory)
-{
-    return 0;
-}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
  2014-03-25 15:59 ` Wei Liu
@ 2014-03-25 16:22   ` Paolo Bonzini
  -1 siblings, 0 replies; 18+ messages in thread
From: Paolo Bonzini @ 2014-03-25 16:22 UTC (permalink / raw)
  To: Wei Liu, xen-devel, qemu-devel; +Cc: anthony.perard, stefano.stabellini

Il 25/03/2014 16:59, Wei Liu ha scritto:
> This small series disentangles Xen-specific files in QEMU. PV and HVM guests
> related files are moved to corresponding locations. Build system is updated to
> reflect those changes.
>
> This series was sent back in Jan but fell through the crack. It is now rebased
> on current QEMU master and tested with usual Xen building runes. Everything
> works as before.
>
> Wei.
>
> Wei Liu (3):
>   xen: move Xen PV machine files to hw/xenpv
>   xen: move Xen HVM files under hw/i386/xen
>   xen: factor out common functions

Please regenerate with the "-M" option or add the following to .gitconfig:

[diff]
	renames = true

Paolo

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
@ 2014-03-25 16:22   ` Paolo Bonzini
  0 siblings, 0 replies; 18+ messages in thread
From: Paolo Bonzini @ 2014-03-25 16:22 UTC (permalink / raw)
  To: Wei Liu, xen-devel, qemu-devel; +Cc: anthony.perard, stefano.stabellini

Il 25/03/2014 16:59, Wei Liu ha scritto:
> This small series disentangles Xen-specific files in QEMU. PV and HVM guests
> related files are moved to corresponding locations. Build system is updated to
> reflect those changes.
>
> This series was sent back in Jan but fell through the crack. It is now rebased
> on current QEMU master and tested with usual Xen building runes. Everything
> works as before.
>
> Wei.
>
> Wei Liu (3):
>   xen: move Xen PV machine files to hw/xenpv
>   xen: move Xen HVM files under hw/i386/xen
>   xen: factor out common functions

Please regenerate with the "-M" option or add the following to .gitconfig:

[diff]
	renames = true

Paolo

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
  2014-03-25 16:22   ` Paolo Bonzini
@ 2014-03-25 16:32     ` Wei Liu
  -1 siblings, 0 replies; 18+ messages in thread
From: Wei Liu @ 2014-03-25 16:32 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: anthony.perard, stefano.stabellini, Wei Liu, qemu-devel, xen-devel

On Tue, Mar 25, 2014 at 05:22:08PM +0100, Paolo Bonzini wrote:
> Il 25/03/2014 16:59, Wei Liu ha scritto:
> >This small series disentangles Xen-specific files in QEMU. PV and HVM guests
> >related files are moved to corresponding locations. Build system is updated to
> >reflect those changes.
> >
> >This series was sent back in Jan but fell through the crack. It is now rebased
> >on current QEMU master and tested with usual Xen building runes. Everything
> >works as before.
> >
> >Wei.
> >
> >Wei Liu (3):
> >  xen: move Xen PV machine files to hw/xenpv
> >  xen: move Xen HVM files under hw/i386/xen
> >  xen: factor out common functions
>
> Please regenerate with the "-M" option or add the following to .gitconfig:
>
> [diff]
> 	renames = true

Oops, sorry. I did this for first series but forgot about it when
resending. Updated diff stat attached.

Wei.

 Wei Liu (3):
  xen: move Xen PV machine files to hw/xenpv
  xen: move Xen HVM files under hw/i386/xen
  xen: factor out common functions

 Makefile.target                      |    6 +-
 hw/i386/Makefile.objs                |    2 +-
 hw/i386/xen/Makefile.objs            |    1 +
 hw/{ => i386}/xen/xen_apic.c         |    0
 hw/{ => i386}/xen/xen_platform.c     |    0
 hw/{ => i386}/xen/xen_pvdevice.c     |    0
 hw/xen/Makefile.objs                 |    1 -
 hw/xenpv/Makefile.objs               |    2 +
 hw/{i386 => xenpv}/xen_domainbuild.c |    0
 hw/{i386 => xenpv}/xen_domainbuild.h |    0
 hw/{i386 => xenpv}/xen_machine_pv.c  |    0
 xen-common-stub.c                    |   19 ++++++
 xen-common.c                         |  123 ++++++++++++++++++++++++++++++++++
 xen-stub.c => xen-hvm-stub.c         |   18 ++---
 xen-all.c => xen-hvm.c               |  121 +++------------------------------
 xen-mapcache-stub.c                  |   39 +++++++++++
 16 files changed, 207 insertions(+), 125 deletions(-)
 create mode 100644 hw/i386/xen/Makefile.objs
 rename hw/{ => i386}/xen/xen_apic.c (100%)
 rename hw/{ => i386}/xen/xen_platform.c (100%)
 rename hw/{ => i386}/xen/xen_pvdevice.c (100%)
 create mode 100644 hw/xenpv/Makefile.objs
 rename hw/{i386 => xenpv}/xen_domainbuild.c (100%)
 rename hw/{i386 => xenpv}/xen_domainbuild.h (100%)
 rename hw/{i386 => xenpv}/xen_machine_pv.c (100%)
 create mode 100644 xen-common-stub.c
 create mode 100644 xen-common.c
 rename xen-stub.c => xen-hvm-stub.c (90%)
 rename xen-all.c => xen-hvm.c (93%)
 create mode 100644 xen-mapcache-stub.c

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
@ 2014-03-25 16:32     ` Wei Liu
  0 siblings, 0 replies; 18+ messages in thread
From: Wei Liu @ 2014-03-25 16:32 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: anthony.perard, stefano.stabellini, Wei Liu, qemu-devel, xen-devel

On Tue, Mar 25, 2014 at 05:22:08PM +0100, Paolo Bonzini wrote:
> Il 25/03/2014 16:59, Wei Liu ha scritto:
> >This small series disentangles Xen-specific files in QEMU. PV and HVM guests
> >related files are moved to corresponding locations. Build system is updated to
> >reflect those changes.
> >
> >This series was sent back in Jan but fell through the crack. It is now rebased
> >on current QEMU master and tested with usual Xen building runes. Everything
> >works as before.
> >
> >Wei.
> >
> >Wei Liu (3):
> >  xen: move Xen PV machine files to hw/xenpv
> >  xen: move Xen HVM files under hw/i386/xen
> >  xen: factor out common functions
>
> Please regenerate with the "-M" option or add the following to .gitconfig:
>
> [diff]
> 	renames = true

Oops, sorry. I did this for first series but forgot about it when
resending. Updated diff stat attached.

Wei.

 Wei Liu (3):
  xen: move Xen PV machine files to hw/xenpv
  xen: move Xen HVM files under hw/i386/xen
  xen: factor out common functions

 Makefile.target                      |    6 +-
 hw/i386/Makefile.objs                |    2 +-
 hw/i386/xen/Makefile.objs            |    1 +
 hw/{ => i386}/xen/xen_apic.c         |    0
 hw/{ => i386}/xen/xen_platform.c     |    0
 hw/{ => i386}/xen/xen_pvdevice.c     |    0
 hw/xen/Makefile.objs                 |    1 -
 hw/xenpv/Makefile.objs               |    2 +
 hw/{i386 => xenpv}/xen_domainbuild.c |    0
 hw/{i386 => xenpv}/xen_domainbuild.h |    0
 hw/{i386 => xenpv}/xen_machine_pv.c  |    0
 xen-common-stub.c                    |   19 ++++++
 xen-common.c                         |  123 ++++++++++++++++++++++++++++++++++
 xen-stub.c => xen-hvm-stub.c         |   18 ++---
 xen-all.c => xen-hvm.c               |  121 +++------------------------------
 xen-mapcache-stub.c                  |   39 +++++++++++
 16 files changed, 207 insertions(+), 125 deletions(-)
 create mode 100644 hw/i386/xen/Makefile.objs
 rename hw/{ => i386}/xen/xen_apic.c (100%)
 rename hw/{ => i386}/xen/xen_platform.c (100%)
 rename hw/{ => i386}/xen/xen_pvdevice.c (100%)
 create mode 100644 hw/xenpv/Makefile.objs
 rename hw/{i386 => xenpv}/xen_domainbuild.c (100%)
 rename hw/{i386 => xenpv}/xen_domainbuild.h (100%)
 rename hw/{i386 => xenpv}/xen_machine_pv.c (100%)
 create mode 100644 xen-common-stub.c
 create mode 100644 xen-common.c
 rename xen-stub.c => xen-hvm-stub.c (90%)
 rename xen-all.c => xen-hvm.c (93%)
 create mode 100644 xen-mapcache-stub.c

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
  2014-03-25 16:32     ` Wei Liu
@ 2014-03-25 16:40       ` Stefano Stabellini
  -1 siblings, 0 replies; 18+ messages in thread
From: Stefano Stabellini @ 2014-03-25 16:40 UTC (permalink / raw)
  To: Wei Liu
  Cc: anthony.perard, Paolo Bonzini, stefano.stabellini, qemu-devel, xen-devel

On Tue, 25 Mar 2014, Wei Liu wrote:
> On Tue, Mar 25, 2014 at 05:22:08PM +0100, Paolo Bonzini wrote:
> > Il 25/03/2014 16:59, Wei Liu ha scritto:
> > >This small series disentangles Xen-specific files in QEMU. PV and HVM guests
> > >related files are moved to corresponding locations. Build system is updated to
> > >reflect those changes.
> > >
> > >This series was sent back in Jan but fell through the crack. It is now rebased
> > >on current QEMU master and tested with usual Xen building runes. Everything
> > >works as before.
> > >
> > >Wei.
> > >
> > >Wei Liu (3):
> > >  xen: move Xen PV machine files to hw/xenpv
> > >  xen: move Xen HVM files under hw/i386/xen
> > >  xen: factor out common functions
> >
> > Please regenerate with the "-M" option or add the following to .gitconfig:
> >
> > [diff]
> > 	renames = true
> 
> Oops, sorry. I did this for first series but forgot about it when
> resending. Updated diff stat attached.

Much better, thanks.
The patches are fine by me.

Paolo, if you are OK with them, I'll send a pull request.


> Wei.
> 
>  Wei Liu (3):
>   xen: move Xen PV machine files to hw/xenpv
>   xen: move Xen HVM files under hw/i386/xen
>   xen: factor out common functions
> 
>  Makefile.target                      |    6 +-
>  hw/i386/Makefile.objs                |    2 +-
>  hw/i386/xen/Makefile.objs            |    1 +
>  hw/{ => i386}/xen/xen_apic.c         |    0
>  hw/{ => i386}/xen/xen_platform.c     |    0
>  hw/{ => i386}/xen/xen_pvdevice.c     |    0
>  hw/xen/Makefile.objs                 |    1 -
>  hw/xenpv/Makefile.objs               |    2 +
>  hw/{i386 => xenpv}/xen_domainbuild.c |    0
>  hw/{i386 => xenpv}/xen_domainbuild.h |    0
>  hw/{i386 => xenpv}/xen_machine_pv.c  |    0
>  xen-common-stub.c                    |   19 ++++++
>  xen-common.c                         |  123 ++++++++++++++++++++++++++++++++++
>  xen-stub.c => xen-hvm-stub.c         |   18 ++---
>  xen-all.c => xen-hvm.c               |  121 +++------------------------------
>  xen-mapcache-stub.c                  |   39 +++++++++++
>  16 files changed, 207 insertions(+), 125 deletions(-)
>  create mode 100644 hw/i386/xen/Makefile.objs
>  rename hw/{ => i386}/xen/xen_apic.c (100%)
>  rename hw/{ => i386}/xen/xen_platform.c (100%)
>  rename hw/{ => i386}/xen/xen_pvdevice.c (100%)
>  create mode 100644 hw/xenpv/Makefile.objs
>  rename hw/{i386 => xenpv}/xen_domainbuild.c (100%)
>  rename hw/{i386 => xenpv}/xen_domainbuild.h (100%)
>  rename hw/{i386 => xenpv}/xen_machine_pv.c (100%)
>  create mode 100644 xen-common-stub.c
>  create mode 100644 xen-common.c
>  rename xen-stub.c => xen-hvm-stub.c (90%)
>  rename xen-all.c => xen-hvm.c (93%)
>  create mode 100644 xen-mapcache-stub.c
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
@ 2014-03-25 16:40       ` Stefano Stabellini
  0 siblings, 0 replies; 18+ messages in thread
From: Stefano Stabellini @ 2014-03-25 16:40 UTC (permalink / raw)
  To: Wei Liu
  Cc: anthony.perard, Paolo Bonzini, stefano.stabellini, qemu-devel, xen-devel

On Tue, 25 Mar 2014, Wei Liu wrote:
> On Tue, Mar 25, 2014 at 05:22:08PM +0100, Paolo Bonzini wrote:
> > Il 25/03/2014 16:59, Wei Liu ha scritto:
> > >This small series disentangles Xen-specific files in QEMU. PV and HVM guests
> > >related files are moved to corresponding locations. Build system is updated to
> > >reflect those changes.
> > >
> > >This series was sent back in Jan but fell through the crack. It is now rebased
> > >on current QEMU master and tested with usual Xen building runes. Everything
> > >works as before.
> > >
> > >Wei.
> > >
> > >Wei Liu (3):
> > >  xen: move Xen PV machine files to hw/xenpv
> > >  xen: move Xen HVM files under hw/i386/xen
> > >  xen: factor out common functions
> >
> > Please regenerate with the "-M" option or add the following to .gitconfig:
> >
> > [diff]
> > 	renames = true
> 
> Oops, sorry. I did this for first series but forgot about it when
> resending. Updated diff stat attached.

Much better, thanks.
The patches are fine by me.

Paolo, if you are OK with them, I'll send a pull request.


> Wei.
> 
>  Wei Liu (3):
>   xen: move Xen PV machine files to hw/xenpv
>   xen: move Xen HVM files under hw/i386/xen
>   xen: factor out common functions
> 
>  Makefile.target                      |    6 +-
>  hw/i386/Makefile.objs                |    2 +-
>  hw/i386/xen/Makefile.objs            |    1 +
>  hw/{ => i386}/xen/xen_apic.c         |    0
>  hw/{ => i386}/xen/xen_platform.c     |    0
>  hw/{ => i386}/xen/xen_pvdevice.c     |    0
>  hw/xen/Makefile.objs                 |    1 -
>  hw/xenpv/Makefile.objs               |    2 +
>  hw/{i386 => xenpv}/xen_domainbuild.c |    0
>  hw/{i386 => xenpv}/xen_domainbuild.h |    0
>  hw/{i386 => xenpv}/xen_machine_pv.c  |    0
>  xen-common-stub.c                    |   19 ++++++
>  xen-common.c                         |  123 ++++++++++++++++++++++++++++++++++
>  xen-stub.c => xen-hvm-stub.c         |   18 ++---
>  xen-all.c => xen-hvm.c               |  121 +++------------------------------
>  xen-mapcache-stub.c                  |   39 +++++++++++
>  16 files changed, 207 insertions(+), 125 deletions(-)
>  create mode 100644 hw/i386/xen/Makefile.objs
>  rename hw/{ => i386}/xen/xen_apic.c (100%)
>  rename hw/{ => i386}/xen/xen_platform.c (100%)
>  rename hw/{ => i386}/xen/xen_pvdevice.c (100%)
>  create mode 100644 hw/xenpv/Makefile.objs
>  rename hw/{i386 => xenpv}/xen_domainbuild.c (100%)
>  rename hw/{i386 => xenpv}/xen_domainbuild.h (100%)
>  rename hw/{i386 => xenpv}/xen_machine_pv.c (100%)
>  create mode 100644 xen-common-stub.c
>  create mode 100644 xen-common.c
>  rename xen-stub.c => xen-hvm-stub.c (90%)
>  rename xen-all.c => xen-hvm.c (93%)
>  create mode 100644 xen-mapcache-stub.c
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
  2014-03-25 16:40       ` Stefano Stabellini
@ 2014-03-25 16:42         ` Paolo Bonzini
  -1 siblings, 0 replies; 18+ messages in thread
From: Paolo Bonzini @ 2014-03-25 16:42 UTC (permalink / raw)
  To: Stefano Stabellini, Wei Liu; +Cc: anthony.perard, qemu-devel, xen-devel

Il 25/03/2014 17:40, Stefano Stabellini ha scritto:
>> >
>> > Oops, sorry. I did this for first series but forgot about it when
>> > resending. Updated diff stat attached.
> Much better, thanks.
> The patches are fine by me.
>
> Paolo, if you are OK with them, I'll send a pull request.

I guess for 2.1?  Or do they actually fix bugs?

Paolo

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
@ 2014-03-25 16:42         ` Paolo Bonzini
  0 siblings, 0 replies; 18+ messages in thread
From: Paolo Bonzini @ 2014-03-25 16:42 UTC (permalink / raw)
  To: Stefano Stabellini, Wei Liu; +Cc: anthony.perard, qemu-devel, xen-devel

Il 25/03/2014 17:40, Stefano Stabellini ha scritto:
>> >
>> > Oops, sorry. I did this for first series but forgot about it when
>> > resending. Updated diff stat attached.
> Much better, thanks.
> The patches are fine by me.
>
> Paolo, if you are OK with them, I'll send a pull request.

I guess for 2.1?  Or do they actually fix bugs?

Paolo

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
  2014-03-25 16:42         ` Paolo Bonzini
@ 2014-03-25 16:44           ` Stefano Stabellini
  -1 siblings, 0 replies; 18+ messages in thread
From: Stefano Stabellini @ 2014-03-25 16:44 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: anthony.perard, xen-devel, Wei Liu, qemu-devel, Stefano Stabellini

On Tue, 25 Mar 2014, Paolo Bonzini wrote:
> Il 25/03/2014 17:40, Stefano Stabellini ha scritto:
> > > >
> > > > Oops, sorry. I did this for first series but forgot about it when
> > > > resending. Updated diff stat attached.
> > Much better, thanks.
> > The patches are fine by me.
> > 
> > Paolo, if you are OK with them, I'll send a pull request.
> 
> I guess for 2.1?  Or do they actually fix bugs?

For 2.1 is fine.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU
@ 2014-03-25 16:44           ` Stefano Stabellini
  0 siblings, 0 replies; 18+ messages in thread
From: Stefano Stabellini @ 2014-03-25 16:44 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: anthony.perard, xen-devel, Wei Liu, qemu-devel, Stefano Stabellini

On Tue, 25 Mar 2014, Paolo Bonzini wrote:
> Il 25/03/2014 17:40, Stefano Stabellini ha scritto:
> > > >
> > > > Oops, sorry. I did this for first series but forgot about it when
> > > > resending. Updated diff stat attached.
> > Much better, thanks.
> > The patches are fine by me.
> > 
> > Paolo, if you are OK with them, I'll send a pull request.
> 
> I guess for 2.1?  Or do they actually fix bugs?

For 2.1 is fine.

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2014-03-26  4:08 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-25 15:59 [Qemu-devel] [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU Wei Liu
2014-03-25 15:59 ` Wei Liu
2014-03-25 15:59 ` [Qemu-devel] [PATCH resend 1/3] xen: move Xen PV machine files to hw/xenpv Wei Liu
2014-03-25 15:59   ` Wei Liu
2014-03-25 15:59 ` [Qemu-devel] [PATCH resend 2/3] xen: move Xen HVM files under hw/i386/xen Wei Liu
2014-03-25 15:59   ` Wei Liu
2014-03-25 15:59 ` [Qemu-devel] [PATCH resend 3/3] xen: factor out common functions Wei Liu
2014-03-25 15:59   ` Wei Liu
2014-03-25 16:22 ` [Qemu-devel] [PATCH resend 0/3] QEMU/Xen: disentangle PV and HVM in QEMU Paolo Bonzini
2014-03-25 16:22   ` Paolo Bonzini
2014-03-25 16:32   ` [Qemu-devel] " Wei Liu
2014-03-25 16:32     ` Wei Liu
2014-03-25 16:40     ` [Qemu-devel] " Stefano Stabellini
2014-03-25 16:40       ` Stefano Stabellini
2014-03-25 16:42       ` [Qemu-devel] " Paolo Bonzini
2014-03-25 16:42         ` Paolo Bonzini
2014-03-25 16:44         ` [Qemu-devel] " Stefano Stabellini
2014-03-25 16:44           ` Stefano Stabellini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.