mptsas: remove unnecessary internal msi state flag
[qemu/ar7.git] / tests / postcopy-test.c
blob35d5180173892b3b90ca56cf4068ae25785d221c
1 /*
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"
15 #include "libqtest.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;
25 bool got_stop;
27 #if defined(__linux__)
28 #include <sys/syscall.h>
29 #include <sys/vfs.h>
30 #endif
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;
40 uint64_t ioctl_mask;
42 int ufd = ufd = syscall(__NR_userfaultfd, O_CLOEXEC);
44 if (ufd == -1) {
45 g_test_message("Skipping test: userfaultfd not available");
46 return false;
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");
53 return false;
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");
60 return false;
63 return true;
66 #else
67 static bool ufd_version_check(void)
69 g_test_message("Skipping test: Userfault not available (builtdtime)");
70 return false;
73 #endif
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");
136 do {
137 int readvalue = fgetc(serialfile);
139 switch (readvalue) {
140 case 'A':
141 /* Fine */
142 break;
144 case 'B':
145 /* It's alive! */
146 fclose(serialfile);
147 g_free(serialpath);
148 return;
150 case EOF:
151 fseek(serialfile, 0, SEEK_SET);
152 usleep(1000);
153 break;
155 default:
156 fprintf(stderr, "Unexpected %d on %s serial\n", readvalue, side);
157 g_assert_not_reached();
159 } while (true);
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")) {
169 return response;
172 /* OK, it was an event */
173 event_string = qdict_get_str(response, "event");
174 if (!strcmp(event_string, "STOP")) {
175 got_stop = true;
177 QDECREF(response);
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
186 * going postcopy.
189 static uint64_t get_migration_pass(void)
191 QDict *rsp, *rsp_return, *rsp_ram;
192 uint64_t result;
194 rsp = return_or_event(qmp("{ 'execute': 'query-migrate' }"));
195 rsp_return = qdict_get_qdict(rsp, "return");
196 if (!qdict_haskey(rsp_return, "ram")) {
197 /* Still in setup */
198 result = 0;
199 } else {
200 rsp_ram = qdict_get_qdict(rsp_return, "ram");
201 result = qdict_get_try_int(rsp_ram, "dirty-sync-count", 0);
202 QDECREF(rsp);
204 return result;
207 static void wait_for_migration_complete(void)
209 QDict *rsp, *rsp_return;
210 bool completed;
212 do {
213 const char *status;
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");
220 QDECREF(rsp);
221 usleep(1000 * 100);
222 } while (!completed);
225 static void wait_for_migration_pass(void)
227 uint64_t initial_pass = get_migration_pass();
228 uint64_t pass;
230 /* Wait for the 1st sync */
231 do {
232 initial_pass = get_migration_pass();
233 if (got_stop || initial_pass) {
234 break;
236 usleep(1000 * 100);
237 } while (true);
239 do {
240 usleep(1000 * 100);
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).
254 unsigned address;
255 uint8_t first_byte;
256 uint8_t last_byte;
257 bool hit_edge = false;
258 bool bad = 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)
265 uint8_t b;
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
271 * to us yet.
273 hit_edge = true;
274 } else {
275 fprintf(stderr, "Memory content inconsistency at %x"
276 " first_byte = %x last_byte = %x current = %x"
277 " hit_edge = %x\n",
278 address, first_byte, last_byte, b, hit_edge);
279 bad = true;
282 last_byte = b;
284 g_assert_false(bad);
287 static void cleanup(const char *filename)
289 char *path = g_strdup_printf("%s/%s", tmpfs, filename);
291 unlink(path);
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;
299 gchar *cmd;
300 QDict *rsp;
302 char *bootpath = g_strdup_printf("%s/bootsect", tmpfs);
303 FILE *bootfile = fopen(bootpath, "wb");
305 got_stop = false;
306 g_assert_cmpint(fwrite(bootsect, 512, 1, bootfile), ==, 1);
307 fclose(bootfile);
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",
313 tmpfs, bootpath);
314 from = qtest_start(cmd);
315 g_free(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"
321 " -incoming %s",
322 tmpfs, bootpath, uri);
323 to = qtest_init(cmd);
324 g_free(cmd);
326 global_qtest = from;
327 rsp = qmp("{ 'execute': 'migrate-set-capabilities',"
328 "'arguments': { "
329 "'capabilities': [ {"
330 "'capability': 'postcopy-ram',"
331 "'state': true } ] } }");
332 g_assert(qdict_haskey(rsp, "return"));
333 QDECREF(rsp);
335 global_qtest = to;
336 rsp = qmp("{ 'execute': 'migrate-set-capabilities',"
337 "'arguments': { "
338 "'capabilities': [ {"
339 "'capability': 'postcopy-ram',"
340 "'state': true } ] } }");
341 g_assert(qdict_haskey(rsp, "return"));
342 QDECREF(rsp);
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.
348 global_qtest = from;
349 rsp = qmp("{ 'execute': 'migrate_set_speed',"
350 "'arguments': { 'value': 100000000 } }");
351 g_assert(qdict_haskey(rsp, "return"));
352 QDECREF(rsp);
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"));
358 QDECREF(rsp);
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' } }",
366 uri);
367 rsp = qmp(cmd);
368 g_free(cmd);
369 g_assert(qdict_haskey(rsp, "return"));
370 QDECREF(rsp);
372 wait_for_migration_pass();
374 rsp = return_or_event(qmp("{ 'execute': 'migrate-start-postcopy' }"));
375 g_assert(qdict_haskey(rsp, "return"));
376 QDECREF(rsp);
378 if (!got_stop) {
379 qmp_eventwait("STOP");
382 global_qtest = to;
383 qmp_eventwait("RESUME");
385 wait_for_serial("dest_serial");
386 global_qtest = from;
387 wait_for_migration_complete();
389 qtest_quit(from);
391 global_qtest = to;
393 qtest_memread(to, start_address, &dest_byte_a, 1);
395 /* Destination still running, wait for a byte to change */
396 do {
397 qtest_memread(to, start_address, &dest_byte_b, 1);
398 usleep(10 * 1000);
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);
404 sleep(1);
405 qtest_memread(to, start_address, &dest_byte_d, 1);
406 g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
408 check_guests_ram();
410 qtest_quit(to);
411 g_free(uri);
413 global_qtest = global;
415 cleanup("bootsect");
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";
424 int ret;
426 g_test_init(&argc, &argv, NULL);
428 if (!ufd_version_check()) {
429 return 0;
432 tmpfs = mkdtemp(template);
433 if (!tmpfs) {
434 g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
436 g_assert(tmpfs);
438 module_call_init(MODULE_INIT_QOM);
440 qtest_add_func("/postcopy", test_migrate);
442 ret = g_test_run();
444 g_assert_cmpint(ret, ==, 0);
446 ret = rmdir(tmpfs);
447 if (ret != 0) {
448 g_test_message("unable to rmdir: path (%s): %s\n",
449 tmpfs, strerror(errno));
452 return ret;