aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hmp.c13
-rw-r--r--migration/migration.c17
-rw-r--r--migration/ram.c133
-rw-r--r--migration/ram.h1
-rw-r--r--migration/rdma.c2
-rw-r--r--migration/savevm.c7
-rw-r--r--qapi/migration.json26
-rw-r--r--tests/migration-test.c30
-rw-r--r--tests/migration/Makefile35
-rw-r--r--tests/migration/i386/Makefile22
-rw-r--r--tests/migration/i386/a-b-bootblock.S (renamed from tests/migration/x86-a-b-bootblock.s)4
-rw-r--r--tests/migration/i386/a-b-bootblock.h (renamed from tests/migration/x86-a-b-bootblock.h)8
-rw-r--r--tests/migration/migration-test.h21
-rwxr-xr-xtests/migration/rebuild-x86-bootblock.sh33
-rw-r--r--vl.c1
15 files changed, 255 insertions, 98 deletions
diff --git a/hmp.c b/hmp.c
index 3a9f797677..61ef120423 100644
--- a/hmp.c
+++ b/hmp.c
@@ -271,6 +271,19 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
info->xbzrle_cache->overflow);
}
+ if (info->has_compression) {
+ monitor_printf(mon, "compression pages: %" PRIu64 " pages\n",
+ info->compression->pages);
+ monitor_printf(mon, "compression busy: %" PRIu64 "\n",
+ info->compression->busy);
+ monitor_printf(mon, "compression busy rate: %0.2f\n",
+ info->compression->busy_rate);
+ monitor_printf(mon, "compressed size: %" PRIu64 "\n",
+ info->compression->compressed_size);
+ monitor_printf(mon, "compression rate: %0.2f\n",
+ info->compression->compression_rate);
+ }
+
if (info->has_cpu_throttle_percentage) {
monitor_printf(mon, "cpu throttle percentage: %" PRIu64 "\n",
info->cpu_throttle_percentage);
diff --git a/migration/migration.c b/migration/migration.c
index 05d0a7296a..d6ae879dc8 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -758,6 +758,18 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
info->xbzrle_cache->overflow = xbzrle_counters.overflow;
}
+ if (migrate_use_compression()) {
+ info->has_compression = true;
+ info->compression = g_malloc0(sizeof(*info->compression));
+ info->compression->pages = compression_counters.pages;
+ info->compression->busy = compression_counters.busy;
+ info->compression->busy_rate = compression_counters.busy_rate;
+ info->compression->compressed_size =
+ compression_counters.compressed_size;
+ info->compression->compression_rate =
+ compression_counters.compression_rate;
+ }
+
if (cpu_throttle_active()) {
info->has_cpu_throttle_percentage = true;
info->cpu_throttle_percentage = cpu_throttle_get_percentage();
@@ -2268,7 +2280,10 @@ out:
*/
if (postcopy_pause_return_path_thread(ms)) {
/* Reload rp, reset the rest */
- rp = ms->rp_state.from_dst_file;
+ if (rp != ms->rp_state.from_dst_file) {
+ qemu_fclose(rp);
+ rp = ms->rp_state.from_dst_file;
+ }
ms->rp_state.error = false;
goto retry;
}
diff --git a/migration/ram.c b/migration/ram.c
index f6fd8e5e09..bc38d98cc3 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -301,10 +301,19 @@ struct RAMState {
uint64_t num_dirty_pages_period;
/* xbzrle misses since the beginning of the period */
uint64_t xbzrle_cache_miss_prev;
- /* number of iterations at the beginning of period */
- uint64_t iterations_prev;
- /* Iterations since start */
- uint64_t iterations;
+
+ /* compression statistics since the beginning of the period */
+ /* amount of count that no free thread to compress data */
+ uint64_t compress_thread_busy_prev;
+ /* amount bytes after compression */
+ uint64_t compressed_size_prev;
+ /* amount of compressed pages */
+ uint64_t compress_pages_prev;
+
+ /* total handled target pages at the beginning of period */
+ uint64_t target_page_count_prev;
+ /* total handled target pages since start */
+ uint64_t target_page_count;
/* number of dirty bits in the bitmap */
uint64_t migration_dirty_pages;
/* protects modification of the bitmap */
@@ -338,6 +347,8 @@ struct PageSearchStatus {
};
typedef struct PageSearchStatus PageSearchStatus;
+CompressionStats compression_counters;
+
struct CompressParam {
bool done;
bool quit;
@@ -420,28 +431,14 @@ static void *do_data_compress(void *opaque)
return NULL;
}
-static inline void terminate_compression_threads(void)
-{
- int idx, thread_count;
-
- thread_count = migrate_compress_threads();
-
- for (idx = 0; idx < thread_count; idx++) {
- qemu_mutex_lock(&comp_param[idx].mutex);
- comp_param[idx].quit = true;
- qemu_cond_signal(&comp_param[idx].cond);
- qemu_mutex_unlock(&comp_param[idx].mutex);
- }
-}
-
static void compress_threads_save_cleanup(void)
{
int i, thread_count;
- if (!migrate_use_compression()) {
+ if (!migrate_use_compression() || !comp_param) {
return;
}
- terminate_compression_threads();
+
thread_count = migrate_compress_threads();
for (i = 0; i < thread_count; i++) {
/*
@@ -451,6 +448,12 @@ static void compress_threads_save_cleanup(void)
if (!comp_param[i].file) {
break;
}
+
+ qemu_mutex_lock(&comp_param[i].mutex);
+ comp_param[i].quit = true;
+ qemu_cond_signal(&comp_param[i].cond);
+ qemu_mutex_unlock(&comp_param[i].mutex);
+
qemu_thread_join(compress_threads + i);
qemu_mutex_destroy(&comp_param[i].mutex);
qemu_cond_destroy(&comp_param[i].cond);
@@ -648,8 +651,8 @@ static int multifd_recv_initial_packet(QIOChannel *c, Error **errp)
return -1;
}
- be32_to_cpus(&msg.magic);
- be32_to_cpus(&msg.version);
+ msg.magic = be32_to_cpu(msg.magic);
+ msg.version = be32_to_cpu(msg.version);
if (msg.magic != MULTIFD_MAGIC) {
error_setg(errp, "multifd: received packet magic %x "
@@ -734,7 +737,7 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp)
RAMBlock *block;
int i;
- be32_to_cpus(&packet->magic);
+ packet->magic = be32_to_cpu(packet->magic);
if (packet->magic != MULTIFD_MAGIC) {
error_setg(errp, "multifd: received packet "
"magic %x and expected magic %x",
@@ -742,7 +745,7 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp)
return -1;
}
- be32_to_cpus(&packet->version);
+ packet->version = be32_to_cpu(packet->version);
if (packet->version != MULTIFD_VERSION) {
error_setg(errp, "multifd: received packet "
"version %d and expected version %d",
@@ -752,7 +755,7 @@ static int multifd_recv_unfill_packet(MultiFDRecvParams *p, Error **errp)
p->flags = be32_to_cpu(packet->flags);
- be32_to_cpus(&packet->size);
+ packet->size = be32_to_cpu(packet->size);
if (packet->size > migrate_multifd_page_count()) {
error_setg(errp, "multifd: received packet "
"with size %d and expected maximum size %d",
@@ -1592,21 +1595,42 @@ uint64_t ram_pagesize_summary(void)
static void migration_update_rates(RAMState *rs, int64_t end_time)
{
- uint64_t iter_count = rs->iterations - rs->iterations_prev;
+ uint64_t page_count = rs->target_page_count - rs->target_page_count_prev;
+ double compressed_size;
/* calculate period counters */
ram_counters.dirty_pages_rate = rs->num_dirty_pages_period * 1000
/ (end_time - rs->time_last_bitmap_sync);
- if (!iter_count) {
+ if (!page_count) {
return;
}
if (migrate_use_xbzrle()) {
xbzrle_counters.cache_miss_rate = (double)(xbzrle_counters.cache_miss -
- rs->xbzrle_cache_miss_prev) / iter_count;
+ rs->xbzrle_cache_miss_prev) / page_count;
rs->xbzrle_cache_miss_prev = xbzrle_counters.cache_miss;
}
+
+ if (migrate_use_compression()) {
+ compression_counters.busy_rate = (double)(compression_counters.busy -
+ rs->compress_thread_busy_prev) / page_count;
+ rs->compress_thread_busy_prev = compression_counters.busy;
+
+ compressed_size = compression_counters.compressed_size -
+ rs->compressed_size_prev;
+ if (compressed_size) {
+ double uncompressed_size = (compression_counters.pages -
+ rs->compress_pages_prev) * TARGET_PAGE_SIZE;
+
+ /* Compression-Ratio = Uncompressed-size / Compressed-size */
+ compression_counters.compression_rate =
+ uncompressed_size / compressed_size;
+
+ rs->compress_pages_prev = compression_counters.pages;
+ rs->compressed_size_prev = compression_counters.compressed_size;
+ }
+ }
}
static void migration_bitmap_sync(RAMState *rs)
@@ -1662,7 +1686,7 @@ static void migration_bitmap_sync(RAMState *rs)
migration_update_rates(rs, end_time);
- rs->iterations_prev = rs->iterations;
+ rs->target_page_count_prev = rs->target_page_count;
/* reset period counters */
rs->time_last_bitmap_sync = end_time;
@@ -1888,17 +1912,25 @@ exit:
static void
update_compress_thread_counts(const CompressParam *param, int bytes_xmit)
{
+ ram_counters.transferred += bytes_xmit;
+
if (param->zero_page) {
ram_counters.duplicate++;
+ return;
}
- ram_counters.transferred += bytes_xmit;
+
+ /* 8 means a header with RAM_SAVE_FLAG_CONTINUE. */
+ compression_counters.compressed_size += bytes_xmit - 8;
+ compression_counters.pages++;
}
+static bool save_page_use_compression(RAMState *rs);
+
static void flush_compressed_data(RAMState *rs)
{
int idx, len, thread_count;
- if (!migrate_use_compression()) {
+ if (!save_page_use_compression(rs)) {
return;
}
thread_count = migrate_compress_threads();
@@ -1996,17 +2028,22 @@ static bool find_dirty_block(RAMState *rs, PageSearchStatus *pss, bool *again)
pss->page = 0;
pss->block = QLIST_NEXT_RCU(pss->block, next);
if (!pss->block) {
+ /*
+ * If memory migration starts over, we will meet a dirtied page
+ * which may still exists in compression threads's ring, so we
+ * should flush the compressed data to make sure the new page
+ * is not overwritten by the old one in the destination.
+ *
+ * Also If xbzrle is on, stop using the data compression at this
+ * point. In theory, xbzrle can do better than compression.
+ */
+ flush_compressed_data(rs);
+
/* Hit the end of the list */
pss->block = QLIST_FIRST_RCU(&ram_list.blocks);
/* Flag that we've looped */
pss->complete_round = true;
rs->ram_bulk_stage = false;
- if (migrate_use_xbzrle()) {
- /* If xbzrle is on, stop using the data compression at this
- * point. In theory, xbzrle can do better than compression.
- */
- flush_compressed_data(rs);
- }
}
/* Didn't find anything this time, but try again on the new block */
*again = true;
@@ -2259,6 +2296,7 @@ static bool save_compress_page(RAMState *rs, RAMBlock *block, ram_addr_t offset)
return true;
}
+ compression_counters.busy++;
return false;
}
@@ -2372,7 +2410,8 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss,
*
* Called within an RCU critical section.
*
- * Returns the number of pages written where zero means no dirty pages
+ * Returns the number of pages written where zero means no dirty pages,
+ * or negative on error
*
* @rs: current RAM state
* @last_stage: if we are at the completion stage
@@ -3196,7 +3235,13 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
done = 1;
break;
}
- rs->iterations++;
+
+ if (pages < 0) {
+ qemu_file_set_error(f, pages);
+ break;
+ }
+
+ rs->target_page_count += pages;
/* we want to check in the 1st loop, just in case it was the 1st time
and we had to sync the dirty bitmap.
@@ -3212,7 +3257,6 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
}
i++;
}
- flush_compressed_data(rs);
rcu_read_unlock();
/*
@@ -3238,7 +3282,7 @@ out:
/**
* ram_save_complete: function called to send the remaining amount of ram
*
- * Returns zero to indicate success
+ * Returns zero to indicate success or negative on error
*
* Called with iothread lock
*
@@ -3249,6 +3293,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
{
RAMState **temp = opaque;
RAMState *rs = *temp;
+ int ret = 0;
rcu_read_lock();
@@ -3269,6 +3314,10 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
if (pages == 0) {
break;
}
+ if (pages < 0) {
+ ret = pages;
+ break;
+ }
}
flush_compressed_data(rs);
@@ -3280,7 +3329,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
qemu_fflush(f);
- return 0;
+ return ret;
}
static void ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size,
diff --git a/migration/ram.h b/migration/ram.h
index 457bf54b8c..a139066846 100644
--- a/migration/ram.h
+++ b/migration/ram.h
@@ -36,6 +36,7 @@
extern MigrationStats ram_counters;
extern XBZRLECacheStats xbzrle_counters;
+extern CompressionStats compression_counters;
int xbzrle_cache_resize(int64_t new_size, Error **errp);
uint64_t ram_bytes_remaining(void);
diff --git a/migration/rdma.c b/migration/rdma.c
index ae07515e83..9b2e7e10aa 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -4012,7 +4012,7 @@ static void rdma_accept_incoming_migration(void *opaque)
void rdma_start_incoming_migration(const char *host_port, Error **errp)
{
int ret;
- RDMAContext *rdma, *rdma_return_path;
+ RDMAContext *rdma, *rdma_return_path = NULL;
Error *local_err = NULL;
trace_rdma_start_incoming_migration();
diff --git a/migration/savevm.c b/migration/savevm.c
index 13e51f0e34..2d10e45582 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -1679,6 +1679,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
qemu_loadvm_state_cleanup();
rcu_unregister_thread();
+ mis->have_listen_thread = false;
return NULL;
}
@@ -2078,7 +2079,9 @@ qemu_loadvm_section_start_full(QEMUFile *f, MigrationIncomingState *mis)
/* Find savevm section */
se = find_se(idstr, instance_id);
if (se == NULL) {
- error_report("Unknown savevm section or instance '%s' %d",
+ error_report("Unknown savevm section or instance '%s' %d. "
+ "Make sure that your current VM setup matches your "
+ "saved VM setup, including any hotplugged devices",
idstr, instance_id);
return -EINVAL;
}
@@ -2330,11 +2333,13 @@ int qemu_loadvm_state(QEMUFile *f)
if (migrate_get_current()->send_configuration) {
if (qemu_get_byte(f) != QEMU_VM_CONFIGURATION) {
error_report("Configuration section missing");
+ qemu_loadvm_state_cleanup();
return -EINVAL;
}
ret = vmstate_load_state(f, &vmstate_configuration, &savevm_state, 0);
if (ret) {
+ qemu_loadvm_state_cleanup();
return ret;
}
}
diff --git a/qapi/migration.json b/qapi/migration.json
index f62d3f9a4b..6e8c21258a 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -76,6 +76,27 @@
'overflow': 'int' } }
##
+# @CompressionStats:
+#
+# Detailed migration compression statistics
+#
+# @pages: amount of pages compressed and transferred to the target VM
+#
+# @busy: count of times that no free thread was available to compress data
+#
+# @busy-rate: rate of thread busy
+#
+# @compressed-size: amount of bytes after compression
+#
+# @compression-rate: rate of compressed size
+#
+# Since: 3.1
+##
+{ 'struct': 'CompressionStats',
+ 'data': {'pages': 'int', 'busy': 'int', 'busy-rate': 'number',
+ 'compressed-size': 'int', 'compression-rate': 'number' } }
+
+##
# @MigrationStatus:
#
# An enumeration of migration status.
@@ -172,6 +193,8 @@
# only present when the postcopy-blocktime migration capability
# is enabled. (Since 3.0)
#
+# @compression: migration compression statistics, only returned if compression
+# feature is on and status is 'active' or 'completed' (Since 3.1)
#
# Since: 0.14.0
##
@@ -186,7 +209,8 @@
'*cpu-throttle-percentage': 'int',
'*error-desc': 'str',
'*postcopy-blocktime' : 'uint32',
- '*postcopy-vcpu-blocktime': ['uint32']} }
+ '*postcopy-vcpu-blocktime': ['uint32'],
+ '*compression': 'CompressionStats'} }
##
# @query-migrate:
diff --git a/tests/migration-test.c b/tests/migration-test.c
index 967e3d0856..20f38f1930 100644
--- a/tests/migration-test.c
+++ b/tests/migration-test.c
@@ -21,11 +21,13 @@
#include "chardev/char.h"
#include "sysemu/sysemu.h"
+#include "migration/migration-test.h"
+
/* TODO actually test the results and get rid of this */
#define qtest_qmp_discard_response(...) qobject_unref(qtest_qmp(__VA_ARGS__))
-const unsigned start_address = 1024 * 1024;
-const unsigned end_address = 100 * 1024 * 1024;
+unsigned start_address;
+unsigned end_address;
bool got_stop;
static bool uffd_feature_thread_id;
@@ -80,10 +82,10 @@ static bool ufd_version_check(void)
static const char *tmpfs;
-/* A simple PC boot sector that modifies memory (1-100MB) quickly
- * outputting a 'B' every so often if it's still running.
+/* The boot file modifies memory area in [start_address, end_address)
+ * repeatedly. It outputs a 'B' at a fixed rate while it's still running.
*/
-#include "tests/migration/x86-a-b-bootblock.h"
+#include "tests/migration/i386/a-b-bootblock.h"
static void init_bootfile_x86(const char *bootpath)
{
@@ -270,11 +272,11 @@ static void wait_for_migration_pass(QTestState *who)
static void check_guests_ram(QTestState *who)
{
/* Our ASM test will have been incrementing one byte from each page from
- * 1MB to <100MB in order.
- * This gives us a constraint that any page's byte should be equal or less
- * than the previous pages byte (mod 256); and they should all be equal
- * except for one transition at the point where we meet the incrementer.
- * (We're running this with the guest stopped).
+ * start_address to < end_address in order. This gives us a constraint
+ * that any page's byte should be equal or less than the previous pages
+ * byte (mod 256); and they should all be equal except for one transition
+ * at the point where we meet the incrementer. (We're running this with
+ * the guest stopped).
*/
unsigned address;
uint8_t first_byte;
@@ -285,7 +287,8 @@ static void check_guests_ram(QTestState *who)
qtest_memread(who, start_address, &first_byte, 1);
last_byte = first_byte;
- for (address = start_address + 4096; address < end_address; address += 4096)
+ for (address = start_address + TEST_MEM_PAGE_SIZE; address < end_address;
+ address += TEST_MEM_PAGE_SIZE)
{
uint8_t b;
qtest_memread(who, address, &b, 1);
@@ -437,6 +440,8 @@ static int test_migrate_start(QTestState **from, QTestState **to,
" -drive file=%s,format=raw"
" -incoming %s",
accel, tmpfs, bootpath, uri);
+ start_address = X86_TEST_MEM_START;
+ end_address = X86_TEST_MEM_END;
} else if (strcmp(arch, "ppc64") == 0) {
cmd_src = g_strdup_printf("-machine accel=%s -m 256M -nodefaults"
" -name source,debug-threads=on"
@@ -451,6 +456,9 @@ static int test_migrate_start(QTestState **from, QTestState **to,
" -serial file:%s/dest_serial"
" -incoming %s",
accel, tmpfs, uri);
+
+ start_address = PPC_TEST_MEM_START;
+ end_address = PPC_TEST_MEM_END;
} else {
g_assert_not_reached();
}
diff --git a/tests/migration/Makefile b/tests/migration/Makefile
new file mode 100644
index 0000000000..dc3b551976
--- /dev/null
+++ b/tests/migration/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2018 Red Hat, Inc. and/or its affiliates
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+#
+
+TARGET_LIST = i386
+
+SRC_PATH = ../..
+
+override define __note
+/* This file is automatically generated from the assembly file in
+ * tests/migration/$@. Edit that file and then run "make all"
+ * inside tests/migration to update, and then remember to send both
+ * the header and the assembler differences in your patch submission.
+ */
+endef
+export __note
+
+find-arch-cross-cc = $(lastword $(shell grep -h "CROSS_CC_GUEST=" $(wildcard $(SRC_PATH)/$(patsubst i386,*86*,$(1))-softmmu/config-target.mak) /dev/null))
+parse-cross-prefix = $(subst gcc,,$(patsubst cc,gcc,$(patsubst CROSS_CC_GUEST="%",%,$(call find-arch-cross-cc,$(1)))))
+gen-cross-prefix = $(patsubst %-,CROSS_PREFIX=%-,$(call parse-cross-prefix,$(1)))
+
+.PHONY: all $(TARGET_LIST)
+
+all: $(TARGET_LIST)
+
+$(TARGET_LIST):
+ $(MAKE) -C $@ $(call gen-cross-prefix,$@)
+
+clean:
+ for target in $(TARGET_LIST); do \
+ $(MAKE) -C $$target clean; \
+ done
diff --git a/tests/migration/i386/Makefile b/tests/migration/i386/Makefile
new file mode 100644
index 0000000000..5c0324134a
--- /dev/null
+++ b/tests/migration/i386/Makefile
@@ -0,0 +1,22 @@
+# To specify cross compiler prefix, use CROSS_PREFIX=
+# $ make CROSS_PREFIX=x86_64-linux-gnu-
+
+.PHONY: all clean
+all: a-b-bootblock.h
+
+a-b-bootblock.h: x86.bootsect
+ echo "$$__note" > header.tmp
+ xxd -i $< | sed -e 's/.*int.*//' >> header.tmp
+ mv header.tmp $@
+
+x86.bootsect: x86.boot
+ dd if=$< of=$@ bs=256 count=2 skip=124
+
+x86.boot: x86.o
+ $(CROSS_PREFIX)objcopy -O binary $< $@
+
+x86.o: a-b-bootblock.S
+ $(CROSS_PREFIX)gcc -m32 -march=i486 -c $< -o $@
+
+clean:
+ @rm -rf *.boot *.o *.bootsect
diff --git a/tests/migration/x86-a-b-bootblock.s b/tests/migration/i386/a-b-bootblock.S
index b1642641a7..3f97f28023 100644
--- a/tests/migration/x86-a-b-bootblock.s
+++ b/tests/migration/i386/a-b-bootblock.S
@@ -3,10 +3,6 @@
# range.
# Outputs an initial 'A' on serial followed by repeated 'B's
#
-# run tests/migration/rebuild-x86-bootblock.sh
-# to regenerate the hex, and remember to include both the .h and .s
-# in any patches.
-#
# Copyright (c) 2016 Red Hat, Inc. and/or its affiliates
# This work is licensed under the terms of the GNU GPL, version 2 or later.
# See the COPYING file in the top-level directory.
diff --git a/tests/migration/x86-a-b-bootblock.h b/tests/migration/i386/a-b-bootblock.h
index 78a151fe2a..7d459d4fde 100644
--- a/tests/migration/x86-a-b-bootblock.h
+++ b/tests/migration/i386/a-b-bootblock.h
@@ -1,7 +1,7 @@
-/* This file is automatically generated from
- * tests/migration/x86-a-b-bootblock.s, edit that and then run
- * tests/migration/rebuild-x86-bootblock.sh to update,
- * and then remember to send both in your patch submission.
+/* This file is automatically generated from the assembly file in
+ * tests/migration/i386. Edit that file and then run "make all"
+ * inside tests/migration to update, and then remember to send both
+ * the header and the assembler differences in your patch submission.
*/
unsigned char x86_bootsect[] = {
0xfa, 0x0f, 0x01, 0x16, 0x74, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
diff --git a/tests/migration/migration-test.h b/tests/migration/migration-test.h
new file mode 100644
index 0000000000..c4c0c526b6
--- /dev/null
+++ b/tests/migration/migration-test.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018 Red Hat, Inc. and/or its affiliates
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef _TEST_MIGRATION_H_
+#define _TEST_MIGRATION_H_
+
+/* Common */
+#define TEST_MEM_PAGE_SIZE 4096
+
+/* x86 */
+#define X86_TEST_MEM_START (1 * 1024 * 1024)
+#define X86_TEST_MEM_END (100 * 1024 * 1024)
+
+/* PPC */
+#define PPC_TEST_MEM_START (1 * 1024 * 1024)
+#define PPC_TEST_MEM_END (100 * 1024 * 1024)
+
+#endif /* _TEST_MIGRATION_H_ */
diff --git a/tests/migration/rebuild-x86-bootblock.sh b/tests/migration/rebuild-x86-bootblock.sh
deleted file mode 100755
index 86cec5d284..0000000000
--- a/tests/migration/rebuild-x86-bootblock.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-# Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
-# This work is licensed under the terms of the GNU GPL, version 2 or later.
-# See the COPYING file in the top-level directory.
-#
-# Author: dgilbert@redhat.com
-
-ASMFILE=$PWD/tests/migration/x86-a-b-bootblock.s
-HEADER=$PWD/tests/migration/x86-a-b-bootblock.h
-
-if [ ! -e "$ASMFILE" ]
-then
- echo "Couldn't find $ASMFILE" >&2
- exit 1
-fi
-
-ASM_WORK_DIR=$(mktemp -d --tmpdir X86BB.XXXXXX)
-cd "$ASM_WORK_DIR" &&
-as --32 -march=i486 "$ASMFILE" -o x86.o &&
-objcopy -O binary x86.o x86.boot &&
-dd if=x86.boot of=x86.bootsect bs=256 count=2 skip=124 &&
-xxd -i x86.bootsect |
-sed -e 's/.*int.*//' > x86.hex &&
-cat - x86.hex <<HERE > "$HEADER"
-/* This file is automatically generated from
- * tests/migration/x86-a-b-bootblock.s, edit that and then run
- * tests/migration/rebuild-x86-bootblock.sh to update,
- * and then remember to send both in your patch submission.
- */
-HERE
-
-rm x86.hex x86.bootsect x86.boot x86.o
-cd .. && rmdir "$ASM_WORK_DIR"
diff --git a/vl.c b/vl.c
index 3b5c9d3f2d..cc55fe04a2 100644
--- a/vl.c
+++ b/vl.c
@@ -4530,6 +4530,7 @@ int main(int argc, char **argv, char **envp)
if (load_snapshot(loadvm, &local_err) < 0) {
error_report_err(local_err);
autostart = 0;
+ exit(1);
}
}