Statistics
| Branch: | Revision:

root / hw / vhost.c @ 916452df

History | View | Annotate | Download (22.2 kB)

1
/*
2
 * vhost support
3
 *
4
 * Copyright Red Hat, Inc. 2010
5
 *
6
 * Authors:
7
 *  Michael S. Tsirkin <mst@redhat.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10
 * the COPYING file in the top-level directory.
11
 */
12

    
13
#include <sys/ioctl.h>
14
#include "vhost.h"
15
#include "hw/hw.h"
16
/* For range_get_last */
17
#include "pci.h"
18
#include <linux/vhost.h>
19

    
20
static void vhost_dev_sync_region(struct vhost_dev *dev,
21
                                  uint64_t mfirst, uint64_t mlast,
22
                                  uint64_t rfirst, uint64_t rlast)
23
{
24
    uint64_t start = MAX(mfirst, rfirst);
25
    uint64_t end = MIN(mlast, rlast);
26
    vhost_log_chunk_t *from = dev->log + start / VHOST_LOG_CHUNK;
27
    vhost_log_chunk_t *to = dev->log + end / VHOST_LOG_CHUNK + 1;
28
    uint64_t addr = (start / VHOST_LOG_CHUNK) * VHOST_LOG_CHUNK;
29

    
30
    assert(end / VHOST_LOG_CHUNK < dev->log_size);
31
    assert(start / VHOST_LOG_CHUNK < dev->log_size);
32
    if (end < start) {
33
        return;
34
    }
35
    for (;from < to; ++from) {
36
        vhost_log_chunk_t log;
37
        int bit;
38
        /* We first check with non-atomic: much cheaper,
39
         * and we expect non-dirty to be the common case. */
40
        if (!*from) {
41
            continue;
42
        }
43
        /* Data must be read atomically. We don't really
44
         * need the barrier semantics of __sync
45
         * builtins, but it's easier to use them than
46
         * roll our own. */
47
        log = __sync_fetch_and_and(from, 0);
48
        while ((bit = sizeof(log) > sizeof(int) ?
49
                ffsll(log) : ffs(log))) {
50
            bit -= 1;
51
            cpu_physical_memory_set_dirty(addr + bit * VHOST_LOG_PAGE);
52
            log &= ~(0x1ull << bit);
53
        }
54
        addr += VHOST_LOG_CHUNK;
55
    }
56
}
57

    
58
static int vhost_client_sync_dirty_bitmap(CPUPhysMemoryClient *client,
59
                                          target_phys_addr_t start_addr,
60
                                          target_phys_addr_t end_addr)
61
{
62
    struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
63
    int i;
64
    if (!dev->log_enabled || !dev->started) {
65
        return 0;
66
    }
67
    for (i = 0; i < dev->mem->nregions; ++i) {
68
        struct vhost_memory_region *reg = dev->mem->regions + i;
69
        vhost_dev_sync_region(dev, start_addr, end_addr,
70
                              reg->guest_phys_addr,
71
                              range_get_last(reg->guest_phys_addr,
72
                                             reg->memory_size));
73
    }
74
    for (i = 0; i < dev->nvqs; ++i) {
75
        struct vhost_virtqueue *vq = dev->vqs + i;
76
        vhost_dev_sync_region(dev, start_addr, end_addr, vq->used_phys,
77
                              range_get_last(vq->used_phys, vq->used_size));
78
    }
79
    return 0;
80
}
81

    
82
/* Assign/unassign. Keep an unsorted array of non-overlapping
83
 * memory regions in dev->mem. */
84
static void vhost_dev_unassign_memory(struct vhost_dev *dev,
85
                                      uint64_t start_addr,
86
                                      uint64_t size)
