pci/shpc: Move function to generic header file
[qemu.git] / tests / migration-test.c
blob9fd5dadc0d6063df640856304d3d382f7e87703e
1 /*
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"
15 #include "libqtest.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;
27 bool got_stop;
28 static bool uffd_feature_thread_id;
30 #if defined(__linux__)
31 #include <sys/syscall.h>
32 #include <sys/vfs.h>
33 #endif
35 #if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
36 #include <sys/eventfd.h>
37 #include <sys/ioctl.h>
38 #include <linux/userfaultfd.h>
40 static bool ufd_version_check(void)
42 struct uffdio_api api_struct;
43 uint64_t ioctl_mask;
45 int ufd = syscall(__NR_userfaultfd, O_CLOEXEC);
47 if (ufd == -1) {
48 g_test_message("Skipping test: userfaultfd not available");
49 return false;
52 api_struct.api = UFFD_API;
53 api_struct.features = 0;
54 if (ioctl(ufd, UFFDIO_API, &api_struct)) {
55 g_test_message("Skipping test: UFFDIO_API failed");
56 return false;
58 uffd_feature_thread_id = api_struct.features & UFFD_FEATURE_THREAD_ID;
60 ioctl_mask = (__u64)1 << _UFFDIO_REGISTER |
61 (__u64)1 << _UFFDIO_UNREGISTER;
62 if ((api_struct.ioctls & ioctl_mask) != ioctl_mask) {
63 g_test_message("Skipping test: Missing userfault feature");
64 return false;
67 return true;
70 #else
71 static bool ufd_version_check(void)
73 g_test_message("Skipping test: Userfault not available (builtdtime)");
74 return false;
77 #endif
79 static const char *tmpfs;
81 /* A simple PC boot sector that modifies memory (1-100MB) quickly
82 * outputing a 'B' every so often if it's still running.
84 unsigned char bootsect[] = {
85 0xfa, 0x0f, 0x01, 0x16, 0x74, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
86 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02,
88 0xe6, 0x92, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x66, 0xb8, 0x41,
89 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xb3, 0x00, 0xb8, 0x00, 0x00, 0x10,
90 0x00, 0xfe, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40,
91 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x75, 0xe9, 0x66, 0xb8, 0x42, 0x00, 0x66,
92 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xde, 0x66, 0x90, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00,
94 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x27, 0x00, 0x5c, 0x7c,
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
130 static void init_bootfile_x86(const char *bootpath)
132 FILE *bootfile = fopen(bootpath, "wb");
134 g_assert_cmpint(fwrite(bootsect, 512, 1, bootfile), ==, 1);
135 fclose(bootfile);
138 static void init_bootfile_ppc(const char *bootpath)
140 FILE *bootfile;
141 char buf[MIN_NVRAM_SIZE];
142 ChrpNvramPartHdr *header = (ChrpNvramPartHdr *)buf;
144 memset(buf, 0, MIN_NVRAM_SIZE);
146 /* Create a "common" partition in nvram to store boot-command property */
148 header->signature = CHRP_NVPART_SYSTEM;
149 memcpy(header->name, "common", 6);
150 chrp_nvram_finish_partition(header, MIN_NVRAM_SIZE);
152 /* FW_MAX_SIZE is 4MB, but slof.bin is only 900KB,
153 * so let's modify memory between 1MB and 100MB
154 * to do like PC bootsector
157 sprintf(buf + 16,
158 "boot-command=hex .\" _\" begin %x %x do i c@ 1 + i c! 1000 +loop "
159 ".\" B\" 0 until", end_address, start_address);
161 /* Write partition to the NVRAM file */
163 bootfile = fopen(bootpath, "wb");
164 g_assert_cmpint(fwrite(buf, MIN_NVRAM_SIZE, 1, bootfile), ==, 1);
165 fclose(bootfile);
169 * Wait for some output in the serial output file,
170 * we get an 'A' followed by an endless string of 'B's
171 * but on the destination we won't have the A.
173 static void wait_for_serial(const char *side)
175 char *serialpath = g_strdup_printf("%s/%s", tmpfs, side);
176 FILE *serialfile = fopen(serialpath, "r");
177 const char *arch = qtest_get_arch();
178 int started = (strcmp(side, "src_serial") == 0 &&
179 strcmp(arch, "ppc64") == 0) ? 0 : 1;
181 g_free(serialpath);
182 do {
183 int readvalue = fgetc(serialfile);
185 if (!started) {
186 /* SLOF prints its banner before starting test,
187 * to ignore it, mark the start of the test with '_',
188 * ignore all characters until this marker
190 switch (readvalue) {
191 case '_':
192 started = 1;
193 break;
194 case EOF:
195 fseek(serialfile, 0, SEEK_SET);
196 usleep(1000);
197 break;
199 continue;
201 switch (readvalue) {
202 case 'A':
203 /* Fine */
204 break;
206 case 'B':
207 /* It's alive! */
208 fclose(serialfile);
209 return;
211 case EOF:
212 started = (strcmp(side, "src_serial") == 0 &&
213 strcmp(arch, "ppc64") == 0) ? 0 : 1;
214 fseek(serialfile, 0, SEEK_SET);
215 usleep(1000);
216 break;
218 default:
219 fprintf(stderr, "Unexpected %d on %s serial\n", readvalue, side);
220 g_assert_not_reached();
222 } while (true);
226 * Events can get in the way of responses we are actually waiting for.
228 static QDict *wait_command(QTestState *who, const char *command)
230 const char *event_string;
231 QDict *response;
233 response = qtest_qmp(who, command);
235 while (qdict_haskey(response, "event")) {
236 /* OK, it was an event */
237 event_string = qdict_get_str(response, "event");
238 if (!strcmp(event_string, "STOP")) {
239 got_stop = true;
241 QDECREF(response);
242 response = qtest_qmp_receive(who);
244 return response;
249 * It's tricky to use qemu's migration event capability with qtest,
250 * events suddenly appearing confuse the qmp()/hmp() responses.
253 static uint64_t get_migration_pass(QTestState *who)
255 QDict *rsp, *rsp_return, *rsp_ram;
256 uint64_t result;
258 rsp = wait_command(who, "{ 'execute': 'query-migrate' }");
259 rsp_return = qdict_get_qdict(rsp, "return");
260 if (!qdict_haskey(rsp_return, "ram")) {
261 /* Still in setup */
262 result = 0;
263 } else {
264 rsp_ram = qdict_get_qdict(rsp_return, "ram");
265 result = qdict_get_try_int(rsp_ram, "dirty-sync-count", 0);
267 QDECREF(rsp);
268 return result;
271 static void read_blocktime(QTestState *who)
273 QDict *rsp, *rsp_return;
275 rsp = wait_command(who, "{ 'execute': 'query-migrate' }");
276 rsp_return = qdict_get_qdict(rsp, "return");
277 g_assert(qdict_haskey(rsp_return, "postcopy-blocktime"));
278 QDECREF(rsp);
281 static void wait_for_migration_complete(QTestState *who)
283 QDict *rsp, *rsp_return;
284 bool completed;
286 do {
287 const char *status;
289 rsp = wait_command(who, "{ 'execute': 'query-migrate' }");
290 rsp_return = qdict_get_qdict(rsp, "return");
291 status = qdict_get_str(rsp_return, "status");
292 completed = strcmp(status, "completed") == 0;
293 g_assert_cmpstr(status, !=, "failed");
294 QDECREF(rsp);
295 usleep(1000 * 100);
296 } while (!completed);
299 static void wait_for_migration_pass(QTestState *who)
301 uint64_t initial_pass = get_migration_pass(who);
302 uint64_t pass;
304 /* Wait for the 1st sync */
305 do {
306 initial_pass = get_migration_pass(who);
307 if (got_stop || initial_pass) {
308 break;
310 usleep(1000 * 100);
311 } while (true);
313 do {
314 usleep(1000 * 100);
315 pass = get_migration_pass(who);
316 } while (pass == initial_pass && !got_stop);
319 static void check_guests_ram(QTestState *who)
321 /* Our ASM test will have been incrementing one byte from each page from
322 * 1MB to <100MB in order.
323 * This gives us a constraint that any page's byte should be equal or less
324 * than the previous pages byte (mod 256); and they should all be equal
325 * except for one transition at the point where we meet the incrementer.
326 * (We're running this with the guest stopped).
328 unsigned address;
329 uint8_t first_byte;
330 uint8_t last_byte;
331 bool hit_edge = false;
332 bool bad = false;
334 qtest_memread(who, start_address, &first_byte, 1);
335 last_byte = first_byte;
337 for (address = start_address + 4096; address < end_address; address += 4096)
339 uint8_t b;
340 qtest_memread(who, address, &b, 1);
341 if (b != last_byte) {
342 if (((b + 1) % 256) == last_byte && !hit_edge) {
343 /* This is OK, the guest stopped at the point of
344 * incrementing the previous page but didn't get
345 * to us yet.
347 hit_edge = true;
348 } else {
349 fprintf(stderr, "Memory content inconsistency at %x"
350 " first_byte = %x last_byte = %x current = %x"
351 " hit_edge = %x\n",
352 address, first_byte, last_byte, b, hit_edge);
353 bad = true;
356 last_byte = b;
358 g_assert_false(bad);
361 static void cleanup(const char *filename)
363 char *path = g_strdup_printf("%s/%s", tmpfs, filename);
365 unlink(path);
366 g_free(path);
369 static void migrate_check_parameter(QTestState *who, const char *parameter,
370 const char *value)
372 QDict *rsp, *rsp_return;
373 char *result;
375 rsp = wait_command(who, "{ 'execute': 'query-migrate-parameters' }");
376 rsp_return = qdict_get_qdict(rsp, "return");
377 result = g_strdup_printf("%" PRId64,
378 qdict_get_try_int(rsp_return, parameter, -1));
379 g_assert_cmpstr(result, ==, value);
380 g_free(result);
381 QDECREF(rsp);
384 static void migrate_set_downtime(QTestState *who, const double value)
386 QDict *rsp;
387 gchar *cmd;
388 char *expected;
389 int64_t result_int;
391 cmd = g_strdup_printf("{ 'execute': 'migrate_set_downtime',"
392 "'arguments': { 'value': %g } }", value);
393 rsp = qtest_qmp(who, cmd);
394 g_free(cmd);
395 g_assert(qdict_haskey(rsp, "return"));
396 QDECREF(rsp);
397 result_int = value * 1000L;
398 expected = g_strdup_printf("%" PRId64, result_int);
399 migrate_check_parameter(who, "downtime-limit", expected);
400 g_free(expected);
403 static void migrate_set_speed(QTestState *who, const char *value)
405 QDict *rsp;
406 gchar *cmd;
408 cmd = g_strdup_printf("{ 'execute': 'migrate_set_speed',"
409 "'arguments': { 'value': %s } }", value);
410 rsp = qtest_qmp(who, cmd);
411 g_free(cmd);
412 g_assert(qdict_haskey(rsp, "return"));
413 QDECREF(rsp);
414 migrate_check_parameter(who, "max-bandwidth", value);
417 static void migrate_set_capability(QTestState *who, const char *capability,
418 const char *value)
420 QDict *rsp;
421 gchar *cmd;
423 cmd = g_strdup_printf("{ 'execute': 'migrate-set-capabilities',"
424 "'arguments': { "
425 "'capabilities': [ { "
426 "'capability': '%s', 'state': %s } ] } }",
427 capability, value);
428 rsp = qtest_qmp(who, cmd);
429 g_free(cmd);
430 g_assert(qdict_haskey(rsp, "return"));
431 QDECREF(rsp);
434 static void migrate(QTestState *who, const char *uri)
436 QDict *rsp;
437 gchar *cmd;
439 cmd = g_strdup_printf("{ 'execute': 'migrate',"
440 "'arguments': { 'uri': '%s' } }",
441 uri);
442 rsp = qtest_qmp(who, cmd);
443 g_free(cmd);
444 g_assert(qdict_haskey(rsp, "return"));
445 QDECREF(rsp);
448 static void test_migrate_start(QTestState **from, QTestState **to,
449 const char *uri)
451 gchar *cmd_src, *cmd_dst;
452 char *bootpath = g_strdup_printf("%s/bootsect", tmpfs);
453 const char *arch = qtest_get_arch();
455 got_stop = false;
457 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
458 init_bootfile_x86(bootpath);
459 cmd_src = g_strdup_printf("-machine accel=kvm:tcg -m 150M"
460 " -name pcsource,debug-threads=on"
461 " -serial file:%s/src_serial"
462 " -drive file=%s,format=raw",
463 tmpfs, bootpath);
464 cmd_dst = g_strdup_printf("-machine accel=kvm:tcg -m 150M"
465 " -name pcdest,debug-threads=on"
466 " -serial file:%s/dest_serial"
467 " -drive file=%s,format=raw"
468 " -incoming %s",
469 tmpfs, bootpath, uri);
470 } else if (strcmp(arch, "ppc64") == 0) {
471 const char *accel;
473 /* On ppc64, the test only works with kvm-hv, but not with kvm-pr */
474 accel = access("/sys/module/kvm_hv", F_OK) ? "tcg" : "kvm:tcg";
475 init_bootfile_ppc(bootpath);
476 cmd_src = g_strdup_printf("-machine accel=%s -m 256M"
477 " -name pcsource,debug-threads=on"
478 " -serial file:%s/src_serial"
479 " -drive file=%s,if=pflash,format=raw",
480 accel, tmpfs, bootpath);
481 cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
482 " -name pcdest,debug-threads=on"
483 " -serial file:%s/dest_serial"
484 " -incoming %s",
485 accel, tmpfs, uri);
486 } else {
487 g_assert_not_reached();
490 g_free(bootpath);
492 *from = qtest_start(cmd_src);
493 g_free(cmd_src);
495 *to = qtest_init(cmd_dst);
496 g_free(cmd_dst);
499 static void test_migrate_end(QTestState *from, QTestState *to)
501 unsigned char dest_byte_a, dest_byte_b, dest_byte_c, dest_byte_d;
503 qtest_quit(from);
505 qtest_memread(to, start_address, &dest_byte_a, 1);
507 /* Destination still running, wait for a byte to change */
508 do {
509 qtest_memread(to, start_address, &dest_byte_b, 1);
510 usleep(10 * 1000);
511 } while (dest_byte_a == dest_byte_b);
513 qtest_qmp_discard_response(to, "{ 'execute' : 'stop'}");
514 /* With it stopped, check nothing changes */
515 qtest_memread(to, start_address, &dest_byte_c, 1);
516 sleep(1);
517 qtest_memread(to, start_address, &dest_byte_d, 1);
518 g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
520 check_guests_ram(to);
522 qtest_quit(to);
524 cleanup("bootsect");
525 cleanup("migsocket");
526 cleanup("src_serial");
527 cleanup("dest_serial");
530 static void test_migrate(void)
532 char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
533 QTestState *from, *to;
534 QDict *rsp;
536 test_migrate_start(&from, &to, uri);
538 migrate_set_capability(from, "postcopy-ram", "true");
539 migrate_set_capability(to, "postcopy-ram", "true");
540 migrate_set_capability(to, "postcopy-blocktime", "true");
542 /* We want to pick a speed slow enough that the test completes
543 * quickly, but that it doesn't complete precopy even on a slow
544 * machine, so also set the downtime.
546 migrate_set_speed(from, "100000000");
547 migrate_set_downtime(from, 0.001);
549 /* Wait for the first serial output from the source */
550 wait_for_serial("src_serial");
552 migrate(from, uri);
554 wait_for_migration_pass(from);
556 rsp = wait_command(from, "{ 'execute': 'migrate-start-postcopy' }");
557 g_assert(qdict_haskey(rsp, "return"));
558 QDECREF(rsp);
560 if (!got_stop) {
561 qtest_qmp_eventwait(from, "STOP");
564 qtest_qmp_eventwait(to, "RESUME");
566 wait_for_serial("dest_serial");
567 wait_for_migration_complete(from);
569 if (uffd_feature_thread_id) {
570 read_blocktime(to);
572 g_free(uri);
574 test_migrate_end(from, to);
577 int main(int argc, char **argv)
579 char template[] = "/tmp/migration-test-XXXXXX";
580 int ret;
582 g_test_init(&argc, &argv, NULL);
584 if (!ufd_version_check()) {
585 return 0;
588 tmpfs = mkdtemp(template);
589 if (!tmpfs) {
590 g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
592 g_assert(tmpfs);
594 module_call_init(MODULE_INIT_QOM);
596 qtest_add_func("/migration/postcopy/unix", test_migrate);
598 ret = g_test_run();
600 g_assert_cmpint(ret, ==, 0);
602 ret = rmdir(tmpfs);
603 if (ret != 0) {
604 g_test_message("unable to rmdir: path (%s): %s\n",
605 tmpfs, strerror(errno));
608 return ret;