Revision 6b37a23d hw/vhost.c

b/hw/vhost.c
53 53
        log = __sync_fetch_and_and(from, 0);
54 54
        while ((bit = sizeof(log) > sizeof(int) ?
55 55
                ffsll(log) : ffs(log))) {
56
            ram_addr_t ram_addr;
56
            hwaddr page_addr;
57
            hwaddr section_offset;
58
            hwaddr mr_offset;
57 59
            bit -= 1;
58
            ram_addr = section->offset_within_region + bit * VHOST_LOG_PAGE;
59
            memory_region_set_dirty(section->mr, ram_addr, VHOST_LOG_PAGE);
60
            page_addr = addr + bit * VHOST_LOG_PAGE;
61
            section_offset = page_addr - section->offset_within_address_space;
62
            mr_offset = section_offset + section->offset_within_region;
63
            memory_region_set_dirty(section->mr, mr_offset, VHOST_LOG_PAGE);
60 64
            log &= ~(0x1ull << bit);
61 65
        }
62 66
        addr += VHOST_LOG_CHUNK;
......
65 69

  
66 70
static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
67 71
                                   MemoryRegionSection *section,
68
                                   hwaddr start_addr,
69
                                   hwaddr end_addr)
72
                                   hwaddr first,
73
                                   hwaddr last)
70 74
{
71 75
    int i;
76
    hwaddr start_addr;
77
    hwaddr end_addr;
72 78

  
73 79
    if (!dev->log_enabled || !dev->started) {
74 80
        return 0;
75 81
    }
82
    start_addr = section->offset_within_address_space;
83
    end_addr = range_get_last(start_addr, section->size);
84
    start_addr = MAX(first, start_addr);
85
    end_addr = MIN(last, end_addr);
86

  
76 87
    for (i = 0; i < dev->mem->nregions; ++i) {
77 88
        struct vhost_memory_region *reg = dev->mem->regions + i;
78 89
        vhost_dev_sync_region(dev, section, start_addr, end_addr,
......
93 104
{
94 105
    struct vhost_dev *dev = container_of(listener, struct vhost_dev,
95 106
                                         memory_listener);
96
    hwaddr start_addr = section->offset_within_address_space;
97
    hwaddr end_addr = start_addr + section->size;
107
    vhost_sync_dirty_bitmap(dev, section, 0x0, ~0x0ULL);
108
}
98 109

  
99
    vhost_sync_dirty_bitmap(dev, section, start_addr, end_addr);
110
static void vhost_log_sync_range(struct vhost_dev *dev,
111
                                 hwaddr first, hwaddr last)
112
{
113
    int i;
114
    /* FIXME: this is N^2 in number of sections */
115
    for (i = 0; i < dev->n_mem_sections; ++i) {
116
        MemoryRegionSection *section = &dev->mem_sections[i];
117
        vhost_sync_dirty_bitmap(dev, section, first, last);
118
    }
100 119
}
101 120

  
102 121
/* Assign/unassign. Keep an unsorted array of non-overlapping
......
268 287
{
269 288
    vhost_log_chunk_t *log;
270 289
    uint64_t log_base;
271
    int r, i;
290
    int r;
272 291

  
273 292
    log = g_malloc0(size * sizeof *log);
274 293
    log_base = (uint64_t)(unsigned long)log;
275 294
    r = ioctl(dev->control, VHOST_SET_LOG_BASE, &log_base);
276 295
    assert(r >= 0);
277
    for (i = 0; i < dev->n_mem_sections; ++i) {
278
        /* Sync only the range covered by the old log */
279
        vhost_sync_dirty_bitmap(dev, &dev->mem_sections[i], 0,
280
                                dev->log_size * VHOST_LOG_CHUNK - 1);
296
    /* Sync only the range covered by the old log */
297
    if (dev->log_size) {
298
        vhost_log_sync_range(dev, 0, dev->log_size * VHOST_LOG_CHUNK - 1);
281 299
    }
282 300
    if (dev->log) {
283 301
        g_free(dev->log);
......
1014 1032
                             hdev->vqs + i,
1015 1033
                             hdev->vq_index + i);
1016 1034
    }
1017
    for (i = 0; i < hdev->n_mem_sections; ++i) {
1018
        vhost_sync_dirty_bitmap(hdev, &hdev->mem_sections[i],
1019
                                0, (hwaddr)~0x0ull);
1020
    }
1035
    vhost_log_sync_range(hdev, 0, ~0x0ull);
1021 1036

  
1022 1037
    hdev->started = false;
1023 1038
    g_free(hdev->log);

Also available in: Unified diff