Alex Bligh
2013-Jan-19 17:56 UTC
QEMU: Enabling live-migrate on HVM on qemu-xen device model in 4.2
This patch series consists of 2 parts: * 5 patches to QEMU * 11 patches to libxl These patches enable live-migrate on HVM using the upstream qemu-xen device model under Xen 4.2. Currently this is unimplemented. In the main they are backports of patches in xen-unstable, thought the QEMU side in particular needed some fiddling. The patches are the same as previously submitted under the same subject line as a ''request for comment'', save that: 1. An additional obviously-correct patch has been added as the 11th patch to libxl, where a parameter was always being passed as NULL. 2. They are now tested in our environment. With that test case, live migrate works as well as it did under 4.1 with the previous qemu device model. I do not claim all use cases are tested. I would suggest these patches should be included in 4.2.2.
Alex Bligh
2013-Jan-19 17:56 UTC
[PATCH 1/5] QMP, Introduce xen-set-global-dirty-log command.
This command is used during a migration of a guest under Xen. It calls cpu_physical_memory_set_dirty_tracking. Backport of 39f42439d0629d3921629dc4b38e68df8f2f7b83 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- qapi-schema.json | 13 +++++++++++++ qmp-commands.hx | 24 ++++++++++++++++++++++++ xen-all.c | 6 ++++++ xen-stub.c | 5 +++++ 4 files changed, 48 insertions(+), 0 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index a669e98..bb0d7c5 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -905,3 +905,16 @@ # Since: 1.1 ## { ''command'': ''xen-save-devices-state'', ''data'': {''filename'': ''str''} } + +## +# @xen-set-global-dirty-log +# +# Enable or disable the global dirty log mode. +# +# @enable: true to enable, false to disable. +# +# Returns: nothing +# +# Since: 1.3 +## +{ ''command'': ''xen-set-global-dirty-log'', ''data'': { ''enable'': ''bool'' } } diff --git a/qmp-commands.hx b/qmp-commands.hx index bf1df49..0de68df 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -472,6 +472,30 @@ Example: EQMP { + .name = "xen-set-global-dirty-log", + .args_type = "enable:b", + .mhandler.cmd_new = qmp_marshal_input_xen_set_global_dirty_log, + }, + +SQMP +xen-set-global-dirty-log +------- + +Enable or disable the global dirty log mode. + +Arguments: + +- "enable": Enable it or disable it. + +Example: + +-> { "execute": "xen-set-global-dirty-log", + "arguments": { "enable": true } } +<- { "return": {} } + +EQMP + + { .name = "migrate", .args_type = "detach:-d,blk:-b,inc:-i,uri:s", .params = "[-d] [-b] [-i] uri", diff --git a/xen-all.c b/xen-all.c index 3256509..6b4e511 100644 --- a/xen-all.c +++ b/xen-all.c @@ -12,6 +12,7 @@ #include "hw/pc.h" #include "hw/xen_common.h" #include "hw/xen_backend.h" +#include "qmp-commands.h" #include "range.h" #include "xen-mapcache.h" @@ -524,6 +525,11 @@ static CPUPhysMemoryClient xen_cpu_phys_memory_client = { .log_stop = xen_log_stop, }; +void qmp_xen_set_global_dirty_log(bool enable, Error **errp) +{ + cpu_physical_memory_set_dirty_tracking(!!enable); +} + /* VCPU Operations, MMIO, IO ring ... */ static void xen_reset_vcpu(void *opaque) diff --git a/xen-stub.c b/xen-stub.c index efe2ab5..25317ec 100644 --- a/xen-stub.c +++ b/xen-stub.c @@ -8,6 +8,7 @@ #include "qemu-common.h" #include "hw/xen.h" +#include "qmp-commands.h" void xenstore_store_pv_console_info(int i, CharDriverState *chr) { @@ -43,3 +44,7 @@ int xen_init(void) { return -ENOSYS; } + +void qmp_xen_set_global_dirty_log(bool enable, Error **errp) +{ +} -- 1.7.4.1
This function is to be used during live migration. Every write access to the guest memory should call this funcion so the Xen tools knows which pages are dirty. Backport of 910b38e4dc4c37683c8b821e75a7f4cf095e4b21 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- hw/xen.h | 1 + xen-all.c | 21 +++++++++++++++++++++ xen-stub.c | 4 ++++ 3 files changed, 26 insertions(+), 0 deletions(-) diff --git a/hw/xen.h b/hw/xen.h index 2162111..359a275 100644 --- a/hw/xen.h +++ b/hw/xen.h @@ -45,6 +45,7 @@ void xenstore_store_pv_console_info(int i, struct CharDriverState *chr); #if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY) void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size); +void xen_modified_memory(ram_addr_t start, ram_addr_t length); #endif #if defined(CONFIG_XEN) && CONFIG_XEN_CTRL_INTERFACE_VERSION < 400 diff --git a/xen-all.c b/xen-all.c index 6b4e511..121289d 100644 --- a/xen-all.c +++ b/xen-all.c @@ -1135,3 +1135,24 @@ void destroy_hvm_domain(bool reboot) xc_interface_close(xc_handle); } } + +void xen_modified_memory(ram_addr_t start, ram_addr_t length) +{ + if (unlikely(cpu_physical_memory_get_dirty_tracking())) { + 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-stub.c b/xen-stub.c index 25317ec..7b54477 100644 --- a/xen-stub.c +++ b/xen-stub.c @@ -48,3 +48,7 @@ int xen_init(void) void qmp_xen_set_global_dirty_log(bool enable, Error **errp) { } + +void xen_modified_memory(ram_addr_t start, ram_addr_t length) +{ +} -- 1.7.4.1
This new helper/hook is used in the next patch to add an extra call in a single place. Backport of 51d7a9eb2b64e787c90bea1027308087eac22065 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- exec.c | 45 +++++++++++++++++---------------------------- 1 files changed, 17 insertions(+), 28 deletions(-) diff --git a/exec.c b/exec.c index 6c206ff..511777b 100644 --- a/exec.c +++ b/exec.c @@ -3951,6 +3951,18 @@ int cpu_memory_rw_debug(CPUState *env, target_ulong addr, } #else + +static void invalidate_and_set_dirty(target_phys_addr_t addr, + target_phys_addr_t length) +{ + if (!cpu_physical_memory_is_dirty(addr)) { + /* invalidate code */ + tb_invalidate_phys_page_range(addr, addr + length, 0); + /* set dirty bit */ + cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG)); + } +} + void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write) { @@ -4003,13 +4015,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, /* RAM case */ ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + l, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags( - addr1, (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, l); qemu_put_ram_ptr(ptr); } } else { @@ -4081,6 +4087,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, /* ROM/RAM case */ ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); + invalidate_and_set_dirty(addr1, l); qemu_put_ram_ptr(ptr); } len -= l; @@ -4211,13 +4218,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, l = TARGET_PAGE_SIZE; if (l > access_len) l = access_len; - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + l, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags( - addr1, (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, l); addr1 += l; access_len -= l; } @@ -4561,13 +4562,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, stl_p(ptr, val); break; } - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + 4, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags(addr1, - (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, 4); } } @@ -4639,13 +4634,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, stw_p(ptr, val); break; } - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + 2, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags(addr1, - (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, 2); } } -- 1.7.4.1
This patch add some calls to xen_modified_memory to notify Xen about dirtybits during migration. Backport of e226939de5814527a21396903b08c3d0ed989558 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- exec.c | 4 ++++ memory.c | 4 ++++ 2 files changed, 8 insertions(+), 0 deletions(-) diff --git a/exec.c b/exec.c index 511777b..401f9bc 100644 --- a/exec.c +++ b/exec.c @@ -2988,6 +2988,9 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS), 0xff, size >> TARGET_PAGE_BITS); + if (xen_enabled()) + xen_modified_memory(new_block->offset, size); + if (kvm_enabled()) kvm_setup_guest_memory(new_block->host, size); @@ -3961,6 +3964,7 @@ static void invalidate_and_set_dirty(target_phys_addr_t addr, /* set dirty bit */ cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG)); } + xen_modified_memory(addr, length); } void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, diff --git a/memory.c b/memory.c index 7c20a07..6e0c596 100644 --- a/memory.c +++ b/memory.c @@ -16,6 +16,7 @@ #include "ioport.h" #include "bitops.h" #include "kvm.h" +#include "hw/xen.h" #include <assert.h> unsigned memory_region_transaction_depth = 0; @@ -1065,6 +1066,9 @@ bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr, void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr) { assert(mr->terminates); + if (xen_enabled()) + xen_modified_memory((mr->ram_addr + addr) & TARGET_PAGE_MASK, + TARGET_PAGE_SIZE); return cpu_physical_memory_set_dirty(mr->ram_addr + addr); } -- 1.7.4.1
If the call to xc_hvm_track_dirty_vram() fails, then we set dirtybit on all the video ram. This case happens during migration. Backport of 8aba7dc02d5660df7e7d8651304b3079908358be Signed-off-by: Alex Bligh <alex@alex.org.uk> --- xen-all.c | 20 ++++++++++++++++++-- 1 files changed, 18 insertions(+), 2 deletions(-) diff --git a/xen-all.c b/xen-all.c index 121289d..dbd759c 100644 --- a/xen-all.c +++ b/xen-all.c @@ -470,7 +470,21 @@ static int xen_sync_dirty_bitmap(XenIOState *state, rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid, start_addr >> TARGET_PAGE_BITS, npages, bitmap); - if (rc) { + if (rc < 0) { + if (rc != -ENODATA) { + ram_addr_t addr, end; + + xen_modified_memory(start_addr, size); + + end = TARGET_PAGE_ALIGN(start_addr + size); + for (addr = start_addr & TARGET_PAGE_MASK; addr < end; addr += TARGET_PAGE_SIZE) { + cpu_physical_memory_set_dirty(addr); + } + + DPRINTF("xen: track_dirty_vram failed (0x" TARGET_FMT_plx + ", 0x" TARGET_FMT_plx "): %s\n", + start_addr, start_addr + size, strerror(-rc)); + } return rc; } @@ -479,7 +493,9 @@ static int xen_sync_dirty_bitmap(XenIOState *state, while (map != 0) { j = ffsl(map) - 1; map &= ~(1ul << j); - cpu_physical_memory_set_dirty(vram_offset + (i * width + j) * TARGET_PAGE_SIZE); + target_phys_addr_t todirty = vram_offset + (i * width + j) * TARGET_PAGE_SIZE; + xen_modified_memory(todirty, TARGET_PAGE_SIZE); + cpu_physical_memory_set_dirty(todirty); }; } -- 1.7.4.1
Alex Bligh
2013-Jan-19 17:57 UTC
QEMU: Enabling live-migrate on HVM on qemu-xen device model in 4.2
This patch series consists of 2 parts: * 5 patches to QEMU * 11 patches to libxl These patches enable live-migrate on HVM using the upstream qemu-xen device model under Xen 4.2. Currently this is unimplemented. In the main they are backports of patches in xen-unstable, thought the QEMU side in particular needed some fiddling. The patches are the same as previously submitted under the same subject line as a ''request for comment'', save that: 1. An additional obviously-correct patch has been added as the 11th patch to libxl, where a parameter was always being passed as NULL. 2. They are now tested in our environment. With that test case, live migrate works as well as it did under 4.1 with the previous qemu device model. I do not claim all use cases are tested. I would suggest these patches should be included in 4.2.2.
Alex Bligh
2013-Jan-19 17:57 UTC
[PATCH 01/11] libxl_json: Export json_object related function.
Export libxl__json_object_alloc and libxl__json_object_append_to to use them in a later patch. Backported from xen-unstable patch: : User Anthony PERARD <anthony.perard@citrix.com> : Date 1349693129 -3600 : Node ID c9b80c7f8db1a5d26906a2298c481bf7e87fda94 : Parent 93e3e6a33e0a1ec9f92fc575334caa35e6dbc757 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl_internal.h | 14 ++++++++++++-- tools/libxl/libxl_json.c | 32 ++++++++++++++++---------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index a135cd7..2959527 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1512,6 +1512,15 @@ static inline long long libxl__json_object_get_integer(const libxl__json_object return -1; } +/* + * NOGC can be used with those json_object functions, but the + * libxl__json_object* will need to be freed with libxl__json_object_free. + */ +_hidden libxl__json_object *libxl__json_object_alloc(libxl__gc *gc_opt, + libxl__json_node_type type); +_hidden int libxl__json_object_append_to(libxl__gc *gc_opt, + libxl__json_object *obj, + libxl__json_object *dst); _hidden libxl__json_object *libxl__json_array_get(const libxl__json_object *o, int i); _hidden @@ -1520,9 +1529,10 @@ libxl__json_map_node *libxl__json_map_node_get(const libxl__json_object *o, _hidden const libxl__json_object *libxl__json_map_get(const char *key, const libxl__json_object *o, libxl__json_node_type expected_type); -_hidden void libxl__json_object_free(libxl__gc *gc, libxl__json_object *obj); +_hidden void libxl__json_object_free(libxl__gc *gc_opt, + libxl__json_object *obj); -_hidden libxl__json_object *libxl__json_parse(libxl__gc *gc, const char *s); +_hidden libxl__json_object *libxl__json_parse(libxl__gc *gc_opt, const char *s); /* Based on /local/domain/$domid/dm-version xenstore key * default is qemu xen traditional */ diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c index caa8312..0b0cf2f 100644 --- a/tools/libxl/libxl_json.c +++ b/tools/libxl/libxl_json.c @@ -205,7 +205,7 @@ yajl_gen_status libxl__string_gen_json(yajl_gen hand, * libxl__json_object helper functions */ -static libxl__json_object *json_object_alloc(libxl__gc *gc, +libxl__json_object *libxl__json_object_alloc(libxl__gc *gc, libxl__json_node_type type) { libxl__json_object *obj; @@ -236,7 +236,7 @@ static libxl__json_object *json_object_alloc(libxl__gc *gc, return obj; } -static int json_object_append_to(libxl__gc *gc, +int libxl__json_object_append_to(libxl__gc *gc, libxl__json_object *obj, libxl__json_object *dst) { @@ -393,10 +393,10 @@ static int json_callback_null(void *opaque) DEBUG_GEN(ctx, null); - if ((obj = json_object_alloc(ctx->gc, JSON_NULL)) == NULL) + if ((obj = libxl__json_object_alloc(ctx->gc, JSON_NULL)) == NULL) return 0; - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { libxl__json_object_free(ctx->gc, obj); return 0; } @@ -411,11 +411,11 @@ static int json_callback_boolean(void *opaque, int boolean) DEBUG_GEN_VALUE(ctx, bool, boolean); - if ((obj = json_object_alloc(ctx->gc, + if ((obj = libxl__json_object_alloc(ctx->gc, boolean ? JSON_TRUE : JSON_FALSE)) == NULL) return 0; - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { libxl__json_object_free(ctx->gc, obj); return 0; } @@ -448,7 +448,7 @@ static int json_callback_number(void *opaque, const char *s, libxl_yajl_length l goto error; } - if ((obj = json_object_alloc(ctx->gc, JSON_DOUBLE)) == NULL) + if ((obj = libxl__json_object_alloc(ctx->gc, JSON_DOUBLE)) == NULL) return 0; obj->u.d = d; } else { @@ -458,7 +458,7 @@ static int json_callback_number(void *opaque, const char *s, libxl_yajl_length l goto error; } - if ((obj = json_object_alloc(ctx->gc, JSON_INTEGER)) == NULL) + if ((obj = libxl__json_object_alloc(ctx->gc, JSON_INTEGER)) == NULL) return 0; obj->u.i = i; } @@ -466,7 +466,7 @@ static int json_callback_number(void *opaque, const char *s, libxl_yajl_length l error: /* If the conversion fail, we just store the original string. */ - if ((obj = json_object_alloc(ctx->gc, JSON_NUMBER)) == NULL) + if ((obj = libxl__json_object_alloc(ctx->gc, JSON_NUMBER)) == NULL) return 0; t = malloc(len + 1); @@ -481,7 +481,7 @@ error: obj->u.string = t; out: - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { libxl__json_object_free(ctx->gc, obj); return 0; } @@ -508,13 +508,13 @@ static int json_callback_string(void *opaque, const unsigned char *str, strncpy(t, (const char *) str, len); t[len] = 0; - if ((obj = json_object_alloc(ctx->gc, JSON_STRING)) == NULL) { + if ((obj = libxl__json_object_alloc(ctx->gc, JSON_STRING)) == NULL) { free(t); return 0; } obj->u.string = t; - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { libxl__json_object_free(ctx->gc, obj); return 0; } @@ -573,11 +573,11 @@ static int json_callback_start_map(void *opaque) DEBUG_GEN(ctx, map_open); - if ((obj = json_object_alloc(ctx->gc, JSON_MAP)) == NULL) + if ((obj = libxl__json_object_alloc(ctx->gc, JSON_MAP)) == NULL) return 0; if (ctx->current) { - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { libxl__json_object_free(ctx->gc, obj); return 0; } @@ -615,11 +615,11 @@ static int json_callback_start_array(void *opaque) DEBUG_GEN(ctx, array_open); - if ((obj = json_object_alloc(ctx->gc, JSON_ARRAY)) == NULL) + if ((obj = libxl__json_object_alloc(ctx->gc, JSON_ARRAY)) == NULL) return 0; if (ctx->current) { - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { libxl__json_object_free(ctx->gc, obj); return 0; } -- 1.7.4.1
This value from libxl__json_node_type is never used. Backported from xen-unstable patch: : HG changeset patch : User Anthony PERARD <anthony.perard@citrix.com> : Date 1349693130 -3600 : Node ID 4a6d5d8cba4fc44f9bbda201188885868604b8e8 : Parent c9b80c7f8db1a5d26906a2298c481bf7e87fda94 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl_internal.h | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 2959527..5b285d4 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1428,7 +1428,6 @@ _hidden yajl_gen_status libxl__yajl_gen_asciiz(yajl_gen hand, const char *str); _hidden yajl_gen_status libxl__yajl_gen_enum(yajl_gen hand, const char *str); typedef enum { - JSON_ERROR, JSON_NULL, JSON_TRUE, JSON_FALSE, -- 1.7.4.1
Alex Bligh
2013-Jan-19 17:58 UTC
[PATCH 03/11] libxl_json: Replace JSON_TRUE/FALSE by JSON_BOOL.
Those two JSON_TRUE and JSON_FALSE were types of node. But it''s better to have a unique JSON_BOOL type. Backported from xen-unstable patch: : HG changeset patch : User Anthony PERARD <anthony.perard@citrix.com> : Date 1349693131 -3600 : Node ID 3f71aab0e2774ded0c5a03436c364fb031ba9aa0 : Parent 4a6d5d8cba4fc44f9bbda201188885868604b8e8 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl_internal.h | 15 +++++++++++++-- tools/libxl/libxl_json.c | 3 +-- tools/libxl/libxl_qmp.c | 3 ++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 5b285d4..7dbd8af 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1429,8 +1429,7 @@ _hidden yajl_gen_status libxl__yajl_gen_enum(yajl_gen hand, const char *str); typedef enum { JSON_NULL, - JSON_TRUE, - JSON_FALSE, + JSON_BOOL, JSON_INTEGER, JSON_DOUBLE, /* number is store in string, it''s too big to be a long long or a double */ @@ -1444,6 +1443,7 @@ typedef enum { typedef struct libxl__json_object { libxl__json_node_type type; union { + bool b; long long i; double d; char *string; @@ -1462,6 +1462,10 @@ typedef struct { typedef struct libxl__yajl_ctx libxl__yajl_ctx; +static inline bool libxl__json_object_is_bool(const libxl__json_object *o) +{ + return o != NULL && o->type == JSON_BOOL; +} static inline bool libxl__json_object_is_string(const libxl__json_object *o) { return o != NULL && o->type == JSON_STRING; @@ -1479,6 +1483,13 @@ static inline bool libxl__json_object_is_array(const libxl__json_object *o) return o != NULL && o->type == JSON_ARRAY; } +static inline bool libxl__json_object_get_bool(const libxl__json_object *o) +{ + if (libxl__json_object_is_bool(o)) + return o->u.b; + else + return false; +} static inline const char *libxl__json_object_get_string(const libxl__json_object *o) { diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c index 0b0cf2f..98db465 100644 --- a/tools/libxl/libxl_json.c +++ b/tools/libxl/libxl_json.c @@ -411,8 +411,7 @@ static int json_callback_boolean(void *opaque, int boolean) DEBUG_GEN_VALUE(ctx, bool, boolean); - if ((obj = libxl__json_object_alloc(ctx->gc, - boolean ? JSON_TRUE : JSON_FALSE)) == NULL) + if ((obj = libxl__json_object_alloc(ctx->gc, JSON_BOOL)) == NULL) return 0; if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index e33b130..9e86c35 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -178,7 +178,8 @@ static int qmp_register_vnc_callback(libxl__qmp_handler *qmp, goto out; } - if (libxl__json_map_get("enabled", o, JSON_FALSE)) { + obj = libxl__json_map_get("enabled", o, JSON_BOOL); + if (!obj || !libxl__json_object_get_bool(obj)) { rc = 0; goto out; } -- 1.7.4.1
Alex Bligh
2013-Jan-19 17:58 UTC
[PATCH 04/11] libxl_json: Introduce libxl__json_object_to_yajl_gen.
This function converts a libxl__json_object to yajl by calling every yajl_gen_* function on a preallocated yajl_gen hand. This helps to integrate a json_object into an already existing yajl_gen tree. This function is used in a later patch. Backported from xen-unstable patch: : HG changeset patch : User Anthony PERARD <anthony.perard@citrix.com> : Date 1349693132 -3600 : Node ID 74dee58cfc0d2d6594f388db3b4d2ce91d1bb204 : Parent 3f71aab0e2774ded0c5a03436c364fb031ba9aa0 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl_internal.h | 3 ++ tools/libxl/libxl_json.c | 61 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 0 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 7dbd8af..b00ff61 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1539,6 +1539,9 @@ libxl__json_map_node *libxl__json_map_node_get(const libxl__json_object *o, _hidden const libxl__json_object *libxl__json_map_get(const char *key, const libxl__json_object *o, libxl__json_node_type expected_type); +_hidden yajl_status libxl__json_object_to_yajl_gen(libxl__gc *gc_opt, + yajl_gen hand, + libxl__json_object *param); _hidden void libxl__json_object_free(libxl__gc *gc_opt, libxl__json_object *obj); diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c index 98db465..72b52e8 100644 --- a/tools/libxl/libxl_json.c +++ b/tools/libxl/libxl_json.c @@ -381,6 +381,67 @@ const libxl__json_object *libxl__json_map_get(const char *key, return NULL; } +yajl_status libxl__json_object_to_yajl_gen(libxl__gc *gc, + yajl_gen hand, + libxl__json_object *obj) +{ + int idx = 0; + yajl_status rc; + + switch (obj->type) { + case JSON_NULL: + return yajl_gen_null(hand); + case JSON_BOOL: + return yajl_gen_bool(hand, obj->u.b); + case JSON_INTEGER: + return yajl_gen_integer(hand, obj->u.i); + case JSON_DOUBLE: + return yajl_gen_double(hand, obj->u.d); + case JSON_NUMBER: + return yajl_gen_number(hand, obj->u.string, strlen(obj->u.string)); + case JSON_STRING: + return libxl__yajl_gen_asciiz(hand, obj->u.string); + case JSON_MAP: { + libxl__json_map_node *node = NULL; + + rc = yajl_gen_map_open(hand); + if (rc != yajl_status_ok) + return rc; + for (idx = 0; idx < obj->u.map->count; idx++) { + if (flexarray_get(obj->u.map, idx, (void**)&node) != 0) + break; + + rc = libxl__yajl_gen_asciiz(hand, node->map_key); + if (rc != yajl_status_ok) + return rc; + rc = libxl__json_object_to_yajl_gen(gc, hand, node->obj); + if (rc != yajl_status_ok) + return rc; + } + return yajl_gen_map_close(hand); + } + case JSON_ARRAY: { + libxl__json_object *node = NULL; + + rc = yajl_gen_array_open(hand); + if (rc != yajl_status_ok) + return rc; + for (idx = 0; idx < obj->u.array->count; idx++) { + if (flexarray_get(obj->u.array, idx, (void**)&node) != 0) + break; + rc = libxl__json_object_to_yajl_gen(gc, hand, node); + if (rc != yajl_status_ok) + return rc; + } + return yajl_gen_array_close(hand); + } + case JSON_ANY: + /* JSON_ANY is not a valid value for obj->type. */ + ; + } + abort(); +} + /* * JSON callbacks -- 1.7.4.1
Alex Bligh
2013-Jan-19 17:58 UTC
[PATCH 05/11] libxl_qmp: Introduces helpers to create an argument list.
Those functions will be used to create a "list" of parameters that contain more than just strings. This list is converted by qmp_send to a string to be sent to QEMU. Those functions will be used in the next two patches, so right now there are not compiled. Backported from xen-unstable patch: : HG changeset patch : User Anthony PERARD <anthony.perard@citrix.com> : Date 1349693132 -3600 : Node ID 6f7847729f0f42614de516d15257ede7243f995f : Parent 74dee58cfc0d2d6594f388db3b4d2ce91d1bb204 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl_qmp.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index 9e86c35..827f1b7 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -624,6 +624,57 @@ static void qmp_free_handler(libxl__qmp_handler *qmp) free(qmp); } +#if 0 +/* + * QMP Parameters Helpers + */ +static void qmp_parameters_common_add(libxl__gc *gc, + libxl__json_object **param, + const char *name, + libxl__json_object *obj) +{ + libxl__json_map_node *arg = NULL; + + if (!*param) { + *param = libxl__json_object_alloc(gc, JSON_MAP); + } + + arg = libxl__zalloc(gc, sizeof(*arg)); + + arg->map_key = libxl__strdup(gc, name); + arg->obj = obj; + + flexarray_append((*param)->u.map, arg); +} + +static void qmp_parameters_add_string(libxl__gc *gc, + libxl__json_object **param, + const char *name, const char *argument) +{ + libxl__json_object *obj; + + obj = libxl__json_object_alloc(gc, JSON_STRING); + obj->u.string = libxl__strdup(gc, argument); + + qmp_parameters_common_add(gc, param, name, obj); +} + +static void qmp_parameters_add_bool(libxl__gc *gc, + libxl__json_object **param, + const char *name, bool b) +{ + libxl__json_object *obj; + + obj = libxl__json_object_alloc(gc, JSON_BOOL); + obj->u.b = b; + qmp_parameters_common_add(gc, param, name, obj); +} + +#define QMP_PARAMETERS_SPRINTF(args, name, format, ...) \ + qmp_parameters_add_string(gc, args, name, \ + libxl__sprintf(gc, format, __VA_ARGS__)) +#endif + /* * API */ -- 1.7.4.1
Alex Bligh
2013-Jan-19 17:58 UTC
[PATCH 06/11] libxl_qmp: Use qmp_parameters_* functions for param list of a QMP command.
Backported from xen-unstable patch: : HG changeset patch : User Anthony PERARD <anthony.perard@citrix.com> : Date 1349693133 -3600 : Node ID be5d014f91dfbd67afacc3385c265243794a246f : Parent 6f7847729f0f42614de516d15257ede7243f995f Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl_qmp.c | 89 ++++++++++++++++------------------------------- 1 files changed, 30 insertions(+), 59 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index 827f1b7..605e8f3 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -78,7 +78,7 @@ struct libxl__qmp_handler { }; static int qmp_send(libxl__qmp_handler *qmp, - const char *cmd, libxl_key_value_list *args, + const char *cmd, libxl__json_object *args, qmp_callback_t callback, void *opaque, qmp_request_context *context); @@ -503,7 +503,7 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp) } static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp, - const char *cmd, libxl_key_value_list *args, + const char *cmd, libxl__json_object *args, qmp_callback_t callback, void *opaque, qmp_request_context *context) { @@ -527,7 +527,7 @@ static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp, yajl_gen_integer(hand, ++qmp->last_id_used); if (args) { libxl__yajl_gen_asciiz(hand, "arguments"); - libxl_key_value_list_gen_json(hand, args); + libxl__json_object_to_yajl_gen(gc, hand, args); } yajl_gen_map_close(hand); @@ -561,7 +561,7 @@ out: } static int qmp_send(libxl__qmp_handler *qmp, - const char *cmd, libxl_key_value_list *args, + const char *cmd, libxl__json_object *args, qmp_callback_t callback, void *opaque, qmp_request_context *context) { @@ -589,7 +589,7 @@ out: } static int qmp_synchronous_send(libxl__qmp_handler *qmp, const char *cmd, - libxl_key_value_list *args, + libxl__json_object *args, qmp_callback_t callback, void *opaque, int ask_timeout) { @@ -624,7 +624,6 @@ static void qmp_free_handler(libxl__qmp_handler *qmp) free(qmp); } -#if 0 /* * QMP Parameters Helpers */ @@ -659,6 +658,7 @@ static void qmp_parameters_add_string(libxl__gc *gc, qmp_parameters_common_add(gc, param, name, obj); } +#if 0 static void qmp_parameters_add_bool(libxl__gc *gc, libxl__json_object **param, const char *name, bool b) @@ -669,11 +669,11 @@ static void qmp_parameters_add_bool(libxl__gc *gc, obj->u.b = b; qmp_parameters_common_add(gc, param, name, obj); } +#endif #define QMP_PARAMETERS_SPRINTF(args, name, format, ...) \ qmp_parameters_add_string(gc, args, name, \ libxl__sprintf(gc, format, __VA_ARGS__)) -#endif /* * API @@ -801,8 +801,7 @@ out: int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) { libxl__qmp_handler *qmp = NULL; - flexarray_t *parameters = NULL; - libxl_key_value_list args = NULL; + libxl__json_object *args = NULL; char *hostaddr = NULL; int rc = 0; @@ -815,31 +814,22 @@ int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) if (!hostaddr) return -1; - parameters = flexarray_make(6, 1); - flexarray_append_pair(parameters, "driver", "xen-pci-passthrough"); - flexarray_append_pair(parameters, "id", - libxl__sprintf(gc, PCI_PT_QDEV_ID, - pcidev->bus, pcidev->dev, - pcidev->func)); - flexarray_append_pair(parameters, "hostaddr", hostaddr); + qmp_parameters_add_string(gc, &args, "driver", "xen-pci-passthrough"); + QMP_PARAMETERS_SPRINTF(&args, "id", PCI_PT_QDEV_ID, + pcidev->bus, pcidev->dev, pcidev->func); + qmp_parameters_add_string(gc, &args, "hostaddr", hostaddr); if (pcidev->vdevfn) { - flexarray_append_pair(parameters, "addr", - libxl__sprintf(gc, "%x.%x", - PCI_SLOT(pcidev->vdevfn), - PCI_FUNC(pcidev->vdevfn))); + QMP_PARAMETERS_SPRINTF(&args, "addr", "%x.%x", + PCI_SLOT(pcidev->vdevfn), PCI_FUNC(pcidev->vdevfn)); } - args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count); - if (!args) - return -1; - rc = qmp_synchronous_send(qmp, "device_add", &args, + rc = qmp_synchronous_send(qmp, "device_add", args, NULL, NULL, qmp->timeout); if (rc == 0) { rc = qmp_synchronous_send(qmp, "query-pci", NULL, pci_add_callback, pcidev, qmp->timeout); } - flexarray_free(parameters); libxl__qmp_close(qmp); return rc; } @@ -847,24 +837,18 @@ int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) static int qmp_device_del(libxl__gc *gc, int domid, char *id) { libxl__qmp_handler *qmp = NULL; - flexarray_t *parameters = NULL; - libxl_key_value_list args = NULL; + libxl__json_object *args = NULL; int rc = 0; qmp = libxl__qmp_initialize(gc, domid); if (!qmp) return ERROR_FAIL; - parameters = flexarray_make(2, 1); - flexarray_append_pair(parameters, "id", id); - args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count); - if (!args) - return ERROR_NOMEM; + qmp_parameters_add_string(gc, &args, "id", id); - rc = qmp_synchronous_send(qmp, "device_del", &args, + rc = qmp_synchronous_send(qmp, "device_del", args, NULL, NULL, qmp->timeout); - flexarray_free(parameters); libxl__qmp_close(qmp); return rc; } @@ -882,56 +866,43 @@ int libxl__qmp_pci_del(libxl__gc *gc, int domid, libxl_device_pci *pcidev) int libxl__qmp_save(libxl__gc *gc, int domid, const char *filename) { libxl__qmp_handler *qmp = NULL; - flexarray_t *parameters = NULL; - libxl_key_value_list args = NULL; + libxl__json_object *args = NULL; int rc = 0; qmp = libxl__qmp_initialize(gc, domid); if (!qmp) return ERROR_FAIL; - parameters = flexarray_make(2, 1); - if (!parameters) { - rc = ERROR_NOMEM; - goto out; - } - flexarray_append_pair(parameters, "filename", (char *)filename); - args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count); + qmp_parameters_add_string(gc, &args, "filename", (char *)filename); if (!args) { rc = ERROR_NOMEM; - goto out2; + goto out; } - rc = qmp_synchronous_send(qmp, "xen-save-devices-state", &args, + rc = qmp_synchronous_send(qmp, "xen-save-devices-state", args, NULL, NULL, qmp->timeout); -out2: - flexarray_free(parameters); out: libxl__qmp_close(qmp); return rc; + } static int qmp_change(libxl__gc *gc, libxl__qmp_handler *qmp, char *device, char *target, char *arg) { - flexarray_t *parameters = NULL; - libxl_key_value_list args = NULL; + libxl__json_object *args = NULL; int rc = 0; - parameters = flexarray_make(6, 1); - flexarray_append_pair(parameters, "device", device); - flexarray_append_pair(parameters, "target", target); - if (arg) - flexarray_append_pair(parameters, "arg", arg); - args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count); - if (!args) - return ERROR_NOMEM; + qmp_parameters_add_string(gc, &args, "device", device); + qmp_parameters_add_string(gc, &args, "target", target); + if (arg) { + qmp_parameters_add_string(gc, &args, "arg", arg); + } - rc = qmp_synchronous_send(qmp, "change", &args, + rc = qmp_synchronous_send(qmp, "change", args, NULL, NULL, qmp->timeout); - flexarray_free(parameters); return rc; } -- 1.7.4.1
Alex Bligh
2013-Jan-19 17:58 UTC
[PATCH 07/11] libxl_qmp: Simplify run of single QMP commands.
This new function connects to QEMU, sends the command and disconnects. Backport of xen-unstable patch: : HG changeset patch : User Anthony PERARD <anthony.perard@citrix.com> : Date 1349693134 -3600 : Node ID f3890916496445c97d6778d6c986b0270ff707f2 : Parent be5d014f91dfbd67afacc3385c265243794a246f Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl_qmp.c | 77 +++++++++++++--------------------------------- 1 files changed, 22 insertions(+), 55 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index 605e8f3..b09bf13 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -798,6 +798,23 @@ out: return rc; } +static int qmp_run_command(libxl__gc *gc, int domid, + const char *cmd, libxl__json_object *args, + qmp_callback_t callback, void *opaque) +{ + libxl__qmp_handler *qmp = NULL; + int rc = 0; + + qmp = libxl__qmp_initialize(gc, domid); + if (!qmp) + return ERROR_FAIL; + + rc = qmp_synchronous_send(qmp, cmd, args, callback, opaque, qmp->timeout); + + libxl__qmp_close(qmp); + return rc; +} + int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) { libxl__qmp_handler *qmp = NULL; @@ -836,21 +853,10 @@ int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) static int qmp_device_del(libxl__gc *gc, int domid, char *id) { - libxl__qmp_handler *qmp = NULL; libxl__json_object *args = NULL; - int rc = 0; - - qmp = libxl__qmp_initialize(gc, domid); - if (!qmp) - return ERROR_FAIL; qmp_parameters_add_string(gc, &args, "id", id); - - rc = qmp_synchronous_send(qmp, "device_del", args, - NULL, NULL, qmp->timeout); - - libxl__qmp_close(qmp); - return rc; + return qmp_run_command(gc, domid, "device_del", args, NULL, NULL); } int libxl__qmp_pci_del(libxl__gc *gc, int domid, libxl_device_pci *pcidev) @@ -865,27 +871,10 @@ int libxl__qmp_pci_del(libxl__gc *gc, int domid, libxl_device_pci *pcidev) int libxl__qmp_save(libxl__gc *gc, int domid, const char *filename) { - libxl__qmp_handler *qmp = NULL; libxl__json_object *args = NULL; - int rc = 0; - - qmp = libxl__qmp_initialize(gc, domid); - if (!qmp) - return ERROR_FAIL; - - qmp_parameters_add_string(gc, &args, "filename", (char *)filename); - if (!args) { - rc = ERROR_NOMEM; - goto out; - } - - rc = qmp_synchronous_send(qmp, "xen-save-devices-state", args, - NULL, NULL, qmp->timeout); - -out: - libxl__qmp_close(qmp); - return rc; + return qmp_run_command(gc, domid, "xen-save-devices-state", args, + NULL, NULL); } static int qmp_change(libxl__gc *gc, libxl__qmp_handler *qmp, @@ -908,34 +897,12 @@ static int qmp_change(libxl__gc *gc, libxl__qmp_handler *qmp, int libxl__qmp_stop(libxl__gc *gc, int domid) { - libxl__qmp_handler *qmp = NULL; - int rc = 0; - - qmp = libxl__qmp_initialize(gc, domid); - if (!qmp) - return ERROR_FAIL; - - rc = qmp_synchronous_send(qmp, "stop", NULL, - NULL, NULL, qmp->timeout); - - libxl__qmp_close(qmp); - return rc; + return qmp_run_command(gc, domid, "stop", NULL, NULL, NULL); } int libxl__qmp_resume(libxl__gc *gc, int domid) { - libxl__qmp_handler *qmp = NULL; - int rc = 0; - - qmp = libxl__qmp_initialize(gc, domid); - if (!qmp) - return ERROR_FAIL; - - rc = qmp_synchronous_send(qmp, "cont", NULL, - NULL, NULL, qmp->timeout); - - libxl__qmp_close(qmp); - return rc; + return qmp_run_command(gc, domid, "cont", NULL, NULL, NULL); } int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid, -- 1.7.4.1
Alex Bligh
2013-Jan-19 17:58 UTC
[PATCH 08/11] libxl_qmp: Introduce libxl__qmp_set_global_dirty_log.
This function will enable or disable the global dirty log on QEMU, used during a migration. Backport of xen-unstable patch: : HG changeset patch : User Anthony PERARD <anthony.perard@citrix.com> : Date 1349693135 -3600 : Node ID d4aec9eff7e6d15c2805957af620c82555553b3e : Parent f3890916496445c97d6778d6c986b0270ff707f2 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl_internal.h | 2 ++ tools/libxl/libxl_qmp.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index b00ff61..f658562 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1400,6 +1400,8 @@ _hidden int libxl__qmp_stop(libxl__gc *gc, int domid); _hidden int libxl__qmp_resume(libxl__gc *gc, int domid); /* Save current QEMU state into fd. */ _hidden int libxl__qmp_save(libxl__gc *gc, int domid, const char *filename); +/* Set dirty bitmap logging status */ +_hidden int libxl__qmp_set_global_dirty_log(libxl__gc *gc, int domid, bool enable); /* close and free the QMP handler */ _hidden void libxl__qmp_close(libxl__qmp_handler *qmp); /* remove the socket file, if the file has already been removed, diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index b09bf13..ac10f20 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -658,7 +658,6 @@ static void qmp_parameters_add_string(libxl__gc *gc, qmp_parameters_common_add(gc, param, name, obj); } -#if 0 static void qmp_parameters_add_bool(libxl__gc *gc, libxl__json_object **param, const char *name, bool b) @@ -669,7 +668,6 @@ static void qmp_parameters_add_bool(libxl__gc *gc, obj->u.b = b; qmp_parameters_common_add(gc, param, name, obj); } -#endif #define QMP_PARAMETERS_SPRINTF(args, name, format, ...) \ qmp_parameters_add_string(gc, args, name, \ @@ -905,6 +903,16 @@ int libxl__qmp_resume(libxl__gc *gc, int domid) return qmp_run_command(gc, domid, "cont", NULL, NULL, NULL); } +int libxl__qmp_set_global_dirty_log(libxl__gc *gc, int domid, bool enable) +{ + libxl__json_object *args = NULL; + + qmp_parameters_add_bool(gc, &args, "enable", enable); + + return qmp_run_command(gc, domid, "xen-set-global-dirty-log", args, + NULL, NULL); +} + int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid, const libxl_domain_config *guest_config) { -- 1.7.4.1
Alex Bligh
2013-Jan-19 17:58 UTC
[PATCH 09/11] libxl_dom: Call the right switch logdirty for the right DM.
This patch dispatch the switch logdirty call depending on which device model version is running. The call to qemu-xen right now is synchronous, not like the one to qemu-xen-traditional. Backport of xen-unstable patch: : HG changeset patch : User Anthony PERARD <anthony.perard@citrix.com> : Date 1349693136 -3600 : Node ID 08fac5c2bf3dcbc493ce45091383f6ce1938f369 : Parent d4aec9eff7e6d15c2805957af620c82555553b3e Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl_dom.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 42 insertions(+), 3 deletions(-) diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index e1de832..95da18e 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -685,10 +685,10 @@ static void logdirty_init(libxl__logdirty_switch *lds) libxl__ev_time_init(&lds->timeout); } -void libxl__domain_suspend_common_switch_qemu_logdirty - (int domid, unsigned enable, void *user) +static void domain_suspend_switch_qemu_xen_traditional_logdirty + (int domid, unsigned enable, + libxl__save_helper_state *shs) { - libxl__save_helper_state *shs = user; libxl__egc *egc = shs->egc; libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs); libxl__logdirty_switch *lds = &dss->logdirty; @@ -756,6 +756,45 @@ void libxl__domain_suspend_common_switch_qemu_logdirty switch_logdirty_done(egc,dss,-1); } +static void domain_suspend_switch_qemu_xen_logdirty + (int domid, unsigned enable, + libxl__save_helper_state *shs) +{ + libxl__egc *egc = shs->egc; + libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs); + STATE_AO_GC(dss->ao); + int rc; + + rc = libxl__qmp_set_global_dirty_log(gc, domid, enable); + if (!rc) { + libxl__xc_domain_saverestore_async_callback_done(egc, shs, 0); + } else { + LOG(ERROR,"logdirty switch failed (rc=%d), aborting suspend",rc); + libxl__xc_domain_saverestore_async_callback_done(egc, shs, -1); + } +} + +void libxl__domain_suspend_common_switch_qemu_logdirty + (int domid, unsigned enable, void *user) +{ + libxl__save_helper_state *shs = user; + libxl__egc *egc = shs->egc; + libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs); + STATE_AO_GC(dss->ao); + + switch (libxl__device_model_version_running(gc, domid)) { + case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: + domain_suspend_switch_qemu_xen_traditional_logdirty(domid, enable, shs); + break; + case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: + domain_suspend_switch_qemu_xen_logdirty(domid, enable, shs); + break; + default: + LOG(ERROR,"logdirty switch failed" + ", no valid device model version found, aborting suspend"); + libxl__xc_domain_saverestore_async_callback_done(egc, shs, -1); + } +} static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev, const struct timeval *requested_abs) { -- 1.7.4.1
Backport of xen-unstable patch: : HG changeset patch : User Anthony PERARD <anthony.perard@citrix.com> : Date 1349693136 -3600 : Node ID 0995890022391682a2499a202c3c8608e1d3780a : Parent 08fac5c2bf3dcbc493ce45091383f6ce1938f369 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl.c | 17 ----------------- 1 files changed, 0 insertions(+), 17 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 4b4c5b0..9b14364 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -768,23 +768,6 @@ int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags, goto out_err; } - if (type == LIBXL_DOMAIN_TYPE_HVM && flags & LIBXL_SUSPEND_LIVE) { - switch (libxl__device_model_version_running(gc, domid)) { - case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: - LOG(ERROR, - "cannot live migrate HVM domains with qemu-xen device-model"); - rc = ERROR_FAIL; - goto out_err; - case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: - /* No problem */ - break; - case -1: - rc = ERROR_FAIL; - goto out_err; - default: abort(); - } - } - libxl__domain_suspend_state *dss; GCNEW(dss); -- 1.7.4.1
Alex Bligh
2013-Jan-19 17:58 UTC
[PATCH 11/11] libxl: libxl__qmp_save: Add filename as JSON parameter to xen-save-devices-state
Signed-off-by: Alex Bligh <alex@alex.org.uk> --- tools/libxl/libxl_qmp.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index ac10f20..b4cc247 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -871,6 +871,7 @@ int libxl__qmp_save(libxl__gc *gc, int domid, const char *filename) { libxl__json_object *args = NULL; + qmp_parameters_add_string(gc, &args, "filename", (char *)filename); return qmp_run_command(gc, domid, "xen-save-devices-state", args, NULL, NULL); } -- 1.7.4.1
Ian Jackson
2013-Feb-12 15:32 UTC
Re: [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum.
Alex Bligh writes ("[Xen-devel] [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum."):> This value from libxl__json_node_type is never used.We shouldn''t be introducing anything like this into Xen 4.2. Its ABI needs to remain frozen. Ian.
Ian Jackson
2013-Feb-12 15:34 UTC
Re: QEMU: Enabling live-migrate on HVM on qemu-xen device model in 4.2
Alex Bligh writes ("[Xen-devel] QEMU: Enabling live-migrate on HVM on qemu-xen device model in 4.2"):> This patch series consists of 2 parts: > * 11 patches to libxl > > These patches enable live-migrate on HVM using the upstream qemu-xen > device model under Xen 4.2. Currently this is unimplemented. In the > main they are backports of patches in xen-unstable, thought the > QEMU side in particular needed some fiddling.I think we should consider this when all of the required patches are either backports from unstable, or for exceptional cases where there is some reason why a particular patch can''t or shouldn''t go via unstable. I''ll make substantive comment on the individual patches. (Your text formatting is a bit odd.) Thanks, Ian.
Ian Jackson
2013-Feb-12 15:36 UTC
Re: [PATCH 11/11] libxl: libxl__qmp_save: Add filename as JSON parameter to xen-save-devices-state
Alex Bligh writes ("[Xen-devel] [PATCH 11/11] libxl: libxl__qmp_save: Add filename as JSON parameter to xen-save-devices-state"):> + qmp_parameters_add_string(gc, &args, "filename", (char *)filename); > return qmp_run_command(gc, domid, "xen-save-devices-state", args, > NULL, NULL);This looks plausible. Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> Ian.
Ian Jackson
2013-Feb-12 15:37 UTC
Re: [PATCH 09/11] libxl_dom: Call the right switch logdirty for the right DM.
Alex Bligh writes ("[Xen-devel] [PATCH 09/11] libxl_dom: Call the right switch logdirty for the right DM."):> This patch dispatch the switch logdirty call depending on which device model > version is running. > > The call to qemu-xen right now is synchronous, not like the one to > qemu-xen-traditional. > > Backport of xen-unstable patch:This backport will be fine when we have the whole series to put in. Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> (for 4.2) Ian.
Ian Campbell
2013-Feb-12 15:37 UTC
Re: [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum.
On Tue, 2013-02-12 at 15:32 +0000, Ian Jackson wrote:> Alex Bligh writes ("[Xen-devel] [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum."): > > This value from libxl__json_node_type is never used. > > We shouldn''t be introducing anything like this into Xen 4.2. Its ABI > needs to remain frozen.This is a purely internal type, so no ABI implications. Also the libxl ABI is not frozen, only the API. We can always change the SONAME. Ian.
Alex Bligh writes ("[Xen-devel] [PATCH 10/11] libxl: Allow migration with qemu-xen."):> Backport of xen-unstable patch: > : HG changeset patch > : User Anthony PERARD <anthony.perard@citrix.com> > : Date 1349693136 -3600 > : Node ID 0995890022391682a2499a202c3c8608e1d3780a > : Parent 08fac5c2bf3dcbc493ce45091383f6ce1938f369This backport is fine but needs to come at the end of the series, I think ? Ian.
Ian Jackson
2013-Feb-12 15:38 UTC
Re: [PATCH 04/11] libxl_json: Introduce libxl__json_object_to_yajl_gen.
Alex Bligh writes ("[Xen-devel] [PATCH 04/11] libxl_json: Introduce libxl__json_object_to_yajl_gen."):> This function converts a libxl__json_object to yajl by calling every > yajl_gen_* function on a preallocated yajl_gen hand.This backport is also fine. Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> (for 4.2) Ian.
Ian Jackson
2013-Feb-12 15:39 UTC
Re: [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum.
Ian Jackson writes ("Re: [Xen-devel] [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum."):> Alex Bligh writes ("[Xen-devel] [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum."): > > This value from libxl__json_node_type is never used. > > We shouldn''t be introducing anything like this into Xen 4.2. Its ABI > needs to remain frozen.Sorry, forget about that comment. I didn''t spot that this change is in libxl_internal.h. It''s fine. Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> (for 4.2) Ian.
Ian Jackson
2013-Feb-12 15:39 UTC
Re: [PATCH 03/11] libxl_json: Replace JSON_TRUE/FALSE by JSON_BOOL.
Alex Bligh writes ("[Xen-devel] [PATCH 03/11] libxl_json: Replace JSON_TRUE/FALSE by JSON_BOOL."):> Those two JSON_TRUE and JSON_FALSE were types of node. But it''s better > to have a unique JSON_BOOL type. > > Backported from xen-unstable patch: > : HG changeset patch > : User Anthony PERARD <anthony.perard@citrix.com> > : Date 1349693131 -3600 > : Node ID 3f71aab0e2774ded0c5a03436c364fb031ba9aa0 > : Parent 4a6d5d8cba4fc44f9bbda201188885868604b8e8Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> (for 4.2) Ian.
Ian Jackson
2013-Feb-12 15:40 UTC
Re: [PATCH 06/11] libxl_qmp: Use qmp_parameters_* functions for param list of a QMP command.
Alex Bligh writes ("[Xen-devel] [PATCH 06/11] libxl_qmp: Use qmp_parameters_* functions for param list of a QMP command."):> Backported from xen-unstable patch: > : HG changeset patch > : User Anthony PERARD <anthony.perard@citrix.com> > : Date 1349693133 -3600 > : Node ID be5d014f91dfbd67afacc3385c265243794a246f > : Parent 6f7847729f0f42614de516d15257ede7243f995fAcked-by: Ian Jackson <ian.jackson@eu.citrix.com> (for 4.2) Ian.
Ian Jackson
2013-Feb-12 15:41 UTC
Re: [PATCH 07/11] libxl_qmp: Simplify run of single QMP commands.
Alex Bligh writes ("[Xen-devel] [PATCH 07/11] libxl_qmp: Simplify run of single QMP commands."):> This new function connects to QEMU, sends the command and disconnects. > > Backport of xen-unstable patch: > : HG changeset patch > : User Anthony PERARD <anthony.perard@citrix.com> > : Date 1349693134 -3600 > : Node ID f3890916496445c97d6778d6c986b0270ff707f2 > : Parent be5d014f91dfbd67afacc3385c265243794a246fAcked-by: Ian Jackson <ian.jackson@eu.citrix.com> (for 4.2) Ian.
Ian Jackson
2013-Feb-12 15:42 UTC
Re: [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum.
Ian Campbell writes ("Re: [Xen-devel] [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum."):> On Tue, 2013-02-12 at 15:32 +0000, Ian Jackson wrote: > > We shouldn''t be introducing anything like this into Xen 4.2. Its ABI > > needs to remain frozen. > > This is a purely internal type, so no ABI implications. > > Also the libxl ABI is not frozen, only the API. We can always change the > SONAME.The ABI certainly needs to be frozen within a stable release. I don''t know if we document this anywhere but it seems like a fairly basic obvious requirement. Ian.
Ian Jackson
2013-Feb-12 15:43 UTC
Re: [PATCH 08/11] libxl_qmp: Introduce libxl__qmp_set_global_dirty_log.
Alex Bligh writes ("[Xen-devel] [PATCH 08/11] libxl_qmp: Introduce libxl__qmp_set_global_dirty_log."):> This function will enable or disable the global dirty log on QEMU, > used during a migration. > > Backport of xen-unstable patch: > : HG changeset patchAcked-by: Ian Jackson <ian.jackson@eu.citrix.com> (for 4.2) Ian.
Ian Jackson
2013-Feb-12 15:43 UTC
Re: [PATCH 05/11] libxl_qmp: Introduces helpers to create an argument list.
Alex Bligh writes ("[Xen-devel] [PATCH 05/11] libxl_qmp: Introduces helpers to create an argument list."):> Those functions will be used to create a "list" of parameters that > contain more than just strings. This list is converted by qmp_send to > a string to be sent to QEMU. > > Those functions will be used in the next two patches, so right now > there are not compiled. > > Backported from xen-unstable patch: > : HG changeset patch > : User Anthony PERARD <anthony.perard@citrix.com> > : Date 1349693132 -3600 > : Node ID 6f7847729f0f42614de516d15257ede7243f995f > : Parent 74dee58cfc0d2d6594f388db3b4d2ce91d1bb204Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> (for 4.2) Ian.
Ian Jackson
2013-Feb-12 15:43 UTC
Re: [PATCH 01/11] libxl_json: Export json_object related function.
Alex Bligh writes ("[Xen-devel] [PATCH 01/11] libxl_json: Export json_object related function."):> Export libxl__json_object_alloc and libxl__json_object_append_to to > use them in a later patch. > > Backported from xen-unstable patch: > : User Anthony PERARD <anthony.perard@citrix.com> > : Date 1349693129 -3600 > : Node ID c9b80c7f8db1a5d26906a2298c481bf7e87fda94 > : Parent 93e3e6a33e0a1ec9f92fc575334caa35e6dbc757Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> (for 4.2) Ian.
Ian Jackson writes ("Re: [Xen-devel] [PATCH 10/11] libxl: Allow migration with qemu-xen."):> Alex Bligh writes ("[Xen-devel] [PATCH 10/11] libxl: Allow migration with qemu-xen."): > > Backport of xen-unstable patch: > > : HG changeset patch > > : User Anthony PERARD <anthony.perard@citrix.com> > > : Date 1349693136 -3600 > > : Node ID 0995890022391682a2499a202c3c8608e1d3780a > > : Parent 08fac5c2bf3dcbc493ce45091383f6ce1938f369 > > This backport is fine but needs to come at the end of the series, I > think ?I''ve had another thought: what if this series is applied, including this final patch, but the result is used with an older qemu which hasn''t had the relevant features added ? AFAICT the result would probably be a failure to execute the logdirty switch. Is that error sufficiently clean ? Ian.
Ian, Firstly, thanks for the review. I think the issue of JSON_ERROR''s removal you thought was OK in the end because it was from the _internal file --On 12 February 2013 15:44:52 +0000 Ian Jackson <Ian.Jackson@eu.citrix.com> wrote:> Alex Bligh writes ("[Xen-devel] [PATCH 10/11] libxl: Allow migration withqemu-xen."):> > Backport of xen-unstable patch: > > : HG changeset patch > > : User Anthony PERARD <anthony.perard@citrix.com> > > : Date 1349693136 -3600 > > : Node ID 0995890022391682a2499a202c3c8608e1d3780a > > : Parent 08fac5c2bf3dcbc493ce45091383f6ce1938f369 > > This backport is fine but needs to come at the end of the series, I > think ?I can reorder patch 11 so it precedes patch 10 if you want. It''s only there as I found the bug in patch 11 later. Tell me if you want me to do this. If I''m right re JSON_ERROR, the only substantive issue is the following:> I''ve had another thought: what if this series is applied, including > this final patch, but the result is used with an older qemu which > hasn''t had the relevant features added ?Does that ever happen? By which I mean does that ever happen in a manner that is permitted? I thought if you were using Xen 4.2 you pretty much had to be using either a qemu upstream compiled specifically for Xen and thus distributed with it, so you''d expect to upgrade it, or you''d be using one of the newer upstream releases which has all this stuff in anyway. Was there some window where true upstream qemu (as opposed to the one carried by Xen) had a release version which carried Xen 4.2 support and qemu DM, but not live migrate?> AFAICT the result would probably be a failure to execute the logdirty > switch. Is that error sufficiently clean ?This might depend on our policy of using mixed versions of qemu and xen. If a policy of "either use the version of qemu included in Xen or use a version greater than N.N.N" is ok, then I think the answer is yes. If not, then I''m not sure. Does Xen currently check the version of qemu somehow? -- Alex Bligh
Ian Campbell
2013-Feb-13 09:13 UTC
Re: [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum.
On Tue, 2013-02-12 at 15:42 +0000, Ian Jackson wrote:> Ian Campbell writes ("Re: [Xen-devel] [PATCH 02/11] libxl_json: Remove JSON_ERROR from enum."): > > On Tue, 2013-02-12 at 15:32 +0000, Ian Jackson wrote: > > > We shouldn''t be introducing anything like this into Xen 4.2. Its ABI > > > needs to remain frozen. > > > > This is a purely internal type, so no ABI implications. > > > > Also the libxl ABI is not frozen, only the API. We can always change the > > SONAME. > > The ABI certainly needs to be frozen within a stable release. I don''t > know if we document this anywhere but it seems like a fairly basic > obvious requirement.Ah, yes, true.
Alex Bligh writes ("Re: [Xen-devel] [PATCH 10/11] libxl: Allow migration with qemu-xen."):> Firstly, thanks for the review. I think the issue of JSON_ERROR''s removal > you thought was OK in the end because it was from the _internal fileYes.> > This backport is fine but needs to come at the end of the series, I > > think ? > > I can reorder patch 11 so it precedes patch 10 if you want. It''s only > there as I found the bug in patch 11 later. Tell me if you want me to > do this.That would be best, I think.> If I''m right re JSON_ERROR, the only substantive issue is the following: > > > I''ve had another thought: what if this series is applied, including > > this final patch, but the result is used with an older qemu which > > hasn''t had the relevant features added ? > > Does that ever happen? By which I mean does that ever happen in a manner > that is permitted?Certainly there are deployment strategies - often ones used by distros - which might have that result.> I thought if you were using Xen 4.2 you pretty much had to be using either > a qemu upstream compiled specifically for Xen and thus distributed with > it, so you''d expect to upgrade it, or you''d be using one of the newer > upstream releases which has all this stuff in anyway. Was there some > window where true upstream qemu (as opposed to the one carried by Xen) had > a release version which carried Xen 4.2 support and qemu DM, but not > live migrate?I think we can''t assume that people won''t have taken snapshots particularly of our stable branch.> > AFAICT the result would probably be a failure to execute the logdirty > > switch. Is that error sufficiently clean ? > > This might depend on our policy of using mixed versions of qemu and > xen. If a policy of "either use the version of qemu included in Xen > or use a version greater than N.N.N" is ok, then I think the answer is > yes.My concern is only whether turning an existing specifically-diagnosed failure into a more general one is acceptable, under these circumstances. TBH I''m inclined to think it is in this case but I wanted to give you and others a chance to comment. Ian.
Ian,>> I can reorder patch 11 so it precedes patch 10 if you want. It''s only >> there as I found the bug in patch 11 later. Tell me if you want me to >> do this. > > That would be best, I think.OK will do.> My concern is only whether turning an existing specifically-diagnosed > failure into a more general one is acceptable, under these > circumstances. TBH I''m inclined to think it is in this case but I > wanted to give you and others a chance to comment.Agree. -- Alex Bligh
Alex Bligh
2013-Feb-13 18:33 UTC
QEMU: Enabling live-migrate on HVM on qemu-xen device model in 4.2
This patch series consists of 2 parts: * 11 patches to libxl * 5 patches to QEMU The 5 patches to QEMU are unchanged since version 2 of the patch. These patches enable live-migrate on HVM using the upstream qemu-xen device model under Xen 4.2. Currently this is unimplemented. In the main they are backports of patches in xen-unstable, thought the QEMU side in particular needed some fiddling. The difference between this patch series and the previous series is patches 10 and 11 have been swapped around. I would suggest these patches should be included in 4.2.2.
Alex Bligh
2013-Feb-13 18:33 UTC
[PATCH 1/5] QMP, Introduce xen-set-global-dirty-log command.
This command is used during a migration of a guest under Xen. It calls cpu_physical_memory_set_dirty_tracking. Backport of 39f42439d0629d3921629dc4b38e68df8f2f7b83 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- qapi-schema.json | 13 +++++++++++++ qmp-commands.hx | 24 ++++++++++++++++++++++++ xen-all.c | 6 ++++++ xen-stub.c | 5 +++++ 4 files changed, 48 insertions(+), 0 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index a669e98..bb0d7c5 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -905,3 +905,16 @@ # Since: 1.1 ## { ''command'': ''xen-save-devices-state'', ''data'': {''filename'': ''str''} } + +## +# @xen-set-global-dirty-log +# +# Enable or disable the global dirty log mode. +# +# @enable: true to enable, false to disable. +# +# Returns: nothing +# +# Since: 1.3 +## +{ ''command'': ''xen-set-global-dirty-log'', ''data'': { ''enable'': ''bool'' } } diff --git a/qmp-commands.hx b/qmp-commands.hx index bf1df49..0de68df 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -472,6 +472,30 @@ Example: EQMP { + .name = "xen-set-global-dirty-log", + .args_type = "enable:b", + .mhandler.cmd_new = qmp_marshal_input_xen_set_global_dirty_log, + }, + +SQMP +xen-set-global-dirty-log +------- + +Enable or disable the global dirty log mode. + +Arguments: + +- "enable": Enable it or disable it. + +Example: + +-> { "execute": "xen-set-global-dirty-log", + "arguments": { "enable": true } } +<- { "return": {} } + +EQMP + + { .name = "migrate", .args_type = "detach:-d,blk:-b,inc:-i,uri:s", .params = "[-d] [-b] [-i] uri", diff --git a/xen-all.c b/xen-all.c index 3256509..6b4e511 100644 --- a/xen-all.c +++ b/xen-all.c @@ -12,6 +12,7 @@ #include "hw/pc.h" #include "hw/xen_common.h" #include "hw/xen_backend.h" +#include "qmp-commands.h" #include "range.h" #include "xen-mapcache.h" @@ -524,6 +525,11 @@ static CPUPhysMemoryClient xen_cpu_phys_memory_client = { .log_stop = xen_log_stop, }; +void qmp_xen_set_global_dirty_log(bool enable, Error **errp) +{ + cpu_physical_memory_set_dirty_tracking(!!enable); +} + /* VCPU Operations, MMIO, IO ring ... */ static void xen_reset_vcpu(void *opaque) diff --git a/xen-stub.c b/xen-stub.c index efe2ab5..25317ec 100644 --- a/xen-stub.c +++ b/xen-stub.c @@ -8,6 +8,7 @@ #include "qemu-common.h" #include "hw/xen.h" +#include "qmp-commands.h" void xenstore_store_pv_console_info(int i, CharDriverState *chr) { @@ -43,3 +44,7 @@ int xen_init(void) { return -ENOSYS; } + +void qmp_xen_set_global_dirty_log(bool enable, Error **errp) +{ +} -- 1.7.4.1
This function is to be used during live migration. Every write access to the guest memory should call this funcion so the Xen tools knows which pages are dirty. Backport of 910b38e4dc4c37683c8b821e75a7f4cf095e4b21 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- hw/xen.h | 1 + xen-all.c | 21 +++++++++++++++++++++ xen-stub.c | 4 ++++ 3 files changed, 26 insertions(+), 0 deletions(-) diff --git a/hw/xen.h b/hw/xen.h index 2162111..359a275 100644 --- a/hw/xen.h +++ b/hw/xen.h @@ -45,6 +45,7 @@ void xenstore_store_pv_console_info(int i, struct CharDriverState *chr); #if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY) void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size); +void xen_modified_memory(ram_addr_t start, ram_addr_t length); #endif #if defined(CONFIG_XEN) && CONFIG_XEN_CTRL_INTERFACE_VERSION < 400 diff --git a/xen-all.c b/xen-all.c index 6b4e511..121289d 100644 --- a/xen-all.c +++ b/xen-all.c @@ -1135,3 +1135,24 @@ void destroy_hvm_domain(bool reboot) xc_interface_close(xc_handle); } } + +void xen_modified_memory(ram_addr_t start, ram_addr_t length) +{ + if (unlikely(cpu_physical_memory_get_dirty_tracking())) { + 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-stub.c b/xen-stub.c index 25317ec..7b54477 100644 --- a/xen-stub.c +++ b/xen-stub.c @@ -48,3 +48,7 @@ int xen_init(void) void qmp_xen_set_global_dirty_log(bool enable, Error **errp) { } + +void xen_modified_memory(ram_addr_t start, ram_addr_t length) +{ +} -- 1.7.4.1
This new helper/hook is used in the next patch to add an extra call in a single place. Backport of 51d7a9eb2b64e787c90bea1027308087eac22065 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- exec.c | 45 +++++++++++++++++---------------------------- 1 files changed, 17 insertions(+), 28 deletions(-) diff --git a/exec.c b/exec.c index 6c206ff..511777b 100644 --- a/exec.c +++ b/exec.c @@ -3951,6 +3951,18 @@ int cpu_memory_rw_debug(CPUState *env, target_ulong addr, } #else + +static void invalidate_and_set_dirty(target_phys_addr_t addr, + target_phys_addr_t length) +{ + if (!cpu_physical_memory_is_dirty(addr)) { + /* invalidate code */ + tb_invalidate_phys_page_range(addr, addr + length, 0); + /* set dirty bit */ + cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG)); + } +} + void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write) { @@ -4003,13 +4015,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, /* RAM case */ ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + l, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags( - addr1, (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, l); qemu_put_ram_ptr(ptr); } } else { @@ -4081,6 +4087,7 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, /* ROM/RAM case */ ptr = qemu_get_ram_ptr(addr1); memcpy(ptr, buf, l); + invalidate_and_set_dirty(addr1, l); qemu_put_ram_ptr(ptr); } len -= l; @@ -4211,13 +4218,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, l = TARGET_PAGE_SIZE; if (l > access_len) l = access_len; - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + l, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags( - addr1, (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, l); addr1 += l; access_len -= l; } @@ -4561,13 +4562,7 @@ static inline void stl_phys_internal(target_phys_addr_t addr, uint32_t val, stl_p(ptr, val); break; } - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + 4, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags(addr1, - (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, 4); } } @@ -4639,13 +4634,7 @@ static inline void stw_phys_internal(target_phys_addr_t addr, uint32_t val, stw_p(ptr, val); break; } - if (!cpu_physical_memory_is_dirty(addr1)) { - /* invalidate code */ - tb_invalidate_phys_page_range(addr1, addr1 + 2, 0); - /* set dirty bit */ - cpu_physical_memory_set_dirty_flags(addr1, - (0xff & ~CODE_DIRTY_FLAG)); - } + invalidate_and_set_dirty(addr1, 2); } } -- 1.7.4.1
This patch add some calls to xen_modified_memory to notify Xen about dirtybits during migration. Backport of e226939de5814527a21396903b08c3d0ed989558 Signed-off-by: Alex Bligh <alex@alex.org.uk> --- exec.c | 4 ++++ memory.c | 4 ++++ 2 files changed, 8 insertions(+), 0 deletions(-) diff --git a/exec.c b/exec.c index 511777b..401f9bc 100644 --- a/exec.c +++ b/exec.c @@ -2988,6 +2988,9 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS), 0xff, size >> TARGET_PAGE_BITS); + if (xen_enabled()) + xen_modified_memory(new_block->offset, size); + if (kvm_enabled()) kvm_setup_guest_memory(new_block->host, size); @@ -3961,6 +3964,7 @@ static void invalidate_and_set_dirty(target_phys_addr_t addr, /* set dirty bit */ cpu_physical_memory_set_dirty_flags(addr, (0xff & ~CODE_DIRTY_FLAG)); } + xen_modified_memory(addr, length); } void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, diff --git a/memory.c b/memory.c index 7c20a07..6e0c596 100644 --- a/memory.c +++ b/memory.c @@ -16,6 +16,7 @@ #include "ioport.h" #include "bitops.h" #include "kvm.h" +#include "hw/xen.h" #include <assert.h> unsigned memory_region_transaction_depth = 0; @@ -1065,6 +1066,9 @@ bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr, void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr) { assert(mr->terminates); + if (xen_enabled()) + xen_modified_memory((mr->ram_addr + addr) & TARGET_PAGE_MASK, + TARGET_PAGE_SIZE); return cpu_physical_memory_set_dirty(mr->ram_addr + addr); } -- 1.7.4.1
If the call to xc_hvm_track_dirty_vram() fails, then we set dirtybit on all the video ram. This case happens during migration. Backport of 8aba7dc02d5660df7e7d8651304b3079908358be Signed-off-by: Alex Bligh <alex@alex.org.uk> --- xen-all.c | 20 ++++++++++++++++++-- 1 files changed, 18 insertions(+), 2 deletions(-) diff --git a/xen-all.c b/xen-all.c index 121289d..dbd759c 100644 --- a/xen-all.c +++ b/xen-all.c @@ -470,7 +470,21 @@ static int xen_sync_dirty_bitmap(XenIOState *state, rc = xc_hvm_track_dirty_vram(xen_xc, xen_domid, start_addr >> TARGET_PAGE_BITS, npages, bitmap); - if (rc) { + if (rc < 0) { + if (rc != -ENODATA) { + ram_addr_t addr, end; + + xen_modified_memory(start_addr, size); + + end = TARGET_PAGE_ALIGN(start_addr + size); + for (addr = start_addr & TARGET_PAGE_MASK; addr < end; addr += TARGET_PAGE_SIZE) { + cpu_physical_memory_set_dirty(addr); + } + + DPRINTF("xen: track_dirty_vram failed (0x" TARGET_FMT_plx + ", 0x" TARGET_FMT_plx "): %s\n", + start_addr, start_addr + size, strerror(-rc)); + } return rc; } @@ -479,7 +493,9 @@ static int xen_sync_dirty_bitmap(XenIOState *state, while (map != 0) { j = ffsl(map) - 1; map &= ~(1ul << j); - cpu_physical_memory_set_dirty(vram_offset + (i * width + j) * TARGET_PAGE_SIZE); + target_phys_addr_t todirty = vram_offset + (i * width + j) * TARGET_PAGE_SIZE; + xen_modified_memory(todirty, TARGET_PAGE_SIZE); + cpu_physical_memory_set_dirty(todirty); }; } -- 1.7.4.1