From patchwork Sun Sep 15 16:08:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yong Huang X-Patchwork-Id: 13804863 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4BBBFC3ABA0 for ; Sun, 15 Sep 2024 16:10:51 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sproD-0002Q8-1D; Sun, 15 Sep 2024 12:09:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1spro8-0002Ne-Jv for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:05 -0400 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1spro6-0006N5-Is for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:04 -0400 Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-71798a15ce5so3193410b3a.0 for ; Sun, 15 Sep 2024 09:09:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=smartx-com.20230601.gappssmtp.com; s=20230601; t=1726416541; x=1727021341; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3OFIU38UikYUB3gdX1kGRi1xc6HOThSaI+9KQA5Kl24=; b=E1MknaFWdOHgPEXWVTxM9xhxEqDY0vszdnpt1Xv4inupOTWoY4UTr+OcmLac/IWkNZ 9NEaobQuKbVlnrPOZWQ2EayG5ZnHojtLBhOU5B5gLVrQRVSOfEAnmvr3vqe6HaNhZfO5 NvH/GTpW7nGC8MV791deA6zRc/XVSVE/0QuXSn9FWE/ihE2cSFGlbYq+nZFfsenciPmY k/m+KAnSzE1gbioBq5ZBvM7E2iaeZ0oU1LWsoXFcuMGAB3YQ579cFPyT5UvegF7j10Dr c2gkv9ZSem9ZHilMZc/Z5J9LkcXRTMImZr+3tCROb4gO613bNichvjpMStUVNItxh4p0 9a9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726416541; x=1727021341; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3OFIU38UikYUB3gdX1kGRi1xc6HOThSaI+9KQA5Kl24=; b=DwEJHUYCzXvesf/Fr8XHmUgrnt4QJwxlMr91X2zt/REmkkI1qIj8WbBKBHK3eh1yJL aUcYX079sm8GdSDqbId9F73Xps3kQd9Fd76RN/utcJGUSieZFWLEVOvvzgD5KXxz1y0e dMXRRviE/oAbOybQJ3xBKRmoawt3pQX0TXFG53A2jZxX7gOnfGzyMkV9EFF/GvF5fIh8 In1f8awWqCKlF0+SlU55ID50Wz0k8dLIGKp65uFwq5t0CP+1FYonhLYqt4yJQMiMLUJi C1DWWi1NjWWJ0Z629ReIi4wEYcZ1kBl2p7ZogTtoNF5oxQ4zRBHCWgKhgYRiBmMfH1nn 98Fg== X-Gm-Message-State: AOJu0YzuDk8/VfgPdoqcByskqxT0CrzD5HQM9oqKkm1yiJsT4H7c/kxS zDRUXJaYzLYFnDMSaOSSrEjWcNoLO3V/JiWb1w3vDJz0M9v6uO/IqKYNK75e97VDGwnUGLrwRcq a0kIpXQ== X-Google-Smtp-Source: AGHT+IFh1U2MKNLDcaCu/t2xOiFeWPrezQ5sXg+TZK8gPYm0NLZ5WFpOfOsKQwyzvP6FtmXLKAh5pg== X-Received: by 2002:a05:6a20:e605:b0:1cf:1228:c175 with SMTP id adf61e73a8af0-1cf755c76eamr18380582637.8.1726416540322; Sun, 15 Sep 2024 09:09:00 -0700 (PDT) Received: from localhost.localdomain ([118.114.94.247]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71944bb5967sm2344795b3a.182.2024.09.15.09.08.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Sep 2024 09:09:00 -0700 (PDT) From: Hyman Huang To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , Eric Blake , Markus Armbruster , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Paolo Bonzini , yong.huang@smartx.com Subject: [PATCH v1 1/7] migration: Introduce structs for background sync Date: Mon, 16 Sep 2024 00:08:44 +0800 Message-Id: <531750c8d7b6c09f877b5f335a60fab402c168be.1726390098.git.yong.huang@smartx.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::429; envelope-from=yong.huang@smartx.com; helo=mail-pf1-x429.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org shadow_bmap, iter_bmap and iter_dirty_pages are introduced to satisfy the need for background sync. Meanwhile, introduce enumeration of sync method. Signed-off-by: Hyman Huang --- include/exec/ramblock.h | 45 +++++++++++++++++++++++++++++++++++++++++ migration/ram.c | 6 ++++++ 2 files changed, 51 insertions(+) diff --git a/include/exec/ramblock.h b/include/exec/ramblock.h index 0babd105c0..0e327bc0ae 100644 --- a/include/exec/ramblock.h +++ b/include/exec/ramblock.h @@ -24,6 +24,30 @@ #include "qemu/rcu.h" #include "exec/ramlist.h" +/* Possible bits for cpu_physical_memory_sync_dirty_bitmap */ + +/* + * The old-fashioned sync, which is, in turn, used for CPU + * throttle and memory transfer. + */ +#define RAMBLOCK_SYN_LEGACY_ITER (1U << 0) + +/* + * The modern sync, which is, in turn, used for CPU throttle + * and memory transfer. + */ +#define RAMBLOCK_SYN_MODERN_ITER (1U << 1) + +/* The modern sync, which is used for CPU throttle only */ +#define RAMBLOCK_SYN_MODERN_BACKGROUND (1U << 2) + +#define RAMBLOCK_SYN_MASK (0x7) + +typedef enum RAMBlockSynMode { + RAMBLOCK_SYN_LEGACY, /* Old-fashined mode */ + RAMBLOCK_SYN_MODERN, /* Background-sync-supported mode */ +} RAMBlockSynMode; + struct RAMBlock { struct rcu_head rcu; struct MemoryRegion *mr; @@ -89,6 +113,27 @@ struct RAMBlock { * could not have been valid on the source. */ ram_addr_t postcopy_length; + + /* + * Used to backup the bmap during background sync to see whether any dirty + * pages were sent during that time. + */ + unsigned long *shadow_bmap; + + /* + * The bitmap "bmap," which was initially used for both sync and memory + * transfer, will be replaced by two bitmaps: the previously used "bmap" + * and the recently added "iter_bmap." Only the memory transfer is + * conducted with the previously used "bmap"; the recently added + * "iter_bmap" is utilized for dirty bitmap sync. + */ + unsigned long *iter_bmap; + + /* Number of new dirty pages during iteration */ + uint64_t iter_dirty_pages; + + /* If background sync has shown up during iteration */ + bool background_sync_shown_up; }; #endif #endif diff --git a/migration/ram.c b/migration/ram.c index 67ca3d5d51..f29faa82d6 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -2362,6 +2362,10 @@ static void ram_bitmaps_destroy(void) block->bmap = NULL; g_free(block->file_bmap); block->file_bmap = NULL; + g_free(block->shadow_bmap); + block->shadow_bmap = NULL; + g_free(block->iter_bmap); + block->iter_bmap = NULL; } } @@ -2753,6 +2757,8 @@ static void ram_list_init_bitmaps(void) } block->clear_bmap_shift = shift; block->clear_bmap = bitmap_new(clear_bmap_size(pages, shift)); + block->shadow_bmap = bitmap_new(pages); + block->iter_bmap = bitmap_new(pages); } } } From patchwork Sun Sep 15 16:08:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yong Huang X-Patchwork-Id: 13804862 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D0EC1C3ABA0 for ; Sun, 15 Sep 2024 16:10:32 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sproE-0002Vc-72; Sun, 15 Sep 2024 12:09:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sproC-0002Q7-2A for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:08 -0400 Received: from mail-pf1-x436.google.com ([2607:f8b0:4864:20::436]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sproA-0006Nu-5k for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:07 -0400 Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-71911585911so3163090b3a.3 for ; Sun, 15 Sep 2024 09:09:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=smartx-com.20230601.gappssmtp.com; s=20230601; t=1726416544; x=1727021344; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kd3beDozenchrE206KfSrUYWzrjJyNNe06v58gw/duI=; b=yEQYOhEIvrvxI5b2FuEDxj0PiGE2MkvPbslp7bb6y+Eqt8BwlG3pYY+qX7/s2Ge36Y rRNuvllbS2fgOF5LfTzd7Crui9L8H5KhKzNe5d5zPcpcf4dIFKUAs2YyEnlu6eZNJ1sx u/Vp9FcsHn3H9ivIMfp4rlm3qrGC2zVMYtgSPZBOw3u/LXbzUJXR3Zm6unfXwC33ihuC PWSDhYDAROJWnmSdkursnWcPB+UiTTdjD83a1kVO6f92rK+l75wNVKj7BrmiSofaf/jZ W96XCHoBkzh2KhuIDCzv8JZl+2Ah8ymn/LyvFbug1nnJL+ZScKPDOr4x/tbALpQlwj8T HPWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726416544; x=1727021344; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kd3beDozenchrE206KfSrUYWzrjJyNNe06v58gw/duI=; b=CkgVUiHznIxkhUIU/67WxZ2HRjPgTKMiq3UEQbqoP4sU/OT8vQEnvdtjqJpdiiQHet vq/aX5fdro4sDsLtK6mxPJy0p+dZC8L6UQ4TxdjsJfBQEDpL8mntt2y20OWvkNFVSshg tq/H2vF7K9etFItMJhrlIxg706Uisqk1IboJo9B+H5+hsdslRQBFF1YkROUQSYEkojTT cpNqiQGks59TWHWAb4qDDE3hFSnNSCErYcx7ORRrZJ61YAeVqUAkikV9fOlMKTpPgraM HAA2Rvjy2Xg6IBzJIpJGc8sdbNKIOI4q9PqiLkv2hgk49/4NRjZ3q81CaqFFG/Nwhw0e nh+A== X-Gm-Message-State: AOJu0YzlF7l2ILGMk0BM28pH9RSGSgC5TUXqxRGSLAupH8Don48OmAnN r3N0QMlU3ZqFh5RDnGgv2Jf8uQaPUAp/dvQyYPsA/NHDb7nJpGkSGpXJ3fBq100shn8jeq1MFZU tfDxTYA== X-Google-Smtp-Source: AGHT+IHjeAWCnYdv/kn1KTYiGONkAjRum8dFk3LHq4oFOJo/ii1dXGZjlk+rwih2DURX1q2dErlLmQ== X-Received: by 2002:a05:6a00:174b:b0:714:2620:d235 with SMTP id d2e1a72fcca58-71926089bf6mr19964374b3a.16.1726416543709; Sun, 15 Sep 2024 09:09:03 -0700 (PDT) Received: from localhost.localdomain ([118.114.94.247]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71944bb5967sm2344795b3a.182.2024.09.15.09.09.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Sep 2024 09:09:03 -0700 (PDT) From: Hyman Huang To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , Eric Blake , Markus Armbruster , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Paolo Bonzini , yong.huang@smartx.com Subject: [PATCH v1 2/7] migration: Refine util functions to support background sync Date: Mon, 16 Sep 2024 00:08:45 +0800 Message-Id: X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::436; envelope-from=yong.huang@smartx.com; helo=mail-pf1-x436.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Supply the migration_bitmap_sync function along with the background argument. Introduce the sync_mode global variable to track the sync mode and support background sync while keeping backward compatibility. Signed-off-by: Hyman Huang --- include/exec/ram_addr.h | 107 +++++++++++++++++++++++++++++++++++++--- migration/ram.c | 53 ++++++++++++++++---- 2 files changed, 144 insertions(+), 16 deletions(-) diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 891c44cf2d..d0d123ac60 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -472,17 +472,68 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, cpu_physical_memory_test_and_clear_dirty(start, length, DIRTY_MEMORY_CODE); } +static void ramblock_clear_iter_bmap(RAMBlock *rb, + ram_addr_t start, + ram_addr_t length) +{ + ram_addr_t addr; + unsigned long *bmap = rb->bmap; + unsigned long *shadow_bmap = rb->shadow_bmap; + unsigned long *iter_bmap = rb->iter_bmap; + + for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) { + long k = (start + addr) >> TARGET_PAGE_BITS; + if (test_bit(k, shadow_bmap) && !test_bit(k, bmap)) { + /* Page has been sent, clear the iter bmap */ + clear_bit(k, iter_bmap); + } + } +} + +static void ramblock_update_iter_bmap(RAMBlock *rb, + ram_addr_t start, + ram_addr_t length) +{ + ram_addr_t addr; + unsigned long *bmap = rb->bmap; + unsigned long *iter_bmap = rb->iter_bmap; + + for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) { + long k = (start + addr) >> TARGET_PAGE_BITS; + if (test_bit(k, iter_bmap)) { + if (!test_bit(k, bmap)) { + set_bit(k, bmap); + rb->iter_dirty_pages++; + } + } + } +} /* Called with RCU critical section */ static inline uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, ram_addr_t start, - ram_addr_t length) + ram_addr_t length, + unsigned int flag) { ram_addr_t addr; unsigned long word = BIT_WORD((start + rb->offset) >> TARGET_PAGE_BITS); uint64_t num_dirty = 0; unsigned long *dest = rb->bmap; + unsigned long *shadow_bmap = rb->shadow_bmap; + unsigned long *iter_bmap = rb->iter_bmap; + + assert(flag && !(flag & (~RAMBLOCK_SYN_MASK))); + + /* + * We must remove the sent dirty page from the iter_bmap in order to + * minimize redundant page transfers if background sync has appeared + * during this iteration. + */ + if (rb->background_sync_shown_up && + (flag & (RAMBLOCK_SYN_MODERN_ITER | RAMBLOCK_SYN_MODERN_BACKGROUND))) { + ramblock_clear_iter_bmap(rb, start, length); + } /* start address and length is aligned at the start of a word? */ if (((word * BITS_PER_LONG) << TARGET_PAGE_BITS) == @@ -503,8 +554,20 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, if (src[idx][offset]) { unsigned long bits = qatomic_xchg(&src[idx][offset], 0); unsigned long new_dirty; + if (flag & (RAMBLOCK_SYN_MODERN_ITER | + RAMBLOCK_SYN_MODERN_BACKGROUND)) { + /* Back-up bmap for the next iteration */ + iter_bmap[k] |= bits; + if (flag == RAMBLOCK_SYN_MODERN_BACKGROUND) { + /* Back-up bmap to detect pages has been sent */ + shadow_bmap[k] = dest[k]; + } + } new_dirty = ~dest[k]; - dest[k] |= bits; + if (flag == RAMBLOCK_SYN_LEGACY_ITER) { + dest[k] |= bits; + } + new_dirty &= bits; num_dirty += ctpopl(new_dirty); } @@ -534,18 +597,50 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, ram_addr_t offset = rb->offset; for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) { - if (cpu_physical_memory_test_and_clear_dirty( + bool dirty = false; + long k = (start + addr) >> TARGET_PAGE_BITS; + if (flag == RAMBLOCK_SYN_MODERN_BACKGROUND) { + if (test_bit(k, dest)) { + /* Back-up bmap to detect pages has been sent */ + set_bit(k, shadow_bmap); + } + } + + dirty = cpu_physical_memory_test_and_clear_dirty( start + addr + offset, TARGET_PAGE_SIZE, - DIRTY_MEMORY_MIGRATION)) { - long k = (start + addr) >> TARGET_PAGE_BITS; - if (!test_and_set_bit(k, dest)) { + DIRTY_MEMORY_MIGRATION); + + if (flag == RAMBLOCK_SYN_LEGACY_ITER) { + if (dirty && !test_and_set_bit(k, dest)) { num_dirty++; } + } else { + if (dirty) { + if (!test_bit(k, dest)) { + num_dirty++; + } + /* Back-up bmap for the next iteration */ + set_bit(k, iter_bmap); + } } } } + /* + * We have to re-fetch dirty pages from the iter_bmap one by one. + * It's possible that not all of the dirty pages that meant to + * send in the current iteration are included in the bitmap + * that the current sync retrieved from the KVM. + */ + if (flag == RAMBLOCK_SYN_MODERN_ITER) { + ramblock_update_iter_bmap(rb, start, length); + } + + if (flag == RAMBLOCK_SYN_MODERN_BACKGROUND) { + rb->background_sync_shown_up = true; + } + return num_dirty; } #endif diff --git a/migration/ram.c b/migration/ram.c index f29faa82d6..e205806a5f 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -112,6 +112,8 @@ XBZRLECacheStats xbzrle_counters; +static RAMBlockSynMode sync_mode = RAMBLOCK_SYN_LEGACY; + /* used by the search for pages to send */ struct PageSearchStatus { /* The migration channel used for a specific host page */ @@ -912,13 +914,42 @@ bool ramblock_page_is_discarded(RAMBlock *rb, ram_addr_t start) return false; } +static void ramblock_reset_iter_stats(RAMBlock *rb) +{ + bitmap_clear(rb->shadow_bmap, 0, rb->used_length >> TARGET_PAGE_BITS); + bitmap_clear(rb->iter_bmap, 0, rb->used_length >> TARGET_PAGE_BITS); + rb->iter_dirty_pages = 0; + rb->background_sync_shown_up = false; +} + /* Called with RCU critical section */ -static void ramblock_sync_dirty_bitmap(RAMState *rs, RAMBlock *rb) +static void ramblock_sync_dirty_bitmap(RAMState *rs, + RAMBlock *rb, + bool background) { - uint64_t new_dirty_pages = - cpu_physical_memory_sync_dirty_bitmap(rb, 0, rb->used_length); + uint64_t new_dirty_pages; + unsigned int flag = RAMBLOCK_SYN_LEGACY_ITER; + + if (sync_mode == RAMBLOCK_SYN_MODERN) { + if (background) { + flag = RAMBLOCK_SYN_MODERN_BACKGROUND; + } else { + flag = RAMBLOCK_SYN_MODERN_ITER; + } + } + + new_dirty_pages = + cpu_physical_memory_sync_dirty_bitmap(rb, 0, rb->used_length, flag); + + if (flag & (RAMBLOCK_SYN_LEGACY_ITER | RAMBLOCK_SYN_MODERN_ITER)) { + if (flag == RAMBLOCK_SYN_LEGACY_ITER) { + rs->migration_dirty_pages += new_dirty_pages; + } else { + rs->migration_dirty_pages += rb->iter_dirty_pages; + ramblock_reset_iter_stats(rb); + } + } - rs->migration_dirty_pages += new_dirty_pages; rs->num_dirty_pages_period += new_dirty_pages; } @@ -1041,7 +1072,9 @@ static void migration_trigger_throttle(RAMState *rs) } } -static void migration_bitmap_sync(RAMState *rs, bool last_stage) +static void migration_bitmap_sync(RAMState *rs, + bool last_stage, + bool background) { RAMBlock *block; int64_t end_time; @@ -1058,7 +1091,7 @@ static void migration_bitmap_sync(RAMState *rs, bool last_stage) WITH_QEMU_LOCK_GUARD(&rs->bitmap_mutex) { WITH_RCU_READ_LOCK_GUARD() { RAMBLOCK_FOREACH_NOT_IGNORED(block) { - ramblock_sync_dirty_bitmap(rs, block); + ramblock_sync_dirty_bitmap(rs, block, background); } stat64_set(&mig_stats.dirty_bytes_last_sync, ram_bytes_remaining()); } @@ -1101,7 +1134,7 @@ static void migration_bitmap_sync_precopy(RAMState *rs, bool last_stage) local_err = NULL; } - migration_bitmap_sync(rs, last_stage); + migration_bitmap_sync(rs, last_stage, false); if (precopy_notify(PRECOPY_NOTIFY_AFTER_BITMAP_SYNC, &local_err)) { error_report_err(local_err); @@ -2594,7 +2627,7 @@ void ram_postcopy_send_discard_bitmap(MigrationState *ms) RCU_READ_LOCK_GUARD(); /* This should be our last sync, the src is now paused */ - migration_bitmap_sync(rs, false); + migration_bitmap_sync(rs, false, false); /* Easiest way to make sure we don't resume in the middle of a host-page */ rs->pss[RAM_CHANNEL_PRECOPY].last_sent_block = NULL; @@ -3581,7 +3614,7 @@ void colo_incoming_start_dirty_log(void) memory_global_dirty_log_sync(false); WITH_RCU_READ_LOCK_GUARD() { RAMBLOCK_FOREACH_NOT_IGNORED(block) { - ramblock_sync_dirty_bitmap(ram_state, block); + ramblock_sync_dirty_bitmap(ram_state, block, false); /* Discard this dirty bitmap record */ bitmap_zero(block->bmap, block->max_length >> TARGET_PAGE_BITS); } @@ -3862,7 +3895,7 @@ void colo_flush_ram_cache(void) qemu_mutex_lock(&ram_state->bitmap_mutex); WITH_RCU_READ_LOCK_GUARD() { RAMBLOCK_FOREACH_NOT_IGNORED(block) { - ramblock_sync_dirty_bitmap(ram_state, block); + ramblock_sync_dirty_bitmap(ram_state, block, false); } } From patchwork Sun Sep 15 16:08:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yong Huang X-Patchwork-Id: 13804857 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8F1A4C3ABA2 for ; Sun, 15 Sep 2024 16:10:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sproG-0002eq-Ct; Sun, 15 Sep 2024 12:09:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sproF-0002aR-7g for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:11 -0400 Received: from mail-pf1-x434.google.com ([2607:f8b0:4864:20::434]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sproD-0006OV-EF for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:10 -0400 Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-718e285544fso1966124b3a.1 for ; Sun, 15 Sep 2024 09:09:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=smartx-com.20230601.gappssmtp.com; s=20230601; t=1726416548; x=1727021348; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lxw6C89QI6UbPkGgu8mJTGVSMtVBCh9fCukElZHUmoY=; b=OVyu8h/sjH73JizOZRhjloYT6H8vHAIhv20tGmfeMwPx5yMEu81sorrn2Z42xusvK1 ycGqk9anmdAyTzRXDXukAMUxKPPLYKKg4ASLAHdEr2rfmpGgSI/8GHM/+EB/aENEJgQk dqN3rF0XYwbMXxL9py6YWQ/hGWz0LdbPx+dxIPfFu8I1u4htkhwEYP7XzETDPDLMMAVA ODHaYez5Akslb6oph2e6mxMaW1uY9b7C00lC+W9wTrrnMxE0bbCMTnOCm3LVSjYTDKIl g6RkCc5WMgYeTPWvGzosvPaM3MgvANJ2ycs6cg+zQEvOSDKZvqNV4dElV1P9bwjd3mC+ EJIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726416548; x=1727021348; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lxw6C89QI6UbPkGgu8mJTGVSMtVBCh9fCukElZHUmoY=; b=TK9YbUEB/jmKDymJk5DBQs4fofWJgrPrraeNNvPtnphDiocDDSHoj4hu9sRXq2RR/p Cixi/ztNyo/Hbree9LIMOa8JcXRPY2pl5k2ttEce7G+nZnxGDGjZ5ShzWJL902QBn+j7 WHWOODjFldEdlDTEWv8YPo5PnX/y31BnPZymPHxhf3QLRp6uhVNdOticxejUqrE6sRR0 jgESb9Sf/bYMYwsrOIA5MuhDQu8DK4f4SY+pF9djjp9y4VuCXMfXj3ft6Y1CApMap2bm 7W3IwzlfX/TvJR8mVOdlX06woRjhHhG+hmvDZr1KkxDkMMbZNlZiSk3/gE1HhLSvL0BC 9+qQ== X-Gm-Message-State: AOJu0YxxL6Xa/jPHifeu7cvWX1Us+PoWC1Ni+heFdZNJt8veFkalx2Uo u3j4YXveU9y70HshLHIuTTaQL2KPfuWjc0bA6LRR4ZuPwMK7/C9JEMCj1yqUCm4VOtb2Ga87kNa qgjIjCQ== X-Google-Smtp-Source: AGHT+IHcQgpMzCVLaxZ7nd9l+/mRVcrIgDS1crPkkTQqxVV+tdV0103WWiTUcqtVZvtfVOSToeRgCw== X-Received: by 2002:a05:6a21:164a:b0:1cf:44ac:7144 with SMTP id adf61e73a8af0-1d112e89110mr12537636637.31.1726416547253; Sun, 15 Sep 2024 09:09:07 -0700 (PDT) Received: from localhost.localdomain ([118.114.94.247]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71944bb5967sm2344795b3a.182.2024.09.15.09.09.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Sep 2024 09:09:07 -0700 (PDT) From: Hyman Huang To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , Eric Blake , Markus Armbruster , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Paolo Bonzini , yong.huang@smartx.com Subject: [PATCH v1 3/7] qapi/migration: Introduce the iteration-count Date: Mon, 16 Sep 2024 00:08:46 +0800 Message-Id: <654bfad294e2cc3394f744bd8536e0448c0bf550.1726390099.git.yong.huang@smartx.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::434; envelope-from=yong.huang@smartx.com; helo=mail-pf1-x434.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The original migration information dirty-sync-count could no longer reflect iteration count due to the introduction of background synchronization in the next commit; add the iteration count to compensate. Signed-off-by: Hyman Huang --- migration/migration-stats.h | 4 ++++ migration/migration.c | 1 + migration/ram.c | 12 ++++++++---- qapi/migration.json | 6 +++++- tests/qtest/migration-test.c | 2 +- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/migration/migration-stats.h b/migration/migration-stats.h index 05290ade76..43ee0f4f05 100644 --- a/migration/migration-stats.h +++ b/migration/migration-stats.h @@ -50,6 +50,10 @@ typedef struct { * Number of times we have synchronized guest bitmaps. */ Stat64 dirty_sync_count; + /* + * Number of migration iteration processed. + */ + Stat64 iteration_count; /* * Number of times zero copy failed to send any page using zero * copy. diff --git a/migration/migration.c b/migration/migration.c index 3dea06d577..055d527ff6 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1197,6 +1197,7 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s) info->ram->mbps = s->mbps; info->ram->dirty_sync_count = stat64_get(&mig_stats.dirty_sync_count); + info->ram->iteration_count = stat64_get(&mig_stats.iteration_count); info->ram->dirty_sync_missed_zero_copy = stat64_get(&mig_stats.dirty_sync_missed_zero_copy); info->ram->postcopy_requests = diff --git a/migration/ram.c b/migration/ram.c index e205806a5f..ca5a1b5f16 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -594,7 +594,7 @@ static void xbzrle_cache_zero_page(ram_addr_t current_addr) /* We don't care if this fails to allocate a new cache page * as long as it updated an old one */ cache_insert(XBZRLE.cache, current_addr, XBZRLE.zero_target_page, - stat64_get(&mig_stats.dirty_sync_count)); + stat64_get(&mig_stats.iteration_count)); } #define ENCODING_FLAG_XBZRLE 0x1 @@ -620,7 +620,7 @@ static int save_xbzrle_page(RAMState *rs, PageSearchStatus *pss, int encoded_len = 0, bytes_xbzrle; uint8_t *prev_cached_page; QEMUFile *file = pss->pss_channel; - uint64_t generation = stat64_get(&mig_stats.dirty_sync_count); + uint64_t generation = stat64_get(&mig_stats.iteration_count); if (!cache_is_cached(XBZRLE.cache, current_addr, generation)) { xbzrle_counters.cache_miss++; @@ -1079,6 +1079,10 @@ static void migration_bitmap_sync(RAMState *rs, RAMBlock *block; int64_t end_time; + if (!background) { + stat64_add(&mig_stats.iteration_count, 1); + } + stat64_add(&mig_stats.dirty_sync_count, 1); if (!rs->time_last_bitmap_sync) { @@ -1115,8 +1119,8 @@ static void migration_bitmap_sync(RAMState *rs, rs->num_dirty_pages_period = 0; rs->bytes_xfer_prev = migration_transferred_bytes(); } - if (migrate_events()) { - uint64_t generation = stat64_get(&mig_stats.dirty_sync_count); + if (!background && migrate_events()) { + uint64_t generation = stat64_get(&mig_stats.iteration_count); qapi_event_send_migration_pass(generation); } } diff --git a/qapi/migration.json b/qapi/migration.json index b66cccf107..95b490706c 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -60,6 +60,9 @@ # between 0 and @dirty-sync-count * @multifd-channels. (since # 7.1) # +# @iteration-count: The number of iterations since migration started. +# (since 9.2) +# # Since: 0.14 ## { 'struct': 'MigrationStats', @@ -72,7 +75,8 @@ 'multifd-bytes': 'uint64', 'pages-per-second': 'uint64', 'precopy-bytes': 'uint64', 'downtime-bytes': 'uint64', 'postcopy-bytes': 'uint64', - 'dirty-sync-missed-zero-copy': 'uint64' } } + 'dirty-sync-missed-zero-copy': 'uint64', + 'iteration-count' : 'int' } } ## # @XBZRLECacheStats: diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index d6768d5d71..b796a90cad 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -278,7 +278,7 @@ static int64_t read_migrate_property_int(QTestState *who, const char *property) static uint64_t get_migration_pass(QTestState *who) { - return read_ram_property_int(who, "dirty-sync-count"); + return read_ram_property_int(who, "iteration-count"); } static void read_blocktime(QTestState *who) From patchwork Sun Sep 15 16:08:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yong Huang X-Patchwork-Id: 13804861 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 764ABC3ABA1 for ; Sun, 15 Sep 2024 16:10:18 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sproM-00031d-5N; Sun, 15 Sep 2024 12:09:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sproJ-0002sV-Pf for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:15 -0400 Received: from mail-pf1-x42b.google.com ([2607:f8b0:4864:20::42b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sproH-0006P3-QN for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:15 -0400 Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-717934728adso2743027b3a.2 for ; Sun, 15 Sep 2024 09:09:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=smartx-com.20230601.gappssmtp.com; s=20230601; t=1726416552; x=1727021352; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=i5g6CmFxoxPUE5mXYvXg3z4LzjNCvav86tcPdIXvVHo=; b=gqI1n1AZXkYScqS5zInpAyXQysUlph4zpIOySUl9eKF4gpA2k2n13eGQHtQpeKVjOy /gEQG2b9CK0+In8FuACUwh+VrxcJQkMNV1n1eeKVlgIpBA9uhbxfAdx6pqIWn8bT6xNl MqCYMGMe5fTYUftOecfBdBY21Uax9nVgTIDBHdvsystQ7qZhgk33BrDZqrbReYzPXppu tKcASraLofywuGX3//56iZWAI8ovN2b00Jwnzfm6AYKtmHVfgEzo1I+DN43nkw/AaODJ c88ZAoZ+5hyaFGasb4NKBqSFZnD8eYzQZaP0ARb7S3jtLo0Xocg0evVQvFluc3Mh8V2l ePww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726416552; x=1727021352; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=i5g6CmFxoxPUE5mXYvXg3z4LzjNCvav86tcPdIXvVHo=; b=cEPDngfRqlOL/2AnoLQJccxgLwMqqn7xnrL7Uo0s5R4mq0yIr6W+ZnmB7WTWm6JPKY UbGRlRj522d4LYLc27NGfcowlTbF76d5sSCXciF+qp/nej0kRyt3b6kIjv6CDNcDpjcD QElaSB7ft/U0rZwDLdUe3cqOHI4W0SUlM24NYCi/3sbUmXvTmhLt2tADaPTJUDWtUFn+ gsOOy8Jz7jkmQAaei2vyqpwFFmbZbQasJzZx3ltZgQiAPy0NTECqHBbD39BzwxeF+rDX GHx6o4wUZodRoYU7u0vtfx5yh1pYAMkLdKRuyd261ZPIBctThHza+oxlNiu1EJAdSZ07 4CNg== X-Gm-Message-State: AOJu0Yxc4zOLLNOPAnDrJEKdN2V4KmgO/9Hqh40RzQPprCZLc61ZhMdU Vqp4KMLTS7dwcFdEPaO+ZcZF4+6MFQ70QVKtQFJA3XW9myUGCJGdWwOY7gPsZZYw4fJ8p7KAPuF RLZx+AA== X-Google-Smtp-Source: AGHT+IGOubS0qQwcM949ApoEklLQVYHXrT33G57vSY5G+WB3aG7GvQzHiNgrf0Yw0nHjjfj27waYrA== X-Received: by 2002:a05:6a00:2352:b0:714:3831:ec91 with SMTP id d2e1a72fcca58-71926213e47mr18367228b3a.25.1726416551092; Sun, 15 Sep 2024 09:09:11 -0700 (PDT) Received: from localhost.localdomain ([118.114.94.247]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71944bb5967sm2344795b3a.182.2024.09.15.09.09.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Sep 2024 09:09:10 -0700 (PDT) From: Hyman Huang To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , Eric Blake , Markus Armbruster , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Paolo Bonzini , yong.huang@smartx.com Subject: [PATCH v1 4/7] migration: Implment background sync watcher Date: Mon, 16 Sep 2024 00:08:47 +0800 Message-Id: <4c105e23be9a2d1a6be71e6abf9c938a4d091dfc.1726390099.git.yong.huang@smartx.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::42b; envelope-from=yong.huang@smartx.com; helo=mail-pf1-x42b.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The background sync watcher is used to detect that if the iteration lasts a long time, if so, trigger the background sync. Signed-off-by: Hyman Huang --- migration/ram.c | 110 +++++++++++++++++++++++++++++++++++++++++ migration/ram.h | 3 ++ migration/trace-events | 3 ++ 3 files changed, 116 insertions(+) diff --git a/migration/ram.c b/migration/ram.c index ca5a1b5f16..799eaa0382 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -416,6 +416,11 @@ struct RAMState { * RAM migration. */ unsigned int postcopy_bmap_sync_requested; + + /* Background throttle information */ + bool background_sync_running; + QemuThread background_sync_thread; + QemuSemaphore quit_sem; }; typedef struct RAMState RAMState; @@ -1125,6 +1130,111 @@ static void migration_bitmap_sync(RAMState *rs, } } +/* + * Iteration lasting more than five seconds is undesirable; + * launch a background dirty bitmap sync. + */ +#define MIGRATION_MAX_ITERATION_DURATION 5 + +static void *migration_background_sync_watcher(void *opaque) +{ + RAMState *rs = opaque; + uint64_t iter_cnt, prev_iter_cnt = 2; + bool iter_cnt_unchanged = false; + int max_pct = migrate_max_cpu_throttle(); + + trace_migration_background_sync_watcher_start(); + rcu_register_thread(); + + while (qatomic_read(&rs->background_sync_running)) { + int cur_pct = cpu_throttle_get_percentage(); + if ((cur_pct == max_pct) || (!migration_is_active())) { + break; + } + + if (qemu_sem_timedwait(&rs->quit_sem, 1000) == 0) { + /* We were woken by background_sync_cleanup, quit */ + break; + } + + /* + * The first iteration copies all memory anyhow and has no + * effect on guest performance, therefore omit it to avoid + * paying extra for the sync penalty. + */ + iter_cnt = stat64_get(&mig_stats.iteration_count); + if (iter_cnt <= 1) { + continue; + } + + iter_cnt_unchanged = (iter_cnt == prev_iter_cnt); + prev_iter_cnt = iter_cnt; + + if (iter_cnt_unchanged) { + int64_t curr_time, iter_duration; + + curr_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + iter_duration = curr_time - rs->time_last_bitmap_sync; + + if (iter_duration > + MIGRATION_MAX_ITERATION_DURATION * 1000) { + sync_mode = RAMBLOCK_SYN_MODERN; + bql_lock(); + trace_migration_background_sync(); + WITH_RCU_READ_LOCK_GUARD() { + migration_bitmap_sync(rs, false, true); + } + bql_unlock(); + } + } + } + + qatomic_set(&rs->background_sync_running, 0); + + rcu_unregister_thread(); + trace_migration_background_sync_watcher_end(); + + return NULL; +} + +void migration_background_sync_setup(void) +{ + RAMState *rs = ram_state; + + if (!rs) { + return; + } + + if (qatomic_read(&rs->background_sync_running)) { + return; + } + + qemu_sem_init(&rs->quit_sem, 0); + qatomic_set(&rs->background_sync_running, 1); + + qemu_thread_create(&rs->background_sync_thread, + NULL, migration_background_sync_watcher, + rs, QEMU_THREAD_JOINABLE); +} + +void migration_background_sync_cleanup(void) +{ + RAMState *rs = ram_state; + + if (!rs) { + return; + } + + if (!qatomic_read(&rs->background_sync_running)) { + return; + } + + qatomic_set(&rs->background_sync_running, 0); + qemu_sem_post(&rs->quit_sem); + qemu_thread_join(&rs->background_sync_thread); + qemu_sem_destroy(&rs->quit_sem); +} + static void migration_bitmap_sync_precopy(RAMState *rs, bool last_stage) { Error *local_err = NULL; diff --git a/migration/ram.h b/migration/ram.h index bc0318b834..0315d22a66 100644 --- a/migration/ram.h +++ b/migration/ram.h @@ -93,4 +93,7 @@ void ram_write_tracking_prepare(void); int ram_write_tracking_start(void); void ram_write_tracking_stop(void); +/* Migration background sync */ +void migration_background_sync_setup(void); +void migration_background_sync_cleanup(void); #endif diff --git a/migration/trace-events b/migration/trace-events index c65902f042..4f95f9fe14 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -92,6 +92,9 @@ qemu_file_fclose(void) "" # ram.c get_queued_page(const char *block_name, uint64_t tmp_offset, unsigned long page_abs) "%s/0x%" PRIx64 " page_abs=0x%lx" get_queued_page_not_dirty(const char *block_name, uint64_t tmp_offset, unsigned long page_abs) "%s/0x%" PRIx64 " page_abs=0x%lx" +migration_background_sync(void) "" +migration_background_sync_watcher_start(void) "" +migration_background_sync_watcher_end(void) "" migration_bitmap_sync_start(void) "" migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64 migration_bitmap_clear_dirty(char *str, uint64_t start, uint64_t size, unsigned long page) "rb %s start 0x%"PRIx64" size 0x%"PRIx64" page 0x%lx" From patchwork Sun Sep 15 16:08:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yong Huang X-Patchwork-Id: 13804858 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8BC2AC3ABA0 for ; Sun, 15 Sep 2024 16:10:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sproR-0003Dt-Av; Sun, 15 Sep 2024 12:09:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sproM-00033w-LI for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:18 -0400 Received: from mail-pf1-x436.google.com ([2607:f8b0:4864:20::436]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sproL-0006PX-2g for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:18 -0400 Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-718e285544fso1966191b3a.1 for ; Sun, 15 Sep 2024 09:09:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=smartx-com.20230601.gappssmtp.com; s=20230601; t=1726416555; x=1727021355; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bQRFeU81jcoENLpfNtd5Au7rCLXiDo8NwDyNJcevB8Q=; b=asqfHek8p83xx66MaWOxWub16DpVVGlpBeGKdYOJhyQfUBofwyUueI2FMtzfWB7I8o 3Q+QEz4jRae5mY5NbR0YgfavKPmRj+GLuO0MJezS6cQ42oNtnfJV0FfPOTj0yZ17Ze8O C52tGXnAdwnkfK9sMhsFEAy7cxZWUSWjPLD+7EeWcule9PVjB+qE1jE2uq7OKc0jp9I7 kJVu9/8OQs5HiCBsYnwMf9hSoBOnPR2F5xEePJR+Rl8hxVVmk16mF4aE3Dl0zWQduAKf sYAyy25TBwx8i68/WZYOk0ls86Dexht9x0D4yanI/ELBWVy0/6xBWxXNo+9EBLMONiN3 jjYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726416555; x=1727021355; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bQRFeU81jcoENLpfNtd5Au7rCLXiDo8NwDyNJcevB8Q=; b=xVfVBBThNPA8OndyotvRrJjK4h6X/NeTfTsEHB/wNU39AqrxtHufdC02ev9LUVJ7ov vApwPp0ObOaHvEihFxQKrtxi2mh8UX4tQAF1u03K/QO2TmW093PRRDGaSjCBFa/RVrRN h44MXKHvf8v/RQSRD+G8St+XXNwPQHY7ITOscNhy+V70tZndQGOLTPf690ekIM3H1J8h 8LCdYFtEX6ym2eOkolHv5ffhzpoFeOWZnZNItphmtcZuSyUTVydMtNbmafJKgA0HH8pM Sqh6P2wVZ4A1DfFUuit3Tbyf5bCSun1kzWln4GRte2hMIHqMnL2eErfJhQ8bYAvm28j0 T91A== X-Gm-Message-State: AOJu0Yz+H61wdDaYsxCkAmM4cHy9juJ/cyxYBmPSvG+Gf+rNu8TPTJ2t 3FFVcFJ8J5FoRGTULK0KVD3DIUv6XOciC7pRfPSXsKJtO5Wd1SJrvYxVqFltcSq1Ys/dTWuRe3x GZmVEDA== X-Google-Smtp-Source: AGHT+IG0e0TCV+nv2O3GJ2JNvVUMgF7RXhLFswJCVRXgnavSu6kqBOUL+WqWbDn24u846J6GkiPd3A== X-Received: by 2002:a05:6a00:1ad3:b0:717:88b6:6b1e with SMTP id d2e1a72fcca58-71936adf416mr13975811b3a.18.1726416554838; Sun, 15 Sep 2024 09:09:14 -0700 (PDT) Received: from localhost.localdomain ([118.114.94.247]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71944bb5967sm2344795b3a.182.2024.09.15.09.09.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Sep 2024 09:09:14 -0700 (PDT) From: Hyman Huang To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , Eric Blake , Markus Armbruster , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Paolo Bonzini , yong.huang@smartx.com Subject: [PATCH v1 5/7] migration: Support background dirty bitmap sync and throttle Date: Mon, 16 Sep 2024 00:08:48 +0800 Message-Id: X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::436; envelope-from=yong.huang@smartx.com; helo=mail-pf1-x436.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org When VM is configured with huge memory, the current throttle logic doesn't look like to scale, because migration_trigger_throttle() is only called for each iteration, so it won't be invoked for a long time if one iteration can take a long time. The background sync and throttle aim to fix the above issue by synchronizing the remote dirty bitmap and triggering the throttle once detect that iteration lasts a long time. This is a trade-off between synchronization overhead and CPU throttle impact. Signed-off-by: Hyman Huang --- migration/migration.c | 12 +++++++++++ tests/qtest/migration-test.c | 39 ++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/migration/migration.c b/migration/migration.c index 055d527ff6..af8b22fa15 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1416,6 +1416,7 @@ static void migrate_fd_cleanup(MigrationState *s) trace_migrate_fd_cleanup(); bql_unlock(); + migration_background_sync_cleanup(); if (s->migration_thread_running) { qemu_thread_join(&s->thread); s->migration_thread_running = false; @@ -3263,6 +3264,7 @@ static MigIterateState migration_iteration_run(MigrationState *s) if ((!pending_size || pending_size < s->threshold_size) && can_switchover) { trace_migration_thread_low_pending(pending_size); + migration_background_sync_cleanup(); migration_completion(s); return MIG_ITERATE_BREAK; } @@ -3508,6 +3510,16 @@ static void *migration_thread(void *opaque) ret = qemu_savevm_state_setup(s->to_dst_file, &local_err); bql_unlock(); + if (!migrate_dirty_limit()) { + /* + * Initiate the background sync watcher in order to guarantee + * that the CPU throttling acts appropriately. Dirty Limit + * doesn't use CPU throttle to make guest down, so ignore that + * case. + */ + migration_background_sync_setup(); + } + qemu_savevm_wait_unplug(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_ACTIVE); diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index b796a90cad..e0e94d26be 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -281,6 +281,11 @@ static uint64_t get_migration_pass(QTestState *who) return read_ram_property_int(who, "iteration-count"); } +static uint64_t get_dirty_sync_count(QTestState *who) +{ + return read_ram_property_int(who, "dirty-sync-count"); +} + static void read_blocktime(QTestState *who) { QDict *rsp_return; @@ -468,6 +473,12 @@ static void migrate_ensure_converge(QTestState *who) migrate_set_parameter_int(who, "downtime-limit", 30 * 1000); } +static void migrate_ensure_iteration_last_long(QTestState *who) +{ + /* Set 10Byte/s bandwidth limit to make the iteration last long enough */ + migrate_set_parameter_int(who, "max-bandwidth", 10); +} + /* * Our goal is to ensure that we run a single full migration * iteration, and also dirty memory, ensuring that at least @@ -2791,6 +2802,10 @@ static void test_migrate_auto_converge(void) * so we need to decrease a bandwidth. */ const int64_t init_pct = 5, inc_pct = 25, max_pct = 95; + uint64_t prev_iter_cnt = 0, iter_cnt; + uint64_t iter_cnt_changes = 0; + uint64_t prev_dirty_sync_cnt = 0, dirty_sync_cnt; + uint64_t dirty_sync_cnt_changes = 0; if (test_migrate_start(&from, &to, uri, &args)) { return; @@ -2827,6 +2842,30 @@ static void test_migrate_auto_converge(void) } while (true); /* The first percentage of throttling should be at least init_pct */ g_assert_cmpint(percentage, >=, init_pct); + + /* Make sure the iteration take a long time enough */ + migrate_ensure_iteration_last_long(from); + + /* + * End the loop when the dirty sync count or iteration count changes. + */ + while (iter_cnt_changes < 2 && dirty_sync_cnt_changes < 2) { + usleep(1000 * 1000); + iter_cnt = get_migration_pass(from); + iter_cnt_changes += (iter_cnt != prev_iter_cnt); + prev_iter_cnt = iter_cnt; + + dirty_sync_cnt = get_dirty_sync_count(from); + dirty_sync_cnt_changes += (dirty_sync_cnt != prev_dirty_sync_cnt); + prev_dirty_sync_cnt = dirty_sync_cnt; + } + + /* + * The dirty sync count must have changed because we are in the same + * iteration. + */ + g_assert_cmpint(iter_cnt_changes , < , dirty_sync_cnt_changes); + /* Now, when we tested that throttling works, let it converge */ migrate_ensure_converge(from); From patchwork Sun Sep 15 16:08:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yong Huang X-Patchwork-Id: 13804864 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CF640C3ABA0 for ; Sun, 15 Sep 2024 16:11:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sproV-0003Hl-3W; Sun, 15 Sep 2024 12:09:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sproQ-0003Dw-Re for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:23 -0400 Received: from mail-pf1-x432.google.com ([2607:f8b0:4864:20::432]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sproO-0006Px-Nf for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:22 -0400 Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-718e11e4186so3544935b3a.2 for ; Sun, 15 Sep 2024 09:09:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=smartx-com.20230601.gappssmtp.com; s=20230601; t=1726416559; x=1727021359; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VxfIUT8pMVWFFKuG2ha9l+max75wFuRXKMQhUKzr0eU=; b=fWUJnH2Yi+N163kYIT0B5xSAcp4z9t6klV8jSNdwRW20Wrr+/tUSFgGNVEQgsei0nL 1iwB5xNJJ11aHjJa3W96wWu0RQbCuFQ/1MfUDq8x6I1LIQ7UqYuTbnWyTiBjhk0kanFF adXagL3RR7dSF4ALcN8DbGPbhlKB0P+Kk4Vb8taCkEOb51HbIToSiXLm1u8Hfaon6hDp NwUeKoAR2ov5H4b8MZYoqGPDa1LbK9ebR6qVsFiAXkoGqjyZ7bD6qNzBXGACzQ70dFdo fDkGDyx93a0Woo6j0LD0hyjPLJiYz0+2DN1yuIqtUVJI6RrrCooP7dd+jO7ExOnLye0N l1Jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726416559; x=1727021359; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VxfIUT8pMVWFFKuG2ha9l+max75wFuRXKMQhUKzr0eU=; b=exoP6kfrZ+aMtzInGm1moSnaoLH+9Je58EgY+MfRxZ2WXGdZ/CkU9154dNQbwf6Bty wYjgAxHvH3RKxkMxUM7et7LLtcJHg1z/1QJvNX0GqDacw0nRx+783mTr+JNRcB0hNqAy o9xmVAH+T7s4TkOknk/amnWfuVbDC/Xwj4tyvjocSAU+ZujQZ9DcfT0SWBEGJA+fDNUJ qhqVBy49ZsI/r0qeLmDJhLJn+aUvIf4BCnMWcJs66aXKbqBEWncgrGuWsjAjcJtODWs5 BTxQ14KYR8I2mNX5i4StCfHpPcQ2pE3vH5cue2E61rADWIIgKY9GVzcqLZPva59OsPjE cwdQ== X-Gm-Message-State: AOJu0Yz46KSsdbztUv5tVRUWVJ7GtzGkhgq+5LfXiX+dazNOPWTiytxe YXhT3BNTdDga9JWBAm0QV3RWYUaZrmElVxNm5Pfw+T/aGLAKnK71/FP38WxfKrS48TEIH0XLIIa kY/nQDw== X-Google-Smtp-Source: AGHT+IGO3cZ8epqoxRRAaW2eKvyivLEIxVnTWOBSybaA9cfAcCbYsndlt4bvvQrFE4RauY2gKzw7ZQ== X-Received: by 2002:a05:6a21:168e:b0:1d2:bb49:6381 with SMTP id adf61e73a8af0-1d2bb496410mr5558241637.47.1726416558401; Sun, 15 Sep 2024 09:09:18 -0700 (PDT) Received: from localhost.localdomain ([118.114.94.247]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71944bb5967sm2344795b3a.182.2024.09.15.09.09.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Sep 2024 09:09:18 -0700 (PDT) From: Hyman Huang To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , Eric Blake , Markus Armbruster , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Paolo Bonzini , yong.huang@smartx.com Subject: [PATCH v1 6/7] qapi/migration: Introduce cpu-responsive-throttle parameter Date: Mon, 16 Sep 2024 00:08:49 +0800 Message-Id: <81d939d716918ed5feea3850cf0644a66d9f1a7b.1726390099.git.yong.huang@smartx.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::432; envelope-from=yong.huang@smartx.com; helo=mail-pf1-x432.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org To enable the responsive throttle that will be implemented in the next commit, introduce the cpu-responsive-throttle parameter. Signed-off-by: Hyman Huang --- migration/migration-hmp-cmds.c | 8 ++++++++ migration/options.c | 20 ++++++++++++++++++++ migration/options.h | 1 + qapi/migration.json | 16 +++++++++++++++- 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c index 28165cfc9e..1fe6c74d66 100644 --- a/migration/migration-hmp-cmds.c +++ b/migration/migration-hmp-cmds.c @@ -264,6 +264,10 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) monitor_printf(mon, "%s: %s\n", MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_TAILSLOW), params->cpu_throttle_tailslow ? "on" : "off"); + assert(params->has_cpu_responsive_throttle); + monitor_printf(mon, "%s: %s\n", + MigrationParameter_str(MIGRATION_PARAMETER_CPU_RESPONSIVE_THROTTLE), + params->cpu_responsive_throttle ? "on" : "off"); assert(params->has_max_cpu_throttle); monitor_printf(mon, "%s: %u\n", MigrationParameter_str(MIGRATION_PARAMETER_MAX_CPU_THROTTLE), @@ -512,6 +516,10 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) p->has_cpu_throttle_tailslow = true; visit_type_bool(v, param, &p->cpu_throttle_tailslow, &err); break; + case MIGRATION_PARAMETER_CPU_RESPONSIVE_THROTTLE: + p->has_cpu_responsive_throttle = true; + visit_type_bool(v, param, &p->cpu_responsive_throttle, &err); + break; case MIGRATION_PARAMETER_MAX_CPU_THROTTLE: p->has_max_cpu_throttle = true; visit_type_uint8(v, param, &p->max_cpu_throttle, &err); diff --git a/migration/options.c b/migration/options.c index 147cd2b8fd..b4c269bf1d 100644 --- a/migration/options.c +++ b/migration/options.c @@ -111,6 +111,8 @@ Property migration_properties[] = { DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT), DEFINE_PROP_BOOL("x-cpu-throttle-tailslow", MigrationState, parameters.cpu_throttle_tailslow, false), + DEFINE_PROP_BOOL("x-cpu-responsive-throttle", MigrationState, + parameters.cpu_responsive_throttle, false), DEFINE_PROP_SIZE("x-max-bandwidth", MigrationState, parameters.max_bandwidth, MAX_THROTTLE), DEFINE_PROP_SIZE("avail-switchover-bandwidth", MigrationState, @@ -705,6 +707,13 @@ uint8_t migrate_cpu_throttle_initial(void) return s->parameters.cpu_throttle_initial; } +bool migrate_responsive_throttle(void) +{ + MigrationState *s = migrate_get_current(); + + return s->parameters.cpu_responsive_throttle; +} + bool migrate_cpu_throttle_tailslow(void) { MigrationState *s = migrate_get_current(); @@ -891,6 +900,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) params->cpu_throttle_increment = s->parameters.cpu_throttle_increment; params->has_cpu_throttle_tailslow = true; params->cpu_throttle_tailslow = s->parameters.cpu_throttle_tailslow; + params->has_cpu_responsive_throttle = true; + params->cpu_responsive_throttle = s->parameters.cpu_responsive_throttle; params->tls_creds = g_strdup(s->parameters.tls_creds); params->tls_hostname = g_strdup(s->parameters.tls_hostname); params->tls_authz = g_strdup(s->parameters.tls_authz ? @@ -959,6 +970,7 @@ void migrate_params_init(MigrationParameters *params) params->has_cpu_throttle_initial = true; params->has_cpu_throttle_increment = true; params->has_cpu_throttle_tailslow = true; + params->has_cpu_responsive_throttle = true; params->has_max_bandwidth = true; params->has_downtime_limit = true; params->has_x_checkpoint_delay = true; @@ -1191,6 +1203,10 @@ static void migrate_params_test_apply(MigrateSetParameters *params, dest->cpu_throttle_tailslow = params->cpu_throttle_tailslow; } + if (params->has_cpu_responsive_throttle) { + dest->cpu_responsive_throttle = params->cpu_responsive_throttle; + } + if (params->tls_creds) { assert(params->tls_creds->type == QTYPE_QSTRING); dest->tls_creds = params->tls_creds->u.s; @@ -1302,6 +1318,10 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) s->parameters.cpu_throttle_tailslow = params->cpu_throttle_tailslow; } + if (params->has_cpu_responsive_throttle) { + s->parameters.cpu_responsive_throttle = params->cpu_responsive_throttle; + } + if (params->tls_creds) { g_free(s->parameters.tls_creds); assert(params->tls_creds->type == QTYPE_QSTRING); diff --git a/migration/options.h b/migration/options.h index a0bd6edc06..80d0fcdaf9 100644 --- a/migration/options.h +++ b/migration/options.h @@ -68,6 +68,7 @@ bool migrate_has_block_bitmap_mapping(void); uint32_t migrate_checkpoint_delay(void); uint8_t migrate_cpu_throttle_increment(void); uint8_t migrate_cpu_throttle_initial(void); +bool migrate_responsive_throttle(void); bool migrate_cpu_throttle_tailslow(void); bool migrate_direct_io(void); uint64_t migrate_downtime_limit(void); diff --git a/qapi/migration.json b/qapi/migration.json index 95b490706c..c61d3b3a6b 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -732,6 +732,10 @@ # be excessive at tail stage. The default value is false. (Since # 5.1) # +# @cpu-responsive-throttle: Make CPU throttling more responsively by +# introduce an extra detection metric of +# migration convergence. (Since 9.1) +# # @tls-creds: ID of the 'tls-creds' object that provides credentials # for establishing a TLS connection over the migration data # channel. On the outgoing side of the migration, the credentials @@ -857,7 +861,7 @@ 'announce-rounds', 'announce-step', 'throttle-trigger-threshold', 'cpu-throttle-initial', 'cpu-throttle-increment', - 'cpu-throttle-tailslow', + 'cpu-throttle-tailslow', 'cpu-responsive-throttle', 'tls-creds', 'tls-hostname', 'tls-authz', 'max-bandwidth', 'avail-switchover-bandwidth', 'downtime-limit', { 'name': 'x-checkpoint-delay', 'features': [ 'unstable' ] }, @@ -913,6 +917,10 @@ # be excessive at tail stage. The default value is false. (Since # 5.1) # +# @cpu-responsive-throttle: Make CPU throttling more responsively by +# introduce an extra detection metric of +# migration convergence. (Since 9.1) +# # @tls-creds: ID of the 'tls-creds' object that provides credentials # for establishing a TLS connection over the migration data # channel. On the outgoing side of the migration, the credentials @@ -1045,6 +1053,7 @@ '*cpu-throttle-initial': 'uint8', '*cpu-throttle-increment': 'uint8', '*cpu-throttle-tailslow': 'bool', + '*cpu-responsive-throttle': 'bool', '*tls-creds': 'StrOrNull', '*tls-hostname': 'StrOrNull', '*tls-authz': 'StrOrNull', @@ -1127,6 +1136,10 @@ # be excessive at tail stage. The default value is false. (Since # 5.1) # +# @cpu-responsive-throttle: Make CPU throttling more responsively by +# introduce an extra detection metric of +# migration convergence. (Since 9.1) +# # @tls-creds: ID of the 'tls-creds' object that provides credentials # for establishing a TLS connection over the migration data # channel. On the outgoing side of the migration, the credentials @@ -1252,6 +1265,7 @@ '*cpu-throttle-initial': 'uint8', '*cpu-throttle-increment': 'uint8', '*cpu-throttle-tailslow': 'bool', + '*cpu-responsive-throttle': 'bool', '*tls-creds': 'str', '*tls-hostname': 'str', '*tls-authz': 'str', From patchwork Sun Sep 15 16:08:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yong Huang X-Patchwork-Id: 13804859 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E09E3C3ABA0 for ; Sun, 15 Sep 2024 16:10:05 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sproY-0003RO-I5; Sun, 15 Sep 2024 12:09:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sproU-0003GW-3T for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:26 -0400 Received: from mail-pf1-x42a.google.com ([2607:f8b0:4864:20::42a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sproS-0006Qb-4V for qemu-devel@nongnu.org; Sun, 15 Sep 2024 12:09:25 -0400 Received: by mail-pf1-x42a.google.com with SMTP id d2e1a72fcca58-71911585911so3163231b3a.3 for ; Sun, 15 Sep 2024 09:09:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=smartx-com.20230601.gappssmtp.com; s=20230601; t=1726416563; x=1727021363; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GVIR2VPmJg+nV5CN3iMpYvvRb8M20NpY1SeasAo60A4=; b=qM8BaXk/UPmxJgjEbO8U3Dsgq4Nf28QoLhJeXVoQA7rpO+Kr3uPEnWAjdg2zjkVay0 MI+hfFqD9AvtM1zfX74hFJv8IB4bAveyHGWiPwP6pHN5it7H8CqpthaG9+i0U3iyvVeZ byNEriJnZnMfLdpwUraKofvF0XpKWKXQjrEX9Uv2IHnubE2mgYailSB4DBtME/X/hZ20 L1TDZWF2bgevp+iEaJ2/5OENNNHkQwUW8Tyipszh+wENSv+TzTuEYZpYGi54RUhXliZN xTmgB8qU+GN21UPVY/Gk5snMZl63DQz22s4lt5Dt/haP4V/7uLYa2e+fyhhkRrAY6XAs qPZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726416563; x=1727021363; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GVIR2VPmJg+nV5CN3iMpYvvRb8M20NpY1SeasAo60A4=; b=n0NFN2owjCiiXnlouSTSQFw9chxCWnAcmo2PfVFotKXP+8Fdjb9M5vJy46S2Y63kI6 uTaoI4AGFWDNvWRhYrrc03fg5loZsz53qf7QJAxCvzJpM9CnTZXUmfzmtbyDfSVfSC6d lJcHFpjycMLDxdN13bo4yK81ZonEUXjMXY7ZR+XsgkU+aqpoh1NfG0JkjIVzEWfNIxL5 kRKYXUDz1rKYyLxcqfAD8uKSx8pKaN65bw1g6/WDn+t9u3zAqpUdl2xLyb3hkJzggJRA x1lS7XGN4JPhmBYD9YhldM1Cc2HlZmn561MrlzRBJR0TGYibbMSZPMdRvKglkSis5U1D cnmA== X-Gm-Message-State: AOJu0YyANjiLSoiQqZfrjkfTx6anQokqvwJkz4kLtl13PeHT/G6z2RmX PqJTr3ZIP6puvHkkP0Uy4A9aZc16Kvx7/Uh8KZPsULQJjqArTSTuCD41A8j/R1sWBhl6ZbA48Rm tDn5Sug== X-Google-Smtp-Source: AGHT+IFPlUPgQuwPek7A1EJ4jngrk8mlPeLbu5d7tnWvK2ySCdXGUF//La4NB6x5h1nSpvKCfUHnFQ== X-Received: by 2002:a05:6a21:168d:b0:1ce:f77a:67bf with SMTP id adf61e73a8af0-1cf764c577cmr17969925637.49.1726416561953; Sun, 15 Sep 2024 09:09:21 -0700 (PDT) Received: from localhost.localdomain ([118.114.94.247]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71944bb5967sm2344795b3a.182.2024.09.15.09.09.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Sep 2024 09:09:21 -0700 (PDT) From: Hyman Huang To: qemu-devel@nongnu.org Cc: Peter Xu , Fabiano Rosas , Eric Blake , Markus Armbruster , David Hildenbrand , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Paolo Bonzini , yong.huang@smartx.com Subject: [PATCH v1 7/7] migration: Support responsive CPU throttle Date: Mon, 16 Sep 2024 00:08:50 +0800 Message-Id: <495340ef44d5d6865553503324d4717ebf98dd28.1726390099.git.yong.huang@smartx.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::42a; envelope-from=yong.huang@smartx.com; helo=mail-pf1-x42a.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Currently, the convergence algorithm determines that the migration cannot converge according to the following principle: The dirty pages generated in current iteration exceed a specific percentage (throttle-trigger-threshold, 50 by default) of the number of transmissions. Let's refer to this criteria as the "dirty rate". If this criteria is met more than or equal to twice (dirty_rate_high_cnt >= 2), the throttle percentage increased. In most cases, above implementation is appropriate. However, for a VM with high memory overload, each iteration is time-consuming. The VM's computing performance may be throttled at a high percentage and last for a long time due to the repeated confirmation behavior. Which may be intolerable for some computationally sensitive software in the VM. As the comment mentioned in the migration_trigger_throttle function, in order to avoid erroneous detection, the original algorithm confirms the criteria repeatedly. Put differently, the criteria does not need to be validated again once the detection is more reliable. In the refinement, in order to make the detection more accurate, we introduce another criteria, called the "dirty ratio" to determine the migration convergence. The "dirty ratio" is the ratio of bytes_xfer_period and bytes_dirty_period. When the algorithm repeatedly detects that the "dirty ratio" of current sync is lower than the previous, the algorithm determines that the migration cannot converge. For the "dirty rate" and "dirty ratio", if one of the two criteria is met, the penalty percentage would be increased. This makes CPU throttle more responsively and therefor saves the time of the entire iteration and therefore reduces the time of VM performance degradation. In conclusion, this refinement significantly reduces the processing time required for the throttle percentage step to its maximum while the VM is under a high memory load. Signed-off-by: Hyman Huang --- migration/ram.c | 55 ++++++++++++++++++++++++++++++++++-- migration/trace-events | 1 + tests/qtest/migration-test.c | 1 + 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index 799eaa0382..8d856a89db 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -421,6 +421,12 @@ struct RAMState { bool background_sync_running; QemuThread background_sync_thread; QemuSemaphore quit_sem; + + /* + * Ratio of bytes_dirty_period and bytes_xfer_period in the + * previous sync. + */ + uint64_t dirty_ratio_pct; }; typedef struct RAMState RAMState; @@ -1049,6 +1055,43 @@ static void migration_dirty_limit_guest(void) trace_migration_dirty_limit_guest(quota_dirtyrate); } +static bool migration_dirty_ratio_high(RAMState *rs) +{ + static int dirty_ratio_high_cnt; + uint64_t threshold = migrate_throttle_trigger_threshold(); + uint64_t bytes_xfer_period = + migration_transferred_bytes() - rs->bytes_xfer_prev; + uint64_t bytes_dirty_period = rs->num_dirty_pages_period * TARGET_PAGE_SIZE; + bool dirty_ratio_high = false; + uint64_t prev, curr; + + /* Calculate the dirty ratio percentage */ + curr = 100 * (bytes_dirty_period * 1.0 / bytes_xfer_period); + + prev = rs->dirty_ratio_pct; + rs->dirty_ratio_pct = curr; + + if (prev == 0) { + return false; + } + + /* + * If current dirty ratio is greater than previouse, determine + * that the migration do not converge. + */ + if (curr > threshold && curr >= prev) { + trace_migration_dirty_ratio_high(curr, prev); + dirty_ratio_high_cnt++; + } + + if (dirty_ratio_high_cnt >= 2) { + dirty_ratio_high = true; + dirty_ratio_high_cnt = 0; + } + + return dirty_ratio_high; +} + static void migration_trigger_throttle(RAMState *rs) { uint64_t threshold = migrate_throttle_trigger_threshold(); @@ -1056,6 +1099,11 @@ static void migration_trigger_throttle(RAMState *rs) migration_transferred_bytes() - rs->bytes_xfer_prev; uint64_t bytes_dirty_period = rs->num_dirty_pages_period * TARGET_PAGE_SIZE; uint64_t bytes_dirty_threshold = bytes_xfer_period * threshold / 100; + bool dirty_ratio_high = false; + + if (migrate_responsive_throttle() && (bytes_xfer_period != 0)) { + dirty_ratio_high = migration_dirty_ratio_high(rs); + } /* * The following detection logic can be refined later. For now: @@ -1065,8 +1113,11 @@ static void migration_trigger_throttle(RAMState *rs) * twice, start or increase throttling. */ if ((bytes_dirty_period > bytes_dirty_threshold) && - (++rs->dirty_rate_high_cnt >= 2)) { - rs->dirty_rate_high_cnt = 0; + ((++rs->dirty_rate_high_cnt >= 2) || dirty_ratio_high)) { + + rs->dirty_rate_high_cnt = + rs->dirty_rate_high_cnt >= 2 ? 0 : rs->dirty_rate_high_cnt; + if (migrate_auto_converge()) { trace_migration_throttle(); mig_throttle_guest_down(bytes_dirty_period, diff --git a/migration/trace-events b/migration/trace-events index 4f95f9fe14..0b219516e9 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -98,6 +98,7 @@ migration_background_sync_watcher_end(void) "" migration_bitmap_sync_start(void) "" migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64 migration_bitmap_clear_dirty(char *str, uint64_t start, uint64_t size, unsigned long page) "rb %s start 0x%"PRIx64" size 0x%"PRIx64" page 0x%lx" +migration_dirty_ratio_high(uint64_t cur, uint64_t prev) "current ratio: %" PRIu64 " previous ratio: %" PRIu64 migration_throttle(void) "" migration_dirty_limit_guest(int64_t dirtyrate) "guest dirty page rate limit %" PRIi64 " MB/s" ram_discard_range(const char *rbname, uint64_t start, size_t len) "%s: start: %" PRIx64 " %zx" diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index e0e94d26be..9f7c2f49a0 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -2815,6 +2815,7 @@ static void test_migrate_auto_converge(void) migrate_set_parameter_int(from, "cpu-throttle-initial", init_pct); migrate_set_parameter_int(from, "cpu-throttle-increment", inc_pct); migrate_set_parameter_int(from, "max-cpu-throttle", max_pct); + migrate_set_parameter_bool(from, "cpu-responsive-throttle", true); /* * Set the initial parameters so that the migration could not converge