From patchwork Wed Feb 10 14:11:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 8272331 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C6A0EBEEE5 for ; Wed, 10 Feb 2016 14:12:02 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 119F62039E for ; Wed, 10 Feb 2016 14:12:02 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 330FD2020F for ; Wed, 10 Feb 2016 14:12:01 +0000 (UTC) Received: from localhost ([::1]:39615 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTVUu-00072z-Ip for patchwork-qemu-devel@patchwork.kernel.org; Wed, 10 Feb 2016 09:12:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59406) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTVUn-00071g-Qf for qemu-devel@nongnu.org; Wed, 10 Feb 2016 09:11:55 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aTVUk-0002IS-CO for qemu-devel@nongnu.org; Wed, 10 Feb 2016 09:11:53 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48510) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aTVUk-0002IL-4l for qemu-devel@nongnu.org; Wed, 10 Feb 2016 09:11:50 -0500 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 E75A980504; Wed, 10 Feb 2016 14:11:48 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-112-58.ams2.redhat.com [10.36.112.58]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u1AEBkGW007493; Wed, 10 Feb 2016 09:11:47 -0500 From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Wed, 10 Feb 2016 15:11:45 +0100 Message-Id: <1455113505-11237-1-git-send-email-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: peter.maydell@linaro.org, stefanha@redhat.com Subject: [Qemu-devel] [PATCH] memory: fix usage of find_next_bit and find_next_zero_bit X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The last two arguments to these functions are the last and first bit to check relative to the base. The code was using incorrectly the first bit and the number of bits. Fix this in cpu_physical_memory_get_dirty and cpu_physical_memory_all_dirty. This requires a few changes in the iteration; change the code in cpu_physical_memory_set_dirty_range to match. Fixes: 5b82b70 Cc: Stefan Hajnoczi Signed-off-by: Paolo Bonzini Reviewed-by: Stefan Hajnoczi Tested-by: Leon Alrae Tested-by: Thomas Huth --- include/exec/ram_addr.h | 55 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index b1413a1..5d33def 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -121,6 +121,7 @@ static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, { DirtyMemoryBlocks *blocks; unsigned long end, page; + unsigned long idx, offset, base; bool dirty = false; assert(client < DIRTY_MEMORY_NUM); @@ -132,17 +133,22 @@ static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); + idx = page / DIRTY_MEMORY_BLOCK_SIZE; + offset = page % DIRTY_MEMORY_BLOCK_SIZE; + base = page - offset; while (page < end) { - unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; - unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE; - unsigned long num = MIN(end - page, DIRTY_MEMORY_BLOCK_SIZE - offset); - - if (find_next_bit(blocks->blocks[idx], offset, num) < num) { + unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE); + unsigned long num = next - base; + unsigned long found = find_next_bit(blocks->blocks[idx], num, offset); + if (found < num) { dirty = true; break; } - page += num; + page = next; + idx++; + offset = 0; + base += DIRTY_MEMORY_BLOCK_SIZE; } rcu_read_unlock(); @@ -156,6 +162,7 @@ static inline bool cpu_physical_memory_all_dirty(ram_addr_t start, { DirtyMemoryBlocks *blocks; unsigned long end, page; + unsigned long idx, offset, base; bool dirty = true; assert(client < DIRTY_MEMORY_NUM); @@ -167,17 +174,22 @@ static inline bool cpu_physical_memory_all_dirty(ram_addr_t start, blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); + idx = page / DIRTY_MEMORY_BLOCK_SIZE; + offset = page % DIRTY_MEMORY_BLOCK_SIZE; + base = page - offset; while (page < end) { - unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; - unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE; - unsigned long num = MIN(end - page, DIRTY_MEMORY_BLOCK_SIZE - offset); - - if (find_next_zero_bit(blocks->blocks[idx], offset, num) < num) { + unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE); + unsigned long num = next - base; + unsigned long found = find_next_zero_bit(blocks->blocks[idx], num, offset); + if (found < num) { dirty = false; break; } - page += num; + page = next; + idx++; + offset = 0; + base += DIRTY_MEMORY_BLOCK_SIZE; } rcu_read_unlock(); @@ -248,6 +260,7 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, { DirtyMemoryBlocks *blocks[DIRTY_MEMORY_NUM]; unsigned long end, page; + unsigned long idx, offset, base; int i; if (!mask && !xen_enabled()) { @@ -263,25 +276,29 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, blocks[i] = atomic_rcu_read(&ram_list.dirty_memory[i]); } + idx = page / DIRTY_MEMORY_BLOCK_SIZE; + offset = page % DIRTY_MEMORY_BLOCK_SIZE; + base = page - offset; while (page < end) { - unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; - unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE; - unsigned long num = MIN(end - page, DIRTY_MEMORY_BLOCK_SIZE - offset); + unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE); if (likely(mask & (1 << DIRTY_MEMORY_MIGRATION))) { bitmap_set_atomic(blocks[DIRTY_MEMORY_MIGRATION]->blocks[idx], - offset, num); + offset, next - page); } if (unlikely(mask & (1 << DIRTY_MEMORY_VGA))) { bitmap_set_atomic(blocks[DIRTY_MEMORY_VGA]->blocks[idx], - offset, num); + offset, next - page); } if (unlikely(mask & (1 << DIRTY_MEMORY_CODE))) { bitmap_set_atomic(blocks[DIRTY_MEMORY_CODE]->blocks[idx], - offset, num); + offset, next - page); } - page += num; + page = next; + idx++; + offset = 0; + base += DIRTY_MEMORY_BLOCK_SIZE; } rcu_read_unlock();