From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36209) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZNl0Z-0002ZN-Q4 for qemu-devel@nongnu.org; Fri, 07 Aug 2015 13:00:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZNl0V-0004Cl-6k for qemu-devel@nongnu.org; Fri, 07 Aug 2015 13:00:38 -0400 Received: from mail-wi0-f171.google.com ([209.85.212.171]:37582) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZNl0U-0004CP-Oz for qemu-devel@nongnu.org; Fri, 07 Aug 2015 13:00:35 -0400 Received: by wibhh20 with SMTP id hh20so73618416wib.0 for ; Fri, 07 Aug 2015 10:00:34 -0700 (PDT) From: Alvise Rigo Date: Fri, 7 Aug 2015 19:03:07 +0200 Message-Id: <1438966995-5913-2-git-send-email-a.rigo@virtualopensystems.com> In-Reply-To: <1438966995-5913-1-git-send-email-a.rigo@virtualopensystems.com> References: <1438966995-5913-1-git-send-email-a.rigo@virtualopensystems.com> Subject: [Qemu-devel] [RFC v4 1/9] exec.c: Add new exclusive bitmap to ram_list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, mttcg@listserver.greensocs.com Cc: alex.bennee@linaro.org, jani.kokkonen@huawei.com, tech@virtualopensystems.com, claudio.fontana@huawei.com, pbonzini@redhat.com The purpose of this new bitmap is to flag the memory pages that are in the middle of LL/SC operations (after a LL, before a SC) on a per-vCPU basis. For all these pages, the corresponding TLB entries will be generated in such a way to force the slow-path if at least one vCPU has the bit not set. When the system starts, the whole memory is dirty (all the bitmap is set). A page, after being marked as exclusively-clean, will be restored as dirty after the SC. The accessors to this bitmap are currently not atomic, but they have to be so in a real multi-threading TCG. Suggested-by: Jani Kokkonen Suggested-by: Claudio Fontana Signed-off-by: Alvise Rigo --- exec.c | 7 +++-- include/exec/memory.h | 3 ++- include/exec/ram_addr.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/exec.c b/exec.c index 7d60e15..f113076 100644 --- a/exec.c +++ b/exec.c @@ -1493,11 +1493,14 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp) int i; /* ram_list.dirty_memory[] is protected by the iothread lock. */ - for (i = 0; i < DIRTY_MEMORY_NUM; i++) { + for (i = 0; i < DIRTY_MEMORY_EXCLUSIVE; i++) { ram_list.dirty_memory[i] = bitmap_zero_extend(ram_list.dirty_memory[i], old_ram_size, new_ram_size); - } + } + ram_list.dirty_memory[DIRTY_MEMORY_EXCLUSIVE] = bitmap_zero_extend( + ram_list.dirty_memory[DIRTY_MEMORY_EXCLUSIVE], + old_ram_size * smp_cpus, new_ram_size * smp_cpus); } cpu_physical_memory_set_dirty_range(new_block->offset, new_block->used_length, diff --git a/include/exec/memory.h b/include/exec/memory.h index 1394715..a525259 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -19,7 +19,8 @@ #define DIRTY_MEMORY_VGA 0 #define DIRTY_MEMORY_CODE 1 #define DIRTY_MEMORY_MIGRATION 2 -#define DIRTY_MEMORY_NUM 3 /* num of dirty bits */ +#define DIRTY_MEMORY_EXCLUSIVE 3 +#define DIRTY_MEMORY_NUM 4 /* num of dirty bits */ #include #include diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index c113f21..6b678d6 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -21,6 +21,7 @@ #ifndef CONFIG_USER_ONLY #include "hw/xen/xen.h" +#include "sysemu/sysemu.h" ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, bool share, const char *mem_path, @@ -135,6 +136,10 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, if (unlikely(mask & (1 << DIRTY_MEMORY_CODE))) { bitmap_set_atomic(d[DIRTY_MEMORY_CODE], page, end - page); } + if (unlikely(mask & (1 << DIRTY_MEMORY_EXCLUSIVE))) { + bitmap_set_atomic(d[DIRTY_MEMORY_EXCLUSIVE], + page * smp_cpus, (end - page) * smp_cpus); + } xen_modified_memory(start, length); } @@ -249,5 +254,68 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest, return num_dirty; } +/* Exclusive bitmap support. */ +#define EXCL_BITMAP_GET_OFFSET(addr) (smp_cpus * (addr >> TARGET_PAGE_BITS)) +static inline void cpu_physical_memory_set_excl_dirty(ram_addr_t addr, + uint32_t cpu_index) +{ + set_bit_atomic(EXCL_BITMAP_GET_OFFSET(addr) + cpu_index, + ram_list.dirty_memory[DIRTY_MEMORY_EXCLUSIVE]); +} + +static inline int cpu_physical_memory_excl_atleast_one_clean(ram_addr_t addr) +{ + unsigned long *bitmap = ram_list.dirty_memory[DIRTY_MEMORY_EXCLUSIVE]; + unsigned long next, end; + + if (likely(smp_cpus <= BITS_PER_LONG)) { + unsigned long mask = (1 << smp_cpus) - 1; + + return + (mask & (bitmap[BIT_WORD(EXCL_BITMAP_GET_OFFSET(addr))] >> + (EXCL_BITMAP_GET_OFFSET(addr) & (BITS_PER_LONG-1)))) != mask; + } + + end = BIT_WORD(EXCL_BITMAP_GET_OFFSET(addr)) + smp_cpus; + next = find_next_zero_bit(bitmap, end, + BIT_WORD(EXCL_BITMAP_GET_OFFSET(addr))); + + return next < end; +} + +static inline int cpu_physical_memory_excl_is_dirty(ram_addr_t addr, + unsigned long cpu) +{ + unsigned long *bitmap = ram_list.dirty_memory[DIRTY_MEMORY_EXCLUSIVE]; + unsigned long end, next; + uint32_t add; + + assert(cpu <= smp_cpus); + + if (likely(smp_cpus <= BITS_PER_LONG)) { + cpu = (cpu == smp_cpus) ? (1 << cpu) - 1 : (1 << cpu); + + return cpu & (bitmap[BIT_WORD(EXCL_BITMAP_GET_OFFSET(addr))] >> + (EXCL_BITMAP_GET_OFFSET(addr) & (BITS_PER_LONG-1))); + } + + add = (cpu == smp_cpus) ? 0 : 1; + end = BIT_WORD(EXCL_BITMAP_GET_OFFSET(addr)) + cpu + add; + next = find_next_bit(bitmap, end, BIT_WORD(EXCL_BITMAP_GET_OFFSET(addr)) + + (cpu % smp_cpus)); + + return next < end; +} + +static inline bool cpu_physical_memory_clear_excl_dirty(ram_addr_t addr, + uint32_t cpu_index) +{ + return bitmap_test_and_clear_atomic( + ram_list.dirty_memory[DIRTY_MEMORY_EXCLUSIVE], + EXCL_BITMAP_GET_OFFSET(addr) + cpu_index, 1); +} + + + #endif #endif -- 2.5.0