87
{
88
    int from, to, n = dev->mem->nregions;
89
    /* Track overlapping/split regions for sanity checking. */
90
    int overlap_start = 0, overlap_end = 0, overlap_middle = 0, split = 0;
91

    
92
    for (from = 0, to = 0; from < n; ++from, ++to) {
93
        struct vhost_memory_region *reg = dev->mem->regions + to;
94
        uint64_t reglast;
95
        uint64_t memlast;
96
        uint64_t change;
97

    
98
        /* clone old region */
99
        if (to != from) {
100
            memcpy(reg, dev->mem->regions + from, sizeof *reg);
101
        }
102

    
103
        /* No overlap is simple */
104
        if (!ranges_overlap(reg->guest_phys_addr, reg->memory_size,
105
                            start_addr, size)) {
106
            continue;
107
        }
108

    
109
        /* Split only happens if supplied region
110
         * is in the middle of an existing one. Thus it can not
111
         * overlap with any other existing region. */
112
        assert(!split);
113

    
114
        reglast = range_get_last(reg->guest_phys_addr, reg->memory_size);
115
        memlast = range_get_last(start_addr, size);
116

    
117
        /* Remove whole region */
118
        if (start_addr <= reg->guest_phys_addr && memlast >= reglast) {
119
            --dev->mem->nregions;
120
            --to;
121
            assert(to >= 0);
122
            ++overlap_middle;
123
            continue;
124
        }
125

    
126
        /* Shrink region */
127
        if (memlast >= reglast) {
128
            reg->memory_size = start_addr - reg->guest_phys_addr;
129
            assert(reg->memory_size);
130
            assert(!overlap_end);
131
            ++overlap_end;
132
            continue;
133
        }
134

    
135
        /* Shift region */
136
        if (start_addr <= reg->guest_phys_addr) {
137
            change = memlast + 1 - reg->guest_phys_addr;
138
            reg->memory_size -= change;
139
            reg->guest_phys_addr += change;
140
            reg->userspace_addr += change;
141
            assert(reg->memory_size);
142
            assert(!overlap_start);
143
            ++overlap_start;
144
            continue;
145
        }
146

    
147
        /* This only happens if supplied region
148
         * is in the middle of an existing one. Thus it can not
149
         * overlap with any other existing region. */
150
        assert(!overlap_start);
151
        assert(!overlap_end);
152
        assert(!overlap_middle);
153
        /* Split region: shrink first part, shift second part. */
154
        memcpy(dev->mem->regions + n, reg, sizeof *reg);
155
        reg->memory_size = start_addr - reg->guest_phys_addr;
156
        assert(reg->memory_size);
157
        change = memlast + 1 - reg->guest_phys_addr;
158
        reg = dev->mem->regions + n;
159
        reg->memory_size -= change;
160
        assert(reg->memory_size);
161
        reg->guest_phys_addr += change;
162
        reg->userspace_addr += change;
163
        /* Never add more than 1 region */
164
        assert(dev->mem->nregions == n);
165
        ++dev->mem->nregions;
166
        ++split;
167
    }
168
}
169

    
170
/* Called after unassign, so no regions overlap the given range. */
171
static void vhost_dev_assign_memory(struct vhost_dev *dev,
172
                                    uint64_t start_addr,
173
                                    uint64_t size,
174
                                    uint64_t uaddr)
