1 /*
2 * QTest migration utilities
3 *
4 * Copyright (c) 2016-2018 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.
7 *
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.
10 *
11 */
12
13 #include "qemu/osdep.h"
14 #include "qemu/ctype.h"
15 #include "qapi/qapi-visit-sockets.h"
16 #include "qapi/qobject-input-visitor.h"
17 #include "qapi/error.h"
18 #include "qobject/qlist.h"
19 #include "qemu/cutils.h"
20 #include "qemu/memalign.h"
21
22 #include "migration/bootfile.h"
23 #include "migration/migration-util.h"
24
25 #if defined(__linux__)
26 #include <sys/ioctl.h>
27 #include <sys/syscall.h>
28 #endif
29
30 /* for uffd_version_check() */
31 #if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
32 #include <sys/eventfd.h>
33 #include "qemu/userfaultfd.h"
34 #endif
35
36 /* For dirty ring test; so far only x86_64 is supported */
37 #if defined(__linux__) && defined(HOST_X86_64)
38 #include "linux/kvm.h"
39 #endif
40
41
SocketAddress_to_str(SocketAddress * addr)42 static char *SocketAddress_to_str(SocketAddress *addr)
43 {
44 switch (addr->type) {
45 case SOCKET_ADDRESS_TYPE_INET:
46 return g_strdup_printf("tcp:%s:%s",
47 addr->u.inet.host,
48 addr->u.inet.port);
49 case SOCKET_ADDRESS_TYPE_UNIX:
50 return g_strdup_printf("unix:%s",
51 addr->u.q_unix.path);
52 case SOCKET_ADDRESS_TYPE_FD:
53 return g_strdup_printf("fd:%s", addr->u.fd.str);
54 case SOCKET_ADDRESS_TYPE_VSOCK:
55 return g_strdup_printf("vsock:%s:%s",
56 addr->u.vsock.cid,
57 addr->u.vsock.port);
58 default:
59 return g_strdup("unknown address type");
60 }
61 }
62
SocketAddress_to_qdict(SocketAddress * addr)63 static QDict *SocketAddress_to_qdict(SocketAddress *addr)
64 {
65 QDict *dict = qdict_new();
66
67 switch (addr->type) {
68 case SOCKET_ADDRESS_TYPE_INET:
69 qdict_put_str(dict, "type", "inet");
70 qdict_put_str(dict, "host", addr->u.inet.host);
71 qdict_put_str(dict, "port", addr->u.inet.port);
72 break;
73 case SOCKET_ADDRESS_TYPE_UNIX:
74 qdict_put_str(dict, "type", "unix");
75 qdict_put_str(dict, "path", addr->u.q_unix.path);
76 break;
77 case SOCKET_ADDRESS_TYPE_FD:
78 qdict_put_str(dict, "type", "fd");
79 qdict_put_str(dict, "str", addr->u.fd.str);
80 break;
81 case SOCKET_ADDRESS_TYPE_VSOCK:
82 qdict_put_str(dict, "type", "vsock");
83 qdict_put_str(dict, "cid", addr->u.vsock.cid);
84 qdict_put_str(dict, "port", addr->u.vsock.port);
85 break;
86 default:
87 g_assert_not_reached();
88 }
89
90 return dict;
91 }
92
migrate_get_socket_address(QTestState * who)93 static SocketAddressList *migrate_get_socket_address(QTestState *who)
94 {
95 QDict *rsp;
96 SocketAddressList *addrs;
97 Visitor *iv = NULL;
98 QObject *object;
99
100 rsp = migrate_query(who);
101 object = qdict_get(rsp, "socket-address");
102
103 iv = qobject_input_visitor_new(object);
104 visit_type_SocketAddressList(iv, NULL, &addrs, &error_abort);
105 visit_free(iv);
106
107 qobject_unref(rsp);
108 return addrs;
109 }
110
migrate_get_connect_uri(QTestState * who)111 char *migrate_get_connect_uri(QTestState *who)
112 {
113 SocketAddressList *addrs;
114 char *connect_uri;
115
116 addrs = migrate_get_socket_address(who);
117 connect_uri = SocketAddress_to_str(addrs->value);
118
119 qapi_free_SocketAddressList(addrs);
120 return connect_uri;
121 }
122
123 static QDict *
migrate_get_connect_qdict(QTestState * who)124 migrate_get_connect_qdict(QTestState *who)
125 {
126 SocketAddressList *addrs;
127 QDict *connect_qdict;
128
129 addrs = migrate_get_socket_address(who);
130 connect_qdict = SocketAddress_to_qdict(addrs->value);
131
132 qapi_free_SocketAddressList(addrs);
133 return connect_qdict;
134 }
135
migrate_set_ports(QTestState * to,QList * channel_list)136 void migrate_set_ports(QTestState *to, QList *channel_list)
137 {
138 g_autoptr(QDict) addr = NULL;
139 QListEntry *entry;
140 const char *addr_port = NULL;
141
142 QLIST_FOREACH_ENTRY(channel_list, entry) {
143 QDict *channel = qobject_to(QDict, qlist_entry_obj(entry));
144 QDict *addrdict = qdict_get_qdict(channel, "addr");
145
146 if (!qdict_haskey(addrdict, "port") ||
147 strcmp(qdict_get_str(addrdict, "port"), "0")) {
148 continue;
149 }
150
151 /*
152 * Fetch addr only if needed, so tests that are not yet connected to
153 * the monitor do not query it. Such tests cannot use port=0.
154 */
155 if (!addr) {
156 addr = migrate_get_connect_qdict(to);
157 }
158
159 if (qdict_haskey(addr, "port")) {
160 addr_port = qdict_get_str(addr, "port");
161 qdict_put_str(addrdict, "port", addr_port);
162 }
163 }
164 }
165
migrate_watch_for_events(QTestState * who,const char * name,QDict * event,void * opaque)166 bool migrate_watch_for_events(QTestState *who, const char *name,
167 QDict *event, void *opaque)
168 {
169 QTestMigrationState *state = opaque;
170
171 if (g_str_equal(name, "STOP")) {
172 state->stop_seen = true;
173 return true;
174 } else if (g_str_equal(name, "SUSPEND")) {
175 state->suspend_seen = true;
176 return true;
177 } else if (g_str_equal(name, "RESUME")) {
178 state->resume_seen = true;
179 return true;
180 }
181
182 return false;
183 }
184
find_common_machine_version(const char * mtype,const char * var1,const char * var2)185 char *find_common_machine_version(const char *mtype, const char *var1,
186 const char *var2)
187 {
188 g_autofree char *type1 = qtest_resolve_machine_alias(var1, mtype);
189 g_autofree char *type2 = qtest_resolve_machine_alias(var2, mtype);
190
191 g_assert(type1 && type2);
192
193 if (g_str_equal(type1, type2)) {
194 /* either can be used */
195 return g_strdup(type1);
196 }
197
198 if (qtest_has_machine_with_env(var2, type1)) {
199 return g_strdup(type1);
200 }
201
202 if (qtest_has_machine_with_env(var1, type2)) {
203 return g_strdup(type2);
204 }
205
206 g_test_message("No common machine version for machine type '%s' between "
207 "binaries %s and %s", mtype, getenv(var1), getenv(var2));
208 g_assert_not_reached();
209 }
210
resolve_machine_version(const char * alias,const char * var1,const char * var2)211 char *resolve_machine_version(const char *alias, const char *var1,
212 const char *var2)
213 {
214 const char *mname = g_getenv("QTEST_QEMU_MACHINE_TYPE");
215 g_autofree char *machine_name = NULL;
216
217 if (mname) {
218 const char *dash = strrchr(mname, '-');
219 const char *dot = strrchr(mname, '.');
220
221 machine_name = g_strdup(mname);
222
223 if (dash && dot) {
224 assert(qtest_has_machine(machine_name));
225 return g_steal_pointer(&machine_name);
226 }
227 /* else: probably an alias, let it be resolved below */
228 } else {
229 /* use the hardcoded alias */
230 machine_name = g_strdup(alias);
231 }
232
233 return find_common_machine_version(machine_name, var1, var2);
234 }
235
236 typedef struct {
237 char *name;
238 void (*func)(void);
239 void (*func_full)(void *);
240 } MigrationTest;
241
migration_test_destroy(gpointer data)242 static void migration_test_destroy(gpointer data)
243 {
244 MigrationTest *test = (MigrationTest *)data;
245
246 g_free(test->name);
247 g_free(test);
248 }
249
migration_test_wrapper(const void * data)250 static void migration_test_wrapper(const void *data)
251 {
252 MigrationTest *test = (MigrationTest *)data;
253
254 g_test_message("Running /%s%s", qtest_get_arch(), test->name);
255 test->func();
256 }
257
migration_test_add(const char * path,void (* fn)(void))258 void migration_test_add(const char *path, void (*fn)(void))
259 {
260 MigrationTest *test = g_new0(MigrationTest, 1);
261
262 test->func = fn;
263 test->name = g_strdup(path);
264
265 qtest_add_data_func_full(path, test, migration_test_wrapper,
266 migration_test_destroy);
267 }
268
migration_test_wrapper_full(const void * data)269 static void migration_test_wrapper_full(const void *data)
270 {
271 MigrationTest *test = (MigrationTest *)data;
272
273 g_test_message("Running /%s%s", qtest_get_arch(), test->name);
274 test->func_full(test->name);
275 }
276
migration_test_add_suffix(const char * path,const char * suffix,void (* fn)(void *))277 void migration_test_add_suffix(const char *path, const char *suffix,
278 void (*fn)(void *))
279 {
280 MigrationTest *test = g_new0(MigrationTest, 1);
281
282 g_assert(g_str_has_suffix(path, "/"));
283 g_assert(!g_str_has_prefix(suffix, "/"));
284
285 test->func_full = fn;
286 test->name = g_strconcat(path, suffix, NULL);
287
288 qtest_add_data_func_full(test->name, test, migration_test_wrapper_full,
289 migration_test_destroy);
290 }
291
292 #ifdef O_DIRECT
293 /*
294 * Probe for O_DIRECT support on the filesystem. Since this is used
295 * for tests, be conservative, if anything fails, assume it's
296 * unsupported.
297 */
probe_o_direct_support(const char * tmpfs)298 bool probe_o_direct_support(const char *tmpfs)
299 {
300 g_autofree char *filename = g_strdup_printf("%s/probe-o-direct", tmpfs);
301 int fd, flags = O_CREAT | O_RDWR | O_TRUNC | O_DIRECT;
302 void *buf;
303 ssize_t ret, len;
304 uint64_t offset;
305
306 fd = open(filename, flags, 0660);
307 if (fd < 0) {
308 unlink(filename);
309 return false;
310 }
311
312 /*
313 * Using 1MB alignment as conservative choice to satisfy any
314 * plausible architecture default page size, and/or filesystem
315 * alignment restrictions.
316 */
317 len = 0x100000;
318 offset = 0x100000;
319
320 buf = qemu_try_memalign(len, len);
321 g_assert(buf);
322 memset(buf, 0, len);
323
324 ret = pwrite(fd, buf, len, offset);
325 unlink(filename);
326 g_free(buf);
327
328 if (ret < 0) {
329 return false;
330 }
331
332 return true;
333 }
334 #endif
335
336 #if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
ufd_version_check(bool * uffd_feature_thread_id)337 bool ufd_version_check(bool *uffd_feature_thread_id)
338 {
339 struct uffdio_api api_struct;
340 uint64_t ioctl_mask;
341
342 int ufd = uffd_open(O_CLOEXEC);
343
344 if (ufd == -1) {
345 g_test_message("Skipping test: userfaultfd not available");
346 return false;
347 }
348
349 api_struct.api = UFFD_API;
350 api_struct.features = 0;
351 if (ioctl(ufd, UFFDIO_API, &api_struct)) {
352 g_test_message("Skipping test: UFFDIO_API failed");
353 return false;
354 }
355
356 if (uffd_feature_thread_id) {
357 *uffd_feature_thread_id = api_struct.features & UFFD_FEATURE_THREAD_ID;
358 }
359
360 ioctl_mask = (1ULL << _UFFDIO_REGISTER |
361 1ULL << _UFFDIO_UNREGISTER);
362 if ((api_struct.ioctls & ioctl_mask) != ioctl_mask) {
363 g_test_message("Skipping test: Missing userfault feature");
364 return false;
365 }
366
367 return true;
368 }
369 #else
ufd_version_check(bool * uffd_feature_thread_id)370 bool ufd_version_check(bool *uffd_feature_thread_id)
371 {
372 g_test_message("Skipping test: Userfault not available (builtdtime)");
373 return false;
374 }
375 #endif
376
kvm_dirty_ring_supported(void)377 bool kvm_dirty_ring_supported(void)
378 {
379 #if defined(__linux__) && defined(HOST_X86_64)
380 int ret, kvm_fd = open("/dev/kvm", O_RDONLY);
381
382 if (kvm_fd < 0) {
383 return false;
384 }
385
386 ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_DIRTY_LOG_RING);
387 close(kvm_fd);
388
389 /* We test with 4096 slots */
390 if (ret < 4096) {
391 return false;
392 }
393
394 return true;
395 #else
396 return false;
397 #endif
398 }
399