mirror of https://github.com/proxmox/mirror_qemu
xen/hvm: correct reporting of modified memory under physmap during migration
When global_log_dirty is enabled VRAM modification tracking never worked correctly. The address that is passed to xen_hvm_modified_memory() is not the effective PFN but RAM block address which is not the same for VRAM. We need to make a translation for this address into PFN using physmap. Since there is no way to access physmap properly inside xen_hvm_modified_memory() let's make it a global structure. Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com> Acked-by: Anthony PERARD <anthony.perard@citrix.com> Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>master
parent
c181ddaa17
commit
04a8f72e87
|
@ -86,6 +86,8 @@ typedef struct XenPhysmap {
|
||||||
QLIST_ENTRY(XenPhysmap) list;
|
QLIST_ENTRY(XenPhysmap) list;
|
||||||
} XenPhysmap;
|
} XenPhysmap;
|
||||||
|
|
||||||
|
static QLIST_HEAD(, XenPhysmap) xen_physmap;
|
||||||
|
|
||||||
typedef struct XenIOState {
|
typedef struct XenIOState {
|
||||||
ioservid_t ioservid;
|
ioservid_t ioservid;
|
||||||
shared_iopage_t *shared_page;
|
shared_iopage_t *shared_page;
|
||||||
|
@ -107,7 +109,6 @@ typedef struct XenIOState {
|
||||||
MemoryListener memory_listener;
|
MemoryListener memory_listener;
|
||||||
MemoryListener io_listener;
|
MemoryListener io_listener;
|
||||||
DeviceListener device_listener;
|
DeviceListener device_listener;
|
||||||
QLIST_HEAD(, XenPhysmap) physmap;
|
|
||||||
hwaddr free_phys_offset;
|
hwaddr free_phys_offset;
|
||||||
const XenPhysmap *log_for_dirtybit;
|
const XenPhysmap *log_for_dirtybit;
|
||||||
|
|
||||||
|
@ -274,14 +275,13 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
|
||||||
g_free(pfn_list);
|
g_free(pfn_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static XenPhysmap *get_physmapping(XenIOState *state,
|
static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size)
|
||||||
hwaddr start_addr, ram_addr_t size)
|
|
||||||
{
|
{
|
||||||
XenPhysmap *physmap = NULL;
|
XenPhysmap *physmap = NULL;
|
||||||
|
|
||||||
start_addr &= TARGET_PAGE_MASK;
|
start_addr &= TARGET_PAGE_MASK;
|
||||||
|
|
||||||
QLIST_FOREACH(physmap, &state->physmap, list) {
|
QLIST_FOREACH(physmap, &xen_physmap, list) {
|
||||||
if (range_covers_byte(physmap->start_addr, physmap->size, start_addr)) {
|
if (range_covers_byte(physmap->start_addr, physmap->size, start_addr)) {
|
||||||
return physmap;
|
return physmap;
|
||||||
}
|
}
|
||||||
|
@ -289,23 +289,21 @@ static XenPhysmap *get_physmapping(XenIOState *state,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XEN_COMPAT_PHYSMAP
|
static hwaddr xen_phys_offset_to_gaddr(hwaddr phys_offset, ram_addr_t size)
|
||||||
static hwaddr xen_phys_offset_to_gaddr(hwaddr start_addr,
|
|
||||||
ram_addr_t size, void *opaque)
|
|
||||||
{
|
{
|
||||||
hwaddr addr = start_addr & TARGET_PAGE_MASK;
|
hwaddr addr = phys_offset & TARGET_PAGE_MASK;
|
||||||
XenIOState *xen_io_state = opaque;
|
|
||||||
XenPhysmap *physmap = NULL;
|
XenPhysmap *physmap = NULL;
|
||||||
|
|
||||||
QLIST_FOREACH(physmap, &xen_io_state->physmap, list) {
|
QLIST_FOREACH(physmap, &xen_physmap, list) {
|
||||||
if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
|
if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
|
||||||
return physmap->start_addr;
|
return physmap->start_addr + (phys_offset - physmap->phys_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return start_addr;
|
return phys_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XEN_COMPAT_PHYSMAP
|
||||||
static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
|
static int xen_save_physmap(XenIOState *state, XenPhysmap *physmap)
|
||||||
{
|
{
|
||||||
char path[80], value[17];
|
char path[80], value[17];
|
||||||
|
@ -355,7 +353,7 @@ static int xen_add_to_physmap(XenIOState *state,
|
||||||
hwaddr phys_offset = memory_region_get_ram_addr(mr);
|
hwaddr phys_offset = memory_region_get_ram_addr(mr);
|
||||||
const char *mr_name;
|
const char *mr_name;
|
||||||
|
|
||||||
if (get_physmapping(state, start_addr, size)) {
|
if (get_physmapping(start_addr, size)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (size <= 0) {
|
if (size <= 0) {
|
||||||
|
@ -384,7 +382,7 @@ go_physmap:
|
||||||
physmap->name = mr_name;
|
physmap->name = mr_name;
|
||||||
physmap->phys_offset = phys_offset;
|
physmap->phys_offset = phys_offset;
|
||||||
|
|
||||||
QLIST_INSERT_HEAD(&state->physmap, physmap, list);
|
QLIST_INSERT_HEAD(&xen_physmap, physmap, list);
|
||||||
|
|
||||||
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
||||||
/* Now when we have a physmap entry we can replace a dummy mapping with
|
/* Now when we have a physmap entry we can replace a dummy mapping with
|
||||||
|
@ -428,7 +426,7 @@ static int xen_remove_from_physmap(XenIOState *state,
|
||||||
XenPhysmap *physmap = NULL;
|
XenPhysmap *physmap = NULL;
|
||||||
hwaddr phys_offset = 0;
|
hwaddr phys_offset = 0;
|
||||||
|
|
||||||
physmap = get_physmapping(state, start_addr, size);
|
physmap = get_physmapping(start_addr, size);
|
||||||
if (physmap == NULL) {
|
if (physmap == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -597,7 +595,7 @@ static void xen_sync_dirty_bitmap(XenIOState *state,
|
||||||
int rc, i, j;
|
int rc, i, j;
|
||||||
const XenPhysmap *physmap = NULL;
|
const XenPhysmap *physmap = NULL;
|
||||||
|
|
||||||
physmap = get_physmapping(state, start_addr, size);
|
physmap = get_physmapping(start_addr, size);
|
||||||
if (physmap == NULL) {
|
if (physmap == NULL) {
|
||||||
/* not handled */
|
/* not handled */
|
||||||
return;
|
return;
|
||||||
|
@ -1222,7 +1220,7 @@ static void xen_read_physmap(XenIOState *state)
|
||||||
xen_domid, entries[i]);
|
xen_domid, entries[i]);
|
||||||
physmap->name = xs_read(state->xenstore, 0, path, &len);
|
physmap->name = xs_read(state->xenstore, 0, path, &len);
|
||||||
|
|
||||||
QLIST_INSERT_HEAD(&state->physmap, physmap, list);
|
QLIST_INSERT_HEAD(&xen_physmap, physmap, list);
|
||||||
}
|
}
|
||||||
free(entries);
|
free(entries);
|
||||||
}
|
}
|
||||||
|
@ -1374,7 +1372,6 @@ void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory)
|
||||||
qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
|
qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
|
||||||
|
|
||||||
state->memory_listener = xen_memory_listener;
|
state->memory_listener = xen_memory_listener;
|
||||||
QLIST_INIT(&state->physmap);
|
|
||||||
memory_listener_register(&state->memory_listener, &address_space_memory);
|
memory_listener_register(&state->memory_listener, &address_space_memory);
|
||||||
state->log_for_dirtybit = NULL;
|
state->log_for_dirtybit = NULL;
|
||||||
|
|
||||||
|
@ -1390,6 +1387,8 @@ void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
xen_be_register_common();
|
xen_be_register_common();
|
||||||
|
|
||||||
|
QLIST_INIT(&xen_physmap);
|
||||||
xen_read_physmap(state);
|
xen_read_physmap(state);
|
||||||
|
|
||||||
/* Disable ACPI build because Xen handles it */
|
/* Disable ACPI build because Xen handles it */
|
||||||
|
@ -1461,6 +1460,8 @@ void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length)
|
||||||
int rc;
|
int rc;
|
||||||
ram_addr_t start_pfn, nb_pages;
|
ram_addr_t start_pfn, nb_pages;
|
||||||
|
|
||||||
|
start = xen_phys_offset_to_gaddr(start, length);
|
||||||
|
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
length = TARGET_PAGE_SIZE;
|
length = TARGET_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,7 +319,7 @@ tryagain:
|
||||||
mapcache->last_entry = NULL;
|
mapcache->last_entry = NULL;
|
||||||
#ifdef XEN_COMPAT_PHYSMAP
|
#ifdef XEN_COMPAT_PHYSMAP
|
||||||
if (!translated && mapcache->phys_offset_to_gaddr) {
|
if (!translated && mapcache->phys_offset_to_gaddr) {
|
||||||
phys_addr = mapcache->phys_offset_to_gaddr(phys_addr, size, mapcache->opaque);
|
phys_addr = mapcache->phys_offset_to_gaddr(phys_addr, size);
|
||||||
translated = true;
|
translated = true;
|
||||||
goto tryagain;
|
goto tryagain;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,8 @@
|
||||||
#ifndef XEN_MAPCACHE_H
|
#ifndef XEN_MAPCACHE_H
|
||||||
#define XEN_MAPCACHE_H
|
#define XEN_MAPCACHE_H
|
||||||
|
|
||||||
typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr start_addr,
|
typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset,
|
||||||
ram_addr_t size,
|
ram_addr_t size);
|
||||||
void *opaque);
|
|
||||||
#ifdef CONFIG_XEN
|
#ifdef CONFIG_XEN
|
||||||
|
|
||||||
void xen_map_cache_init(phys_offset_to_gaddr_t f,
|
void xen_map_cache_init(phys_offset_to_gaddr_t f,
|
||||||
|
|
Loading…
Reference in New Issue