175
{
176
    int from, to;
177
    struct vhost_memory_region *merged = NULL;
178
    for (from = 0, to = 0; from < dev->mem->nregions; ++from, ++to) {
179
        struct vhost_memory_region *reg = dev->mem->regions + to;
180
        uint64_t prlast, urlast;
181
        uint64_t pmlast, umlast;
182
        uint64_t s, e, u;
183

    
184
        /* clone old region */
185
        if (to != from) {
186
            memcpy(reg, dev->mem->regions + from, sizeof *reg);
187
        }
188
        prlast = range_get_last(reg->guest_phys_addr, reg->memory_size);
189
        pmlast = range_get_last(start_addr, size);
190
        urlast = range_get_last(reg->userspace_addr, reg->memory_size);
191
        umlast = range_get_last(uaddr, size);
192

    
193
        /* check for overlapping regions: should never happen. */
194
        assert(prlast < start_addr || pmlast < reg->guest_phys_addr);
195
        /* Not an adjacent or overlapping region - do not merge. */
196
        if ((prlast + 1 != start_addr || urlast + 1 != uaddr) &&
197
            (pmlast + 1 != reg->guest_phys_addr ||
198
             umlast + 1 != reg->userspace_addr)) {
199
            continue;
200
        }
201

    
202
        if (merged) {
203
            --to;
204
            assert(to >= 0);
205
        } else {
206
            merged = reg;
207
        }
208
        u = MIN(uaddr, reg->userspace_addr);
209
        s = MIN(start_addr, reg->guest_phys_addr);
210
        e = MAX(pmlast, prlast);
211
        uaddr = merged->userspace_addr = u;
212
        start_addr = merged->guest_phys_addr = s;
213
        size = merged->memory_size = e - s + 1;
214
        assert(merged->memory_size);
215
    }
216

    
217
    if (!merged) {
218
        struct vhost_memory_region *reg = dev->mem->regions + to;
219
        memset(reg, 0, sizeof *reg);
220
        reg->memory_size = size;
221
        assert(reg->memory_size);
222
        reg->guest_phys_addr = start_addr;
223
        reg->userspace_addr = uaddr;
224
        ++to;
225
    }
226
    assert(to <= dev->mem->nregions + 1);
227
    dev->mem->nregions = to;
228
}
229

    
230
static uint64_t vhost_get_log_size(struct vhost_dev *dev)
231
{
232
    uint64_t log_size = 0;
233
    int i;
234
    for (i = 0; i < dev->mem->nregions; ++i) {
235
        struct vhost_memory_region *reg = dev->mem->regions + i;
236
        uint64_t last = range_get_last(reg->guest_phys_addr,
237
                                       reg->memory_size);
238
        log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
239
    }
240
    for (i = 0; i < dev->nvqs; ++i) {
241
        struct vhost_virtqueue *vq = dev->vqs + i;
242
        uint64_t last = vq->used_phys + vq->used_size - 1;
243
        log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
244
    }
245
    return log_size;
246
}
247

    
248
static inline void vhost_dev_log_resize(struct vhost_dev* dev, uint64_t size)
249
{
250
    vhost_log_chunk_t *log;
251
    uint64_t log_base;
252
    int r;
253
    if (size) {
254
        log = qemu_mallocz(size * sizeof *log);
255
    } else {
256
        log = NULL;
257
    }
258
    log_base = (uint64_t)(unsigned long)log;
259
    r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base);
260
    assert(r >= 0);
261
    vhost_client_sync_dirty_bitmap(&dev->client, 0,
262
                                   (target_phys_addr_t)~0x0ull);
263
    if (dev->log) {
264
        qemu_free(dev->log);
265
    }
266
    dev->log = log;
267
    dev->log_size = size;
268
}
269

    
270
static int vhost_verify_ring_mappings(struct vhost_dev *dev,
271
                                      uint64_t start_addr,
272
                                      uint64_t size)
273
{
274
    int i;
275
    for (i = 0; i < dev->nvqs; ++i) {
276
        struct vhost_virtqueue *vq = dev->vqs + i;
277
        target_phys_addr_t l;
278
        void *p;
279

    
280
        if (!ranges_overlap(start_addr, size, vq->ring_phys, vq->ring_size)) {
281
            continue;
282
        }
283
        l = vq->ring_size;
284
        p = cpu_physical_memory_map(vq->ring_phys, &l, 1);
285
        if (!p || l != vq->ring_size) {
286
            fprintf(stderr, "Unable to map ring buffer for ring %d\n", i);
287
            return -ENOMEM;
288
        }
289
        if (p != vq->ring) {
290
            fprintf(stderr, "Ring buffer relocated for ring %d\n", i);
291
            return -EBUSY;
292
        }
293
        cpu_physical_memory_unmap(p, l, 0, 0);
294
    }
295
    return 0;
296
}
297

    
298
static void vhost_client_set_memory(CPUPhysMemoryClient *client,
299
                                    target_phys_addr_t start_addr,
300
                                    ram_addr_t size,
301
                                    ram_addr_t phys_offset)
