diff mbox series

[PATCH-for-9.0,7/9] hw/xen/hvm: Extract common code to xen-hvm-common.c

Message ID 20231114163123.74888-8-philmd@linaro.org (mailing list archive)
State New, archived
Headers show
Series hw/xen: Have ARM targets use common xen_memory_listener | expand

Commit Message

Philippe Mathieu-Daudé Nov. 14, 2023, 4:31 p.m. UTC
Extract non-x86 specific code out of xen-hvm.c,
to xen-hvm-common.c. For now this new file is
only build for x86 targets.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/i386/xen/xen-hvm-common.c | 473 +++++++++++++++++++++++++++++++++++
 hw/i386/xen/xen-hvm.c        | 459 ---------------------------------
 hw/i386/xen/meson.build      |   1 +
 3 files changed, 474 insertions(+), 459 deletions(-)
 create mode 100644 hw/i386/xen/xen-hvm-common.c

Comments

Manos Pitsidianakis March 7, 2024, 12:01 p.m. UTC | #1
On Tue, 14 Nov 2023 18:31, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>Extract non-x86 specific code out of xen-hvm.c,
>to xen-hvm-common.c. For now this new file is
>only build for x86 targets.

s/build/built

>
>Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>---
> hw/i386/xen/xen-hvm-common.c | 473 +++++++++++++++++++++++++++++++++++
> hw/i386/xen/xen-hvm.c        | 459 ---------------------------------
> hw/i386/xen/meson.build      |   1 +
> 3 files changed, 474 insertions(+), 459 deletions(-)
> create mode 100644 hw/i386/xen/xen-hvm-common.c
>
>diff --git a/hw/i386/xen/xen-hvm-common.c b/hw/i386/xen/xen-hvm-common.c
>new file mode 100644
>index 0000000000..e8ef0e0c94
>--- /dev/null
>+++ b/hw/i386/xen/xen-hvm-common.c
>@@ -0,0 +1,473 @@
>+/*
>+ * 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/osdep.h"
>+#include "qemu/range.h"
>+#include "qapi/qapi-commands-migration.h"
>+#include "exec/target_page.h"
>+#include "hw/xen/xen-hvm-common.h"
>+#include "trace.h"
>+
>+static MemoryRegion *framebuffer;
>+static bool xen_in_migration;
>+
>+static QLIST_HEAD(, XenPhysmap) xen_physmap;
>+static const XenPhysmap *log_for_dirtybit;
>+/* Buffer used by xen_sync_dirty_bitmap */
>+static unsigned long *dirty_bitmap;
>+
>+static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size,
>+                                   int page_mask)
>+{
>+    XenPhysmap *physmap = NULL;
>+
>+    start_addr &= -page_mask;
>+
>+    QLIST_FOREACH(physmap, &xen_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 phys_offset, ram_addr_t size,
>+                                       int page_mask)
>+{
>+    hwaddr addr = phys_offset & -page_mask;
>+    XenPhysmap *physmap = NULL;
>+
>+    QLIST_FOREACH(physmap, &xen_physmap, list) {
>+        if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
>+            return physmap->start_addr + (phys_offset - physmap->phys_offset);
>+        }
>+    }
>+
>+    return phys_offset;
>+}
>+
>+#ifdef XEN_COMPAT_PHYSMAP
>+static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
>+{
>+    char path[80], value[17];
>+
>+    snprintf(path, sizeof(path),
>+            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
>+            xen_domid, (uint64_t)physmap->phys_offset);
>+    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->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)physmap->phys_offset);
>+    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->size);
>+    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
>+        return -1;
>+    }
>+    if (physmap->name) {
>+        snprintf(path, sizeof(path),
>+                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
>+                xen_domid, (uint64_t)physmap->phys_offset);
>+        if (!xs_write(state->xenstore, 0, path,
>+                      physmap->name, strlen(physmap->name))) {
>+            return -1;
>+        }
>+    }
>+    return 0;
>+}
>+#else
>+static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
>+{
>+    return 0;
>+}
>+#endif
>+
>+static int xen_add_to_physmap(XenIOState *state,
>+                              hwaddr start_addr,
>+                              ram_addr_t size,
>+                              MemoryRegion *mr,
>+                              hwaddr offset_within_region)
>+{
>+    unsigned target_page_bits = qemu_target_page_bits();
>+    int page_size = qemu_target_page_size();
>+    int page_mask = -page_size;
>+    unsigned long nr_pages;
>+    int rc = 0;
>+    XenPhysmap *physmap = NULL;
>+    hwaddr pfn, start_gpfn;
>+    hwaddr phys_offset = memory_region_get_ram_addr(mr);
>+    const char *mr_name;
>+
>+    if (get_physmapping(start_addr, size, page_mask)) {
>+        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);
>+
>+    mr_name = memory_region_name(mr);
>+
>+    physmap = g_new(XenPhysmap, 1);
>+
>+    physmap->start_addr = start_addr;
>+    physmap->size = size;
>+    physmap->name = mr_name;
>+    physmap->phys_offset = phys_offset;
>+
>+    QLIST_INSERT_HEAD(&xen_physmap, physmap, list);
>+
>+    if (runstate_check(RUN_STATE_INMIGRATE)) {
>+        /* Now when we have a physmap entry we can replace a dummy mapping with
>+         * a real one of guest foreign memory. */
>+        uint8_t *p = xen_replace_cache_entry(phys_offset, start_addr, size);
>+        assert(p && p == memory_region_get_ram_ptr(mr));
>+
>+        return 0;
>+    }
>+
>+    pfn = phys_offset >> target_page_bits;
>+    start_gpfn = start_addr >> target_page_bits;
>+    nr_pages = size >> target_page_bits;
>+    rc = xendevicemodel_relocate_memory(xen_dmod, xen_domid, nr_pages, pfn,
>+                                        start_gpfn);
>+    if (rc) {
>+        int saved_errno = errno;
>+
>+        error_report("relocate_memory %lu pages from GFN %"HWADDR_PRIx
>+                     " to GFN %"HWADDR_PRIx" failed: %s",
>+                     nr_pages, pfn, start_gpfn, strerror(saved_errno));
>+        errno = saved_errno;
>+        return -1;
>+    }
>+
>+    rc = xendevicemodel_pin_memory_cacheattr(xen_dmod, xen_domid,
>+                                   start_addr >> target_page_bits,
>+                                   (start_addr + size - 1) >> target_page_bits,
>+                                   XEN_DOMCTL_MEM_CACHEATTR_WB);
>+    if (rc) {
>+        error_report("pin_memory_cacheattr failed: %s", strerror(errno));
>+    }
>+    return xen_save_physmap(state, physmap);
>+}
>+
>+static int xen_remove_from_physmap(XenIOState *state,
>+                                   hwaddr start_addr,
>+                                   ram_addr_t size)
>+{
>+    unsigned target_page_bits = qemu_target_page_bits();
>+    int page_size = qemu_target_page_size();
>+    int page_mask = -page_size;
>+    int rc = 0;
>+    XenPhysmap *physmap = NULL;
>+    hwaddr phys_offset = 0;
>+
>+    physmap = get_physmapping(start_addr, size, page_mask);
>+    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;
>+    rc = xendevicemodel_relocate_memory(xen_dmod, xen_domid, size, start_addr,
>+                                        phys_offset);
>+    if (rc) {
>+        int saved_errno = errno;
>+
>+        error_report("relocate_memory "RAM_ADDR_FMT" pages"
>+                     " from GFN %"HWADDR_PRIx
>+                     " to GFN %"HWADDR_PRIx" failed: %s",
>+                     size, start_addr, phys_offset, strerror(saved_errno));
>+        errno = saved_errno;
>+        return -1;
>+    }
>+
>+    QLIST_REMOVE(physmap, list);
>+    if (log_for_dirtybit == physmap) {
>+        log_for_dirtybit = NULL;
>+        g_free(dirty_bitmap);
>+        dirty_bitmap = NULL;
>+    }
>+    g_free(physmap);
>+
>+    return 0;
>+}
>+
>+static void xen_sync_dirty_bitmap(XenIOState *state,
>+                                  hwaddr start_addr,
>+                                  ram_addr_t size)
>+{
>+    unsigned target_page_bits = qemu_target_page_bits();
>+    int page_size = qemu_target_page_size();
>+    int page_mask = -page_size;
>+    hwaddr npages = size >> target_page_bits;
>+    const int width = sizeof(unsigned long) * 8;
>+    size_t bitmap_size = DIV_ROUND_UP(npages, width);
>+    int rc, i, j;
>+    const XenPhysmap *physmap = NULL;
>+
>+    physmap = get_physmapping(start_addr, size, page_mask);
>+    if (physmap == NULL) {
>+        /* not handled */
>+        return;
>+    }
>+
>+    if (log_for_dirtybit == NULL) {
>+        log_for_dirtybit = physmap;
>+        dirty_bitmap = g_new(unsigned long, bitmap_size);
>+    } else if (log_for_dirtybit != physmap) {
>+        /* Only one range for dirty bitmap can be tracked. */
>+        return;
>+    }
>+
>+    rc = xen_track_dirty_vram(xen_domid, start_addr >> target_page_bits,
>+                              npages, dirty_bitmap);
>+    if (rc < 0) {
>+#ifndef ENODATA
>+#define ENODATA  ENOENT
>+#endif
>+        if (errno == ENODATA) {
>+            memory_region_set_dirty(framebuffer, 0, size);
>+            DPRINTF("xen: track_dirty_vram failed (0x" HWADDR_FMT_plx
>+                    ", 0x" HWADDR_FMT_plx "): %s\n",
>+                    start_addr, start_addr + size, strerror(errno));
>+        }
>+        return;
>+    }
>+
>+    for (i = 0; i < bitmap_size; i++) {
>+        unsigned long map = dirty_bitmap[i];
>+        while (map != 0) {
>+            j = ctzl(map);
>+            map &= ~(1ul << j);
>+            memory_region_set_dirty(framebuffer,
>+                                    (i * width + j) * page_size,
>+                                    page_size);
>+        };
>+    }
>+}
>+
>+static void xen_log_start(MemoryListener *listener,
>+                          MemoryRegionSection *section,
>+                          int old, int new)
>+{
>+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
>+
>+    if (new & ~old & (1 << DIRTY_MEMORY_VGA)) {
>+        xen_sync_dirty_bitmap(state, section->offset_within_address_space,
>+                              int128_get64(section->size));
>+    }
>+}
>+
>+static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section,
>+                         int old, int new)
>+{
>+    if (old & ~new & (1 << DIRTY_MEMORY_VGA)) {
>+        log_for_dirtybit = NULL;
>+        g_free(dirty_bitmap);
>+        dirty_bitmap = NULL;
>+        /* Disable dirty bit tracking */
>+        xen_track_dirty_vram(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;
>+}
>+
>+const MemoryListener xen_memory_listener = {
>+    .name = "xen-memory",
>+    .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 = MEMORY_LISTENER_PRIORITY_ACCEL,
>+};
>+
>+#ifdef XEN_COMPAT_PHYSMAP
>+void xen_read_physmap(XenIOState *state)
>+{
>+    XenPhysmap *physmap = NULL;
>+    unsigned int len, num, i;
>+    char path[80], *value = NULL;
>+    char **entries = NULL;
>+
>+    QLIST_INIT(&xen_physmap);
>+
>+    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_new(XenPhysmap, 1);
>+        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(&xen_physmap, physmap, list);
>+    }
>+    free(entries);
>+}
>+#else
>+void xen_read_physmap(XenIOState *state)
>+{
>+    QLIST_INIT(&xen_physmap);
>+}
>+#endif
>+
>+void xen_register_framebuffer(MemoryRegion *mr)
>+{
>+    framebuffer = mr;
>+}
>+
>+void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length)
>+{
>+    unsigned target_page_bits = qemu_target_page_bits();
>+    int page_size = qemu_target_page_size();
>+    int page_mask = -page_size;
>+
>+    if (unlikely(xen_in_migration)) {
>+        int rc;
>+        ram_addr_t start_pfn, nb_pages;
>+
>+        start = xen_phys_offset_to_gaddr(start, length, page_mask);
>+
>+        if (length == 0) {
>+            length = page_size;
>+        }
>+        start_pfn = start >> target_page_bits;
>+        nb_pages = ((start + length + page_size - 1) >> target_page_bits)
>+            - start_pfn;
>+        rc = xen_modified_memory(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, errno, strerror(errno));
>+        }
>+    }
>+}
>+
>+void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
>+{
>+    if (enable) {
>+        memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION);
>+    } else {
>+        memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION);
>+    }
>+}
>+
>+void xen_arch_set_memory(XenIOState *state, MemoryRegionSection *section,
>+                         bool add)
>+{
>+    unsigned target_page_bits = qemu_target_page_bits();
>+    int page_size = qemu_target_page_size();
>+    int page_mask = -page_size;
>+    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, DIRTY_MEMORY_VGA);
>+    hvmmem_type_t mem_type;
>+
>+    if (!memory_region_is_ram(section->mr)) {
>+        return;
>+    }
>+
>+    if (log_dirty != add) {
>+        return;
>+    }
>+
>+    trace_xen_client_set_memory(start_addr, size, log_dirty);
>+
>+    start_addr &= page_mask;
>+    size = ROUND_UP(size, page_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 (xen_set_mem_type(xen_domid, mem_type,
>+                                 start_addr >> target_page_bits,
>+                                 size >> target_page_bits)) {
>+                DPRINTF("xen_set_mem_type error, addr: "HWADDR_FMT_plx"\n",
>+                        start_addr);
>+            }
>+        }
>+    } else {
>+        if (xen_remove_from_physmap(state, start_addr, size) < 0) {
>+            DPRINTF("physmapping does not exist at "HWADDR_FMT_plx"\n", start_addr);
>+        }
>+    }
>+}
>diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
>index 3b9c31c1c8..5657693e1b 100644
>--- a/hw/i386/xen/xen-hvm.c
>+++ b/hw/i386/xen/xen-hvm.c
>@@ -9,16 +9,11 @@
>  */
> 
> #include "qemu/osdep.h"
>-#include "qemu/units.h"
>-#include "qapi/error.h"
>-#include "qapi/qapi-commands-migration.h"
>-#include "trace.h"
> 
> #include "hw/i386/pc.h"
> #include "hw/irq.h"
> #include "hw/i386/apic-msidef.h"
> #include "hw/xen/xen-x86.h"
>-#include "qemu/range.h"
> 
> #include "hw/xen/xen-hvm-common.h"
> #include <xen/hvm/e820.h>
>@@ -26,8 +21,6 @@
> #include "cpu.h"
> 
> static MemoryRegion ram_640k, ram_lo, ram_hi;
>-static MemoryRegion *framebuffer;
>-static bool xen_in_migration;
> 
> /* Compatibility with older version */
> 
>@@ -56,10 +49,6 @@ typedef struct shared_vmport_iopage shared_vmport_iopage_t;
> 
> static shared_vmport_iopage_t *shared_vmport_page;
> 
>-static QLIST_HEAD(, XenPhysmap) xen_physmap;
>-static const XenPhysmap *log_for_dirtybit;
>-/* Buffer used by xen_sync_dirty_bitmap */
>-static unsigned long *dirty_bitmap;
> static Notifier suspend;
> static Notifier wakeup;
> 
>@@ -175,312 +164,6 @@ static void xen_ram_init(PCMachineState *pcms,
>     }
> }
> 
>-static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size,
>-                                   int page_mask)
>-{
>-    XenPhysmap *physmap = NULL;
>-
>-    start_addr &= page_mask;
>-
>-    QLIST_FOREACH(physmap, &xen_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 phys_offset, ram_addr_t size,
>-                                       int page_mask)
>-{
>-    hwaddr addr = phys_offset & page_mask;
>-    XenPhysmap *physmap = NULL;
>-
>-    QLIST_FOREACH(physmap, &xen_physmap, list) {
>-        if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
>-            return physmap->start_addr + (phys_offset - physmap->phys_offset);
>-        }
>-    }
>-
>-    return phys_offset;
>-}
>-
>-#ifdef XEN_COMPAT_PHYSMAP
>-static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
>-{
>-    char path[80], value[17];
>-
>-    snprintf(path, sizeof(path),
>-            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
>-            xen_domid, (uint64_t)physmap->phys_offset);
>-    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->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)physmap->phys_offset);
>-    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->size);
>-    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
>-        return -1;
>-    }
>-    if (physmap->name) {
>-        snprintf(path, sizeof(path),
>-                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
>-                xen_domid, (uint64_t)physmap->phys_offset);
>-        if (!xs_write(state->xenstore, 0, path,
>-                      physmap->name, strlen(physmap->name))) {
>-            return -1;
>-        }
>-    }
>-    return 0;
>-}
>-#else
>-static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
>-{
>-    return 0;
>-}
>-#endif
>-
>-static int xen_add_to_physmap(XenIOState *state,
>-                              hwaddr start_addr,
>-                              ram_addr_t size,
>-                              MemoryRegion *mr,
>-                              hwaddr offset_within_region)
>-{
>-    unsigned target_page_bits = qemu_target_page_bits();
>-    int page_size = qemu_target_page_size();
>-    int page_mask = -page_size;
>-    unsigned long nr_pages;
>-    int rc = 0;
>-    XenPhysmap *physmap = NULL;
>-    hwaddr pfn, start_gpfn;
>-    hwaddr phys_offset = memory_region_get_ram_addr(mr);
>-    const char *mr_name;
>-
>-    if (get_physmapping(start_addr, size, page_mask)) {
>-        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);
>-
>-    mr_name = memory_region_name(mr);
>-
>-    physmap = g_new(XenPhysmap, 1);
>-
>-    physmap->start_addr = start_addr;
>-    physmap->size = size;
>-    physmap->name = mr_name;
>-    physmap->phys_offset = phys_offset;
>-
>-    QLIST_INSERT_HEAD(&xen_physmap, physmap, list);
>-
>-    if (runstate_check(RUN_STATE_INMIGRATE)) {
>-        /* Now when we have a physmap entry we can replace a dummy mapping with
>-         * a real one of guest foreign memory. */
>-        uint8_t *p = xen_replace_cache_entry(phys_offset, start_addr, size);
>-        assert(p && p == memory_region_get_ram_ptr(mr));
>-
>-        return 0;
>-    }
>-
>-    pfn = phys_offset >> target_page_bits;
>-    start_gpfn = start_addr >> target_page_bits;
>-    nr_pages = size >> target_page_bits;
>-    rc = xendevicemodel_relocate_memory(xen_dmod, xen_domid, nr_pages, pfn,
>-                                        start_gpfn);
>-    if (rc) {
>-        int saved_errno = errno;
>-
>-        error_report("relocate_memory %lu pages from GFN %"HWADDR_PRIx
>-                     " to GFN %"HWADDR_PRIx" failed: %s",
>-                     nr_pages, pfn, start_gpfn, strerror(saved_errno));
>-        errno = saved_errno;
>-        return -1;
>-    }
>-
>-    rc = xendevicemodel_pin_memory_cacheattr(xen_dmod, xen_domid,
>-                                   start_addr >> target_page_bits,
>-                                   (start_addr + size - 1) >> target_page_bits,
>-                                   XEN_DOMCTL_MEM_CACHEATTR_WB);
>-    if (rc) {
>-        error_report("pin_memory_cacheattr failed: %s", strerror(errno));
>-    }
>-    return xen_save_physmap(state, physmap);
>-}
>-
>-static int xen_remove_from_physmap(XenIOState *state,
>-                                   hwaddr start_addr,
>-                                   ram_addr_t size)
>-{
>-    unsigned target_page_bits = qemu_target_page_bits();
>-    int page_size = qemu_target_page_size();
>-    int page_mask = -page_size;
>-    int rc = 0;
>-    XenPhysmap *physmap = NULL;
>-    hwaddr phys_offset = 0;
>-
>-    physmap = get_physmapping(start_addr, size, page_mask);
>-    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;
>-    rc = xendevicemodel_relocate_memory(xen_dmod, xen_domid, size, start_addr,
>-                                        phys_offset);
>-    if (rc) {
>-        int saved_errno = errno;
>-
>-        error_report("relocate_memory "RAM_ADDR_FMT" pages"
>-                     " from GFN %"HWADDR_PRIx
>-                     " to GFN %"HWADDR_PRIx" failed: %s",
>-                     size, start_addr, phys_offset, strerror(saved_errno));
>-        errno = saved_errno;
>-        return -1;
>-    }
>-
>-    QLIST_REMOVE(physmap, list);
>-    if (log_for_dirtybit == physmap) {
>-        log_for_dirtybit = NULL;
>-        g_free(dirty_bitmap);
>-        dirty_bitmap = NULL;
>-    }
>-    g_free(physmap);
>-
>-    return 0;
>-}
>-
>-static void xen_sync_dirty_bitmap(XenIOState *state,
>-                                  hwaddr start_addr,
>-                                  ram_addr_t size)
>-{
>-    unsigned target_page_bits = qemu_target_page_bits();
>-    int page_size = qemu_target_page_size();
>-    int page_mask = -page_size;
>-    hwaddr npages = size >> target_page_bits;
>-    const int width = sizeof(unsigned long) * 8;
>-    size_t bitmap_size = DIV_ROUND_UP(npages, width);
>-    int rc, i, j;
>-    const XenPhysmap *physmap = NULL;
>-
>-    physmap = get_physmapping(start_addr, size, page_mask);
>-    if (physmap == NULL) {
>-        /* not handled */
>-        return;
>-    }
>-
>-    if (log_for_dirtybit == NULL) {
>-        log_for_dirtybit = physmap;
>-        dirty_bitmap = g_new(unsigned long, bitmap_size);
>-    } else if (log_for_dirtybit != physmap) {
>-        /* Only one range for dirty bitmap can be tracked. */
>-        return;
>-    }
>-
>-    rc = xen_track_dirty_vram(xen_domid, start_addr >> target_page_bits,
>-                              npages, dirty_bitmap);
>-    if (rc < 0) {
>-#ifndef ENODATA
>-#define ENODATA  ENOENT
>-#endif
>-        if (errno == ENODATA) {
>-            memory_region_set_dirty(framebuffer, 0, size);
>-            DPRINTF("xen: track_dirty_vram failed (0x" HWADDR_FMT_plx
>-                    ", 0x" HWADDR_FMT_plx "): %s\n",
>-                    start_addr, start_addr + size, strerror(errno));
>-        }
>-        return;
>-    }
>-
>-    for (i = 0; i < bitmap_size; i++) {
>-        unsigned long map = dirty_bitmap[i];
>-        while (map != 0) {
>-            j = ctzl(map);
>-            map &= ~(1ul << j);
>-            memory_region_set_dirty(framebuffer,
>-                                    (i * width + j) * page_size, page_size);
>-        };
>-    }
>-}
>-
>-static void xen_log_start(MemoryListener *listener,
>-                          MemoryRegionSection *section,
>-                          int old, int new)
>-{
>-    XenIOState *state = container_of(listener, XenIOState, memory_listener);
>-
>-    if (new & ~old & (1 << DIRTY_MEMORY_VGA)) {
>-        xen_sync_dirty_bitmap(state, section->offset_within_address_space,
>-                              int128_get64(section->size));
>-    }
>-}
>-
>-static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section,
>-                         int old, int new)
>-{
>-    if (old & ~new & (1 << DIRTY_MEMORY_VGA)) {
>-        log_for_dirtybit = NULL;
>-        g_free(dirty_bitmap);
>-        dirty_bitmap = NULL;
>-        /* Disable dirty bit tracking */
>-        xen_track_dirty_vram(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;
>-}
>-
>-const MemoryListener xen_memory_listener = {
>-    .name = "xen-memory",
>-    .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 = MEMORY_LISTENER_PRIORITY_ACCEL,
>-};
>-
> static void regs_to_cpu(vmware_regs_t *vmport_regs, ioreq_t *req)
> {
>     X86CPU *cpu;
>@@ -524,63 +207,6 @@ static void handle_vmport_ioreq(XenIOState *state, ioreq_t *req)
>     current_cpu = NULL;
> }
> 
>-#ifdef XEN_COMPAT_PHYSMAP
>-void xen_read_physmap(XenIOState *state)
>-{
>-    XenPhysmap *physmap = NULL;
>-    unsigned int len, num, i;
>-    char path[80], *value = NULL;
>-    char **entries = NULL;
>-
>-    QLIST_INIT(&xen_physmap);
>-
>-    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_new(XenPhysmap, 1);
>-        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(&xen_physmap, physmap, list);
>-    }
>-    free(entries);
>-}
>-#else
>-void xen_read_physmap(XenIOState *state)
>-{
>-    QLIST_INIT(&xen_physmap);
>-}
>-#endif
>-
> static void xen_wakeup_notifier(Notifier *notifier, void *data)
> {
>     xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
>@@ -635,91 +261,6 @@ err:
>     exit(1);
> }
> 
>-void xen_register_framebuffer(MemoryRegion *mr)
>-{
>-    framebuffer = mr;
>-}
>-
>-void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length)
>-{
>-    unsigned target_page_bits = qemu_target_page_bits();
>-    int page_size = qemu_target_page_size();
>-    int page_mask = -page_size;
>-
>-    if (unlikely(xen_in_migration)) {
>-        int rc;
>-        ram_addr_t start_pfn, nb_pages;
>-
>-        start = xen_phys_offset_to_gaddr(start, length, page_mask);
>-
>-        if (length == 0) {
>-            length = page_size;
>-        }
>-        start_pfn = start >> target_page_bits;
>-        nb_pages = ((start + length + page_size - 1) >> target_page_bits)
>-            - start_pfn;
>-        rc = xen_modified_memory(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, errno, strerror(errno));
>-        }
>-    }
>-}
>-
>-void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
>-{
>-    if (enable) {
>-        memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION);
>-    } else {
>-        memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION);
>-    }
>-}
>-
>-void xen_arch_set_memory(XenIOState *state, MemoryRegionSection *section,
>-                         bool add)
>-{
>-    unsigned target_page_bits = qemu_target_page_bits();
>-    int page_size = qemu_target_page_size();
>-    int page_mask = -page_size;
>-    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, DIRTY_MEMORY_VGA);
>-    hvmmem_type_t mem_type;
>-
>-    if (!memory_region_is_ram(section->mr)) {
>-        return;
>-    }
>-
>-    if (log_dirty != add) {
>-        return;
>-    }
>-
>-    trace_xen_client_set_memory(start_addr, size, log_dirty);
>-
>-    start_addr &= page_mask;
>-    size = ROUND_UP(size, page_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 (xen_set_mem_type(xen_domid, mem_type,
>-                                 start_addr >> target_page_bits,
>-                                 size >> target_page_bits)) {
>-                DPRINTF("xen_set_mem_type error, addr: "HWADDR_FMT_plx"\n",
>-                        start_addr);
>-            }
>-        }
>-    } else {
>-        if (xen_remove_from_physmap(state, start_addr, size) < 0) {
>-            DPRINTF("physmapping does not exist at "HWADDR_FMT_plx"\n", start_addr);
>-        }
>-    }
>-}
>-
> void xen_arch_handle_ioreq(XenIOState *state, ioreq_t *req)
> {
>     switch (req->type) {
>diff --git a/hw/i386/xen/meson.build b/hw/i386/xen/meson.build
>index 3f0df8bc07..d38759cfe4 100644
>--- a/hw/i386/xen/meson.build
>+++ b/hw/i386/xen/meson.build
>@@ -1,6 +1,7 @@
> i386_ss.add(when: 'CONFIG_XEN', if_true: files(
>   'xen_apic.c',
>   'xen_pvdevice.c',
>+  'xen-hvm-common.c',
> ))
> i386_ss.add(when: ['CONFIG_XEN', xen], if_true: files(
>   'xen-hvm.c',
>-- 
>2.41.0
>
>


Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
diff mbox series

Patch

diff --git a/hw/i386/xen/xen-hvm-common.c b/hw/i386/xen/xen-hvm-common.c
new file mode 100644
index 0000000000..e8ef0e0c94
--- /dev/null
+++ b/hw/i386/xen/xen-hvm-common.c
@@ -0,0 +1,473 @@ 
+/*
+ * 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/osdep.h"
+#include "qemu/range.h"
+#include "qapi/qapi-commands-migration.h"
+#include "exec/target_page.h"
+#include "hw/xen/xen-hvm-common.h"
+#include "trace.h"
+
+static MemoryRegion *framebuffer;
+static bool xen_in_migration;
+
+static QLIST_HEAD(, XenPhysmap) xen_physmap;
+static const XenPhysmap *log_for_dirtybit;
+/* Buffer used by xen_sync_dirty_bitmap */
+static unsigned long *dirty_bitmap;
+
+static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size,
+                                   int page_mask)
+{
+    XenPhysmap *physmap = NULL;
+
+    start_addr &= -page_mask;
+
+    QLIST_FOREACH(physmap, &xen_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 phys_offset, ram_addr_t size,
+                                       int page_mask)
+{
+    hwaddr addr = phys_offset & -page_mask;
+    XenPhysmap *physmap = NULL;
+
+    QLIST_FOREACH(physmap, &xen_physmap, list) {
+        if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
+            return physmap->start_addr + (phys_offset - physmap->phys_offset);
+        }
+    }
+
+    return phys_offset;
+}
+
+#ifdef XEN_COMPAT_PHYSMAP
+static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
+{
+    char path[80], value[17];
+
+    snprintf(path, sizeof(path),
+            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
+            xen_domid, (uint64_t)physmap->phys_offset);
+    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->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)physmap->phys_offset);
+    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->size);
+    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
+        return -1;
+    }
+    if (physmap->name) {
+        snprintf(path, sizeof(path),
+                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
+                xen_domid, (uint64_t)physmap->phys_offset);
+        if (!xs_write(state->xenstore, 0, path,
+                      physmap->name, strlen(physmap->name))) {
+            return -1;
+        }
+    }
+    return 0;
+}
+#else
+static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
+{
+    return 0;
+}
+#endif
+
+static int xen_add_to_physmap(XenIOState *state,
+                              hwaddr start_addr,
+                              ram_addr_t size,
+                              MemoryRegion *mr,
+                              hwaddr offset_within_region)
+{
+    unsigned target_page_bits = qemu_target_page_bits();
+    int page_size = qemu_target_page_size();
+    int page_mask = -page_size;
+    unsigned long nr_pages;
+    int rc = 0;
+    XenPhysmap *physmap = NULL;
+    hwaddr pfn, start_gpfn;
+    hwaddr phys_offset = memory_region_get_ram_addr(mr);
+    const char *mr_name;
+
+    if (get_physmapping(start_addr, size, page_mask)) {
+        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);
+
+    mr_name = memory_region_name(mr);
+
+    physmap = g_new(XenPhysmap, 1);
+
+    physmap->start_addr = start_addr;
+    physmap->size = size;
+    physmap->name = mr_name;
+    physmap->phys_offset = phys_offset;
+
+    QLIST_INSERT_HEAD(&xen_physmap, physmap, list);
+
+    if (runstate_check(RUN_STATE_INMIGRATE)) {
+        /* Now when we have a physmap entry we can replace a dummy mapping with
+         * a real one of guest foreign memory. */
+        uint8_t *p = xen_replace_cache_entry(phys_offset, start_addr, size);
+        assert(p && p == memory_region_get_ram_ptr(mr));
+
+        return 0;
+    }
+
+    pfn = phys_offset >> target_page_bits;
+    start_gpfn = start_addr >> target_page_bits;
+    nr_pages = size >> target_page_bits;
+    rc = xendevicemodel_relocate_memory(xen_dmod, xen_domid, nr_pages, pfn,
+                                        start_gpfn);
+    if (rc) {
+        int saved_errno = errno;
+
+        error_report("relocate_memory %lu pages from GFN %"HWADDR_PRIx
+                     " to GFN %"HWADDR_PRIx" failed: %s",
+                     nr_pages, pfn, start_gpfn, strerror(saved_errno));
+        errno = saved_errno;
+        return -1;
+    }
+
+    rc = xendevicemodel_pin_memory_cacheattr(xen_dmod, xen_domid,
+                                   start_addr >> target_page_bits,
+                                   (start_addr + size - 1) >> target_page_bits,
+                                   XEN_DOMCTL_MEM_CACHEATTR_WB);
+    if (rc) {
+        error_report("pin_memory_cacheattr failed: %s", strerror(errno));
+    }
+    return xen_save_physmap(state, physmap);
+}
+
+static int xen_remove_from_physmap(XenIOState *state,
+                                   hwaddr start_addr,
+                                   ram_addr_t size)
+{
+    unsigned target_page_bits = qemu_target_page_bits();
+    int page_size = qemu_target_page_size();
+    int page_mask = -page_size;
+    int rc = 0;
+    XenPhysmap *physmap = NULL;
+    hwaddr phys_offset = 0;
+
+    physmap = get_physmapping(start_addr, size, page_mask);
+    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;
+    rc = xendevicemodel_relocate_memory(xen_dmod, xen_domid, size, start_addr,
+                                        phys_offset);
+    if (rc) {
+        int saved_errno = errno;
+
+        error_report("relocate_memory "RAM_ADDR_FMT" pages"
+                     " from GFN %"HWADDR_PRIx
+                     " to GFN %"HWADDR_PRIx" failed: %s",
+                     size, start_addr, phys_offset, strerror(saved_errno));
+        errno = saved_errno;
+        return -1;
+    }
+
+    QLIST_REMOVE(physmap, list);
+    if (log_for_dirtybit == physmap) {
+        log_for_dirtybit = NULL;
+        g_free(dirty_bitmap);
+        dirty_bitmap = NULL;
+    }
+    g_free(physmap);
+
+    return 0;
+}
+
+static void xen_sync_dirty_bitmap(XenIOState *state,
+                                  hwaddr start_addr,
+                                  ram_addr_t size)
+{
+    unsigned target_page_bits = qemu_target_page_bits();
+    int page_size = qemu_target_page_size();
+    int page_mask = -page_size;
+    hwaddr npages = size >> target_page_bits;
+    const int width = sizeof(unsigned long) * 8;
+    size_t bitmap_size = DIV_ROUND_UP(npages, width);
+    int rc, i, j;
+    const XenPhysmap *physmap = NULL;
+
+    physmap = get_physmapping(start_addr, size, page_mask);
+    if (physmap == NULL) {
+        /* not handled */
+        return;
+    }
+
+    if (log_for_dirtybit == NULL) {
+        log_for_dirtybit = physmap;
+        dirty_bitmap = g_new(unsigned long, bitmap_size);
+    } else if (log_for_dirtybit != physmap) {
+        /* Only one range for dirty bitmap can be tracked. */
+        return;
+    }
+
+    rc = xen_track_dirty_vram(xen_domid, start_addr >> target_page_bits,
+                              npages, dirty_bitmap);
+    if (rc < 0) {
+#ifndef ENODATA
+#define ENODATA  ENOENT
+#endif
+        if (errno == ENODATA) {
+            memory_region_set_dirty(framebuffer, 0, size);
+            DPRINTF("xen: track_dirty_vram failed (0x" HWADDR_FMT_plx
+                    ", 0x" HWADDR_FMT_plx "): %s\n",
+                    start_addr, start_addr + size, strerror(errno));
+        }
+        return;
+    }
+
+    for (i = 0; i < bitmap_size; i++) {
+        unsigned long map = dirty_bitmap[i];
+        while (map != 0) {
+            j = ctzl(map);
+            map &= ~(1ul << j);
+            memory_region_set_dirty(framebuffer,
+                                    (i * width + j) * page_size,
+                                    page_size);
+        };
+    }
+}
+
+static void xen_log_start(MemoryListener *listener,
+                          MemoryRegionSection *section,
+                          int old, int new)
+{
+    XenIOState *state = container_of(listener, XenIOState, memory_listener);
+
+    if (new & ~old & (1 << DIRTY_MEMORY_VGA)) {
+        xen_sync_dirty_bitmap(state, section->offset_within_address_space,
+                              int128_get64(section->size));
+    }
+}
+
+static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section,
+                         int old, int new)
+{
+    if (old & ~new & (1 << DIRTY_MEMORY_VGA)) {
+        log_for_dirtybit = NULL;
+        g_free(dirty_bitmap);
+        dirty_bitmap = NULL;
+        /* Disable dirty bit tracking */
+        xen_track_dirty_vram(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;
+}
+
+const MemoryListener xen_memory_listener = {
+    .name = "xen-memory",
+    .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 = MEMORY_LISTENER_PRIORITY_ACCEL,
+};
+
+#ifdef XEN_COMPAT_PHYSMAP
+void xen_read_physmap(XenIOState *state)
+{
+    XenPhysmap *physmap = NULL;
+    unsigned int len, num, i;
+    char path[80], *value = NULL;
+    char **entries = NULL;
+
+    QLIST_INIT(&xen_physmap);
+
+    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_new(XenPhysmap, 1);
+        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(&xen_physmap, physmap, list);
+    }
+    free(entries);
+}
+#else
+void xen_read_physmap(XenIOState *state)
+{
+    QLIST_INIT(&xen_physmap);
+}
+#endif
+
+void xen_register_framebuffer(MemoryRegion *mr)
+{
+    framebuffer = mr;
+}
+
+void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length)
+{
+    unsigned target_page_bits = qemu_target_page_bits();
+    int page_size = qemu_target_page_size();
+    int page_mask = -page_size;
+
+    if (unlikely(xen_in_migration)) {
+        int rc;
+        ram_addr_t start_pfn, nb_pages;
+
+        start = xen_phys_offset_to_gaddr(start, length, page_mask);
+
+        if (length == 0) {
+            length = page_size;
+        }
+        start_pfn = start >> target_page_bits;
+        nb_pages = ((start + length + page_size - 1) >> target_page_bits)
+            - start_pfn;
+        rc = xen_modified_memory(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, errno, strerror(errno));
+        }
+    }
+}
+
+void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
+{
+    if (enable) {
+        memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION);
+    } else {
+        memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION);
+    }
+}
+
+void xen_arch_set_memory(XenIOState *state, MemoryRegionSection *section,
+                         bool add)
+{
+    unsigned target_page_bits = qemu_target_page_bits();
+    int page_size = qemu_target_page_size();
+    int page_mask = -page_size;
+    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, DIRTY_MEMORY_VGA);
+    hvmmem_type_t mem_type;
+
+    if (!memory_region_is_ram(section->mr)) {
+        return;
+    }
+
+    if (log_dirty != add) {
+        return;
+    }
+
+    trace_xen_client_set_memory(start_addr, size, log_dirty);
+
+    start_addr &= page_mask;
+    size = ROUND_UP(size, page_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 (xen_set_mem_type(xen_domid, mem_type,
+                                 start_addr >> target_page_bits,
+                                 size >> target_page_bits)) {
+                DPRINTF("xen_set_mem_type error, addr: "HWADDR_FMT_plx"\n",
+                        start_addr);
+            }
+        }
+    } else {
+        if (xen_remove_from_physmap(state, start_addr, size) < 0) {
+            DPRINTF("physmapping does not exist at "HWADDR_FMT_plx"\n", start_addr);
+        }
+    }
+}
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 3b9c31c1c8..5657693e1b 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -9,16 +9,11 @@ 
  */
 
 #include "qemu/osdep.h"
