diff options
author | Dr. David Alan Gilbert <dgilbert@redhat.com> | 2018-01-19 10:39:21 +0000 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2018-02-08 21:06:40 +0200 |
commit | ade6d081fc33948e56e655ee37b1306b6de6e0ef (patch) | |
tree | c1a21332fa08b61685afebf7fbe33de6bfd6f287 /hw/virtio/vhost.c | |
parent | 48d7c97577498657f9ccbcbf1f990fdb4b79501f (diff) |
vhost: Regenerate region list from changed sections list
Compare the sections list that's just been generated, and if it's
different from the old one regenerate the region list.
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Diffstat (limited to 'hw/virtio/vhost.c')
-rw-r--r-- | hw/virtio/vhost.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 351c691439..f3badc4827 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -643,21 +643,52 @@ static void vhost_commit(MemoryListener *listener) MemoryRegionSection *old_sections; int n_old_sections; uint64_t log_size; + size_t regions_size; int r; int i; + bool changed = false; + /* Note we can be called before the device is started, but then + * starting the device calls set_mem_table, so we need to have + * built the data structures. + */ old_sections = dev->mem_sections; n_old_sections = dev->n_mem_sections; dev->mem_sections = dev->tmp_sections; dev->n_mem_sections = dev->n_tmp_sections; - if (!dev->memory_changed) { - goto out; + if (dev->n_mem_sections != n_old_sections) { + changed = true; + } else { + /* Same size, lets check the contents */ + changed = n_old_sections && memcmp(dev->mem_sections, old_sections, + n_old_sections * sizeof(old_sections[0])) != 0; } - if (!dev->started) { + + trace_vhost_commit(dev->started, changed); + if (!changed) { goto out; } - if (dev->mem_changed_start_addr > dev->mem_changed_end_addr) { + + /* Rebuild the regions list from the new sections list */ + regions_size = offsetof(struct vhost_memory, regions) + + dev->n_mem_sections * sizeof dev->mem->regions[0]; + dev->mem = g_realloc(dev->mem, regions_size); + dev->mem->nregions = dev->n_mem_sections; + used_memslots = dev->mem->nregions; + for (i = 0; i < dev->n_mem_sections; i++) { + struct vhost_memory_region *cur_vmr = dev->mem->regions + i; + struct MemoryRegionSection *mrs = dev->mem_sections + i; + + cur_vmr->guest_phys_addr = mrs->offset_within_address_space; + cur_vmr->memory_size = int128_get64(mrs->size); + cur_vmr->userspace_addr = + (uintptr_t)memory_region_get_ram_ptr(mrs->mr) + + mrs->offset_within_region; + cur_vmr->flags_padding = 0; + } + + if (!dev->started) { goto out; } |