From nobody Thu Nov 6 19:37:00 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543805611753171.94540350745353; Sun, 2 Dec 2018 18:53:31 -0800 (PST) Received: from localhost ([::1]:46546 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeMN-0002GG-6c for importer@patchew.org; Sun, 02 Dec 2018 21:53:23 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49846) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeKd-0000sk-7u for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:36 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTeKa-0000aO-GJ for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:35 -0500 Received: from mga07.intel.com ([134.134.136.100]:65450) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTeKa-0000Zq-91 for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:32 -0500 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Dec 2018 18:51:31 -0800 Received: from devel-ww.sh.intel.com ([10.239.48.119]) by FMSMGA003.fm.intel.com with ESMTP; 02 Dec 2018 18:51:29 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,308,1539673200"; d="scan'208";a="115254775" From: Wei Wang To: qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org, mst@redhat.com, quintela@redhat.com, dgilbert@redhat.com, peterx@redhat.com Date: Mon, 3 Dec 2018 10:18:25 +0800 Message-Id: <1543803511-34793-2-git-send-email-wei.w.wang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> References: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.100 Subject: [Qemu-devel] [PATCH v10 1/7] bitmap: fix bitmap_count_one X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, liliang.opensource@gmail.com, nilal@redhat.com, wei.w.wang@intel.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BITMAP_LAST_WORD_MASK(nbits) returns 0xffffffff when "nbits=3D0", which makes bitmap_count_one fail to handle the "nbits=3D0" case. It appears to be preferred to remain BITMAP_LAST_WORD_MASK identical to the kernel implementation that it is ported from. So this patch fixes bitmap_count_one to handle the nbits=3D0 case. Inital Discussion Link: https://www.mail-archive.com/qemu-devel@nongnu.org/msg554316.html Signed-off-by: Wei Wang CC: Juan Quintela CC: Dr. David Alan Gilbert CC: Peter Xu --- include/qemu/bitmap.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/qemu/bitmap.h b/include/qemu/bitmap.h index 509eedd..679f1bd 100644 --- a/include/qemu/bitmap.h +++ b/include/qemu/bitmap.h @@ -221,6 +221,10 @@ static inline int bitmap_intersects(const unsigned lon= g *src1, =20 static inline long bitmap_count_one(const unsigned long *bitmap, long nbit= s) { + if (unlikely(!nbits)) { + return 0; + } + if (small_nbits(nbits)) { return ctpopl(*bitmap & BITMAP_LAST_WORD_MASK(nbits)); } else { --=20 1.8.3.1 From nobody Thu Nov 6 19:37:00 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 15438056221231022.4801249586833; Sun, 2 Dec 2018 18:53:42 -0800 (PST) Received: from localhost ([::1]:46547 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeMN-0002J4-Oz for importer@patchew.org; Sun, 02 Dec 2018 21:53:23 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49843) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeKd-0000si-7R for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:35 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTeKc-0000ar-CH for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:35 -0500 Received: from mga07.intel.com ([134.134.136.100]:65450) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTeKc-0000Zq-3J for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:34 -0500 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Dec 2018 18:51:33 -0800 Received: from devel-ww.sh.intel.com ([10.239.48.119]) by FMSMGA003.fm.intel.com with ESMTP; 02 Dec 2018 18:51:31 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,308,1539673200"; d="scan'208";a="115254781" From: Wei Wang To: qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org, mst@redhat.com, quintela@redhat.com, dgilbert@redhat.com, peterx@redhat.com Date: Mon, 3 Dec 2018 10:18:26 +0800 Message-Id: <1543803511-34793-3-git-send-email-wei.w.wang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> References: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.100 Subject: [Qemu-devel] [PATCH v10 2/7] bitmap: bitmap_count_one_with_offset X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, liliang.opensource@gmail.com, nilal@redhat.com, wei.w.wang@intel.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Count the number of 1s in a bitmap starting from an offset. Signed-off-by: Wei Wang CC: Dr. David Alan Gilbert CC: Juan Quintela CC: Michael S. Tsirkin Reviewed-by: Dr. David Alan Gilbert --- include/qemu/bitmap.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/qemu/bitmap.h b/include/qemu/bitmap.h index 679f1bd..5c31334 100644 --- a/include/qemu/bitmap.h +++ b/include/qemu/bitmap.h @@ -232,6 +232,19 @@ static inline long bitmap_count_one(const unsigned lon= g *bitmap, long nbits) } } =20 +static inline long bitmap_count_one_with_offset(const unsigned long *bitma= p, + long offset, long nbits) +{ + long aligned_offset =3D QEMU_ALIGN_DOWN(offset, BITS_PER_LONG); + long redundant_bits =3D offset - aligned_offset; + long bits_to_count =3D nbits + redundant_bits; + const unsigned long *bitmap_start =3D bitmap + + aligned_offset / BITS_PER_LONG; + + return bitmap_count_one(bitmap_start, bits_to_count) - + bitmap_count_one(bitmap_start, redundant_bits); +} + void bitmap_set(unsigned long *map, long i, long len); void bitmap_set_atomic(unsigned long *map, long i, long len); void bitmap_clear(unsigned long *map, long start, long nr); --=20 1.8.3.1 From nobody Thu Nov 6 19:37:00 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543805617125653.6388478398258; Sun, 2 Dec 2018 18:53:37 -0800 (PST) Received: from localhost ([::1]:46548 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeMO-0002Ng-SS for importer@patchew.org; Sun, 02 Dec 2018 21:53:24 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49871) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeKf-0000sz-9E for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTeKe-0000bg-JG for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:37 -0500 Received: from mga07.intel.com ([134.134.136.100]:65450) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTeKe-0000Zq-Am for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:36 -0500 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Dec 2018 18:51:35 -0800 Received: from devel-ww.sh.intel.com ([10.239.48.119]) by FMSMGA003.fm.intel.com with ESMTP; 02 Dec 2018 18:51:33 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,308,1539673200"; d="scan'208";a="115254786" From: Wei Wang To: qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org, mst@redhat.com, quintela@redhat.com, dgilbert@redhat.com, peterx@redhat.com Date: Mon, 3 Dec 2018 10:18:27 +0800 Message-Id: <1543803511-34793-4-git-send-email-wei.w.wang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> References: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.100 Subject: [Qemu-devel] [PATCH v10 3/7] migration: use bitmap_mutex in migration_bitmap_clear_dirty X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, liliang.opensource@gmail.com, nilal@redhat.com, wei.w.wang@intel.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The bitmap mutex is used to synchronize threads to update the dirty bitmap and the migration_dirty_pages counter. For example, the free page optimization clears bits of free pages from the bitmap in an iothread context. This patch makes migration_bitmap_clear_dirty update the bitmap and counter under the mutex. Signed-off-by: Wei Wang CC: Dr. David Alan Gilbert CC: Juan Quintela CC: Michael S. Tsirkin CC: Peter Xu Reviewed-by: Peter Xu --- migration/ram.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/migration/ram.c b/migration/ram.c index 7e7deec..01d267f 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -316,7 +316,7 @@ struct RAMState { uint64_t target_page_count; /* number of dirty bits in the bitmap */ uint64_t migration_dirty_pages; - /* protects modification of the bitmap */ + /* Protects modification of the bitmap and migration dirty pages */ QemuMutex bitmap_mutex; /* The RAMBlock used in the last src_page_requests */ RAMBlock *last_req_rb; @@ -1556,11 +1556,14 @@ static inline bool migration_bitmap_clear_dirty(RAM= State *rs, { bool ret; =20 + qemu_mutex_lock(&rs->bitmap_mutex); ret =3D test_and_clear_bit(page, rb->bmap); =20 if (ret) { rs->migration_dirty_pages--; } + qemu_mutex_unlock(&rs->bitmap_mutex); + return ret; } =20 --=20 1.8.3.1 From nobody Thu Nov 6 19:37:00 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543805746222262.57943335187156; Sun, 2 Dec 2018 18:55:46 -0800 (PST) Received: from localhost ([::1]:46562 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeOf-00059Y-4B for importer@patchew.org; Sun, 02 Dec 2018 21:55:45 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49893) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeKh-0000uy-JU for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTeKg-0000cS-Oe for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:39 -0500 Received: from mga07.intel.com ([134.134.136.100]:65450) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTeKg-0000Zq-Fw for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:38 -0500 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Dec 2018 18:51:38 -0800 Received: from devel-ww.sh.intel.com ([10.239.48.119]) by FMSMGA003.fm.intel.com with ESMTP; 02 Dec 2018 18:51:36 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,308,1539673200"; d="scan'208";a="115254791" From: Wei Wang To: qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org, mst@redhat.com, quintela@redhat.com, dgilbert@redhat.com, peterx@redhat.com Date: Mon, 3 Dec 2018 10:18:28 +0800 Message-Id: <1543803511-34793-5-git-send-email-wei.w.wang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> References: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.100 Subject: [Qemu-devel] [PATCH v10 4/7] migration: API to clear bits of guest free pages from the dirty bitmap X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, liliang.opensource@gmail.com, nilal@redhat.com, wei.w.wang@intel.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This patch adds an API to clear bits corresponding to guest free pages from the dirty bitmap. Spilt the free page block if it crosses the QEMU RAMBlock boundary. Signed-off-by: Wei Wang CC: Dr. David Alan Gilbert CC: Juan Quintela CC: Michael S. Tsirkin CC: Peter Xu Reviewed-by: Peter Xu --- include/migration/misc.h | 2 ++ migration/ram.c | 47 ++++++++++++++++++++++++++++++++++++++++++++= +++ 2 files changed, 49 insertions(+) diff --git a/include/migration/misc.h b/include/migration/misc.h index 4ebf24c..113320e 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -14,11 +14,13 @@ #ifndef MIGRATION_MISC_H #define MIGRATION_MISC_H =20 +#include "exec/cpu-common.h" #include "qemu/notify.h" =20 /* migration/ram.c */ =20 void ram_mig_init(void); +void qemu_guest_free_page_hint(void *addr, size_t len); =20 /* migration/block.c */ =20 diff --git a/migration/ram.c b/migration/ram.c index 01d267f..4f7a3fe 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -3131,6 +3131,53 @@ static void ram_state_resume_prepare(RAMState *rs, Q= EMUFile *out) } =20 /* + * This function clears bits of the free pages reported by the caller from= the + * migration dirty bitmap. @addr is the host address corresponding to the + * start of the continuous guest free pages, and @len is the total bytes of + * those pages. + */ +void qemu_guest_free_page_hint(void *addr, size_t len) +{ + RAMBlock *block; + ram_addr_t offset; + size_t used_len, start, npages; + MigrationState *s =3D migrate_get_current(); + + /* This function is currently expected to be used during live migratio= n */ + if (!migration_is_setup_or_active(s->state)) { + return; + } + + for (; len > 0; len -=3D used_len, addr +=3D used_len) { + block =3D qemu_ram_block_from_host(addr, false, &offset); + if (unlikely(!block || offset > block->used_length)) { + /* + * The implementation might not support RAMBlock resize during + * live migration, but it could happen in theory with future + * updates. So we add a check here to capture that case. + */ + error_report_once("%s unexpected error", __func__); + return; + } + + if (len <=3D block->used_length - offset) { + used_len =3D len; + } else { + used_len =3D block->used_length - offset; + } + + start =3D offset >> TARGET_PAGE_BITS; + npages =3D used_len >> TARGET_PAGE_BITS; + + qemu_mutex_lock(&ram_state->bitmap_mutex); + ram_state->migration_dirty_pages -=3D + bitmap_count_one_with_offset(block->bmap, start, npa= ges); + bitmap_clear(block->bmap, start, npages); + qemu_mutex_unlock(&ram_state->bitmap_mutex); + } +} + +/* * Each of ram_save_setup, ram_save_iterate and ram_save_complete has * long-running RCU critical section. When rcu-reclaims in the code * start to become numerous it will be necessary to reduce the --=20 1.8.3.1 From nobody Thu Nov 6 19:37:00 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543805747128990.404710436318; Sun, 2 Dec 2018 18:55:47 -0800 (PST) Received: from localhost ([::1]:46561 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeOf-00059U-Rc for importer@patchew.org; Sun, 02 Dec 2018 21:55:45 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49925) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeKm-00011H-Ed for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTeKi-0000dE-Q3 for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:44 -0500 Received: from mga07.intel.com ([134.134.136.100]:65450) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTeKi-0000Zq-IC for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:40 -0500 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Dec 2018 18:51:40 -0800 Received: from devel-ww.sh.intel.com ([10.239.48.119]) by FMSMGA003.fm.intel.com with ESMTP; 02 Dec 2018 18:51:38 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,308,1539673200"; d="scan'208";a="115254794" From: Wei Wang To: qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org, mst@redhat.com, quintela@redhat.com, dgilbert@redhat.com, peterx@redhat.com Date: Mon, 3 Dec 2018 10:18:29 +0800 Message-Id: <1543803511-34793-6-git-send-email-wei.w.wang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> References: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.100 Subject: [Qemu-devel] [PATCH v10 5/7] migration/ram.c: add a notifier chain for precopy X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, liliang.opensource@gmail.com, nilal@redhat.com, wei.w.wang@intel.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This patch adds a notifier chain for the memory precopy. This enables vario= us precopy optimizations to be invoked at specific places. Signed-off-by: Wei Wang CC: Dr. David Alan Gilbert CC: Juan Quintela CC: Michael S. Tsirkin CC: Peter Xu Reviewed-by: Peter Xu --- include/migration/misc.h | 19 ++++++++++++++++++ migration/ram.c | 51 ++++++++++++++++++++++++++++++++++++++++++++= +--- migration/savevm.c | 15 ++++++++++++++ vl.c | 1 + 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/include/migration/misc.h b/include/migration/misc.h index 113320e..15f8d00 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -19,6 +19,25 @@ =20 /* migration/ram.c */ =20 +typedef enum PrecopyNotifyReason { + PRECOPY_NOTIFY_SETUP =3D 0, + PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC =3D 1, + PRECOPY_NOTIFY_AFTER_BITMAP_SYNC =3D 2, + PRECOPY_NOTIFY_COMPLETE =3D 3, + PRECOPY_NOTIFY_CLEANUP =3D 4, + PRECOPY_NOTIFY_MAX =3D 5, +} PrecopyNotifyReason; + +typedef struct PrecopyNotifyData { + enum PrecopyNotifyReason reason; + Error **errp; +} PrecopyNotifyData; + +void precopy_infrastructure_init(void); +void precopy_add_notifier(NotifierWithReturn *n); +void precopy_remove_notifier(NotifierWithReturn *n); +int precopy_notify(PrecopyNotifyReason reason, Error **errp); + void ram_mig_init(void); void qemu_guest_free_page_hint(void *addr, size_t len); =20 diff --git a/migration/ram.c b/migration/ram.c index 4f7a3fe..b90a3f2 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -328,6 +328,32 @@ typedef struct RAMState RAMState; =20 static RAMState *ram_state; =20 +static NotifierWithReturnList precopy_notifier_list; + +void precopy_infrastructure_init(void) +{ + notifier_with_return_list_init(&precopy_notifier_list); +} + +void precopy_add_notifier(NotifierWithReturn *n) +{ + notifier_with_return_list_add(&precopy_notifier_list, n); +} + +void precopy_remove_notifier(NotifierWithReturn *n) +{ + notifier_with_return_remove(n); +} + +int precopy_notify(PrecopyNotifyReason reason, Error **errp) +{ + PrecopyNotifyData pnd; + pnd.reason =3D reason; + pnd.errp =3D errp; + + return notifier_with_return_list_notify(&precopy_notifier_list, &pnd); +} + uint64_t ram_bytes_remaining(void) { return ram_state ? (ram_state->migration_dirty_pages * TARGET_PAGE_SIZ= E) : @@ -1701,6 +1727,25 @@ static void migration_bitmap_sync(RAMState *rs) } } =20 +static void migration_bitmap_sync_precopy(RAMState *rs) +{ + Error *local_err =3D NULL; + + /* + * The current notifier usage is just an optimization to migration, so= we + * don't stop the normal migration process in the error case. + */ + if (precopy_notify(PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC, &local_err)) { + error_report_err(local_err); + } + + migration_bitmap_sync(rs); + + if (precopy_notify(PRECOPY_NOTIFY_AFTER_BITMAP_SYNC, &local_err)) { + error_report_err(local_err); + } +} + /** * save_zero_page_to_file: send the zero page to the file * @@ -3072,7 +3117,7 @@ static void ram_init_bitmaps(RAMState *rs) =20 ram_list_init_bitmaps(); memory_global_dirty_log_start(); - migration_bitmap_sync(rs); + migration_bitmap_sync_precopy(rs); =20 rcu_read_unlock(); qemu_mutex_unlock_ramlist(); @@ -3348,7 +3393,7 @@ static int ram_save_complete(QEMUFile *f, void *opaqu= e) rcu_read_lock(); =20 if (!migration_in_postcopy()) { - migration_bitmap_sync(rs); + migration_bitmap_sync_precopy(rs); } =20 ram_control_before_iterate(f, RAM_CONTROL_FINISH); @@ -3397,7 +3442,7 @@ static void ram_save_pending(QEMUFile *f, void *opaqu= e, uint64_t max_size, remaining_size < max_size) { qemu_mutex_lock_iothread(); rcu_read_lock(); - migration_bitmap_sync(rs); + migration_bitmap_sync_precopy(rs); rcu_read_unlock(); qemu_mutex_unlock_iothread(); remaining_size =3D rs->migration_dirty_pages * TARGET_PAGE_SIZE; diff --git a/migration/savevm.c b/migration/savevm.c index 9e45fb4..ec74f44 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1018,6 +1018,7 @@ void qemu_savevm_state_header(QEMUFile *f) void qemu_savevm_state_setup(QEMUFile *f) { SaveStateEntry *se; + Error *local_err =3D NULL; int ret; =20 trace_savevm_state_setup(); @@ -1039,6 +1040,10 @@ void qemu_savevm_state_setup(QEMUFile *f) break; } } + + if (precopy_notify(PRECOPY_NOTIFY_SETUP, &local_err)) { + error_report_err(local_err); + } } =20 int qemu_savevm_state_resume_prepare(MigrationState *s) @@ -1181,6 +1186,11 @@ int qemu_savevm_state_complete_precopy(QEMUFile *f, = bool iterable_only, SaveStateEntry *se; int ret; bool in_postcopy =3D migration_in_postcopy(); + Error *local_err =3D NULL; + + if (precopy_notify(PRECOPY_NOTIFY_COMPLETE, &local_err)) { + error_report_err(local_err); + } =20 trace_savevm_state_complete_precopy(); =20 @@ -1313,6 +1323,11 @@ void qemu_savevm_state_pending(QEMUFile *f, uint64_t= threshold_size, void qemu_savevm_state_cleanup(void) { SaveStateEntry *se; + Error *local_err =3D NULL; + + if (precopy_notify(PRECOPY_NOTIFY_CLEANUP, &local_err)) { + error_report_err(local_err); + } =20 trace_savevm_state_cleanup(); QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { diff --git a/vl.c b/vl.c index a5ae5f2..1621e1c 100644 --- a/vl.c +++ b/vl.c @@ -3062,6 +3062,7 @@ int main(int argc, char **argv, char **envp) module_call_init(MODULE_INIT_OPTS); =20 runstate_init(); + precopy_infrastructure_init(); postcopy_infrastructure_init(); monitor_init_globals(); =20 --=20 1.8.3.1 From nobody Thu Nov 6 19:37:00 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543805839860240.27958705725075; Sun, 2 Dec 2018 18:57:19 -0800 (PST) Received: from localhost ([::1]:46567 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeQA-0006LH-TL for importer@patchew.org; Sun, 02 Dec 2018 21:57:18 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49927) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeKm-00011J-FC for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTeKk-0000dp-K0 for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:44 -0500 Received: from mga07.intel.com ([134.134.136.100]:65450) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTeKk-0000Zq-CQ for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:42 -0500 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Dec 2018 18:51:42 -0800 Received: from devel-ww.sh.intel.com ([10.239.48.119]) by FMSMGA003.fm.intel.com with ESMTP; 02 Dec 2018 18:51:40 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,308,1539673200"; d="scan'208";a="115254799" From: Wei Wang To: qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org, mst@redhat.com, quintela@redhat.com, dgilbert@redhat.com, peterx@redhat.com Date: Mon, 3 Dec 2018 10:18:30 +0800 Message-Id: <1543803511-34793-7-git-send-email-wei.w.wang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> References: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.100 Subject: [Qemu-devel] [PATCH v10 6/7] migration/ram.c: add a function to disable the bulk stage X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, liliang.opensource@gmail.com, nilal@redhat.com, wei.w.wang@intel.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This patch adds a function to enable a precopy notifier callback outside the migration subsystem to disable the bulk stage flag. This is needed by the free page optimization offered by virtio-balloon. Signed-off-by: Wei Wang CC: Dr. David Alan Gilbert CC: Juan Quintela CC: Michael S. Tsirkin CC: Peter Xu --- include/migration/misc.h | 1 + migration/ram.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/migration/misc.h b/include/migration/misc.h index 15f8d00..47e7ff5 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -37,6 +37,7 @@ void precopy_infrastructure_init(void); void precopy_add_notifier(NotifierWithReturn *n); void precopy_remove_notifier(NotifierWithReturn *n); int precopy_notify(PrecopyNotifyReason reason, Error **errp); +void precopy_disable_bulk_stage(void); =20 void ram_mig_init(void); void qemu_guest_free_page_hint(void *addr, size_t len); diff --git a/migration/ram.c b/migration/ram.c index b90a3f2..739dc97 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -354,6 +354,15 @@ int precopy_notify(PrecopyNotifyReason reason, Error *= *errp) return notifier_with_return_list_notify(&precopy_notifier_list, &pnd); } =20 +void precopy_disable_bulk_stage(void) +{ + if (!ram_state) { + return; + } + + ram_state->ram_bulk_stage =3D false; +} + uint64_t ram_bytes_remaining(void) { return ram_state ? (ram_state->migration_dirty_pages * TARGET_PAGE_SIZ= E) : --=20 1.8.3.1 From nobody Thu Nov 6 19:37:00 2025 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=temperror (zoho.com: Error in retrieving data from DNS) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=intel.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543805938626978.7542949858542; Sun, 2 Dec 2018 18:58:58 -0800 (PST) Received: from localhost ([::1]:46571 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeRV-00008d-Tg for importer@patchew.org; Sun, 02 Dec 2018 21:58:41 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49955) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTeKo-00013W-VM for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:50 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTeKm-0000en-Rz for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:46 -0500 Received: from mga07.intel.com ([134.134.136.100]:65450) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTeKm-0000Zq-HV for qemu-devel@nongnu.org; Sun, 02 Dec 2018 21:51:44 -0500 Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Dec 2018 18:51:44 -0800 Received: from devel-ww.sh.intel.com ([10.239.48.119]) by FMSMGA003.fm.intel.com with ESMTP; 02 Dec 2018 18:51:42 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,308,1539673200"; d="scan'208";a="115254802" From: Wei Wang To: qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org, mst@redhat.com, quintela@redhat.com, dgilbert@redhat.com, peterx@redhat.com Date: Mon, 3 Dec 2018 10:18:31 +0800 Message-Id: <1543803511-34793-8-git-send-email-wei.w.wang@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> References: <1543803511-34793-1-git-send-email-wei.w.wang@intel.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.100 Subject: [Qemu-devel] [PATCH v10 7/7] virtio-balloon: VIRTIO_BALLOON_F_FREE_PAGE_HINT X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, liliang.opensource@gmail.com, nilal@redhat.com, wei.w.wang@intel.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The new feature enables the virtio-balloon device to receive hints of guest free pages from the free page vq. A notifier is registered to the migration precopy notifier chain. The notifier calls free_page_start after the migration thread syncs the dirty bitmap, so that the free page optimization starts to clear bits of free pages from the bitmap. It calls the free_page_stop before the migration thread syncs the bitmap, which is the end of the current round of ram save. The free_page_stop is also called to stop the optimization in the case when there is an error occurred in the process of ram saving. Note: balloon will report pages which were free at the time of this call. As the reporting happens asynchronously, dirty bit logging must be enabled before this free_page_start call is made. Guest reporting must be disabled before the migration dirty bitmap is synchronized. Signed-off-by: Wei Wang CC: Michael S. Tsirkin CC: Dr. David Alan Gilbert CC: Juan Quintela CC: Peter Xu --- hw/virtio/virtio-balloon.c | 263 ++++++++++++++++++++= ++++ include/hw/virtio/virtio-balloon.h | 28 ++- include/standard-headers/linux/virtio_balloon.h | 5 + 3 files changed, 295 insertions(+), 1 deletion(-) diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 1728e4f..5376f9b 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -27,6 +27,7 @@ #include "qapi/visitor.h" #include "trace.h" #include "qemu/error-report.h" +#include "migration/misc.h" =20 #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" @@ -308,6 +309,184 @@ out: } } =20 +static void virtio_balloon_handle_free_page_vq(VirtIODevice *vdev, + VirtQueue *vq) +{ + VirtIOBalloon *s =3D VIRTIO_BALLOON(vdev); + qemu_bh_schedule(s->free_page_bh); +} + +static bool get_free_page_hints(VirtIOBalloon *dev) +{ + VirtQueueElement *elem; + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + VirtQueue *vq =3D dev->free_page_vq; + + while (dev->block_iothread) { + qemu_cond_wait(&dev->free_page_cond, &dev->free_page_lock); + } + + elem =3D virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + return false; + } + + if (elem->out_num) { + uint32_t id; + size_t size =3D iov_to_buf(elem->out_sg, elem->out_num, 0, + &id, sizeof(id)); + virtqueue_push(vq, elem, size); + g_free(elem); + + virtio_tswap32s(vdev, &id); + if (unlikely(size !=3D sizeof(id))) { + virtio_error(vdev, "received an incorrect cmd id"); + return false; + } + if (id =3D=3D dev->free_page_report_cmd_id) { + dev->free_page_report_status =3D FREE_PAGE_REPORT_S_START; + } else { + /* + * Stop the optimization only when it has started. This + * avoids a stale stop sign for the previous command. + */ + if (dev->free_page_report_status =3D=3D FREE_PAGE_REPORT_S_STA= RT) { + dev->free_page_report_status =3D FREE_PAGE_REPORT_S_STOP; + } + } + } + + if (elem->in_num) { + if (dev->free_page_report_status =3D=3D FREE_PAGE_REPORT_S_START) { + qemu_guest_free_page_hint(elem->in_sg[0].iov_base, + elem->in_sg[0].iov_len); + } + virtqueue_push(vq, elem, 1); + g_free(elem); + } + + return true; +} + +static void virtio_ballloon_get_free_page_hints(void *opaque) +{ + VirtIOBalloon *dev =3D opaque; + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + VirtQueue *vq =3D dev->free_page_vq; + bool continue_to_get_hints; + + do { + qemu_mutex_lock(&dev->free_page_lock); + virtio_queue_set_notification(vq, 0); + continue_to_get_hints =3D get_free_page_hints(dev); + qemu_mutex_unlock(&dev->free_page_lock); + virtio_notify(vdev, vq); + /* + * Start to poll the vq once the reporting started. Otherwise, conti= nue + * only when there are entries on the vq, which need to be given bac= k. + */ + } while (continue_to_get_hints || + dev->free_page_report_status =3D=3D FREE_PAGE_REPORT_S_START); + virtio_queue_set_notification(vq, 1); +} + +static bool virtio_balloon_free_page_support(void *opaque) +{ + VirtIOBalloon *s =3D opaque; + VirtIODevice *vdev =3D VIRTIO_DEVICE(s); + + return virtio_vdev_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT); +} + +static void virtio_balloon_free_page_start(VirtIOBalloon *s) +{ + VirtIODevice *vdev =3D VIRTIO_DEVICE(s); + + /* For the stop and copy phase, we don't need to start the optimizatio= n */ + if (!vdev->vm_running) { + return; + } + + if (s->free_page_report_cmd_id =3D=3D UINT_MAX) { + s->free_page_report_cmd_id =3D + VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN; + } else { + s->free_page_report_cmd_id++; + } + + s->free_page_report_status =3D FREE_PAGE_REPORT_S_REQUESTED; + virtio_notify_config(vdev); +} + +static void virtio_balloon_free_page_stop(VirtIOBalloon *s) +{ + VirtIODevice *vdev =3D VIRTIO_DEVICE(s); + + if (s->free_page_report_status !=3D FREE_PAGE_REPORT_S_STOP) { + /* + * The lock also guarantees us that the + * virtio_ballloon_get_free_page_hints exits after the + * free_page_report_status is set to S_STOP. + */ + qemu_mutex_lock(&s->free_page_lock); + /* + * The guest hasn't done the reporting, so host sends a notificati= on + * to the guest to actively stop the reporting. + */ + s->free_page_report_status =3D FREE_PAGE_REPORT_S_STOP; + qemu_mutex_unlock(&s->free_page_lock); + virtio_notify_config(vdev); + } +} + +static void virtio_balloon_free_page_done(VirtIOBalloon *s) +{ + VirtIODevice *vdev =3D VIRTIO_DEVICE(s); + + s->free_page_report_status =3D FREE_PAGE_REPORT_S_DONE; + virtio_notify_config(vdev); +} + +static int +virtio_balloon_free_page_report_notify(NotifierWithReturn *n, void *data) +{ + VirtIOBalloon *dev =3D container_of(n, VirtIOBalloon, + free_page_report_notify); + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); + PrecopyNotifyData *pnd =3D data; + + if (!virtio_balloon_free_page_support(dev)) { + /* + * This is an optimization provided to migration, so just return 0= to + * have the normal migration process not affected when this featur= e is + * not supported. + */ + return 0; + } + + switch (pnd->reason) { + case PRECOPY_NOTIFY_SETUP: + precopy_disable_bulk_stage(); + break; + case PRECOPY_NOTIFY_COMPLETE: + case PRECOPY_NOTIFY_CLEANUP: + case PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC: + virtio_balloon_free_page_stop(dev); + break; + case PRECOPY_NOTIFY_AFTER_BITMAP_SYNC: + if (vdev->vm_running) { + virtio_balloon_free_page_start(dev); + } else { + virtio_balloon_free_page_done(dev); + } + break; + default: + virtio_error(vdev, "%s: %d reason unknown", __func__, pnd->reason); + } + + return 0; +} + static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_= data) { VirtIOBalloon *dev =3D VIRTIO_BALLOON(vdev); @@ -316,6 +495,17 @@ static void virtio_balloon_get_config(VirtIODevice *vd= ev, uint8_t *config_data) config.num_pages =3D cpu_to_le32(dev->num_pages); config.actual =3D cpu_to_le32(dev->actual); =20 + if (dev->free_page_report_status =3D=3D FREE_PAGE_REPORT_S_REQUESTED) { + config.free_page_report_cmd_id =3D + cpu_to_le32(dev->free_page_report_cmd_id); + } else if (dev->free_page_report_status =3D=3D FREE_PAGE_REPORT_S_STOP= ) { + config.free_page_report_cmd_id =3D + cpu_to_le32(VIRTIO_BALLOON_FREE_PAGE_REPORT_STOP_ID= ); + } else if (dev->free_page_report_status =3D=3D FREE_PAGE_REPORT_S_DONE= ) { + config.free_page_report_cmd_id =3D + cpu_to_le32(VIRTIO_BALLOON_FREE_PAGE_REPORT_DONE_ID= ); + } + trace_virtio_balloon_get_config(config.num_pages, config.actual); memcpy(config_data, &config, sizeof(struct virtio_balloon_config)); } @@ -376,6 +566,7 @@ static uint64_t virtio_balloon_get_features(VirtIODevic= e *vdev, uint64_t f, VirtIOBalloon *dev =3D VIRTIO_BALLOON(vdev); f |=3D dev->host_features; virtio_add_feature(&f, VIRTIO_BALLOON_F_STATS_VQ); + return f; } =20 @@ -412,6 +603,18 @@ static int virtio_balloon_post_load_device(void *opaqu= e, int version_id) return 0; } =20 +static const VMStateDescription vmstate_virtio_balloon_free_page_report = =3D { + .name =3D "virtio-balloon-device/free-page-report", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D virtio_balloon_free_page_support, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(free_page_report_cmd_id, VirtIOBalloon), + VMSTATE_UINT32(free_page_report_status, VirtIOBalloon), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_virtio_balloon_device =3D { .name =3D "virtio-balloon-device", .version_id =3D 1, @@ -422,6 +625,10 @@ static const VMStateDescription vmstate_virtio_balloon= _device =3D { VMSTATE_UINT32(actual, VirtIOBalloon), VMSTATE_END_OF_LIST() }, + .subsections =3D (const VMStateDescription * []) { + &vmstate_virtio_balloon_free_page_report, + NULL + } }; =20 static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) @@ -446,6 +653,29 @@ static void virtio_balloon_device_realize(DeviceState = *dev, Error **errp) s->dvq =3D virtio_add_queue(vdev, 128, virtio_balloon_handle_output); s->svq =3D virtio_add_queue(vdev, 128, virtio_balloon_receive_stats); =20 + if (virtio_has_feature(s->host_features, + VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { + s->free_page_vq =3D virtio_add_queue(vdev, VIRTQUEUE_MAX_SIZE, + virtio_balloon_handle_free_page= _vq); + s->free_page_report_status =3D FREE_PAGE_REPORT_S_STOP; + s->free_page_report_cmd_id =3D + VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN; + s->free_page_report_notify.notify =3D + virtio_balloon_free_page_report_not= ify; + precopy_add_notifier(&s->free_page_report_notify); + if (s->iothread) { + object_ref(OBJECT(s->iothread)); + s->free_page_bh =3D aio_bh_new(iothread_get_aio_context(s->iot= hread), + virtio_ballloon_get_free_page_hints= , s); + qemu_mutex_init(&s->free_page_lock); + qemu_cond_init(&s->free_page_cond); + s->block_iothread =3D false; + } else { + /* Simply disable this feature if the iothread wasn't created.= */ + s->host_features &=3D ~(1 << VIRTIO_BALLOON_F_FREE_PAGE_HINT); + virtio_error(vdev, "iothread is missing"); + } + } reset_stats(s); } =20 @@ -454,6 +684,11 @@ static void virtio_balloon_device_unrealize(DeviceStat= e *dev, Error **errp) VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); VirtIOBalloon *s =3D VIRTIO_BALLOON(dev); =20 + if (virtio_balloon_free_page_support(s)) { + qemu_bh_delete(s->free_page_bh); + virtio_balloon_free_page_stop(s); + precopy_remove_notifier(&s->free_page_report_notify); + } balloon_stats_destroy_timer(s); qemu_remove_balloon_handler(s); virtio_cleanup(vdev); @@ -463,6 +698,10 @@ static void virtio_balloon_device_reset(VirtIODevice *= vdev) { VirtIOBalloon *s =3D VIRTIO_BALLOON(vdev); =20 + if (virtio_balloon_free_page_support(s)) { + virtio_balloon_free_page_stop(s); + } + if (s->stats_vq_elem !=3D NULL) { virtqueue_unpop(s->svq, s->stats_vq_elem, 0); g_free(s->stats_vq_elem); @@ -480,6 +719,26 @@ static void virtio_balloon_set_status(VirtIODevice *vd= ev, uint8_t status) * was stopped */ virtio_balloon_receive_stats(vdev, s->svq); } + + if (virtio_balloon_free_page_support(s)) { + /* + * The VM is woken up and the iothread was blocked, so signal it to + * continue. + */ + if (vdev->vm_running && s->block_iothread) { + qemu_mutex_lock(&s->free_page_lock); + s->block_iothread =3D false; + qemu_cond_signal(&s->free_page_cond); + qemu_mutex_unlock(&s->free_page_lock); + } + + /* The VM is stopped, block the iothread. */ + if (!vdev->vm_running) { + qemu_mutex_lock(&s->free_page_lock); + s->block_iothread =3D true; + qemu_mutex_unlock(&s->free_page_lock); + } + } } =20 static void virtio_balloon_instance_init(Object *obj) @@ -508,6 +767,10 @@ static const VMStateDescription vmstate_virtio_balloon= =3D { static Property virtio_balloon_properties[] =3D { DEFINE_PROP_BIT("deflate-on-oom", VirtIOBalloon, host_features, VIRTIO_BALLOON_F_DEFLATE_ON_OOM, false), + DEFINE_PROP_BIT("free-page-hint", VirtIOBalloon, host_features, + VIRTIO_BALLOON_F_FREE_PAGE_HINT, false), + DEFINE_PROP_LINK("iothread", VirtIOBalloon, iothread, TYPE_IOTHREAD, + IOThread *), DEFINE_PROP_END_OF_LIST(), }; =20 diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-= balloon.h index e0df352..503349a 100644 --- a/include/hw/virtio/virtio-balloon.h +++ b/include/hw/virtio/virtio-balloon.h @@ -17,11 +17,14 @@ =20 #include "standard-headers/linux/virtio_balloon.h" #include "hw/virtio/virtio.h" +#include "sysemu/iothread.h" =20 #define TYPE_VIRTIO_BALLOON "virtio-balloon-device" #define VIRTIO_BALLOON(obj) \ OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON) =20 +#define VIRTIO_BALLOON_FREE_PAGE_REPORT_CMD_ID_MIN 0x80000000 + typedef struct virtio_balloon_stat VirtIOBalloonStat; =20 typedef struct virtio_balloon_stat_modern { @@ -30,15 +33,38 @@ typedef struct virtio_balloon_stat_modern { uint64_t val; } VirtIOBalloonStatModern; =20 +enum virtio_balloon_free_page_report_status { + FREE_PAGE_REPORT_S_STOP =3D 0, + FREE_PAGE_REPORT_S_REQUESTED =3D 1, + FREE_PAGE_REPORT_S_START =3D 2, + FREE_PAGE_REPORT_S_DONE =3D 3, +}; + typedef struct VirtIOBalloon { VirtIODevice parent_obj; - VirtQueue *ivq, *dvq, *svq; + VirtQueue *ivq, *dvq, *svq, *free_page_vq; + uint32_t free_page_report_status; uint32_t num_pages; uint32_t actual; + uint32_t free_page_report_cmd_id; uint64_t stats[VIRTIO_BALLOON_S_NR]; VirtQueueElement *stats_vq_elem; size_t stats_vq_offset; QEMUTimer *stats_timer; + IOThread *iothread; + QEMUBH *free_page_bh; + /* + * Lock to synchronize threads to access the free page reporting relat= ed + * fields (e.g. free_page_report_status). + */ + QemuMutex free_page_lock; + QemuCond free_page_cond; + /* + * Set to block iothread to continue reading free page hints as the VM= is + * stopped. + */ + bool block_iothread; + NotifierWithReturn free_page_report_notify; int64_t stats_last_update; int64_t stats_poll_interval; uint32_t host_features; diff --git a/include/standard-headers/linux/virtio_balloon.h b/include/stan= dard-headers/linux/virtio_balloon.h index 4dbb7dc..9eee1c6 100644 --- a/include/standard-headers/linux/virtio_balloon.h +++ b/include/standard-headers/linux/virtio_balloon.h @@ -34,15 +34,20 @@ #define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages = */ #define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory Stats virtqueue */ #define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* Deflate balloon on OOM */ +#define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* VQ to report free pages */ =20 /* Size of a PFN in the balloon interface. */ #define VIRTIO_BALLOON_PFN_SHIFT 12 =20 +#define VIRTIO_BALLOON_FREE_PAGE_REPORT_STOP_ID 0 +#define VIRTIO_BALLOON_FREE_PAGE_REPORT_DONE_ID 1 struct virtio_balloon_config { /* Number of pages host wants Guest to give up. */ uint32_t num_pages; /* Number of pages we've actually got in balloon. */ uint32_t actual; + /* Free page report command id, readonly by guest */ + uint32_t free_page_report_cmd_id; }; =20 #define VIRTIO_BALLOON_S_SWAP_IN 0 /* Amount of memory swapped in */ --=20 1.8.3.1