From: Liu Ping Fan <pingf...@linux.vnet.ibm.com> With ref()/unref() interface of MemoryRegion, we can pin RAM-Device when using its memory, and release it when done.
Signed-off-by: Liu Ping Fan <pingf...@linux.vnet.ibm.com> --- hw/virtio/dataplane/hostmem.c | 24 +++++++++++++++++++----- hw/virtio/dataplane/vring.c | 8 ++++---- include/hw/virtio/dataplane/hostmem.h | 4 +++- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/hw/virtio/dataplane/hostmem.c b/hw/virtio/dataplane/hostmem.c index f31a703..420c9be 100644 --- a/hw/virtio/dataplane/hostmem.c +++ b/hw/virtio/dataplane/hostmem.c @@ -42,18 +42,23 @@ static void hostmem_ref(HostMem *hostmem) static void hostmem_unref(HostMem *hostmem) { - int t; + int i, t; + HostMemRegion *hmr; t = __sync_sub_and_fetch(&hostmem->ref, 1); assert(t >= 0); if (!t) { + for (i = 0; i < hostmem->num_current_regions; i++) { + hmr = &hostmem->current_regions[i]; + memory_region_unref(hmr->mr); + } g_free(hostmem->current_regions); g_free(hostmem); } } static void *address_space_mem_lookup(AddrSpaceMem *as_mem, hwaddr phys, - hwaddr len, bool is_write) + hwaddr len, MemoryRegion **mr, bool is_write) { HostMemRegion *region; void *host_addr = NULL; @@ -65,6 +70,9 @@ static void *address_space_mem_lookup(AddrSpaceMem *as_mem, hwaddr phys, hostmem_ref(hostmem); qemu_mutex_unlock(&as_mem->cur_lock); + if (mr) { + *mr = NULL; + } region = bsearch(&phys, hostmem->current_regions, hostmem->num_current_regions, sizeof(hostmem->current_regions[0]), @@ -79,7 +87,10 @@ static void *address_space_mem_lookup(AddrSpaceMem *as_mem, hwaddr phys, if (len <= region->size - offset_within_region) { host_addr = region->host_addr + offset_within_region; } - + if (mr) { + *mr = region->mr; + memory_region_ref(*mr); + } out: hostmem_unref(hostmem); return host_addr; @@ -88,9 +99,10 @@ out: /** * Map guest physical address to host pointer */ -void *hostmem_lookup(hwaddr phys, hwaddr len, bool is_write) +void *hostmem_lookup(hwaddr phys, hwaddr len, MemoryRegion **mr, + bool is_write) { - return address_space_mem_lookup(system_mem, phys, len, is_write); + return address_space_mem_lookup(system_mem, phys, len, mr, is_write); } static void hostmem_listener_begin(MemoryListener *listener) @@ -134,6 +146,7 @@ static void hostmem_append_new_region(HostMem *hostmem, hostmem->current_regions[num] = (HostMemRegion){ .host_addr = ram_ptr + section->offset_within_region, .guest_addr = section->offset_within_address_space, + .mr = section->mr, .size = section->size, .readonly = section->readonly, }; @@ -155,6 +168,7 @@ static void hostmem_listener_append_region(MemoryListener *listener, return; } + memory_region_ref(section->mr); hostmem_append_new_region(as_mem->next_hostmem, section); } diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 4d6d735..e3c3afb 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -27,7 +27,7 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n) vring->broken = false; - vring_ptr = hostmem_lookup(vring_addr, vring_size, true); + vring_ptr = hostmem_lookup(vring_addr, vring_size, NULL, true); if (!vring_ptr) { error_report("Failed to map vring " "addr %#" HWADDR_PRIx " size %" HWADDR_PRIu, @@ -137,7 +137,7 @@ static int get_indirect(Vring *vring, /* Translate indirect descriptor */ desc_ptr = hostmem_lookup(indirect->addr + found * sizeof(desc), - sizeof(desc), false); + sizeof(desc), NULL, false); if (!desc_ptr) { error_report("Failed to map indirect descriptor " "addr %#" PRIx64 " len %zu", @@ -169,7 +169,7 @@ static int get_indirect(Vring *vring, return -ENOBUFS; } - iov->iov_base = hostmem_lookup(desc.addr, desc.len, + iov->iov_base = hostmem_lookup(desc.addr, desc.len, NULL, desc.flags & VRING_DESC_F_WRITE); if (!iov->iov_base) { error_report("Failed to map indirect descriptor" @@ -297,7 +297,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, } /* TODO handle non-contiguous memory across region boundaries */ - iov->iov_base = hostmem_lookup(desc.addr, desc.len, + iov->iov_base = hostmem_lookup(desc.addr, desc.len, NULL, desc.flags & VRING_DESC_F_WRITE); if (!iov->iov_base) { error_report("Failed to map vring desc addr %#" PRIx64 " len %u", diff --git a/include/hw/virtio/dataplane/hostmem.h b/include/hw/virtio/dataplane/hostmem.h index d04ce55..094102b 100644 --- a/include/hw/virtio/dataplane/hostmem.h +++ b/include/hw/virtio/dataplane/hostmem.h @@ -21,6 +21,7 @@ typedef struct { void *host_addr; hwaddr guest_addr; + MemoryRegion *mr; uint64_t size; bool readonly; } HostMemRegion; @@ -52,7 +53,8 @@ typedef struct { * can be done with other mechanisms like bdrv_drain_all() that quiesce * in-flight I/O. */ -void *hostmem_lookup(hwaddr phys, hwaddr len, bool is_write); +void *hostmem_lookup(hwaddr phys, hwaddr len, MemoryRegion **mr, + bool is_write); void hostmem_init(void); #else -- 1.7.4.4