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 *wait_command(QTestState *who, const char *command)
228 const char *event_string;
231 response = qtest_qmp(who, command);
233 while (qdict_haskey(response, "event")) {
234 /* OK, it was an event */
235 event_string = qdict_get_str(response, "event");
236 if (!strcmp(event_string, "STOP")) {
240 response = qtest_qmp_receive(who);
247 * It's tricky to use qemu's migration event capability with qtest,
248 * events suddenly appearing confuse the qmp()/hmp() responses.
251 static uint64_t get_migration_pass(QTestState *who)
253 QDict *rsp, *rsp_return, *rsp_ram;
256 rsp = wait_command(who, "{ 'execute': 'query-migrate' }");
257 rsp_return = qdict_get_qdict(rsp, "return");
258 if (!qdict_haskey(rsp_return, "ram")) {
262 rsp_ram = qdict_get_qdict(rsp_return, "ram");
263 result = qdict_get_try_int(rsp_ram, "dirty-sync-count", 0);
269 static void wait_for_migration_complete(QTestState *who)
271 QDict *rsp, *rsp_return;
277 rsp = wait_command(who, "{ 'execute': 'query-migrate' }");
278 rsp_return = qdict_get_qdict(rsp, "return");
279 status = qdict_get_str(rsp_return, "status");
280 completed = strcmp(status, "completed") == 0;
281 g_assert_cmpstr(status, !=, "failed");
284 } while (!completed);
287 static void wait_for_migration_pass(QTestState *who)
289 uint64_t initial_pass = get_migration_pass(who);
292 /* Wait for the 1st sync */
294 initial_pass = get_migration_pass(who);
295 if (got_stop || initial_pass) {
303 pass = get_migration_pass(who);
304 } while (pass == initial_pass && !got_stop);
307 static void check_guests_ram(QTestState *who)
309 /* Our ASM test will have been incrementing one byte from each page from
310 * 1MB to <100MB in order.
311 * This gives us a constraint that any page's byte should be equal or less
312 * than the previous pages byte (mod 256); and they should all be equal
313 * except for one transition at the point where we meet the incrementer.
314 * (We're running this with the guest stopped).
319 bool hit_edge = false;
322 qtest_memread(who, start_address, &first_byte, 1);
323 last_byte = first_byte;
325 for (address = start_address + 4096; address < end_address; address += 4096)
328 qtest_memread(who, address, &b, 1);
329 if (b != last_byte) {
330 if (((b + 1) % 256) == last_byte && !hit_edge) {
331 /* This is OK, the guest stopped at the point of
332 * incrementing the previous page but didn't get
337 fprintf(stderr, "Memory content inconsistency at %x"
338 " first_byte = %x last_byte = %x current = %x"
340 address, first_byte, last_byte, b, hit_edge);
349 static void cleanup(const char *filename)
351 char *path = g_strdup_printf("%s/%s", tmpfs, filename);
357 static void migrate_check_parameter(QTestState *who, const char *parameter,
360 QDict *rsp, *rsp_return;
363 rsp = wait_command(who, "{ 'execute': 'query-migrate-parameters' }");
364 rsp_return = qdict_get_qdict(rsp, "return");
365 result = g_strdup_printf("%" PRId64,
366 qdict_get_try_int(rsp_return, parameter, -1));
367 g_assert_cmpstr(result, ==, value);
372 static void migrate_set_parameter(QTestState *who, const char *parameter,
378 cmd = g_strdup_printf("{ 'execute': 'migrate-set-parameters',"
379 "'arguments': { '%s': %s } }",
381 rsp = qtest_qmp(who, cmd);
383 g_assert(qdict_haskey(rsp, "return"));
385 migrate_check_parameter(who, parameter, value);
388 static void migrate_set_capability(QTestState *who, const char *capability,
394 cmd = g_strdup_printf("{ 'execute': 'migrate-set-capabilities',"
396 "'capabilities': [ { "
397 "'capability': '%s', 'state': %s } ] } }",
399 rsp = qtest_qmp(who, cmd);
401 g_assert(qdict_haskey(rsp, "return"));
405 static void migrate(QTestState *who, const char *uri)
410 cmd = g_strdup_printf("{ 'execute': 'migrate',"
411 "'arguments': { 'uri': '%s' } }",
413 rsp = qtest_qmp(who, cmd);
415 g_assert(qdict_haskey(rsp, "return"));
419 static void test_migrate_start(QTestState **from, QTestState **to,
422 gchar *cmd_src, *cmd_dst;
423 char *bootpath = g_strdup_printf("%s/bootsect", tmpfs);
424 const char *arch = qtest_get_arch();
425 const char *accel = "kvm:tcg";
429 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
430 init_bootfile_x86(bootpath);
431 cmd_src = g_strdup_printf("-machine accel=%s -m 150M"
432 " -name source,debug-threads=on"
433 " -serial file:%s/src_serial"
434 " -drive file=%s,format=raw",
435 accel, tmpfs, bootpath);
436 cmd_dst = g_strdup_printf("-machine accel=%s -m 150M"
437 " -name target,debug-threads=on"
438 " -serial file:%s/dest_serial"
439 " -drive file=%s,format=raw"
441 accel, tmpfs, bootpath, uri);
442 } else if (strcmp(arch, "ppc64") == 0) {
444 /* On ppc64, the test only works with kvm-hv, but not with kvm-pr */
445 if (access("/sys/module/kvm_hv", F_OK)) {
448 init_bootfile_ppc(bootpath);
449 cmd_src = g_strdup_printf("-machine accel=%s -m 256M"
450 " -name source,debug-threads=on"
451 " -serial file:%s/src_serial"
452 " -drive file=%s,if=pflash,format=raw",
453 accel, tmpfs, bootpath);
454 cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
455 " -name target,debug-threads=on"
456 " -serial file:%s/dest_serial"
460 g_assert_not_reached();
465 *from = qtest_start(cmd_src);
468 *to = qtest_init(cmd_dst);
472 static void test_migrate_end(QTestState *from, QTestState *to)
474 unsigned char dest_byte_a, dest_byte_b, dest_byte_c, dest_byte_d;
478 qtest_memread(to, start_address, &dest_byte_a, 1);
480 /* Destination still running, wait for a byte to change */
482 qtest_memread(to, start_address, &dest_byte_b, 1);
484 } while (dest_byte_a == dest_byte_b);
486 qtest_qmp_discard_response(to, "{ 'execute' : 'stop'}");
487 /* With it stopped, check nothing changes */
488 qtest_memread(to, start_address, &dest_byte_c, 1);
490 qtest_memread(to, start_address, &dest_byte_d, 1);
491 g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
493 check_guests_ram(to);
498 cleanup("migsocket");
499 cleanup("src_serial");
500 cleanup("dest_serial");
503 static void deprecated_set_downtime(QTestState *who, const double value)
510 cmd = g_strdup_printf("{ 'execute': 'migrate_set_downtime',"
511 "'arguments': { 'value': %g } }", value);
512 rsp = qtest_qmp(who, cmd);
514 g_assert(qdict_haskey(rsp, "return"));
516 result_int = value * 1000L;
517 expected = g_strdup_printf("%" PRId64, result_int);
518 migrate_check_parameter(who, "downtime-limit", expected);
522 static void deprecated_set_speed(QTestState *who, const char *value)
527 cmd = g_strdup_printf("{ 'execute': 'migrate_set_speed',"
528 "'arguments': { 'value': %s } }", value);
529 rsp = qtest_qmp(who, cmd);
531 g_assert(qdict_haskey(rsp, "return"));
533 migrate_check_parameter(who, "max-bandwidth", value);
536 static void test_deprecated(void)
540 from = qtest_start("");
542 deprecated_set_downtime(from, 0.12345);
543 deprecated_set_speed(from, "12345");
548 static void test_migrate(void)
550 char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
551 QTestState *from, *to;
554 test_migrate_start(&from, &to, uri);
556 migrate_set_capability(from, "postcopy-ram", "true");
557 migrate_set_capability(to, "postcopy-ram", "true");
559 /* We want to pick a speed slow enough that the test completes
560 * quickly, but that it doesn't complete precopy even on a slow
561 * machine, so also set the downtime.
563 migrate_set_parameter(from, "max-bandwidth", "100000000");
564 migrate_set_parameter(from, "downtime-limit", "1");
566 /* Wait for the first serial output from the source */
567 wait_for_serial("src_serial");
571 wait_for_migration_pass(from);
573 rsp = wait_command(from, "{ 'execute': 'migrate-start-postcopy' }");
574 g_assert(qdict_haskey(rsp, "return"));
578 qtest_qmp_eventwait(from, "STOP");
581 qtest_qmp_eventwait(to, "RESUME");
583 wait_for_serial("dest_serial");
584 wait_for_migration_complete(from);
588 test_migrate_end(from, to);
591 int main(int argc, char **argv)
593 char template[] = "/tmp/migration-test-XXXXXX";
596 g_test_init(&argc, &argv, NULL);
598 if (!ufd_version_check()) {
602 tmpfs = mkdtemp(template);
604 g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
608 module_call_init(MODULE_INIT_QOM);
610 qtest_add_func("/migration/postcopy/unix", test_migrate);
611 qtest_add_func("/migration/deprecated", test_deprecated);
615 g_assert_cmpint(ret, ==, 0);
619 g_test_message("unable to rmdir: path (%s): %s\n",
620 tmpfs, strerror(errno));