302
{
303
    struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
304
    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
305
    int s = offsetof(struct vhost_memory, regions) +
306
        (dev->mem->nregions + 1) * sizeof dev->mem->regions[0];
307
    uint64_t log_size;
308
    int r;
309
    dev->mem = qemu_realloc(dev->mem, s);
310

    
311
    assert(size);
312

    
313
    vhost_dev_unassign_memory(dev, start_addr, size);
314
    if (flags == IO_MEM_RAM) {
315
        /* Add given mapping, merging adjacent regions if any */
316
        vhost_dev_assign_memory(dev, start_addr, size,
317
                                (uintptr_t)qemu_get_ram_ptr(phys_offset));
318
    } else {
319
        /* Remove old mapping for this memory, if any. */
320
        vhost_dev_unassign_memory(dev, start_addr, size);
321
    }
322

    
323
    if (!dev->started) {
324
        return;
325
    }
326

    
327
    if (dev->started) {
328
        r = vhost_verify_ring_mappings(dev, start_addr, size);
329
        assert(r >= 0);
330
    }
331

    
332
    if (!dev->log_enabled) {
333
        r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem);
334
        assert(r >= 0);
335
        return;
336
    }
337
    log_size = vhost_get_log_size(dev);
338
    /* We allocate an extra 4K bytes to log,
339
     * to reduce the * number of reallocations. */
340
#define VHOST_LOG_BUFFER (0x1000 / sizeof *dev->log)
341
    /* To log more, must increase log size before table update. */
342
    if (dev->log_size < log_size) {
343
        vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER);
344
    }
345
    r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem);
346
    assert(r >= 0);
347
    /* To log less, can only decrease log size after table update. */
348
    if (dev->log_size > log_size + VHOST_LOG_BUFFER) {
349
        vhost_dev_log_resize(dev, log_size);
350
    }
351
}
352

    
353
static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
354
                                    struct vhost_virtqueue *vq,
355
                                    unsigned idx, bool enable_log)
356
{
357
    struct vhost_vring_addr addr = {
358
        .index = idx,
359
        .desc_user_addr = (uint64_t)(unsigned long)vq->desc,
360
        .avail_user_addr = (uint64_t)(unsigned long)vq->avail,
361
        .used_user_addr = (uint64_t)(unsigned long)vq->used,
362
        .log_guest_addr = vq->used_phys,
363
        .flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0,
364
    };
365
    int r = ioctl(dev->control, VHOST_SET_VRING_ADDR, &addr);
366
    if (r < 0) {
367
        return -errno;
368
    }
369
    return 0;
370
}
371

    
372
static int vhost_dev_set_features(struct vhost_dev *dev, bool enable_log)
373
{
374
    uint64_t features = dev->acked_features;
375
    int r;
376
    if (enable_log) {
377
        features |= 0x1 << VHOST_F_LOG_ALL;
378
    }
379
    r = ioctl(dev->control, VHOST_SET_FEATURES, &features);
380
    return r < 0 ? -errno : 0;
381
}
382

    
383
static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
384
{
385
    int r, t, i;
386
    r = vhost_dev_set_features(dev, enable_log);
387
    if (r < 0) {
388
        goto err_features;
389
    }
390
    for (i = 0; i < dev->nvqs; ++i) {
391
        r = vhost_virtqueue_set_addr(dev, dev->vqs + i, i,
392
                                     enable_log);
393
        if (r < 0) {
394
            goto err_vq;
395
        }
396
    }
397
    return 0;
398
err_vq:
399
    for (; i >= 0; --i) {
400
        t = vhost_virtqueue_set_addr(dev, dev->vqs + i, i,
401
                                     dev->log_enabled);
402
        assert(t >= 0);
403
    }
404
    t = vhost_dev_set_features(dev, dev->log_enabled);
405
    assert(t >= 0);
406
err_features:
407
    return r;
408
}
409

    
410
static int vhost_client_migration_log(CPUPhysMemoryClient *client,
411
                                      int enable)
