From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43149) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z1ypj-0006NW-6C for qemu-devel@nongnu.org; Mon, 08 Jun 2015 11:19:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z1yph-0005F9-BJ for qemu-devel@nongnu.org; Mon, 08 Jun 2015 11:19:27 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36260) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z1yph-0005Dw-4x for qemu-devel@nongnu.org; Mon, 08 Jun 2015 11:19:25 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id C42178E4F8 for ; Mon, 8 Jun 2015 15:19:24 +0000 (UTC) From: Igor Mammedov Date: Mon, 8 Jun 2015 17:19:14 +0200 Message-Id: <1433776757-61958-4-git-send-email-imammedo@redhat.com> In-Reply-To: <1433776757-61958-1-git-send-email-imammedo@redhat.com> References: <1433776757-61958-1-git-send-email-imammedo@redhat.com> Subject: [Qemu-devel] [RFC v2 3/6] memory: support unmapping of MemoryRegion mapped into HVA parent List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, mst@redhat.com due to need to preserve HVA reserved range continous (make it atomic), unmap subregion's host memory by placing reservation mapping on it's range and invalidate subregion since it can't be reused anymore. Also add memory_region_is_hva_mapped() to let backend check if MemoryRegion should be recreated instead of returning invalidated region. Signed-off-by: Igor Mammedov --- exec.c | 17 ++++++++++++++++- include/exec/cpu-common.h | 1 + include/exec/memory.h | 13 +++++++++++++ memory.c | 16 ++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 7e47f64..7bef7f9 100644 --- a/exec.c +++ b/exec.c @@ -1332,11 +1332,22 @@ void *qemu_ram_reserve_hva(ram_addr_t length) MAP_NORESERVE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); } +void qemu_ram_unmap_hva(ram_addr_t addr) +{ + RAMBlock *block = find_ram_block(addr); + + assert(block); + mmap(block->host, block->used_length, PROT_NONE, + MAP_FIXED | MAP_NORESERVE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); +} + void qemu_ram_remap_hva(ram_addr_t addr, void *new_hva) { RAMBlock *block = find_ram_block(addr); assert(block); + assert(!(block->flags & RAM_PREALLOC)); + block->flags |= RAM_PREALLOC; block->host = mremap(block->host, block->used_length, block->used_length, MREMAP_MAYMOVE | MREMAP_FIXED, new_hva); @@ -1595,11 +1606,15 @@ static void reclaim_ramblock(RAMBlock *block) #ifndef _WIN32 } else if (block->fd >= 0) { munmap(block->host, block->max_length); - close(block->fd); #endif } else { qemu_anon_ram_free(block->host, block->max_length); } +#ifndef _WIN32 + if (block->fd >= 0) { + close(block->fd); + } +#endif g_free(block); } diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index ec077ee..817762c 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -62,6 +62,7 @@ typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr); void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); void *qemu_ram_reserve_hva(ram_addr_t length); void qemu_ram_remap_hva(ram_addr_t addr, void *new_hva); +void qemu_ram_unmap_hva(ram_addr_t addr); /* This should not be used by devices. */ MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr); void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev); diff --git a/include/exec/memory.h b/include/exec/memory.h index 5e16026..f9e86d6 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -175,6 +175,7 @@ struct MemoryRegion { bool romd_mode; bool ram; void *rsvd_hva; + bool hva_mapped; bool skip_dump; bool readonly; /* For RAM regions */ bool enabled; @@ -902,6 +903,10 @@ void memory_region_add_subregion(MemoryRegion *mr, * memory_region_del_subregion()); use memory_region_init_alias() if you * want a region to be a subregion in multiple locations. * + * if @subregion has HVA container as parent, the call rereseves HVA + * range ocicupied by @subregion, freeing host memory along the way + * and invalidates @subregion so it coudn't be reused. + * * @mr: the region to contain the new subregion; must be a container * initialized with memory_region_init(). * @offset: the offset relative to @mr where @subregion is added. @@ -1003,6 +1008,14 @@ bool memory_region_present(MemoryRegion *container, hwaddr addr); bool memory_region_is_mapped(MemoryRegion *mr); /** + * memory_region_is_hva_mapped: returns true if #MemoryRegion is/was + * mapped into HVA container. + * + * @mr: a #MemoryRegion which should be checked if it's HVA parent + */ +bool memory_region_is_hva_mapped(MemoryRegion *mr); + +/** * memory_region_find: translate an address/size relative to a * MemoryRegion into a #MemoryRegionSection. * diff --git a/memory.c b/memory.c index f9b8a60..ab6d41b 100644 --- a/memory.c +++ b/memory.c @@ -1754,7 +1754,9 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, if (mr->ram) { MemoryRegionSection rsvd_hva = memory_region_find_hva_range(mr); + assert(!subregion->hva_mapped); if (rsvd_hva.mr) { + subregion->hva_mapped = true; qemu_ram_remap_hva(mr->ram_addr, memory_region_get_ram_ptr(rsvd_hva.mr) + rsvd_hva.offset_within_region); @@ -1788,6 +1790,15 @@ void memory_region_del_subregion(MemoryRegion *mr, { memory_region_transaction_begin(); assert(subregion->container == mr); + + if (mr->ram) { + MemoryRegionSection rsvd_hva = memory_region_find_hva_range(mr); + + if (rsvd_hva.mr) { + qemu_ram_unmap_hva(mr->ram_addr); + } + } + subregion->container = NULL; QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link); memory_region_unref(subregion); @@ -1903,6 +1914,11 @@ bool memory_region_is_mapped(MemoryRegion *mr) return mr->container ? true : false; } +bool memory_region_is_hva_mapped(MemoryRegion *mr) +{ + return mr->hva_mapped ? true : false; +} + MemoryRegionSection memory_region_find_hva_range(MemoryRegion *mr) { MemoryRegionSection ret = { .mr = NULL }; -- 1.8.3.1