From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:40532) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TBLHB-0007sO-Hm for qemu-devel@nongnu.org; Tue, 11 Sep 2012 03:52:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TBLH5-0007M0-IY for qemu-devel@nongnu.org; Tue, 11 Sep 2012 03:52:53 -0400 Received: from mail-ob0-f173.google.com ([209.85.214.173]:38954) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TBLH5-0007Gb-Dh for qemu-devel@nongnu.org; Tue, 11 Sep 2012 03:52:47 -0400 Received: by mail-ob0-f173.google.com with SMTP id ta14so286204obb.4 for ; Tue, 11 Sep 2012 00:52:47 -0700 (PDT) From: Liu Ping Fan Date: Tue, 11 Sep 2012 15:51:47 +0800 Message-Id: <1347349912-15611-7-git-send-email-qemulist@gmail.com> In-Reply-To: <1347349912-15611-1-git-send-email-qemulist@gmail.com> References: <1347349912-15611-1-git-send-email-qemulist@gmail.com> Subject: [Qemu-devel] [PATCH V3 06/11] memory: make mmio dispatch able to be out of biglock List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Jan Kiszka , Marcelo Tosatti , Avi Kivity , Anthony Liguori , Paolo Bonzini From: Liu Ping Fan Without biglock, we try to protect the mr by increase refcnt. If we can inc refcnt, go backward and resort to biglock. Another point is memory radix-tree can be flushed by another thread, so we should get the copy of terminal mr to survive from such issue. Signed-off-by: Liu Ping Fan --- exec.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 94 insertions(+), 1 deletions(-) diff --git a/exec.c b/exec.c index 5834766..93205b1 100644 --- a/exec.c +++ b/exec.c @@ -3163,8 +3163,11 @@ static void io_mem_init(void) "watch", UINT64_MAX); } +static QemuMutex mem_map_lock; + static void core_begin(MemoryListener *listener) { + qemu_mutex_lock(&mem_map_lock); destroy_all_mappings(); phys_sections_clear(); phys_map.ptr = PHYS_MAP_NODE_NIL; @@ -3184,17 +3187,32 @@ static void core_commit(MemoryListener *listener) for(env = first_cpu; env != NULL; env = env->next_cpu) { tlb_flush(env, 1); } + qemu_mutex_unlock(&mem_map_lock); } static void core_region_add(MemoryListener *listener, MemoryRegionSection *section) { + MemoryRegion *mr = section->mr; + + if (mr->ops != NULL) { + if (mr->ops->ref != NULL) { + mr->ops->ref(mr); + } + } cpu_register_physical_memory_log(section, section->readonly); } static void core_region_del(MemoryListener *listener, MemoryRegionSection *section) { + MemoryRegion *mr = section->mr; + + if (mr->ops != NULL) { + if (mr->ops->unref != NULL) { + mr->ops->unref(mr); + } + } } static void core_region_nop(MemoryListener *listener, @@ -3348,6 +3366,8 @@ static void memory_map_init(void) memory_region_init(system_io, "io", 65536); set_system_io_map(system_io); + qemu_mutex_init(&mem_map_lock); + memory_listener_register(&core_memory_listener, system_memory); memory_listener_register(&io_memory_listener, system_io); } @@ -3406,6 +3426,52 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr, } #else + +static MemoryRegionSection *subpage_get_terminal(subpage_t *mmio, + target_phys_addr_t addr) +{ + MemoryRegionSection *section; + unsigned int idx = SUBPAGE_IDX(addr); + + section = &phys_sections[mmio->sub_section[idx]]; + return section; +} + +static MemoryRegionSection mrs_get_terminal(MemoryRegionSection *mrs, + target_phys_addr_t addr) +{ + if (mrs->mr->subpage) { + mrs = subpage_get_terminal(mrs->mr->opaque, addr); + } + return *mrs; +} + +static int mrs_ref(MemoryRegionSection *mrs) +{ + MemoryRegion *mr; + int ret; + + mr = mrs->mr; + if (mr->ops != NULL) { + if (mr->ops->ref != NULL) { + ret = mr->ops->ref(mr); + } + } + return ret; +} + +static void mrs_unref(MemoryRegionSection *mrs) +{ + MemoryRegion *mr; + + mr = mrs->mr; + if (mr->ops != NULL) { + if (mr->ops->unref != NULL) { + mr->ops->unref(mr); + } + } +} + void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write) { @@ -3413,14 +3479,35 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, uint8_t *ptr; uint32_t val; target_phys_addr_t page; - MemoryRegionSection *section; + MemoryRegionSection *section, obj_mrs; + int ret; + int need_biglock = 0; + /* Will finally removed after all mr->ops implement ref/unref() */ +try_big_lock: + if (need_biglock == 1) { + qemu_mutex_lock_iothread(); + } while (len > 0) { page = addr & TARGET_PAGE_MASK; l = (page + TARGET_PAGE_SIZE) - addr; if (l > len) l = len; + + qemu_mutex_lock(&mem_map_lock); section = phys_page_find(page >> TARGET_PAGE_BITS); + if (need_biglock == 0) { + obj_mrs = mrs_get_terminal(section, addr); + ret = mrs_ref(&obj_mrs); + if (ret <= 0) { + need_biglock = 1; + qemu_mutex_unlock(&mem_map_lock); + goto try_big_lock; + } + /* rely on local variable */ + section = &obj_mrs; + } + qemu_mutex_unlock(&mem_map_lock); if (is_write) { if (!memory_region_is_ram(section->mr)) { @@ -3491,10 +3578,16 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, qemu_put_ram_ptr(ptr); } } + + mrs_unref(&obj_mrs); len -= l; buf += l; addr += l; } + + if (need_biglock == 1) { + qemu_mutex_unlock_iothread(); + } } /* used for ROM loading : can write in RAM and ROM */ -- 1.7.4.4