ui: avoid 'local_err' variable shadowing in VNC SASL auth
[qemu/ar7.git] / tests / migration-test.c
blobd0abad40f5e9cbd72c13f0c1824bd3613eace2eb
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 "qapi/qmp/qdict.h"
17 #include "qemu/option.h"
18 #include "qemu/range.h"
19 #include "qemu/sockets.h"
20 #include "chardev/char.h"
21 #include "sysemu/sysemu.h"
22 #include "hw/nvram/chrp_nvram.h"
24 #define MIN_NVRAM_SIZE 8192 /* from spapr_nvram.c */
26 const unsigned start_address = 1024 * 1024;
27 const unsigned end_address = 100 * 1024 * 1024;
28 bool got_stop;
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;
59 ioctl_mask = (__u64)1 << _UFFDIO_REGISTER |
60 (__u64)1 << _UFFDIO_UNREGISTER;
61 if ((api_struct.ioctls & ioctl_mask) != ioctl_mask) {
62 g_test_message("Skipping test: Missing userfault feature");
63 return false;
66 return true;
69 #else
70 static bool ufd_version_check(void)
72 g_test_message("Skipping test: Userfault not available (builtdtime)");
73 return false;
76 #endif
78 static const char *tmpfs;
80 /* A simple PC boot sector that modifies memory (1-100MB) quickly
81 * outputing a 'B' every so often if it's still running.
83 unsigned char bootsect[] = {
84 0xfa, 0x0f, 0x01, 0x16, 0x74, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
85 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02,
87 0xe6, 0x92, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x66, 0xb8, 0x41,
88 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xb3, 0x00, 0xb8, 0x00, 0x00, 0x10,
89 0x00, 0xfe, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40,
90 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x75, 0xe9, 0x66, 0xb8, 0x42, 0x00, 0x66,
91 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xde, 0x66, 0x90, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00,
93 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x27, 0x00, 0x5c, 0x7c,
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
129 static void init_bootfile_x86(const char *bootpath)
131 FILE *bootfile = fopen(bootpath, "wb");
133 g_assert_cmpint(fwrite(bootsect, 512, 1, bootfile), ==, 1);
134 fclose(bootfile);
137 static void init_bootfile_ppc(const char *bootpath)
139 FILE *bootfile;
140 char buf[MIN_NVRAM_SIZE];
141 ChrpNvramPartHdr *header = (ChrpNvramPartHdr *)buf;
143 memset(buf, 0, MIN_NVRAM_SIZE);
145 /* Create a "common" partition in nvram to store boot-command property */
147 header->signature = CHRP_NVPART_SYSTEM;
148 memcpy(header->name, "common", 6);
149 chrp_nvram_finish_partition(header, MIN_NVRAM_SIZE);
151 /* FW_MAX_SIZE is 4MB, but slof.bin is only 900KB,
152 * so let's modify memory between 1MB and 100MB
153 * to do like PC bootsector
156 sprintf(buf + 16,
157 "boot-command=hex .\" _\" begin %x %x do i c@ 1 + i c! 1000 +loop "
158 ".\" B\" 0 until", end_address, start_address);
160 /* Write partition to the NVRAM file */
162 bootfile = fopen(bootpath, "wb");
163 g_assert_cmpint(fwrite(buf, MIN_NVRAM_SIZE, 1, bootfile), ==, 1);
164 fclose(bootfile);
168 * Wait for some output in the serial output file,
169 * we get an 'A' followed by an endless string of 'B's
170 * but on the destination we won't have the A.
172 static void wait_for_serial(const char *side)
174 char *serialpath = g_strdup_printf("%s/%s", tmpfs, side);
175 FILE *serialfile = fopen(serialpath, "r");
176 const char *arch = qtest_get_arch();
177 int started = (strcmp(side, "src_serial") == 0 &&
178 strcmp(arch, "ppc64") == 0) ? 0 : 1;
180 g_free(serialpath);
181 do {
182 int readvalue = fgetc(serialfile);
184 if (!started) {
185 /* SLOF prints its banner before starting test,
186 * to ignore it, mark the start of the test with '_',
187 * ignore all characters until this marker
189 switch (readvalue) {
190 case '_':
191 started = 1;
192 break;
193 case EOF:
194 fseek(serialfile, 0, SEEK_SET);
195 usleep(1000);
196 break;
198 continue;
200 switch (readvalue) {
201 case 'A':
202 /* Fine */
203 break;
205 case 'B':
206 /* It's alive! */
207 fclose(serialfile);
208 return;
210 case EOF:
211 started = (strcmp(side, "src_serial") == 0 &&
212 strcmp(arch, "ppc64") == 0) ? 0 : 1;
213 fseek(serialfile, 0, SEEK_SET);
214 usleep(1000);
215 break;
217 default:
218 fprintf(stderr, "Unexpected %d on %s serial\n", readvalue, side);
219 g_assert_not_reached();
221 } while (true);
225 * Events can get in the way of responses we are actually waiting for.
227 static QDict *wait_command(QTestState *who, const char *command)
229 const char *event_string;
230 QDict *response;
232 response = qtest_qmp(who, command);
234 while (qdict_haskey(response, "event")) {
235 /* OK, it was an event */
236 event_string = qdict_get_str(response, "event");
237 if (!strcmp(event_string, "STOP")) {
238 got_stop = true;
240 QDECREF(response);
241 response = qtest_qmp_receive(who);
243 return response;
248 * It's tricky to use qemu's migration event capability with qtest,
249 * events suddenly appearing confuse the qmp()/hmp() responses.
252 static uint64_t get_migration_pass(QTestState *who)
254 QDict *rsp, *rsp_return, *rsp_ram;
255 uint64_t result;
257 rsp = wait_command(who, "{ 'execute': 'query-migrate' }");
258 rsp_return = qdict_get_qdict(rsp, "return");
259 if (!qdict_haskey(rsp_return, "ram")) {
260 /* Still in setup */
261 result = 0;
262 } else {
263 rsp_ram = qdict_get_qdict(rsp_return, "ram");
264 result = qdict_get_try_int(rsp_ram, "dirty-sync-count", 0);
266 QDECREF(rsp);
267 return result;
270 static void wait_for_migration_complete(QTestState *who)
272 while (true) {
273 QDict *rsp, *rsp_return;
274 bool completed;
275 const char *status;
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");
282 QDECREF(rsp);
283 if (completed) {
284 return;
286 usleep(1000);
290 static void wait_for_migration_pass(QTestState *who)
292 uint64_t initial_pass = get_migration_pass(who);
293 uint64_t pass;
295 /* Wait for the 1st sync */
296 while (!got_stop && !initial_pass) {
297 usleep(1000);
298 initial_pass = get_migration_pass(who);
301 do {
302 usleep(1000);
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).
316 unsigned address;
317 uint8_t first_byte;
318 uint8_t last_byte;
319 bool hit_edge = false;
320 bool bad = 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)
327 uint8_t b;
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
333 * to us yet.
335 hit_edge = true;
336 } else {
337 fprintf(stderr, "Memory content inconsistency at %x"
338 " first_byte = %x last_byte = %x current = %x"
339 " hit_edge = %x\n",
340 address, first_byte, last_byte, b, hit_edge);
341 bad = true;
344 last_byte = b;
346 g_assert_false(bad);
349 static void cleanup(const char *filename)
351 char *path = g_strdup_printf("%s/%s", tmpfs, filename);
353 unlink(path);
354 g_free(path);
357 static void migrate_check_parameter(QTestState *who, const char *parameter,
358 const char *value)
360 QDict *rsp, *rsp_return;
361 char *result;
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);
368 g_free(result);
369 QDECREF(rsp);
372 static void migrate_set_parameter(QTestState *who, const char *parameter,
373 const char *value)
375 QDict *rsp;
376 gchar *cmd;
378 cmd = g_strdup_printf("{ 'execute': 'migrate-set-parameters',"
379 "'arguments': { '%s': %s } }",
380 parameter, value);
381 rsp = qtest_qmp(who, cmd);
382 g_free(cmd);
383 g_assert(qdict_haskey(rsp, "return"));
384 QDECREF(rsp);
385 migrate_check_parameter(who, parameter, value);
388 static void migrate_set_capability(QTestState *who, const char *capability,
389 const char *value)
391 QDict *rsp;
392 gchar *cmd;
394 cmd = g_strdup_printf("{ 'execute': 'migrate-set-capabilities',"
395 "'arguments': { "
396 "'capabilities': [ { "
397 "'capability': '%s', 'state': %s } ] } }",
398 capability, value);
399 rsp = qtest_qmp(who, cmd);
400 g_free(cmd);
401 g_assert(qdict_haskey(rsp, "return"));
402 QDECREF(rsp);
405 static void migrate(QTestState *who, const char *uri)
407 QDict *rsp;
408 gchar *cmd;
410 cmd = g_strdup_printf("{ 'execute': 'migrate',"
411 "'arguments': { 'uri': '%s' } }",
412 uri);
413 rsp = qtest_qmp(who, cmd);
414 g_free(cmd);
415 g_assert(qdict_haskey(rsp, "return"));
416 QDECREF(rsp);
419 static void migrate_start_postcopy(QTestState *who)
421 QDict *rsp;
423 rsp = wait_command(who, "{ 'execute': 'migrate-start-postcopy' }");
424 g_assert(qdict_haskey(rsp, "return"));
425 QDECREF(rsp);
428 static void test_migrate_start(QTestState **from, QTestState **to,
429 const char *uri)
431 gchar *cmd_src, *cmd_dst;
432 char *bootpath = g_strdup_printf("%s/bootsect", tmpfs);
433 const char *arch = qtest_get_arch();
434 const char *accel = "kvm:tcg";
436 got_stop = false;
438 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
439 init_bootfile_x86(bootpath);
440 cmd_src = g_strdup_printf("-machine accel=%s -m 150M"
441 " -name source,debug-threads=on"
442 " -serial file:%s/src_serial"
443 " -drive file=%s,format=raw",
444 accel, tmpfs, bootpath);
445 cmd_dst = g_strdup_printf("-machine accel=%s -m 150M"
446 " -name target,debug-threads=on"
447 " -serial file:%s/dest_serial"
448 " -drive file=%s,format=raw"
449 " -incoming %s",
450 accel, tmpfs, bootpath, uri);
451 } else if (strcmp(arch, "ppc64") == 0) {
453 /* On ppc64, the test only works with kvm-hv, but not with kvm-pr */
454 if (access("/sys/module/kvm_hv", F_OK)) {
455 accel = "tcg";
457 init_bootfile_ppc(bootpath);
458 cmd_src = g_strdup_printf("-machine accel=%s -m 256M"
459 " -name source,debug-threads=on"
460 " -serial file:%s/src_serial"
461 " -drive file=%s,if=pflash,format=raw",
462 accel, tmpfs, bootpath);
463 cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
464 " -name target,debug-threads=on"
465 " -serial file:%s/dest_serial"
466 " -incoming %s",
467 accel, tmpfs, uri);
468 } else {
469 g_assert_not_reached();
472 g_free(bootpath);
474 *from = qtest_start(cmd_src);
475 g_free(cmd_src);
477 *to = qtest_init(cmd_dst);
478 g_free(cmd_dst);
481 static void test_migrate_end(QTestState *from, QTestState *to)
483 unsigned char dest_byte_a, dest_byte_b, dest_byte_c, dest_byte_d;
485 qtest_quit(from);
487 qtest_memread(to, start_address, &dest_byte_a, 1);
489 /* Destination still running, wait for a byte to change */
490 do {
491 qtest_memread(to, start_address, &dest_byte_b, 1);
492 usleep(1000 * 10);
493 } while (dest_byte_a == dest_byte_b);
495 qtest_qmp_discard_response(to, "{ 'execute' : 'stop'}");
496 /* With it stopped, check nothing changes */
497 qtest_memread(to, start_address, &dest_byte_c, 1);
498 usleep(1000 * 200);
499 qtest_memread(to, start_address, &dest_byte_d, 1);
500 g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
502 check_guests_ram(to);
504 qtest_quit(to);
506 cleanup("bootsect");
507 cleanup("migsocket");
508 cleanup("src_serial");
509 cleanup("dest_serial");
512 static void deprecated_set_downtime(QTestState *who, const double value)
514 QDict *rsp;
515 gchar *cmd;
516 char *expected;
517 int64_t result_int;
519 cmd = g_strdup_printf("{ 'execute': 'migrate_set_downtime',"
520 "'arguments': { 'value': %g } }", value);
521 rsp = qtest_qmp(who, cmd);
522 g_free(cmd);
523 g_assert(qdict_haskey(rsp, "return"));
524 QDECREF(rsp);
525 result_int = value * 1000L;
526 expected = g_strdup_printf("%" PRId64, result_int);
527 migrate_check_parameter(who, "downtime-limit", expected);
528 g_free(expected);
531 static void deprecated_set_speed(QTestState *who, const char *value)
533 QDict *rsp;
534 gchar *cmd;
536 cmd = g_strdup_printf("{ 'execute': 'migrate_set_speed',"
537 "'arguments': { 'value': %s } }", value);
538 rsp = qtest_qmp(who, cmd);
539 g_free(cmd);
540 g_assert(qdict_haskey(rsp, "return"));
541 QDECREF(rsp);
542 migrate_check_parameter(who, "max-bandwidth", value);
545 static void test_deprecated(void)
547 QTestState *from;
549 from = qtest_start("");
551 deprecated_set_downtime(from, 0.12345);
552 deprecated_set_speed(from, "12345");
554 qtest_quit(from);
557 static void test_migrate(void)
559 char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
560 QTestState *from, *to;
562 test_migrate_start(&from, &to, uri);
564 migrate_set_capability(from, "postcopy-ram", "true");
565 migrate_set_capability(to, "postcopy-ram", "true");
567 /* We want to pick a speed slow enough that the test completes
568 * quickly, but that it doesn't complete precopy even on a slow
569 * machine, so also set the downtime.
571 migrate_set_parameter(from, "max-bandwidth", "100000000");
572 migrate_set_parameter(from, "downtime-limit", "1");
574 /* Wait for the first serial output from the source */
575 wait_for_serial("src_serial");
577 migrate(from, uri);
579 wait_for_migration_pass(from);
581 migrate_start_postcopy(from);
583 if (!got_stop) {
584 qtest_qmp_eventwait(from, "STOP");
587 qtest_qmp_eventwait(to, "RESUME");
589 wait_for_serial("dest_serial");
590 wait_for_migration_complete(from);
592 g_free(uri);
594 test_migrate_end(from, to);
597 int main(int argc, char **argv)
599 char template[] = "/tmp/migration-test-XXXXXX";
600 int ret;
602 g_test_init(&argc, &argv, NULL);
604 if (!ufd_version_check()) {
605 return 0;
608 tmpfs = mkdtemp(template);
609 if (!tmpfs) {
610 g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
612 g_assert(tmpfs);
614 module_call_init(MODULE_INIT_QOM);
616 qtest_add_func("/migration/postcopy/unix", test_migrate);
617 qtest_add_func("/migration/deprecated", test_deprecated);
619 ret = g_test_run();
621 g_assert_cmpint(ret, ==, 0);
623 ret = rmdir(tmpfs);
624 if (ret != 0) {
625 g_test_message("unable to rmdir: path (%s): %s\n",
626 tmpfs, strerror(errno));
629 return ret;