tests/acpi: update golden master DSDT binary table blobs for q35
[qemu/armbru.git] / tests / vhost-user-test.c.orig
blobb491e6fcb65bf78951a05d196da4839e3aded789
1 /*
2  * QTest testcase for the vhost-user
3  *
4  * Copyright (c) 2014 Virtual Open Systems Sarl.
5  *
6  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7  * See the COPYING file in the top-level directory.
8  *
9  */
11 #include <glib.h>
13 #include "libqtest.h"
14 #include "qemu/option.h"
15 #include "sysemu/char.h"
16 #include "sysemu/sysemu.h"
18 #include <linux/vhost.h>
19 #include <sys/mman.h>
20 #include <sys/vfs.h>
21 #include <qemu/sockets.h>
23 /* GLIB version compatibility flags */
24 #if !GLIB_CHECK_VERSION(2, 26, 0)
25 #define G_TIME_SPAN_SECOND              (G_GINT64_CONSTANT(1000000))
26 #endif
28 #if GLIB_CHECK_VERSION(2, 28, 0)
29 #define HAVE_MONOTONIC_TIME
30 #endif
32 #define QEMU_CMD_ACCEL  " -machine accel=tcg"
33 #define QEMU_CMD_MEM    " -m 512 -object memory-backend-file,id=mem,size=512M,"\
34                         "mem-path=%s,share=on -numa node,memdev=mem"
35 #define QEMU_CMD_CHR    " -chardev socket,id=chr0,path=%s"
36 #define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=chr0,vhostforce"
37 #define QEMU_CMD_NET    " -device virtio-net-pci,netdev=net0 "
38 #define QEMU_CMD_ROM    " -option-rom ../pc-bios/pxe-virtio.rom"
40 #define QEMU_CMD        QEMU_CMD_ACCEL QEMU_CMD_MEM QEMU_CMD_CHR \
41                         QEMU_CMD_NETDEV QEMU_CMD_NET QEMU_CMD_ROM
43 #define HUGETLBFS_MAGIC       0x958458f6
45 /*********** FROM hw/virtio/vhost-user.c *************************************/
47 #define VHOST_MEMORY_MAX_NREGIONS    8
49 #define VHOST_USER_F_PROTOCOL_FEATURES 30
51 typedef enum VhostUserRequest {
52     VHOST_USER_NONE = 0,
53     VHOST_USER_GET_FEATURES = 1,
54     VHOST_USER_SET_FEATURES = 2,
55     VHOST_USER_SET_OWNER = 3,
56     VHOST_USER_RESET_DEVICE = 4,
57     VHOST_USER_SET_MEM_TABLE = 5,
58     VHOST_USER_SET_LOG_BASE = 6,
59     VHOST_USER_SET_LOG_FD = 7,
60     VHOST_USER_SET_VRING_NUM = 8,
61     VHOST_USER_SET_VRING_ADDR = 9,
62     VHOST_USER_SET_VRING_BASE = 10,
63     VHOST_USER_GET_VRING_BASE = 11,
64     VHOST_USER_SET_VRING_KICK = 12,
65     VHOST_USER_SET_VRING_CALL = 13,
66     VHOST_USER_SET_VRING_ERR = 14,
67     VHOST_USER_GET_PROTOCOL_FEATURES = 15,
68     VHOST_USER_SET_PROTOCOL_FEATURES = 16,
69     VHOST_USER_MAX
70 } VhostUserRequest;
72 typedef struct VhostUserMemoryRegion {
73     uint64_t guest_phys_addr;
74     uint64_t memory_size;
75     uint64_t userspace_addr;
76     uint64_t mmap_offset;
77 } VhostUserMemoryRegion;
79 typedef struct VhostUserMemory {
80     uint32_t nregions;
81     uint32_t padding;
82     VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS];
83 } VhostUserMemory;
85 typedef struct VhostUserMsg {
86     VhostUserRequest request;
88 #define VHOST_USER_VERSION_MASK     (0x3)
89 #define VHOST_USER_REPLY_MASK       (0x1<<2)
90     uint32_t flags;
91     uint32_t size; /* the following payload size */
92     union {
93         uint64_t u64;
94         struct vhost_vring_state state;
95         struct vhost_vring_addr addr;
96         VhostUserMemory memory;
97     };
98 } QEMU_PACKED VhostUserMsg;
100 static VhostUserMsg m __attribute__ ((unused));
101 #define VHOST_USER_HDR_SIZE (sizeof(m.request) \
102                             + sizeof(m.flags) \
103                             + sizeof(m.size))
105 #define VHOST_USER_PAYLOAD_SIZE (sizeof(m) - VHOST_USER_HDR_SIZE)
107 /* The version of the protocol we support */
108 #define VHOST_USER_VERSION    (0x1)
109 /*****************************************************************************/
111 int fds_num = 0, fds[VHOST_MEMORY_MAX_NREGIONS];
112 static VhostUserMemory memory;
113 static CompatGMutex data_mutex;
114 static CompatGCond data_cond;
116 #if !GLIB_CHECK_VERSION(2, 32, 0)
117 static gboolean g_cond_wait_until(CompatGCond cond, CompatGMutex mutex,
118                                   gint64 end_time)
120     gboolean ret = FALSE;
121     end_time -= g_get_monotonic_time();
122     GTimeVal time = { end_time / G_TIME_SPAN_SECOND,
123                       end_time % G_TIME_SPAN_SECOND };
124     ret = g_cond_timed_wait(cond, mutex, &time);
125     return ret;
127 #endif
129 static void wait_for_fds(void)
131     gint64 end_time;
133     g_mutex_lock(&data_mutex);
134     end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
135     while (!fds_num) {
136         if (!g_cond_wait_until(&data_cond, &data_mutex, end_time)) {
137             /* timeout has passed */
138             g_assert(fds_num);
139             break;
140         }
141     }
143     /* check for sanity */
144     g_assert_cmpint(fds_num, >, 0);
145     g_assert_cmpint(fds_num, ==, memory.nregions);
147     g_mutex_unlock(&data_mutex);
150 static void read_guest_mem(void)
152     uint32_t *guest_mem;
153     int i, j;
154     size_t size;
156     wait_for_fds();
158     /* iterate all regions */
159     for (i = 0; i < fds_num; i++) {
161         /* We'll check only the region statring at 0x0*/
162         if (memory.regions[i].guest_phys_addr != 0x0) {
163             continue;
164         }
166         g_assert_cmpint(memory.regions[i].memory_size, >, 1024);
168         size =  memory.regions[i].memory_size + memory.regions[i].mmap_offset;
170         guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
171                          MAP_SHARED, fds[i], 0);
173         g_assert(guest_mem != MAP_FAILED);
174         guest_mem += (memory.regions[i].mmap_offset / sizeof(*guest_mem));
176         for (j = 0; j < 256; j++) {
177             uint32_t a = readl(memory.regions[i].guest_phys_addr + j*4);
178             uint32_t b = guest_mem[j];
180             g_assert_cmpint(a, ==, b);
181         }
183         munmap(guest_mem, memory.regions[i].memory_size);
184     }
186     g_mutex_unlock(&data_mutex);
189 static void *thread_function(void *data)
191     GMainLoop *loop;
192     loop = g_main_loop_new(NULL, FALSE);
193     g_main_loop_run(loop);
194     return NULL;
197 static int chr_can_read(void *opaque)
199     return VHOST_USER_HDR_SIZE;
202 static void chr_read(void *opaque, const uint8_t *buf, int size)
204     CharDriverState *chr = opaque;
205     VhostUserMsg msg;
206     uint8_t *p = (uint8_t *) &msg;
207     int fd;
209     if (size != VHOST_USER_HDR_SIZE) {
210         g_test_message("Wrong message size received %d\n", size);
211         return;
212     }
214     g_mutex_lock(&data_mutex);
215     memcpy(p, buf, VHOST_USER_HDR_SIZE);
217     if (msg.size) {
218         p += VHOST_USER_HDR_SIZE;
219         qemu_chr_fe_read_all(chr, p, msg.size);
220     }
222     switch (msg.request) {
223     case VHOST_USER_GET_FEATURES:
224         /* send back features to qemu */
225         msg.flags |= VHOST_USER_REPLY_MASK;
226         msg.size = sizeof(m.u64);
227         msg.u64 = 0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
228         p = (uint8_t *) &msg;
229         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
230         break;
232     case VHOST_USER_SET_FEATURES:
233         g_assert_cmpint(msg.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES),
234                         !=, 0ULL);
235         break;
237     case VHOST_USER_GET_PROTOCOL_FEATURES:
238         /* send back features to qemu */
239         msg.flags |= VHOST_USER_REPLY_MASK;
240         msg.size = sizeof(m.u64);
241         msg.u64 = 0;
242         p = (uint8_t *) &msg;
243         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
244         break;
246     case VHOST_USER_GET_VRING_BASE:
247         /* send back vring base to qemu */
248         msg.flags |= VHOST_USER_REPLY_MASK;
249         msg.size = sizeof(m.state);
250         msg.state.num = 0;
251         p = (uint8_t *) &msg;
252         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
253         break;
255     case VHOST_USER_SET_MEM_TABLE:
256         /* received the mem table */
257         memcpy(&memory, &msg.memory, sizeof(msg.memory));
258         fds_num = qemu_chr_fe_get_msgfds(chr, fds, sizeof(fds) / sizeof(int));
260         /* signal the test that it can continue */
261         g_cond_signal(&data_cond);
262         break;
264     case VHOST_USER_SET_VRING_KICK:
265     case VHOST_USER_SET_VRING_CALL:
266         /* consume the fd */
267         qemu_chr_fe_get_msgfds(chr, &fd, 1);
268         /*
269          * This is a non-blocking eventfd.
270          * The receive function forces it to be blocking,
271          * so revert it back to non-blocking.
272          */
273         qemu_set_nonblock(fd);
274         break;
275     default:
276         break;
277     }
278     g_mutex_unlock(&data_mutex);
281 static const char *init_hugepagefs(void)
283     const char *path;
284     struct statfs fs;
285     int ret;
287     path = getenv("QTEST_HUGETLBFS_PATH");
288     if (!path) {
289         path = "/hugetlbfs";
290     }
292     if (access(path, R_OK | W_OK | X_OK)) {
293         g_test_message("access on path (%s): %s\n", path, strerror(errno));
294         return NULL;
295     }
297     do {
298         ret = statfs(path, &fs);
299     } while (ret != 0 && errno == EINTR);
301     if (ret != 0) {
302         g_test_message("statfs on path (%s): %s\n", path, strerror(errno));
303         return NULL;
304     }
306     if (fs.f_type != HUGETLBFS_MAGIC) {
307         g_test_message("Warning: path not on HugeTLBFS: %s\n", path);
308         return NULL;
309     }
311     return path;
314 int main(int argc, char **argv)
316     QTestState *s = NULL;
317     CharDriverState *chr = NULL;
318     const char *hugefs = 0;
319     char *socket_path = 0;
320     char *qemu_cmd = 0;
321     char *chr_path = 0;
322     int ret;
324     g_test_init(&argc, &argv, NULL);
326     module_call_init(MODULE_INIT_QOM);
328     hugefs = init_hugepagefs();
329     if (!hugefs) {
330         return 0;
331     }
333     socket_path = g_strdup_printf("/tmp/vhost-%d.sock", getpid());
335     /* create char dev and add read handlers */
336     qemu_add_opts(&qemu_chardev_opts);
337     chr_path = g_strdup_printf("unix:%s,server,nowait", socket_path);
338     chr = qemu_chr_new("chr0", chr_path, NULL);
339     g_free(chr_path);
340     qemu_chr_add_handlers(chr, chr_can_read, chr_read, NULL, chr);
342     /* run the main loop thread so the chardev may operate */
343     g_mutex_init(&data_mutex);
344     g_cond_init(&data_cond);
345     g_thread_new(NULL, thread_function, NULL);
347     qemu_cmd = g_strdup_printf(QEMU_CMD, hugefs, socket_path);
348     s = qtest_start(qemu_cmd);
349     g_free(qemu_cmd);
351     qtest_add_func("/vhost-user/read-guest-mem", read_guest_mem);
353     ret = g_test_run();
355     if (s) {
356         qtest_quit(s);
357     }
359     /* cleanup */
360     unlink(socket_path);
361     g_free(socket_path);
363     return ret;