412
{
413
    struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
414
    int r;
415
    if (!!enable == dev->log_enabled) {
416
        return 0;
417
    }
418
    if (!dev->started) {
419
        dev->log_enabled = enable;
420
        return 0;
421
    }
422
    if (!enable) {
423
        r = vhost_dev_set_log(dev, false);
424
        if (r < 0) {
425
            return r;
426
        }
427
        if (dev->log) {
428
            qemu_free(dev->log);
429
        }
430
        dev->log = NULL;
431
        dev->log_size = 0;
432
    } else {
433
        vhost_dev_log_resize(dev, vhost_get_log_size(dev));
434
        r = vhost_dev_set_log(dev, true);
435
        if (r < 0) {
436
            return r;
437
        }
438
    }
439
    dev->log_enabled = enable;
440
    return 0;
441
}
442

    
443
static int vhost_virtqueue_init(struct vhost_dev *dev,
444
                                struct VirtIODevice *vdev,
445
                                struct vhost_virtqueue *vq,
446
                                unsigned idx)
447
{
448
    target_phys_addr_t s, l, a;
449
    int r;
450
    struct vhost_vring_file file = {
451
        .index = idx,
452
    };
453
    struct vhost_vring_state state = {
454
        .index = idx,
455
    };
456
    struct VirtQueue *vvq = virtio_get_queue(vdev, idx);
457

    
458
    if (!vdev->binding->set_guest_notifier) {
459
        fprintf(stderr, "binding does not support guest notifiers\n");
460
        return -ENOSYS;
461
    }
462

    
463
    if (!vdev->binding->set_host_notifier) {
464
        fprintf(stderr, "binding does not support host notifiers\n");
465
        return -ENOSYS;
466
    }
467

    
468
    vq->num = state.num = virtio_queue_get_num(vdev, idx);
469
    r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state);
470
    if (r) {
471
        return -errno;
472
    }
473

    
474
    state.num = virtio_queue_get_last_avail_idx(vdev, idx);
475
    r = ioctl(dev->control, VHOST_SET_VRING_BASE, &state);
476
    if (r) {
477
        return -errno;
478
    }
479

    
480
    s = l = virtio_queue_get_desc_size(vdev, idx);
481
    a = virtio_queue_get_desc_addr(vdev, idx);
482
    vq->desc = cpu_physical_memory_map(a, &l, 0);
483
    if (!vq->desc || l != s) {
484
        r = -ENOMEM;
485
        goto fail_alloc_desc;
486
    }
487
    s = l = virtio_queue_get_avail_size(vdev, idx);
488
    a = virtio_queue_get_avail_addr(vdev, idx);
489
    vq->avail = cpu_physical_memory_map(a, &l, 0);
490
    if (!vq->avail || l != s) {
491
        r = -ENOMEM;
492
        goto fail_alloc_avail;
493
    }
494
    vq->used_size = s = l = virtio_queue_get_used_size(vdev, idx);
495
    vq->used_phys = a = virtio_queue_get_used_addr(vdev, idx);
496
    vq->used = cpu_physical_memory_map(a, &l, 1);
497
    if (!vq->used || l != s) {
498
        r = -ENOMEM;
499
        goto fail_alloc_used;
500
    }
501

    
502
    vq->ring_size = s = l = virtio_queue_get_ring_size(vdev, idx);
