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