-#include "qemu/units.h"
-#include "qapi/error.h"
-#include "qapi/qapi-commands-migration.h"
-#include "trace.h"
 
 #include "hw/i386/pc.h"
 #include "hw/irq.h"
 #include "hw/i386/apic-msidef.h"
 #include "hw/xen/xen-x86.h"
-#include "qemu/range.h"
 
 #include "hw/xen/xen-hvm-common.h"
 #include <xen/hvm/e820.h>
@@ -26,8 +21,6 @@ 
 #include "cpu.h"
 
 static MemoryRegion ram_640k, ram_lo, ram_hi;
-static MemoryRegion *framebuffer;
-static bool xen_in_migration;
 
 /* Compatibility with older version */
 
@@ -56,10 +49,6 @@  typedef struct shared_vmport_iopage shared_vmport_iopage_t;
 
 static shared_vmport_iopage_t *shared_vmport_page;
 
-static QLIST_HEAD(, XenPhysmap) xen_physmap;
-static const XenPhysmap *log_for_dirtybit;
-/* Buffer used by xen_sync_dirty_bitmap */
-static unsigned long *dirty_bitmap;
 static Notifier suspend;
 static Notifier wakeup;
 
@@ -175,312 +164,6 @@  static void xen_ram_init(PCMachineState *pcms,
     }
 }
 