503
    vq->ring_phys = a = virtio_queue_get_ring_addr(vdev, idx);
504
    vq->ring = cpu_physical_memory_map(a, &l, 1);
505
    if (!vq->ring || l != s) {
506
        r = -ENOMEM;
507
        goto fail_alloc_ring;
508
    }
509

    
510
    r = vhost_virtqueue_set_addr(dev, vq, idx, dev->log_enabled);
511
    if (r < 0) {
512
        r = -errno;
513
        goto fail_alloc;
514
    }
515
    r = vdev->binding->set_guest_notifier(vdev->binding_opaque, idx, true);
516
    if (r < 0) {
517
        fprintf(stderr, "Error binding guest notifier: %d\n", -r);
518
        goto fail_guest_notifier;
519
    }
520

    
521
    r = vdev->binding->set_host_notifier(vdev->binding_opaque, idx, true);
522
    if (r < 0) {
523
        fprintf(stderr, "Error binding host notifier: %d\n", -r);
524
        goto fail_host_notifier;
525
    }
526

    
527
    file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq));
528
    r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file);
529
    if (r) {
530
        goto fail_kick;
531
    }
532

    
533
    file.fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vvq));
534
    r = ioctl(dev->control, VHOST_SET_VRING_CALL, &file);
535
    if (r) {
536
        goto fail_call;
537
    }
538

    
539
    return 0;
540

    
541
fail_call:
542
fail_kick:
543
    vdev->binding->set_host_notifier(vdev->binding_opaque, idx, false);
544
fail_host_notifier:
545
    vdev->binding->set_guest_notifier(vdev->binding_opaque, idx, false);
546
fail_guest_notifier:
547
fail_alloc:
548
    cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
549
                              0, 0);
550
fail_alloc_ring:
551
    cpu_physical_memory_unmap(vq->used, virtio_queue_get_used_size(vdev, idx),
552
                              0, 0);
553
fail_alloc_used:
554
    cpu_physical_memory_unmap(vq->avail, virtio_queue_get_avail_size(vdev, idx),
555
                              0, 0);
556
fail_alloc_avail:
557
    cpu_physical_memory_unmap(vq->desc, virtio_queue_get_desc_size(vdev, idx),
558
                              0, 0);
559
fail_alloc_desc:
560
    return r;
561
}
562

    
563
static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
564
                                    struct VirtIODevice *vdev,
565
                                    struct vhost_virtqueue *vq,
566
                                    unsigned idx)
567
{
568
    struct vhost_vring_state state = {
569
        .index = idx,
570
    };
571
    int r;
572
    r = vdev->binding->set_guest_notifier(vdev->binding_opaque, idx, false);
573
    if (r < 0) {
574
        fprintf(stderr, "vhost VQ %d guest cleanup failed: %d\n", idx, r);
575
        fflush(stderr);
576
    }
577
    assert (r >= 0);
578

    
579
    r = vdev->binding->set_host_notifier(vdev->binding_opaque, idx, false);
580
    if (r < 0) {
581
        fprintf(stderr, "vhost VQ %d host cleanup failed: %d\n", idx, r);
582
        fflush(stderr);
583
    }
584
    assert (r >= 0);
585
    r = ioctl(dev->control, VHOST_GET_VRING_BASE, &state);
586
    if (r < 0) {
587
        fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r);
588
        fflush(stderr);
589
    }
590
    virtio_queue_set_last_avail_idx(vdev, idx, state.num);
591
    assert (r >= 0);
592
    cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
593
                              0, virtio_queue_get_ring_size(vdev, idx));
594
    cpu_physical_memory_unmap(vq->used, virtio_queue_get_used_size(vdev, idx),
595
                              1, virtio_queue_get_used_size(vdev, idx));
596
    cpu_physical_memory_unmap(vq->avail, virtio_queue_get_avail_size(vdev, idx),
597
                              0, virtio_queue_get_avail_size(vdev, idx));
