2 * QTest testcase for migration
4 * Copyright (c) 2016 Red Hat, Inc. and/or its affiliates
5 * based on the vhost-user-test.c that is:
6 * Copyright (c) 2014 Virtual Open Systems Sarl.
8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
9 * See the COPYING file in the top-level directory.
13 #include "qemu/osdep.h"
16 #include "qemu/option.h"
17 #include "qemu/range.h"
18 #include "qemu/sockets.h"
19 #include "chardev/char.h"
20 #include "sysemu/sysemu.h"
21 #include "hw/nvram/chrp_nvram.h"
23 #define MIN_NVRAM_SIZE 8192 /* from spapr_nvram.c */
25 const unsigned start_address = 1024 * 1024;
26 const unsigned end_address = 100 * 1024 * 1024;
29 #if defined(__linux__)
30 #include <sys/syscall.h>
34 #if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
35 #include <sys/eventfd.h>
36 #include <sys/ioctl.h>
37 #include <linux/userfaultfd.h>
39 static bool ufd_version_check(void)
41 struct uffdio_api api_struct;
44 int ufd = syscall(__NR_userfaultfd, O_CLOEXEC);
47 g_test_message("Skipping test: userfaultfd not available");
51 api_struct.api = UFFD_API;
52 api_struct.features = 0;
53 if (ioctl(ufd, UFFDIO_API, &api_struct)) {
54 g_test_message("Skipping test: UFFDIO_API failed");
58 ioctl_mask = (__u64)1 << _UFFDIO_REGISTER |
59 (__u64)1 << _UFFDIO_UNREGISTER;
60 if ((api_struct.ioctls & ioctl_mask) != ioctl_mask) {
61 g_test_message("Skipping test: Missing userfault feature");
69 static bool ufd_version_check(void)
71 g_test_message("Skipping test: Userfault not available (builtdtime)");
77 static const char *tmpfs;
79 /* A simple PC boot sector that modifies memory (1-100MB) quickly
80 * outputing a 'B' every so often if it's still running.
82 unsigned char bootsect[] = {
83 0xfa, 0x0f, 0x01, 0x16, 0x74, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
84 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02,
86 0xe6, 0x92, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x66, 0xb8, 0x41,
87 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xb3, 0x00, 0xb8, 0x00, 0x00, 0x10,
88 0x00, 0xfe, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40,
89 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x75, 0xe9, 0x66, 0xb8, 0x42, 0x00, 0x66,
90 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xde, 0x66, 0x90, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00,
92 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x27, 0x00, 0x5c, 0x7c,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
128 static void init_bootfile_x86(const char *bootpath)
130 FILE *bootfile = fopen(bootpath, "wb");
132 g_assert_cmpint(fwrite(bootsect, 512, 1, bootfile), ==, 1);
136 static void init_bootfile_ppc(const char *bootpath)
139 char buf[MIN_NVRAM_SIZE];
140 ChrpNvramPartHdr *header = (ChrpNvramPartHdr *)buf;
142 memset(buf, 0, MIN_NVRAM_SIZE);
144 /* Create a "common" partition in nvram to store boot-command property */
146 header->signature = CHRP_NVPART_SYSTEM;
147 memcpy(header->name, "common", 6);
148 chrp_nvram_finish_partition(header, MIN_NVRAM_SIZE);
150 /* FW_MAX_SIZE is 4MB, but slof.bin is only 900KB,
151 * so let's modify memory between 1MB and 100MB
152 * to do like PC bootsector
156 "boot-command=hex .\" _\" begin %x %x do i c@ 1 + i c! 1000 +loop "
157 ".\" B\" 0 until", end_address, start_address);
159 /* Write partition to the NVRAM file */
161 bootfile = fopen(bootpath, "wb");
162 g_assert_cmpint(fwrite(buf, MIN_NVRAM_SIZE, 1, bootfile), ==, 1);
167 * Wait for some output in the serial output file,
168 * we get an 'A' followed by an endless string of 'B's
169 * but on the destination we won't have the A.
171 static void wait_for_serial(const char *side)
173 char *serialpath = g_strdup_printf("%s/%s", tmpfs, side);
174 FILE *serialfile = fopen(serialpath, "r");
175 const char *arch = qtest_get_arch();
176 int started = (strcmp(side, "src_serial") == 0 &&
177 strcmp(arch, "ppc64") == 0) ? 0 : 1;
181 int readvalue = fgetc(serialfile);
184 /* SLOF prints its banner before starting test,
185 * to ignore it, mark the start of the test with '_',
186 * ignore all characters until this marker
193 fseek(serialfile, 0, SEEK_SET);
210 started = (strcmp(side, "src_serial") == 0 &&
211 strcmp(arch, "ppc64") == 0) ? 0 : 1;
212 fseek(serialfile, 0, SEEK_SET);
217 fprintf(stderr, "Unexpected %d on %s serial\n", readvalue, side);
218 g_assert_not_reached();
224 * Events can get in the way of responses we are actually waiting for.
226 static QDict *return_or_event(QDict *response)
228 const char *event_string;
229 if (!qdict_haskey(response, "event")) {
233 /* OK, it was an event */
234 event_string = qdict_get_str(response, "event");
235 if (!strcmp(event_string, "STOP")) {
239 return return_or_event(qtest_qmp_receive(global_qtest));
244 * It's tricky to use qemu's migration event capability with qtest,
245 * events suddenly appearing confuse the qmp()/hmp() responses.
248 static uint64_t get_migration_pass(void)
250 QDict *rsp, *rsp_return, *rsp_ram;
253 rsp = return_or_event(qmp("{ 'execute': 'query-migrate' }"));
254 rsp_return = qdict_get_qdict(rsp, "return");
255 if (!qdict_haskey(rsp_return, "ram")) {
259 rsp_ram = qdict_get_qdict(rsp_return, "ram");
260 result = qdict_get_try_int(rsp_ram, "dirty-sync-count", 0);
266 static void wait_for_migration_complete(void)
268 QDict *rsp, *rsp_return;
274 rsp = return_or_event(qmp("{ 'execute': 'query-migrate' }"));
275 rsp_return = qdict_get_qdict(rsp, "return");
276 status = qdict_get_str(rsp_return, "status");
277 completed = strcmp(status, "completed") == 0;
278 g_assert_cmpstr(status, !=, "failed");
281 } while (!completed);
284 static void wait_for_migration_pass(void)
286 uint64_t initial_pass = get_migration_pass();
289 /* Wait for the 1st sync */
291 initial_pass = get_migration_pass();
292 if (got_stop || initial_pass) {
300 pass = get_migration_pass();
301 } while (pass == initial_pass && !got_stop);
304 static void check_guests_ram(void)
306 /* Our ASM test will have been incrementing one byte from each page from
307 * 1MB to <100MB in order.
308 * This gives us a constraint that any page's byte should be equal or less
309 * than the previous pages byte (mod 256); and they should all be equal
310 * except for one transition at the point where we meet the incrementer.
311 * (We're running this with the guest stopped).
316 bool hit_edge = false;
319 qtest_memread(global_qtest, start_address, &first_byte, 1);
320 last_byte = first_byte;
322 for (address = start_address + 4096; address < end_address; address += 4096)
325 qtest_memread(global_qtest, address, &b, 1);
326 if (b != last_byte) {
327 if (((b + 1) % 256) == last_byte && !hit_edge) {
328 /* This is OK, the guest stopped at the point of
329 * incrementing the previous page but didn't get
334 fprintf(stderr, "Memory content inconsistency at %x"
335 " first_byte = %x last_byte = %x current = %x"
337 address, first_byte, last_byte, b, hit_edge);
346 static void cleanup(const char *filename)
348 char *path = g_strdup_printf("%s/%s", tmpfs, filename);
354 static void test_migrate(void)
356 char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
357 QTestState *global = global_qtest, *from, *to;
358 unsigned char dest_byte_a, dest_byte_b, dest_byte_c, dest_byte_d;
359 gchar *cmd, *cmd_src, *cmd_dst;
362 char *bootpath = g_strdup_printf("%s/bootsect", tmpfs);
363 const char *arch = qtest_get_arch();
367 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
368 init_bootfile_x86(bootpath);
369 cmd_src = g_strdup_printf("-machine accel=kvm:tcg -m 150M"
370 " -name pcsource,debug-threads=on"
371 " -serial file:%s/src_serial"
372 " -drive file=%s,format=raw",
374 cmd_dst = g_strdup_printf("-machine accel=kvm:tcg -m 150M"
375 " -name pcdest,debug-threads=on"
376 " -serial file:%s/dest_serial"
377 " -drive file=%s,format=raw"
379 tmpfs, bootpath, uri);
380 } else if (strcmp(arch, "ppc64") == 0) {
383 /* On ppc64, the test only works with kvm-hv, but not with kvm-pr */
384 accel = access("/sys/module/kvm_hv", F_OK) ? "tcg" : "kvm:tcg";
385 init_bootfile_ppc(bootpath);
386 cmd_src = g_strdup_printf("-machine accel=%s -m 256M"
387 " -name pcsource,debug-threads=on"
388 " -serial file:%s/src_serial"
389 " -drive file=%s,if=pflash,format=raw",
390 accel, tmpfs, bootpath);
391 cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
392 " -name pcdest,debug-threads=on"
393 " -serial file:%s/dest_serial"
397 g_assert_not_reached();
402 from = qtest_start(cmd_src);
405 to = qtest_init(cmd_dst);
409 rsp = qmp("{ 'execute': 'migrate-set-capabilities',"
411 "'capabilities': [ {"
412 "'capability': 'postcopy-ram',"
413 "'state': true } ] } }");
414 g_assert(qdict_haskey(rsp, "return"));
418 rsp = qmp("{ 'execute': 'migrate-set-capabilities',"
420 "'capabilities': [ {"
421 "'capability': 'postcopy-ram',"
422 "'state': true } ] } }");
423 g_assert(qdict_haskey(rsp, "return"));
426 /* We want to pick a speed slow enough that the test completes
427 * quickly, but that it doesn't complete precopy even on a slow
428 * machine, so also set the downtime.
431 rsp = qmp("{ 'execute': 'migrate_set_speed',"
432 "'arguments': { 'value': 100000000 } }");
433 g_assert(qdict_haskey(rsp, "return"));
436 /* 1ms downtime - it should never finish precopy */
437 rsp = qmp("{ 'execute': 'migrate_set_downtime',"
438 "'arguments': { 'value': 0.001 } }");
439 g_assert(qdict_haskey(rsp, "return"));
443 /* Wait for the first serial output from the source */
444 wait_for_serial("src_serial");
446 cmd = g_strdup_printf("{ 'execute': 'migrate',"
447 "'arguments': { 'uri': '%s' } }",
451 g_assert(qdict_haskey(rsp, "return"));
454 wait_for_migration_pass();
456 rsp = return_or_event(qmp("{ 'execute': 'migrate-start-postcopy' }"));
457 g_assert(qdict_haskey(rsp, "return"));
461 qmp_eventwait("STOP");
465 qmp_eventwait("RESUME");
467 wait_for_serial("dest_serial");
469 wait_for_migration_complete();
475 qtest_memread(to, start_address, &dest_byte_a, 1);
477 /* Destination still running, wait for a byte to change */
479 qtest_memread(to, start_address, &dest_byte_b, 1);
481 } while (dest_byte_a == dest_byte_b);
483 qmp_discard_response("{ 'execute' : 'stop'}");
484 /* With it stopped, check nothing changes */
485 qtest_memread(to, start_address, &dest_byte_c, 1);
487 qtest_memread(to, start_address, &dest_byte_d, 1);
488 g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
495 global_qtest = global;
498 cleanup("migsocket");
499 cleanup("src_serial");
500 cleanup("dest_serial");
503 int main(int argc, char **argv)
505 char template[] = "/tmp/migration-test-XXXXXX";
508 g_test_init(&argc, &argv, NULL);
510 if (!ufd_version_check()) {
514 tmpfs = mkdtemp(template);
516 g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
520 module_call_init(MODULE_INIT_QOM);
522 qtest_add_func("/migration/postcopy/unix", test_migrate);
526 g_assert_cmpint(ret, ==, 0);
530 g_test_message("unable to rmdir: path (%s): %s\n",
531 tmpfs, strerror(errno));