2 * QTest testcase for postcopy
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 "sysemu/char.h"
19 #include "sysemu/sysemu.h"
21 #include <qemu/sockets.h>
23 const unsigned start_address
= 1024 * 1024;
24 const unsigned end_address
= 100 * 1024 * 1024;
27 #if defined(__linux__)
28 #include <sys/syscall.h>
32 #if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
33 #include <sys/eventfd.h>
34 #include <sys/ioctl.h>
35 #include <linux/userfaultfd.h>
37 static bool ufd_version_check(void)
39 struct uffdio_api api_struct
;
42 int ufd
= ufd
= syscall(__NR_userfaultfd
, O_CLOEXEC
);
45 g_test_message("Skipping test: userfaultfd not available");
49 api_struct
.api
= UFFD_API
;
50 api_struct
.features
= 0;
51 if (ioctl(ufd
, UFFDIO_API
, &api_struct
)) {
52 g_test_message("Skipping test: UFFDIO_API failed");
56 ioctl_mask
= (__u64
)1 << _UFFDIO_REGISTER
|
57 (__u64
)1 << _UFFDIO_UNREGISTER
;
58 if ((api_struct
.ioctls
& ioctl_mask
) != ioctl_mask
) {
59 g_test_message("Skipping test: Missing userfault feature");
67 static bool ufd_version_check(void)
69 g_test_message("Skipping test: Userfault not available (builtdtime)");
75 static const char *tmpfs
;
77 /* A simple PC boot sector that modifies memory (1-100MB) quickly
78 * outputing a 'B' every so often if it's still running.
80 unsigned char bootsect
[] = {
81 0xfa, 0x0f, 0x01, 0x16, 0x74, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
82 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02,
84 0xe6, 0x92, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x66, 0xb8, 0x41,
85 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xb3, 0x00, 0xb8, 0x00, 0x00, 0x10,
86 0x00, 0xfe, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40,
87 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x75, 0xe9, 0x66, 0xb8, 0x42, 0x00, 0x66,
88 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xde, 0x66, 0x90, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00,
90 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x27, 0x00, 0x5c, 0x7c,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x55, 0xaa
127 * Wait for some output in the serial output file,
128 * we get an 'A' followed by an endless string of 'B's
129 * but on the destination we won't have the A.
131 static void wait_for_serial(const char *side
)
133 char *serialpath
= g_strdup_printf("%s/%s", tmpfs
, side
);
134 FILE *serialfile
= fopen(serialpath
, "r");
137 int readvalue
= fgetc(serialfile
);
151 fseek(serialfile
, 0, SEEK_SET
);
156 fprintf(stderr
, "Unexpected %d on %s serial\n", readvalue
, side
);
157 g_assert_not_reached();
163 * Events can get in the way of responses we are actually waiting for.
165 static QDict
*return_or_event(QDict
*response
)
167 const char *event_string
;
168 if (!qdict_haskey(response
, "event")) {
172 /* OK, it was an event */
173 event_string
= qdict_get_str(response
, "event");
174 if (!strcmp(event_string
, "STOP")) {
178 return return_or_event(qtest_qmp_receive(global_qtest
));
183 * It's tricky to use qemu's migration event capability with qtest,
184 * events suddenly appearing confuse the qmp()/hmp() responses.
185 * so wait for a couple of passes to have happened before
189 static uint64_t get_migration_pass(void)
191 QDict
*rsp
, *rsp_return
, *rsp_ram
;
194 rsp
= return_or_event(qmp("{ 'execute': 'query-migrate' }"));
195 rsp_return
= qdict_get_qdict(rsp
, "return");
196 if (!qdict_haskey(rsp_return
, "ram")) {
200 rsp_ram
= qdict_get_qdict(rsp_return
, "ram");
201 result
= qdict_get_try_int(rsp_ram
, "dirty-sync-count", 0);
207 static void wait_for_migration_complete(void)
209 QDict
*rsp
, *rsp_return
;
215 rsp
= return_or_event(qmp("{ 'execute': 'query-migrate' }"));
216 rsp_return
= qdict_get_qdict(rsp
, "return");
217 status
= qdict_get_str(rsp_return
, "status");
218 completed
= strcmp(status
, "completed") == 0;
219 g_assert_cmpstr(status
, !=, "failed");
222 } while (!completed
);
225 static void wait_for_migration_pass(void)
227 uint64_t initial_pass
= get_migration_pass();
230 /* Wait for the 1st sync */
232 initial_pass
= get_migration_pass();
233 if (got_stop
|| initial_pass
) {
241 pass
= get_migration_pass();
242 } while (pass
== initial_pass
&& !got_stop
);
245 static void check_guests_ram(void)
247 /* Our ASM test will have been incrementing one byte from each page from
248 * 1MB to <100MB in order.
249 * This gives us a constraint that any page's byte should be equal or less
250 * than the previous pages byte (mod 256); and they should all be equal
251 * except for one transition at the point where we meet the incrementer.
252 * (We're running this with the guest stopped).
257 bool hit_edge
= false;
260 qtest_memread(global_qtest
, start_address
, &first_byte
, 1);
261 last_byte
= first_byte
;
263 for (address
= start_address
+ 4096; address
< end_address
; address
+= 4096)
266 qtest_memread(global_qtest
, address
, &b
, 1);
267 if (b
!= last_byte
) {
268 if (((b
+ 1) % 256) == last_byte
&& !hit_edge
) {
269 /* This is OK, the guest stopped at the point of
270 * incrementing the previous page but didn't get
275 fprintf(stderr
, "Memory content inconsistency at %x"
276 " first_byte = %x last_byte = %x current = %x"
278 address
, first_byte
, last_byte
, b
, hit_edge
);
287 static void cleanup(const char *filename
)
289 char *path
= g_strdup_printf("%s/%s", tmpfs
, filename
);
294 static void test_migrate(void)
296 char *uri
= g_strdup_printf("unix:%s/migsocket", tmpfs
);
297 QTestState
*global
= global_qtest
, *from
, *to
;
298 unsigned char dest_byte_a
, dest_byte_b
, dest_byte_c
, dest_byte_d
;
302 char *bootpath
= g_strdup_printf("%s/bootsect", tmpfs
);
303 FILE *bootfile
= fopen(bootpath
, "wb");
306 g_assert_cmpint(fwrite(bootsect
, 512, 1, bootfile
), ==, 1);
309 cmd
= g_strdup_printf("-machine accel=kvm:tcg -m 150M"
310 " -name pcsource,debug-threads=on"
311 " -serial file:%s/src_serial"
312 " -drive file=%s,format=raw",
314 from
= qtest_start(cmd
);
317 cmd
= g_strdup_printf("-machine accel=kvm:tcg -m 150M"
318 " -name pcdest,debug-threads=on"
319 " -serial file:%s/dest_serial"
320 " -drive file=%s,format=raw"
322 tmpfs
, bootpath
, uri
);
323 to
= qtest_init(cmd
);
327 rsp
= qmp("{ 'execute': 'migrate-set-capabilities',"
329 "'capabilities': [ {"
330 "'capability': 'postcopy-ram',"
331 "'state': true } ] } }");
332 g_assert(qdict_haskey(rsp
, "return"));
336 rsp
= qmp("{ 'execute': 'migrate-set-capabilities',"
338 "'capabilities': [ {"
339 "'capability': 'postcopy-ram',"
340 "'state': true } ] } }");
341 g_assert(qdict_haskey(rsp
, "return"));
344 /* We want to pick a speed slow enough that the test completes
345 * quickly, but that it doesn't complete precopy even on a slow
346 * machine, so also set the downtime.
349 rsp
= qmp("{ 'execute': 'migrate_set_speed',"
350 "'arguments': { 'value': 100000000 } }");
351 g_assert(qdict_haskey(rsp
, "return"));
354 /* 1ms downtime - it should never finish precopy */
355 rsp
= qmp("{ 'execute': 'migrate_set_downtime',"
356 "'arguments': { 'value': 0.001 } }");
357 g_assert(qdict_haskey(rsp
, "return"));
361 /* Wait for the first serial output from the source */
362 wait_for_serial("src_serial");
364 cmd
= g_strdup_printf("{ 'execute': 'migrate',"
365 "'arguments': { 'uri': '%s' } }",
369 g_assert(qdict_haskey(rsp
, "return"));
372 wait_for_migration_pass();
374 rsp
= return_or_event(qmp("{ 'execute': 'migrate-start-postcopy' }"));
375 g_assert(qdict_haskey(rsp
, "return"));
379 qmp_eventwait("STOP");
383 qmp_eventwait("RESUME");
385 wait_for_serial("dest_serial");
387 wait_for_migration_complete();
393 qtest_memread(to
, start_address
, &dest_byte_a
, 1);
395 /* Destination still running, wait for a byte to change */
397 qtest_memread(to
, start_address
, &dest_byte_b
, 1);
399 } while (dest_byte_a
== dest_byte_b
);
401 qmp("{ 'execute' : 'stop'}");
402 /* With it stopped, check nothing changes */
403 qtest_memread(to
, start_address
, &dest_byte_c
, 1);
405 qtest_memread(to
, start_address
, &dest_byte_d
, 1);
406 g_assert_cmpint(dest_byte_c
, ==, dest_byte_d
);
413 global_qtest
= global
;
416 cleanup("migsocket");
417 cleanup("src_serial");
418 cleanup("dest_serial");
421 int main(int argc
, char **argv
)
423 char template[] = "/tmp/postcopy-test-XXXXXX";
426 g_test_init(&argc
, &argv
, NULL
);
428 if (!ufd_version_check()) {
432 tmpfs
= mkdtemp(template);
434 g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno
));
438 module_call_init(MODULE_INIT_QOM
);
440 qtest_add_func("/postcopy", test_migrate
);
444 g_assert_cmpint(ret
, ==, 0);
448 g_test_message("unable to rmdir: path (%s): %s\n",
449 tmpfs
, strerror(errno
));