-static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size,
-                                   int page_mask)
-{
-    XenPhysmap *physmap = NULL;
-
-    start_addr &= page_mask;
-
-    QLIST_FOREACH(physmap, &xen_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 phys_offset, ram_addr_t size,
-                                       int page_mask)
-{
-    hwaddr addr = phys_offset & page_mask;
-    XenPhysmap *physmap = NULL;
-
-    QLIST_FOREACH(physmap, &xen_physmap, list) {
-        if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
-            return physmap->start_addr + (phys_offset - physmap->phys_offset);
-        }
-    }
-
-    return phys_offset;
-}
-
-#ifdef XEN_COMPAT_PHYSMAP
-static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
-{
-    char path[80], value[17];
-
-    snprintf(path, sizeof(path),
-            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
-            xen_domid, (uint64_t)physmap->phys_offset);
-    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->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)physmap->phys_offset);
-    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)physmap->size);
-    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
-        return -1;
-    }
-    if (physmap->name) {
-        snprintf(path, sizeof(path),
-                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
-                xen_domid, (uint64_t)physmap->phys_offset);
-        if (!xs_write(state->xenstore, 0, path,
-                      physmap->name, strlen(physmap->name))) {
-            return -1;
-        }
-    }
-    return 0;
-}
-#else
-static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
-{
-    return 0;
-}
-#endif
-
-static int xen_add_to_physmap(XenIOState *state,
-                              hwaddr start_addr,
-                              ram_addr_t size,
-                              MemoryRegion *mr,
-                              hwaddr offset_within_region)
-{
-    unsigned target_page_bits = qemu_target_page_bits();
-    int page_size = qemu_target_page_size();
-    int page_mask = -page_size;
-    unsigned long nr_pages;
-    int rc = 0;
-    XenPhysmap *physmap = NULL;
-    hwaddr pfn, start_gpfn;
-    hwaddr phys_offset = memory_region_get_ram_addr(mr);
-    const char *mr_name;
-
-    if (get_physmapping(start_addr, size, page_mask)) {
-        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);
-
-    mr_name = memory_region_name(mr);
-
-    physmap = g_new(XenPhysmap, 1);
-
-    physmap->start_addr = start_addr;
-    physmap->size = size;
-    physmap->name = mr_name;
-    physmap->phys_offset = phys_offset;
-
-    QLIST_INSERT_HEAD(&xen_physmap, physmap, list);
-
-    if (runstate_check(RUN_STATE_INMIGRATE)) {
-        /* Now when we have a physmap entry we can replace a dummy mapping with
-         * a real one of guest foreign memory. */
-        uint8_t *p = xen_replace_cache_entry(phys_offset, start_addr, size);
-        assert(p && p == memory_region_get_ram_ptr(mr));
-
-        return 0;
-    }
-
-    pfn = phys_offset >> target_page_bits;
-    start_gpfn = start_addr >> target_page_bits;
-    nr_pages = size >> target_page_bits;
-    rc = xendevicemodel_relocate_memory(xen_dmod, xen_domid, nr_pages, pfn,
-                                        start_gpfn);
-    if (rc) {
-        int saved_errno = errno;
-
-        error_report("relocate_memory %lu pages from GFN %"HWADDR_PRIx
-                     " to GFN %"HWADDR_PRIx" failed: %s",
-                     nr_pages, pfn, start_gpfn, strerror(saved_errno));
-        errno = saved_errno;
-        return -1;
-    }
-
-    rc = xendevicemodel_pin_memory_cacheattr(xen_dmod, xen_domid,
-                                   start_addr >> target_page_bits,
-                                   (start_addr + size - 1) >> target_page_bits,
-                                   XEN_DOMCTL_MEM_CACHEATTR_WB);
-    if (rc) {
-        error_report("pin_memory_cacheattr failed: %s", strerror(errno));
-    }
-    return xen_save_physmap(state, physmap);
-}
-
-static int xen_remove_from_physmap(XenIOState *state,
-                                   hwaddr start_addr,
-                                   ram_addr_t size)
-{
-    unsigned target_page_bits = qemu_target_page_bits();
-    int page_size = qemu_target_page_size();
-    int page_mask = -page_size;
-    int rc = 0;
-    XenPhysmap *physmap = NULL;
-    hwaddr phys_offset = 0;
-
-    physmap = get_physmapping(start_addr, size, page_mask);
-    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;
-    rc = xendevicemodel_relocate_memory(xen_dmod, xen_domid, size, start_addr,
-                                        phys_offset);
-    if (rc) {
-        int saved_errno = errno;
-
-        error_report("relocate_memory "RAM_ADDR_FMT" pages"
-                     " from GFN %"HWADDR_PRIx
-                     " to GFN %"HWADDR_PRIx" failed: %s",
-                     size, start_addr, phys_offset, strerror(saved_errno));
-        errno = saved_errno;
-        return -1;
-    }
-
-    QLIST_REMOVE(physmap, list);
-    if (log_for_dirtybit == physmap) {
-        log_for_dirtybit = NULL;
-        g_free(dirty_bitmap);
-        dirty_bitmap = NULL;
-    }
-    g_free(physmap);
-
-    return 0;
-}
-
-static void xen_sync_dirty_bitmap(XenIOState *state,
-                                  hwaddr start_addr,
-                                  ram_addr_t size)
-{
-    unsigned target_page_bits = qemu_target_page_bits();
-    int page_size = qemu_target_page_size();
-    int page_mask = -page_size;
-    hwaddr npages = size >> target_page_bits;
-    const int width = sizeof(unsigned long) * 8;
-    size_t bitmap_size = DIV_ROUND_UP(npages, width);
-    int rc, i, j;
-    const XenPhysmap *physmap = NULL;
-
-    physmap = get_physmapping(start_addr, size, page_mask);
-    if (physmap == NULL) {
-        /* not handled */
-        return;
-    }
-
-    if (log_for_dirtybit == NULL) {
-        log_for_dirtybit = physmap;
-        dirty_bitmap = g_new(unsigned long, bitmap_size);
-    } else if (log_for_dirtybit != physmap) {
-        /* Only one range for dirty bitmap can be tracked. */
-        return;
-    }
-
-    rc = xen_track_dirty_vram(xen_domid, start_addr >> target_page_bits,
-                              npages, dirty_bitmap);
-    if (rc < 0) {
-#ifndef ENODATA
-#define ENODATA  ENOENT
-#endif
-        if (errno == ENODATA) {
-            memory_region_set_dirty(framebuffer, 0, size);
-            DPRINTF("xen: track_dirty_vram failed (0x" HWADDR_FMT_plx
-                    ", 0x" HWADDR_FMT_plx "): %s\n",
-                    start_addr, start_addr + size, strerror(errno));
-        }
-        return;
-    }
-
-    for (i = 0; i < bitmap_size; i++) {
-        unsigned long map = dirty_bitmap[i];
-        while (map != 0) {
-            j = ctzl(map);
-            map &= ~(1ul << j);
-            memory_region_set_dirty(framebuffer,
-                                    (i * width + j) * page_size, page_size);
-        };
-    }
-}
-
-static void xen_log_start(MemoryListener *listener,
-                          MemoryRegionSection *section,
-                          int old, int new)
-{
-    XenIOState *state = container_of(listener, XenIOState, memory_listener);
-
-    if (new & ~old & (1 << DIRTY_MEMORY_VGA)) {
-        xen_sync_dirty_bitmap(state, section->offset_within_address_space,
-                              int128_get64(section->size));
-    }
-}
-
-static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section,
-                         int old, int new)
-{
-    if (old & ~new & (1 << DIRTY_MEMORY_VGA)) {
-        log_for_dirtybit = NULL;
-        g_free(dirty_bitmap);
-        dirty_bitmap = NULL;
-        /* Disable dirty bit tracking */
-        xen_track_dirty_vram(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;
-}
-
-const MemoryListener xen_memory_listener = {
-    .name = "xen-memory",
-    .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 = MEMORY_LISTENER_PRIORITY_ACCEL,
-};
-
 static void regs_to_cpu(vmware_regs_t *vmport_regs, ioreq_t *req)
 {
     X86CPU *cpu;
@@ -524,63 +207,6 @@  static void handle_vmport_ioreq(XenIOState *state, ioreq_t *req)
     current_cpu = NULL;
 }
 
-#ifdef XEN_COMPAT_PHYSMAP
-void xen_read_physmap(XenIOState *state)
-{
-    XenPhysmap *physmap = NULL;
-    unsigned int len, num, i;
-    char path[80], *value = NULL;
-    char **entries = NULL;
-
-    QLIST_INIT(&xen_physmap);
-
-    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_new(XenPhysmap, 1);
-        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(&xen_physmap, physmap, list);
-    }
-    free(entries);
-}
-#else
-void xen_read_physmap(XenIOState *state)
-{
-    QLIST_INIT(&xen_physmap);
-}
-#endif
-
 static void xen_wakeup_notifier(Notifier *notifier, void *data)
 {
     xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
@@ -635,91 +261,6 @@  err:
     exit(1);
 }
 
-void xen_register_framebuffer(MemoryRegion *mr)
-{
-    framebuffer = mr;
-}
-
-void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length)
-{
-    unsigned target_page_bits = qemu_target_page_bits();
-    int page_size = qemu_target_page_size();
-    int page_mask = -page_size;
-
-    if (unlikely(xen_in_migration)) {
-        int rc;
-        ram_addr_t start_pfn, nb_pages;
-
-        start = xen_phys_offset_to_gaddr(start, length, page_mask);
-
-        if (length == 0) {
-            length = page_size;
-        }
-        start_pfn = start >> target_page_bits;
-        nb_pages = ((start + length + page_size - 1) >> target_page_bits)
-            - start_pfn;
-        rc = xen_modified_memory(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, errno, strerror(errno));
-        }
-    }
-}
-
-void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
-{
-    if (enable) {
-        memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION);
-    } else {
-        memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION);
-    }
-}
-
-void xen_arch_set_memory(XenIOState *state, MemoryRegionSection *section,
-                         bool add)
-{
-    unsigned target_page_bits = qemu_target_page_bits();
-    int page_size = qemu_target_page_size();
-    int page_mask = -page_size;
-    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, DIRTY_MEMORY_VGA);
-    hvmmem_type_t mem_type;
-
-    if (!memory_region_is_ram(section->mr)) {
-        return;
-    }
-
-    if (log_dirty != add) {
-        return;
-    }
-
-    trace_xen_client_set_memory(start_addr, size, log_dirty);
-
-    start_addr &= page_mask;
-    size = ROUND_UP(size, page_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 (xen_set_mem_type(xen_domid, mem_type,
-                                 start_addr >> target_page_bits,
-                                 size >> target_page_bits)) {
-                DPRINTF("xen_set_mem_type error, addr: "HWADDR_FMT_plx"\n",
-                        start_addr);
-            }
-        }
-    } else {
-        if (xen_remove_from_physmap(state, start_addr, size) < 0) {
-            DPRINTF("physmapping does not exist at "HWADDR_FMT_plx"\n", start_addr);
-        }
-    }
-}
-
 void xen_arch_handle_ioreq(XenIOState *state, ioreq_t *req)
 {
     switch (req->type) {
diff --git a/hw/i386/xen/meson.build b/hw/i386/xen/meson.build
index 3f0df8bc07..d38759cfe4 100644
--- a/hw/i386/xen/meson.build
+++ b/hw/i386/xen/meson.build
@@ -1,6 +1,7 @@ 
 i386_ss.add(when: 'CONFIG_XEN', if_true: files(
   'xen_apic.c',
   'xen_pvdevice.c',
+  'xen-hvm-common.c',
 ))
 i386_ss.add(when: ['CONFIG_XEN', xen], if_true: files(
   'xen-hvm.c',