Revision 04097f7c

b/hw/vhost.c
57 57
    }
58 58
}
59 59

  
60
static int vhost_client_sync_dirty_bitmap(CPUPhysMemoryClient *client,
61
                                          target_phys_addr_t start_addr,
62
                                          target_phys_addr_t end_addr)
60
static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
61
                                   target_phys_addr_t start_addr,
62
                                   target_phys_addr_t end_addr)
63 63
{
64
    struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
65 64
    int i;
65

  
66 66
    if (!dev->log_enabled || !dev->started) {
67 67
        return 0;
68 68
    }
......
81 81
    return 0;
82 82
}
83 83

  
84
static void vhost_log_sync(MemoryListener *listener,
85
                          MemoryRegionSection *section)
86
{
87
    struct vhost_dev *dev = container_of(listener, struct vhost_dev,
88
                                         memory_listener);
89
    target_phys_addr_t start_addr = section->offset_within_address_space;
90
    target_phys_addr_t end_addr = start_addr + section->size;
91

  
92
    vhost_sync_dirty_bitmap(dev, start_addr, end_addr);
93
}
94

  
84 95
/* Assign/unassign. Keep an unsorted array of non-overlapping
85 96
 * memory regions in dev->mem. */
86 97
static void vhost_dev_unassign_memory(struct vhost_dev *dev,
......
259 270
    log_base = (uint64_t)(unsigned long)log;
260 271
    r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base);
261 272
    assert(r >= 0);
262
    vhost_client_sync_dirty_bitmap(&dev->client, 0,
263
                                   (target_phys_addr_t)~0x0ull);
273
    vhost_sync_dirty_bitmap(dev, 0, (target_phys_addr_t)~0x0ull);
264 274
    if (dev->log) {
265 275
        g_free(dev->log);
266 276
    }
......
335 345
    return uaddr != reg->userspace_addr + start_addr - reg->guest_phys_addr;
336 346
}
337 347

  
338
static void vhost_client_set_memory(CPUPhysMemoryClient *client,
339
                                    target_phys_addr_t start_addr,
340
                                    ram_addr_t size,
341
                                    ram_addr_t phys_offset,
342
                                    bool log_dirty)
348
static void vhost_set_memory(MemoryListener *listener,
349
                             MemoryRegionSection *section,
350
                             bool add)