598
    cpu_physical_memory_unmap(vq->desc, virtio_queue_get_desc_size(vdev, idx),
599
                              0, virtio_queue_get_desc_size(vdev, idx));
600
}
601

    
602
int vhost_dev_init(struct vhost_dev *hdev, int devfd)
603
{
604
    uint64_t features;
605
    int r;
606
    if (devfd >= 0) {
607
        hdev->control = devfd;
608
    } else {
609
        hdev->control = open("/dev/vhost-net", O_RDWR);
610
        if (hdev->control < 0) {
611
            return -errno;
612
        }
613
    }
614
    r = ioctl(hdev->control, VHOST_SET_OWNER, NULL);
615
    if (r < 0) {
616
        goto fail;
617
    }
618

    
619
    r = ioctl(hdev->control, VHOST_GET_FEATURES, &features);
620
    if (r < 0) {
621
        goto fail;
622
    }
623
    hdev->features = features;
624

    
625
    hdev->client.set_memory = vhost_client_set_memory;
626
    hdev->client.sync_dirty_bitmap = vhost_client_sync_dirty_bitmap;
627
    hdev->client.migration_log = vhost_client_migration_log;
628
    hdev->mem = qemu_mallocz(offsetof(struct vhost_memory, regions));
629
    hdev->log = NULL;
630
    hdev->log_size = 0;
631
    hdev->log_enabled = false;
632
    hdev->started = false;
633
    cpu_register_phys_memory_client(&hdev->client);
634
    return 0;
635
fail:
636
    r = -errno;
637
    close(hdev->control);
638
    return r;
639
}
640

    
641
void vhost_dev_cleanup(struct vhost_dev *hdev)
642
{
643
    cpu_unregister_phys_memory_client(&hdev->client);
644
    qemu_free(hdev->mem);
645
    close(hdev->control);
646
}
647

    
648
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
649
{
650
    int i, r;
651

    
652
    r = vhost_dev_set_features(hdev, hdev->log_enabled);
653
    if (r < 0) {
654
        goto fail;
655
    }
656
    r = ioctl(hdev->control, VHOST_SET_MEM_TABLE, hdev->mem);
657
    if (r < 0) {
658
        r = -errno;
659
        goto fail;
660
    }
661
    for (i = 0; i < hdev->nvqs; ++i) {
662
        r = vhost_virtqueue_init(hdev,
663
                                 vdev,
664
                                 hdev->vqs + i,
665
                                 i);
666
        if (r < 0) {
667
            goto fail_vq;
668
        }
669
    }
670

    
671
    if (hdev->log_enabled) {
672
        hdev->log_size = vhost_get_log_size(hdev);
673
        hdev->log = hdev->log_size ?
674
            qemu_mallocz(hdev->log_size * sizeof *hdev->log) : NULL;
675
        r = ioctl(hdev->control, VHOST_SET_LOG_BASE,
676
                  (uint64_t)(unsigned long)hdev->log);
677
        if (r < 0) {
678
            r = -errno;
679
            goto fail_vq;
680
        }
681
    }
682

    
683
    hdev->started = true;
684

    
685
    return 0;
686
fail_vq:
687
    while (--i >= 0) {
688
        vhost_virtqueue_cleanup(hdev,
689
                                vdev,
690
                                hdev->vqs + i,
691
                                i);
692
    }
693
fail:
694
    return r;
695
}
696

    
697
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
698
{
699
    int i;
700
    for (i = 0; i < hdev->nvqs; ++i) {
701
        vhost_virtqueue_cleanup(hdev,
702
                                vdev,
703
                                hdev->vqs + i,
704
                                i);
705
    }
706
    vhost_client_sync_dirty_bitmap(&hdev->client, 0,
707
                                   (target_phys_addr_t)~0x0ull);
708
    hdev->started = false;
709
    qemu_free(hdev->log);
710
    hdev->log_size = 0;
711
}