343 351
{
344
    struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
345
    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
352
    struct vhost_dev *dev = container_of(listener, struct vhost_dev,
353
                                         memory_listener);
354
    target_phys_addr_t start_addr = section->offset_within_address_space;
355
    ram_addr_t size = section->size;
356
    bool log_dirty = memory_region_is_logging(section->mr);
346 357
    int s = offsetof(struct vhost_memory, regions) +
347 358
        (dev->mem->nregions + 1) * sizeof dev->mem->regions[0];
348 359
    uint64_t log_size;
349 360
    int r;
361
    void *ram;
362

  
363
    if (!memory_region_is_ram(section->mr)) {
364
        return;
365
    }
350 366

  
351 367
    dev->mem = g_realloc(dev->mem, s);
352 368

  
353 369
    if (log_dirty) {
354
        flags = IO_MEM_UNASSIGNED;
370
        add = false;
355 371
    }
356 372

  
357 373
    assert(size);
358 374

  
359 375
    /* Optimize no-change case. At least cirrus_vga does this a lot at this time. */
360
    if (flags == IO_MEM_RAM) {
361
        if (!vhost_dev_cmp_memory(dev, start_addr, size,
362
                                  (uintptr_t)qemu_get_ram_ptr(phys_offset))) {
376
    ram = memory_region_get_ram_ptr(section->mr);
377
    if (add) {
378
        if (!vhost_dev_cmp_memory(dev, start_addr, size, (uintptr_t)ram)) {
363 379
            /* Region exists with same address. Nothing to do. */
364 380
            return;
365 381
        }
......
371 387
    }
372 388

  
373 389
    vhost_dev_unassign_memory(dev, start_addr, size);
374
    if (flags == IO_MEM_RAM) {
390
    if (add) {
375 391
        /* Add given mapping, merging adjacent regions if any */
376
        vhost_dev_assign_memory(dev, start_addr, size,
377
                                (uintptr_t)qemu_get_ram_ptr(phys_offset));
392
        vhost_dev_assign_memory(dev, start_addr, size, (uintptr_t)ram);
378 393
    } else {
379 394
        /* Remove old mapping for this memory, if any. */
380 395
        vhost_dev_unassign_memory(dev, start_addr, size);
......
410 425
    }
411 426
}
412 427

  
428
static void vhost_region_add(MemoryListener *listener,
429
                             MemoryRegionSection *section)
430
{
431
    vhost_set_memory(listener, section, true);
432
}
433

  
434
static void vhost_region_del(MemoryListener *listener,
435
                             MemoryRegionSection *section)
436
{
437
    vhost_set_memory(listener, section, false);
438
}
439

  
413 440
static int vhost_virtqueue_set_addr(struct vhost_dev *dev,
414 441
                                    struct vhost_virtqueue *vq,
415 442
                                    unsigned idx, bool enable_log)
......
467 494
    return r;
468 495
}
469 496

  
470
static int vhost_client_migration_log(CPUPhysMemoryClient *client,
471
                                      int enable)
497
static int vhost_migration_log(MemoryListener *listener, int enable)
472 498
{
473
    struct vhost_dev *dev = container_of(client, struct vhost_dev, client);
499
    struct vhost_dev *dev = container_of(listener, struct vhost_dev,
500
                                         memory_listener);
474 501
    int r;
475 502
    if (!!enable == dev->log_enabled) {
476 503
        return 0;
......
500 527
    return 0;
501 528
}
502 529

  
530
static void vhost_log_global_start(MemoryListener *listener)
531
{
532
    int r;
533

  
534
    r = vhost_migration_log(listener, true);
535
    if (r < 0) {
536
        abort();
537
    }
538
}
539

  
540
static void vhost_log_global_stop(MemoryListener *listener)
541
{
542
    int r;
543

  
544
    r = vhost_migration_log(listener, false);
545
    if (r < 0) {
546
        abort();
547
    }
548
}
549

  
550
static void vhost_log_start(MemoryListener *listener,
551
                            MemoryRegionSection *section)
552
{
553
    /* FIXME: implement */
554
}
555

  
556
static void vhost_log_stop(MemoryListener *listener,
557
                           MemoryRegionSection *section)
558
{
559
    /* FIXME: implement */
560
}
561

  
503 562
static int vhost_virtqueue_init(struct vhost_dev *dev,
504 563
                                struct VirtIODevice *vdev,
505 564
                                struct vhost_virtqueue *vq,
......
645 704
    }
646 705
    hdev->features = features;
647 706

  
648
    hdev->client.set_memory = vhost_client_set_memory;
649
    hdev->client.sync_dirty_bitmap = vhost_client_sync_dirty_bitmap;
650
    hdev->client.migration_log = vhost_client_migration_log;
651
    hdev->client.log_start = NULL;
652
    hdev->client.log_stop = NULL;
707
    hdev->memory_listener = (MemoryListener) {
708
        .region_add = vhost_region_add,
709
        .region_del = vhost_region_del,
710
        .log_start = vhost_log_start,
711
        .log_stop = vhost_log_stop,
712
        .log_sync = vhost_log_sync,
713
        .log_global_start = vhost_log_global_start,
714
        .log_global_stop = vhost_log_global_stop,
715
    };
653 716
    hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
654 717
    hdev->log = NULL;
655 718
    hdev->log_size = 0;
656 719
    hdev->log_enabled = false;
657 720
    hdev->started = false;
658
    cpu_register_phys_memory_client(&hdev->client);
721
    memory_listener_register(&hdev->memory_listener);
659 722
    hdev->force = force;
660 723
    return 0;
661 724
fail:
......
666 729

  
667 730
void vhost_dev_cleanup(struct vhost_dev *hdev)
668 731
{
669
    cpu_unregister_phys_memory_client(&hdev->client);
732
    memory_listener_unregister(&hdev->memory_listener);
670 733
    g_free(hdev->mem);
671 734
    close(hdev->control);
672 735
}
......
808 871
                                hdev->vqs + i,
809 872
                                i);
810 873
    }
811
    vhost_client_sync_dirty_bitmap(&hdev->client, 0,
812
                                   (target_phys_addr_t)~0x0ull);
874
    vhost_sync_dirty_bitmap(hdev, 0, (target_phys_addr_t)~0x0ull);
813 875
    r = vdev->binding->set_guest_notifiers(vdev->binding_opaque, false);
814 876
    if (r < 0) {
815 877
        fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
b/hw/vhost.h
3 3

  
4 4
#include "hw/hw.h"
5 5
#include "hw/virtio.h"
6
#include "memory.h"
6 7

  
7 8
/* Generic structures common for any vhost based device. */
8 9
struct vhost_virtqueue {
......
26 27

  
27 28
struct vhost_memory;
28 29
struct vhost_dev {
29
    CPUPhysMemoryClient client;
30
    MemoryListener memory_listener;
30 31
    int control;
31 32
    struct vhost_memory *mem;
32 33
    struct vhost_virtqueue *vqs;

Also available in: Unified diff