From nobody Sat Nov 15 20:50:02 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1747736968; cv=none; d=zohomail.com; s=zohoarc; b=dhWGHLuPwvQfJ6lwR+PjMNZe2kYdIeW2+Ymzyly9yDE8EV30ooFxL7mGY/voFY+U8g4joMCUmw0o+psjEuxeQ9fk9qTz2kQPwzVOSfgN/UjeIsF7A/gIhKrnqXebvO9wuq0P1pcdOicRZTeb2AtKeJvNsRDg4FbDXNUcZ/Eu95I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1747736968; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Vyrw+adadFxsdj7/q3ZGWnk7UkK5X8nJpruQISgDnUg=; b=Nn8XH6P3icBk9W3d9vZiZ81zKm63WFKm7UEjnK2eb56Y0gjlTI3g3Z1QJC1lx+N6RsqThX2tPayWqBM7BNujOFrsakoBja8TcQvanzfVDtgXnLZfcsViC9Sp23Yyfg99lOKtdcv5penbfvFtxNVv5Z6KvPRce4ECEYBLFFrYQtg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1747736968373197.08169090934643; Tue, 20 May 2025 03:29:28 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHKDh-0004bf-Ng; Tue, 20 May 2025 06:29:13 -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 1uHKDg-0004bG-2f for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:12 -0400 Received: from mgamail.intel.com ([198.175.65.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uHKDd-0004f3-Q6 for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:11 -0400 Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:08 -0700 Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:04 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747736950; x=1779272950; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=pvakodypSo80D6jOTbKAlrpB0vU0hAgMhd1K2+L0NeY=; b=mfsA31kWQGcLPmE4kbSSFH2ZQsVa7aUWxmNcFTBs31DU1j2THWsxfDu/ yHv6JOP7r9aG72DqCU/hYfusSOWbtoJbxfzg+ntEw8z206nIrqsKrInDB 4IR5W+RVX2UrQPoGNX9vQeNgKOkarA2MQY/KQdaR+gBH5TeTw3b0UjrSK D0TGNI9Hle6/MpuyspFh4qHekO6A4jV1rPIhmHFRy/VVxZUKfuQq+LUUX LtOFNluSpSAdCF13kj05VR6zQkD3lQeeI6AX7NpdHCqQfcf9LAU1PdR9j zG1F+EDeHnlX0R4HU8680Bnqt+G1s5gXXO6o5zqCgEHcuLGnHttPUNUTr w==; X-CSE-ConnectionGUID: /mOufPj2QQqJR8c5z0rgEg== X-CSE-MsgGUID: GziRokHSS5utPlqMTdqubA== X-IronPort-AV: E=McAfee;i="6700,10204,11438"; a="49566621" X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="49566621" X-CSE-ConnectionGUID: mVaTGQJsQqajrbrL1g2z1Q== X-CSE-MsgGUID: FWYrQxcpTkqyaLVKg5nkCA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="144905221" From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Gupta Pankaj , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Zhao Liu , Baolu Lu , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v5 01/10] memory: Export a helper to get intersection of a MemoryRegionSection with a given range Date: Tue, 20 May 2025 18:28:41 +0800 Message-ID: <20250520102856.132417-2-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250520102856.132417-1-chenyi.qiang@intel.com> References: <20250520102856.132417-1-chenyi.qiang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.21; envelope-from=chenyi.qiang@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.13, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1747736969777116600 Content-Type: text/plain; charset="utf-8" Rename the helper to memory_region_section_intersect_range() to make it more generic. Meanwhile, define the @end as Int128 and replace the related operations with Int128_* format since the helper is exported as a wider API. Suggested-by: Alexey Kardashevskiy Reviewed-by: Alexey Kardashevskiy Reviewed-by: David Hildenbrand Reviewed-by: Zhao Liu Signed-off-by: Chenyi Qiang --- Changes in v5: - Indent change for int128 ops to avoid the line over 80 - Add two Review-by from Alexey and Zhao Changes in v4: - No change. Changes in v3: - No change Changes in v2: - Make memory_region_section_intersect_range() an inline function. - Add Reviewed-by from David - Define the @end as Int128 and use the related Int128_* ops as a wilder API (Alexey) --- hw/virtio/virtio-mem.c | 32 +++++--------------------------- include/system/memory.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index a3d1a676e7..b3c126ea1e 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -244,28 +244,6 @@ static int virtio_mem_for_each_plugged_range(VirtIOMEM= *vmem, void *arg, return ret; } =20 -/* - * Adjust the memory section to cover the intersection with the given rang= e. - * - * Returns false if the intersection is empty, otherwise returns true. - */ -static bool virtio_mem_intersect_memory_section(MemoryRegionSection *s, - uint64_t offset, uint64_t = size) -{ - uint64_t start =3D MAX(s->offset_within_region, offset); - uint64_t end =3D MIN(s->offset_within_region + int128_get64(s->size), - offset + size); - - if (end <=3D start) { - return false; - } - - s->offset_within_address_space +=3D start - s->offset_within_region; - s->offset_within_region =3D start; - s->size =3D int128_make64(end - start); - return true; -} - typedef int (*virtio_mem_section_cb)(MemoryRegionSection *s, void *arg); =20 static int virtio_mem_for_each_plugged_section(const VirtIOMEM *vmem, @@ -287,7 +265,7 @@ static int virtio_mem_for_each_plugged_section(const Vi= rtIOMEM *vmem, first_bit + 1) - 1; size =3D (last_bit - first_bit + 1) * vmem->block_size; =20 - if (!virtio_mem_intersect_memory_section(&tmp, offset, size)) { + if (!memory_region_section_intersect_range(&tmp, offset, size)) { break; } ret =3D cb(&tmp, arg); @@ -319,7 +297,7 @@ static int virtio_mem_for_each_unplugged_section(const = VirtIOMEM *vmem, first_bit + 1) - 1; size =3D (last_bit - first_bit + 1) * vmem->block_size; =20 - if (!virtio_mem_intersect_memory_section(&tmp, offset, size)) { + if (!memory_region_section_intersect_range(&tmp, offset, size)) { break; } ret =3D cb(&tmp, arg); @@ -355,7 +333,7 @@ static void virtio_mem_notify_unplug(VirtIOMEM *vmem, u= int64_t offset, QLIST_FOREACH(rdl, &vmem->rdl_list, next) { MemoryRegionSection tmp =3D *rdl->section; =20 - if (!virtio_mem_intersect_memory_section(&tmp, offset, size)) { + if (!memory_region_section_intersect_range(&tmp, offset, size)) { continue; } rdl->notify_discard(rdl, &tmp); @@ -371,7 +349,7 @@ static int virtio_mem_notify_plug(VirtIOMEM *vmem, uint= 64_t offset, QLIST_FOREACH(rdl, &vmem->rdl_list, next) { MemoryRegionSection tmp =3D *rdl->section; =20 - if (!virtio_mem_intersect_memory_section(&tmp, offset, size)) { + if (!memory_region_section_intersect_range(&tmp, offset, size)) { continue; } ret =3D rdl->notify_populate(rdl, &tmp); @@ -388,7 +366,7 @@ static int virtio_mem_notify_plug(VirtIOMEM *vmem, uint= 64_t offset, if (rdl2 =3D=3D rdl) { break; } - if (!virtio_mem_intersect_memory_section(&tmp, offset, size)) { + if (!memory_region_section_intersect_range(&tmp, offset, size)= ) { continue; } rdl2->notify_discard(rdl2, &tmp); diff --git a/include/system/memory.h b/include/system/memory.h index fbbf4cf911..b961c4076a 100644 --- a/include/system/memory.h +++ b/include/system/memory.h @@ -1211,6 +1211,36 @@ MemoryRegionSection *memory_region_section_new_copy(= MemoryRegionSection *s); */ void memory_region_section_free_copy(MemoryRegionSection *s); =20 +/** + * memory_region_section_intersect_range: Adjust the memory section to cov= er + * the intersection with the given range. + * + * @s: the #MemoryRegionSection to be adjusted + * @offset: the offset of the given range in the memory region + * @size: the size of the given range + * + * Returns false if the intersection is empty, otherwise returns true. + */ +static inline bool memory_region_section_intersect_range(MemoryRegionSecti= on *s, + uint64_t offset, + uint64_t size) +{ + uint64_t start =3D MAX(s->offset_within_region, offset); + Int128 end =3D int128_min(int128_add(int128_make64(s->offset_within_re= gion), + s->size), + int128_add(int128_make64(offset), + int128_make64(size))); + + if (int128_le(end, int128_make64(start))) { + return false; + } + + s->offset_within_address_space +=3D start - s->offset_within_region; + s->offset_within_region =3D start; + s->size =3D int128_sub(end, int128_make64(start)); + return true; +} + /** * memory_region_init: Initialize a memory region * --=20 2.43.5 From nobody Sat Nov 15 20:50:02 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1747736999; cv=none; d=zohomail.com; s=zohoarc; b=VnedVAl7GUiNLakv6sXPmjJ69ai2ZAkF8r8KqU0nDlhOs9cFpGbzhmUGEs4iGeZBAGZIiMhSxqVALUWaugerPEqJQPWqrqqu/XDYofMgW+aXOXR0SLDi+JDMNTT4SIf6X1WJrvA2HLQBcqx5+FPa9Y8iISs2EYq/q1va13S2AQg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1747736999; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=27kyEkAJfJGXuEI6kQrRz95JludvRGqYgpjyllO97po=; b=DaNASPudt8mtsoPtpIPLorbbZOLp1EtRh5MamBgzy1RUApjF8JDHH+5/Vr6Q8ZG2B1We3vCFyWz7W7SmEqApUCLYC9zlAOQmta+boIgFtTTb3Ma1YX889RJp8+rwKosoSRyOC3nJG199zIu8yvyIBhM8pPviVK8wwqfFs1nbpNE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1747736999284431.47994074015844; Tue, 20 May 2025 03:29:59 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHKDk-0004cB-Fd; Tue, 20 May 2025 06:29:16 -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 1uHKDi-0004c1-Cd for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:14 -0400 Received: from mgamail.intel.com ([198.175.65.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uHKDg-0004eb-9t for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:14 -0400 Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:12 -0700 Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:07 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747736953; x=1779272953; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=R5LFT5AsG3wsPZY3KRrUkPR61WLL1e67GZCvt4H8Tkk=; b=F3uvGEXuxMuoHjpfFyoXqqGlSUzPXG/eEl1xqeAshgc+oQwegWHa1Kjk 7Djj5Q4ptqO+tAH+IfXCAOTF/JjwJuljFQENcwgIqxYZISyLeEHK8fI0r o4tlspkTrqiPBST7ZY58DBqku21UoM2jjYW+FYH35Pk/8MH9xesebck56 LZlPHOgBs2g+ch2MYndZTlIOFU2BxYF/PhILzxib7Xukh9zkfulYY10SV ilTPPRNf51l1WABos08+oB1d9IS/l+sOZCynP27BhfWMihj9fkNXSHTQ8 dUVGkvClS5pGmkJDd78kGTFuuxjSLM56zY/MdHQEtf1L089zca9zLyvog A==; X-CSE-ConnectionGUID: i8tApbm8Tym7tXA0Do2Z1g== X-CSE-MsgGUID: MSSGhU8nR6OQ9fOlyfbmwQ== X-IronPort-AV: E=McAfee;i="6700,10204,11438"; a="49566638" X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="49566638" X-CSE-ConnectionGUID: K0NXmz3yQGqZNd/LaV/iJA== X-CSE-MsgGUID: YnzgoaVORCePeeTjE9lLsg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="144905230" From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Gupta Pankaj , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Zhao Liu , Baolu Lu , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v5 02/10] memory: Change memory_region_set_ram_discard_manager() to return the result Date: Tue, 20 May 2025 18:28:42 +0800 Message-ID: <20250520102856.132417-3-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250520102856.132417-1-chenyi.qiang@intel.com> References: <20250520102856.132417-1-chenyi.qiang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.21; envelope-from=chenyi.qiang@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.13, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1747736999907116600 Content-Type: text/plain; charset="utf-8" Modify memory_region_set_ram_discard_manager() to return -EBUSY if a RamDiscardManager is already set in the MemoryRegion. The caller must handle this failure, such as having virtio-mem undo its actions and fail the realize() process. Opportunistically move the call earlier to avoid complex error handling. This change is beneficial when introducing a new RamDiscardManager instance besides virtio-mem. After ram_block_coordinated_discard_require(true) unlocks all RamDiscardManager instances, only one instance is allowed to be set for one MemoryRegion at present. Suggested-by: David Hildenbrand Signed-off-by: Chenyi Qiang Reviewed-by: Alexey Kardashevskiy Reviewed-by: David Hildenbrand --- Changes in v5: - Nit in commit message (return false -> -EBUSY) - Add set_ram_discard_manager(NULL) when ram_block_discard_range() fails. Changes in v4: - No change. Changes in v3: - Move set_ram_discard_manager() up to avoid a g_free() - Clean up set_ram_discard_manager() definition Changes in v2: - newly added. --- hw/virtio/virtio-mem.c | 30 +++++++++++++++++------------- include/system/memory.h | 6 +++--- system/memory.c | 10 +++++++--- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index b3c126ea1e..2e491e8c44 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -1047,6 +1047,17 @@ static void virtio_mem_device_realize(DeviceState *d= ev, Error **errp) return; } =20 + /* + * Set ourselves as RamDiscardManager before the plug handler maps the + * memory region and exposes it via an address space. + */ + if (memory_region_set_ram_discard_manager(&vmem->memdev->mr, + RAM_DISCARD_MANAGER(vmem))) { + error_setg(errp, "Failed to set RamDiscardManager"); + ram_block_coordinated_discard_require(false); + return; + } + /* * We don't know at this point whether shared RAM is migrated using * QEMU or migrated using the file content. "x-ignore-shared" will be @@ -1061,6 +1072,7 @@ static void virtio_mem_device_realize(DeviceState *de= v, Error **errp) ret =3D ram_block_discard_range(rb, 0, qemu_ram_get_used_length(rb= )); if (ret) { error_setg_errno(errp, -ret, "Unexpected error discarding RAM"= ); + memory_region_set_ram_discard_manager(&vmem->memdev->mr, NULL); ram_block_coordinated_discard_require(false); return; } @@ -1122,13 +1134,6 @@ static void virtio_mem_device_realize(DeviceState *d= ev, Error **errp) vmem->system_reset =3D VIRTIO_MEM_SYSTEM_RESET(obj); vmem->system_reset->vmem =3D vmem; qemu_register_resettable(obj); - - /* - * Set ourselves as RamDiscardManager before the plug handler maps the - * memory region and exposes it via an address space. - */ - memory_region_set_ram_discard_manager(&vmem->memdev->mr, - RAM_DISCARD_MANAGER(vmem)); } =20 static void virtio_mem_device_unrealize(DeviceState *dev) @@ -1136,12 +1141,6 @@ static void virtio_mem_device_unrealize(DeviceState = *dev) VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); VirtIOMEM *vmem =3D VIRTIO_MEM(dev); =20 - /* - * The unplug handler unmapped the memory region, it cannot be - * found via an address space anymore. Unset ourselves. - */ - memory_region_set_ram_discard_manager(&vmem->memdev->mr, NULL); - qemu_unregister_resettable(OBJECT(vmem->system_reset)); object_unref(OBJECT(vmem->system_reset)); =20 @@ -1154,6 +1153,11 @@ static void virtio_mem_device_unrealize(DeviceState = *dev) virtio_del_queue(vdev, 0); virtio_cleanup(vdev); g_free(vmem->bitmap); + /* + * The unplug handler unmapped the memory region, it cannot be + * found via an address space anymore. Unset ourselves. + */ + memory_region_set_ram_discard_manager(&vmem->memdev->mr, NULL); ram_block_coordinated_discard_require(false); } =20 diff --git a/include/system/memory.h b/include/system/memory.h index b961c4076a..896948deb1 100644 --- a/include/system/memory.h +++ b/include/system/memory.h @@ -2499,13 +2499,13 @@ static inline bool memory_region_has_ram_discard_ma= nager(MemoryRegion *mr) * * This function must not be called for a mapped #MemoryRegion, a #MemoryR= egion * that does not cover RAM, or a #MemoryRegion that already has a - * #RamDiscardManager assigned. + * #RamDiscardManager assigned. Return 0 if the rdm is set successfully. * * @mr: the #MemoryRegion * @rdm: #RamDiscardManager to set */ -void memory_region_set_ram_discard_manager(MemoryRegion *mr, - RamDiscardManager *rdm); +int memory_region_set_ram_discard_manager(MemoryRegion *mr, + RamDiscardManager *rdm); =20 /** * memory_region_find: translate an address/size relative to a diff --git a/system/memory.c b/system/memory.c index 63b983efcd..b45b508dce 100644 --- a/system/memory.c +++ b/system/memory.c @@ -2106,12 +2106,16 @@ RamDiscardManager *memory_region_get_ram_discard_ma= nager(MemoryRegion *mr) return mr->rdm; } =20 -void memory_region_set_ram_discard_manager(MemoryRegion *mr, - RamDiscardManager *rdm) +int memory_region_set_ram_discard_manager(MemoryRegion *mr, + RamDiscardManager *rdm) { g_assert(memory_region_is_ram(mr)); - g_assert(!rdm || !mr->rdm); + if (mr->rdm && rdm) { + return -EBUSY; + } + mr->rdm =3D rdm; + return 0; } =20 uint64_t ram_discard_manager_get_min_granularity(const RamDiscardManager *= rdm, --=20 2.43.5 From nobody Sat Nov 15 20:50:02 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1747737014; cv=none; d=zohomail.com; s=zohoarc; b=Or2SrjQL3ygmC400SzLUpt/YE8Iy2NiXzQeHL3HTrVIimXZDFk/ogB0OxAWiTskxwFBPm5zXzde0UPLqtLzjOsSxh28YYpoWww0L5aEwCsEES3HmWgiy0ALKAlXUpmRcMgQrXiV5HQMRdlOlqCKMrXCTg7NJPsQ7nzJGLl6DfPY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1747737014; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=jSgGWMhGwM6TUdhKIUQl3US4JzkaZmpv46dvcjVQ+jo=; b=Q6yJBBFopOptvxzLeFpANbRbjrKeYGCgWXV5BamVFqAdHyo1x3pNCb0xMW8ercNrze0OWAowhILVOjluyHX4h1kIEvqYX8hd1drFXZ5She+eEh1F9shXK68Vl/h0URbA8wfy9L01nUbasi3cDxjCy33JxKykkSL6FA5szHV3ubk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1747737014528357.62786580669024; Tue, 20 May 2025 03:30:14 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHKDp-0004ci-2u; Tue, 20 May 2025 06:29:21 -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 1uHKDm-0004cS-HW for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:18 -0400 Received: from mgamail.intel.com ([198.175.65.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uHKDk-0004gB-GT for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:18 -0400 Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:15 -0700 Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:11 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747736957; x=1779272957; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=buapM487lyBcGcvGhevWysjMWOzzKGFo5Q7pkxmvxGQ=; b=X2oTg6tMgFfXYRpJjtdsBdONGr+IjuzgMjIxsk6OWCa/wM5/CDvq50PW ZUoX0vI2MpL+fEKtUFwZhdkbNV9p2BOUcbcyY2us1/2aG0xfWhlYVpzBf T3rm/Y20o6FYsI/etQcO/dzGjDnOrJU4gxZa2TKMIWphTMoWqHUtyaSax KzWtlAiNxA/lcac4afau9R32pfqEhn/PBjDpPILopCnsxLRS5PtbUegU1 mMC5dngBC+sksOhqMk+cJHPVHwMTC30rp5otzIVtyuWTpjiAxYAFOXlSt IrvZXRr2Ym3cU58TNw+mEjvWKBsi6VkMVPLHXgrBkzjK0f59x20FA2Rd3 A==; X-CSE-ConnectionGUID: Ce/w25rBRXa2rqPEl51p5Q== X-CSE-MsgGUID: QU8ZkQjgT7yOlzDovkWYQw== X-IronPort-AV: E=McAfee;i="6700,10204,11438"; a="49566645" X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="49566645" X-CSE-ConnectionGUID: SniMQfG3Tni8orlthbbS6w== X-CSE-MsgGUID: GlW27O+sRKO/XpL45zkNfg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="144905239" From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Gupta Pankaj , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Zhao Liu , Baolu Lu , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v5 03/10] memory: Unify the definiton of ReplayRamPopulate() and ReplayRamDiscard() Date: Tue, 20 May 2025 18:28:43 +0800 Message-ID: <20250520102856.132417-4-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250520102856.132417-1-chenyi.qiang@intel.com> References: <20250520102856.132417-1-chenyi.qiang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.21; envelope-from=chenyi.qiang@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.13, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1747737016174116600 Content-Type: text/plain; charset="utf-8" Update ReplayRamDiscard() function to return the result and unify the ReplayRamPopulate() and ReplayRamDiscard() to ReplayRamDiscardState() at the same time due to their identical definitions. This unification simplifies related structures, such as VirtIOMEMReplayData, which makes it cleaner. Signed-off-by: Chenyi Qiang Reviewed-by: Alexey Kardashevskiy Reviewed-by: David Hildenbrand --- Changes in v5: - Rename ReplayRamStateChange to ReplayRamDiscardState (David) - return data->fn(s, data->opaque) instead of 0 in virtio_mem_rdm_replay_discarded_cb(). (Alexey) Changes in v4: - Modify the commit message. We won't use Replay() operation when doing the attribute change like v3. Changes in v3: - Newly added. --- hw/virtio/virtio-mem.c | 21 ++++++++++----------- include/system/memory.h | 36 +++++++++++++++++++----------------- migration/ram.c | 5 +++-- system/memory.c | 12 ++++++------ 4 files changed, 38 insertions(+), 36 deletions(-) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index 2e491e8c44..c46f6f9c3e 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -1732,7 +1732,7 @@ static bool virtio_mem_rdm_is_populated(const RamDisc= ardManager *rdm, } =20 struct VirtIOMEMReplayData { - void *fn; + ReplayRamDiscardState fn; void *opaque; }; =20 @@ -1740,12 +1740,12 @@ static int virtio_mem_rdm_replay_populated_cb(Memor= yRegionSection *s, void *arg) { struct VirtIOMEMReplayData *data =3D arg; =20 - return ((ReplayRamPopulate)data->fn)(s, data->opaque); + return data->fn(s, data->opaque); } =20 static int virtio_mem_rdm_replay_populated(const RamDiscardManager *rdm, MemoryRegionSection *s, - ReplayRamPopulate replay_fn, + ReplayRamDiscardState replay_fn, void *opaque) { const VirtIOMEM *vmem =3D VIRTIO_MEM(rdm); @@ -1764,14 +1764,13 @@ static int virtio_mem_rdm_replay_discarded_cb(Memor= yRegionSection *s, { struct VirtIOMEMReplayData *data =3D arg; =20 - ((ReplayRamDiscard)data->fn)(s, data->opaque); - return 0; + return data->fn(s, data->opaque); } =20 -static void virtio_mem_rdm_replay_discarded(const RamDiscardManager *rdm, - MemoryRegionSection *s, - ReplayRamDiscard replay_fn, - void *opaque) +static int virtio_mem_rdm_replay_discarded(const RamDiscardManager *rdm, + MemoryRegionSection *s, + ReplayRamDiscardState replay_fn, + void *opaque) { const VirtIOMEM *vmem =3D VIRTIO_MEM(rdm); struct VirtIOMEMReplayData data =3D { @@ -1780,8 +1779,8 @@ static void virtio_mem_rdm_replay_discarded(const Ram= DiscardManager *rdm, }; =20 g_assert(s->mr =3D=3D &vmem->memdev->mr); - virtio_mem_for_each_unplugged_section(vmem, s, &data, - virtio_mem_rdm_replay_discarded_= cb); + return virtio_mem_for_each_unplugged_section(vmem, s, &data, + virtio_mem_rdm_replay_dis= carded_cb); } =20 static void virtio_mem_rdm_register_listener(RamDiscardManager *rdm, diff --git a/include/system/memory.h b/include/system/memory.h index 896948deb1..83b28551c4 100644 --- a/include/system/memory.h +++ b/include/system/memory.h @@ -575,8 +575,8 @@ static inline void ram_discard_listener_init(RamDiscard= Listener *rdl, rdl->double_discard_supported =3D double_discard_supported; } =20 -typedef int (*ReplayRamPopulate)(MemoryRegionSection *section, void *opaqu= e); -typedef void (*ReplayRamDiscard)(MemoryRegionSection *section, void *opaqu= e); +typedef int (*ReplayRamDiscardState)(MemoryRegionSection *section, + void *opaque); =20 /* * RamDiscardManagerClass: @@ -650,36 +650,38 @@ struct RamDiscardManagerClass { /** * @replay_populated: * - * Call the #ReplayRamPopulate callback for all populated parts within= the - * #MemoryRegionSection via the #RamDiscardManager. + * Call the #ReplayRamDiscardState callback for all populated parts wi= thin + * the #MemoryRegionSection via the #RamDiscardManager. * * In case any call fails, no further calls are made. * * @rdm: the #RamDiscardManager * @section: the #MemoryRegionSection - * @replay_fn: the #ReplayRamPopulate callback + * @replay_fn: the #ReplayRamDiscardState callback * @opaque: pointer to forward to the callback * * Returns 0 on success, or a negative error if any notification faile= d. */ int (*replay_populated)(const RamDiscardManager *rdm, MemoryRegionSection *section, - ReplayRamPopulate replay_fn, void *opaque); + ReplayRamDiscardState replay_fn, void *opaque); =20 /** * @replay_discarded: * - * Call the #ReplayRamDiscard callback for all discarded parts within = the - * #MemoryRegionSection via the #RamDiscardManager. + * Call the #ReplayRamDiscardState callback for all discarded parts wi= thin + * the #MemoryRegionSection via the #RamDiscardManager. * * @rdm: the #RamDiscardManager * @section: the #MemoryRegionSection - * @replay_fn: the #ReplayRamDiscard callback + * @replay_fn: the #ReplayRamDiscardState callback * @opaque: pointer to forward to the callback + * + * Returns 0 on success, or a negative error if any notification faile= d. */ - void (*replay_discarded)(const RamDiscardManager *rdm, - MemoryRegionSection *section, - ReplayRamDiscard replay_fn, void *opaque); + int (*replay_discarded)(const RamDiscardManager *rdm, + MemoryRegionSection *section, + ReplayRamDiscardState replay_fn, void *opaque); =20 /** * @register_listener: @@ -722,13 +724,13 @@ bool ram_discard_manager_is_populated(const RamDiscar= dManager *rdm, =20 int ram_discard_manager_replay_populated(const RamDiscardManager *rdm, MemoryRegionSection *section, - ReplayRamPopulate replay_fn, + ReplayRamDiscardState replay_fn, void *opaque); =20 -void ram_discard_manager_replay_discarded(const RamDiscardManager *rdm, - MemoryRegionSection *section, - ReplayRamDiscard replay_fn, - void *opaque); +int ram_discard_manager_replay_discarded(const RamDiscardManager *rdm, + MemoryRegionSection *section, + ReplayRamDiscardState replay_fn, + void *opaque); =20 void ram_discard_manager_register_listener(RamDiscardManager *rdm, RamDiscardListener *rdl, diff --git a/migration/ram.c b/migration/ram.c index e12913b43e..c004f37060 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -848,8 +848,8 @@ static inline bool migration_bitmap_clear_dirty(RAMStat= e *rs, return ret; } =20 -static void dirty_bitmap_clear_section(MemoryRegionSection *section, - void *opaque) +static int dirty_bitmap_clear_section(MemoryRegionSection *section, + void *opaque) { const hwaddr offset =3D section->offset_within_region; const hwaddr size =3D int128_get64(section->size); @@ -868,6 +868,7 @@ static void dirty_bitmap_clear_section(MemoryRegionSect= ion *section, } *cleared_bits +=3D bitmap_count_one_with_offset(rb->bmap, start, npage= s); bitmap_clear(rb->bmap, start, npages); + return 0; } =20 /* diff --git a/system/memory.c b/system/memory.c index b45b508dce..de45fbdd3f 100644 --- a/system/memory.c +++ b/system/memory.c @@ -2138,7 +2138,7 @@ bool ram_discard_manager_is_populated(const RamDiscar= dManager *rdm, =20 int ram_discard_manager_replay_populated(const RamDiscardManager *rdm, MemoryRegionSection *section, - ReplayRamPopulate replay_fn, + ReplayRamDiscardState replay_fn, void *opaque) { RamDiscardManagerClass *rdmc =3D RAM_DISCARD_MANAGER_GET_CLASS(rdm); @@ -2147,15 +2147,15 @@ int ram_discard_manager_replay_populated(const RamD= iscardManager *rdm, return rdmc->replay_populated(rdm, section, replay_fn, opaque); } =20 -void ram_discard_manager_replay_discarded(const RamDiscardManager *rdm, - MemoryRegionSection *section, - ReplayRamDiscard replay_fn, - void *opaque) +int ram_discard_manager_replay_discarded(const RamDiscardManager *rdm, + MemoryRegionSection *section, + ReplayRamDiscardState replay_fn, + void *opaque) { RamDiscardManagerClass *rdmc =3D RAM_DISCARD_MANAGER_GET_CLASS(rdm); =20 g_assert(rdmc->replay_discarded); - rdmc->replay_discarded(rdm, section, replay_fn, opaque); + return rdmc->replay_discarded(rdm, section, replay_fn, opaque); } =20 void ram_discard_manager_register_listener(RamDiscardManager *rdm, --=20 2.43.5 From nobody Sat Nov 15 20:50:02 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1747737062; cv=none; d=zohomail.com; s=zohoarc; b=DAq4v5pslcTLz0uDOVGttwDWoI7KJCznQVu6QK1/Y47bjqPGWhvHYh+U+u1c0C2C3Y9XZCflrtMhkHJ7F0dcYHypZTcHLWN7c+cnnHnLsb+D0MWVu1sfjvgK7ZY+iJEOHlF1nsyooewJyNrQcMliFCslVdmGm5pbvbWvare6KCU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1747737062; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=MSz/0QPcbk80DOFi2YSnEeu/Rv7riMpPXtvz+oN2Occ=; b=EmDjqX8mKj9ywdOokbvYwtucV4IC7P5P9u3QSa6fkj9ZoXn2cy+eOW0dlQoQlWqE3Ci3gLl0CtPbHKuA6uLfFTOMgoeiomfKjN5rNM8l0pRNsjszpxNteiJfcI1Zu1AIRxEXztibq2lMZIQiP5MSeagN5OHKxS7Qyy/kmQvQa8Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1747737062870164.34459468553712; Tue, 20 May 2025 03:31:02 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHKDx-0004jJ-Q0; Tue, 20 May 2025 06:29: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 1uHKDu-0004dT-Tl for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:26 -0400 Received: from mgamail.intel.com ([198.175.65.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uHKDr-0004gB-Ft for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:26 -0400 Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:19 -0700 Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:15 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747736964; x=1779272964; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8c4TeopTLUWlOA2yHdqDsJj+x3XUBu597J4JC9hu9Wc=; b=B4UagtcluSXGlhdriqvCkaCs6CYJwMC60hYccTfurlyIe/hpY3q3lzH6 cRRblNh1KqiFHKoAfOuDohJwZH4jeAS5KJhoaBwfazK0kDy5GPrpIpqHX 2lTarRybkrBKk3TpkUlyTHvitE7HZt8b38Tcouqtw8WMM7i33XxucMBAy 2K2urLBvzlWGFEV1tN9OKHgeXBgSHxl4pBaMjJCCbJe118/kqskfxJdPY 99fMCt1grp4R+6ZbN97wdGBammhuvIr3CLSt1yu2Y4tTyagcmNdJ5WHBh KPVg2oJh73C4QAKjEkdzMyDvpyRXMPLfJ7FCXhzupoNp74cbittLMqT/b Q==; X-CSE-ConnectionGUID: vDfeLkl3QTSJ5cXOpgFvcw== X-CSE-MsgGUID: yRyelhuuQ0aboiNgATY1HQ== X-IronPort-AV: E=McAfee;i="6700,10204,11438"; a="49566655" X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="49566655" X-CSE-ConnectionGUID: rd3D3QsJTMmOts5oDKPumw== X-CSE-MsgGUID: rd/r1JwwQSW8T+ez4mF8rQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="144905246" From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Gupta Pankaj , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Zhao Liu , Baolu Lu , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v5 04/10] ram-block-attribute: Introduce RamBlockAttribute to manage RAMBlock with guest_memfd Date: Tue, 20 May 2025 18:28:44 +0800 Message-ID: <20250520102856.132417-5-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250520102856.132417-1-chenyi.qiang@intel.com> References: <20250520102856.132417-1-chenyi.qiang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.21; envelope-from=chenyi.qiang@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.13, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1747737065003116600 Content-Type: text/plain; charset="utf-8" Commit 852f0048f3 ("RAMBlock: make guest_memfd require uncoordinated discard") highlighted that subsystems like VFIO may disable RAM block discard. However, guest_memfd relies on discard operations for page conversion between private and shared memory, potentially leading to stale IOMMU mapping issue when assigning hardware devices to confidential VMs via shared memory. To address this and allow shared device assignement, it is crucial to ensure VFIO system refresh its IOMMU mappings. RamDiscardManager is an existing interface (used by virtio-mem) to adjust VFIO mappings in relation to VM page assignment. Effectively page conversion is similar to hot-removing a page in one mode and adding it back in the other. Therefore, similar actions are required for page conversion events. Introduce the RamDiscardManager to guest_memfd to facilitate this process. Since guest_memfd is not an object, it cannot directly implement the RamDiscardManager interface. Implementing it in HostMemoryBackend is not appropriate because guest_memfd is per RAMBlock, and some RAMBlocks have a memory backend while others do not. Notably, virtual BIOS RAMBlocks using memory_region_init_ram_guest_memfd() do not have a backend. To manage RAMBlocks with guest_memfd, define a new object named RamBlockAttribute to implement the RamDiscardManager interface. This object can store the guest_memfd information such as bitmap for shared memory, and handles page conversion notification. In the context of RamDiscardManager, shared state is analogous to populated and private state is treated as discard. The memory state is tracked at the host page size granularity, as minimum memory conversion size can be one page per request. Additionally, VFIO expects the DMA mapping for a specific iova to be mapped and unmapped with the same granularity. Confidential VMs may perform partial conversions, such as conversions on small regions within larger regions. To prevent such invalid cases and until cut_mapping operation support is available, all operations are performed with 4K granularity. Signed-off-by: Chenyi Qiang --- Changes in v5: - Revert to use RamDiscardManager interface instead of introducing new hierarchy of class to manage private/shared state, and keep using the new name of RamBlockAttribute compared with the MemoryAttributeManager in v3. - Use *simple* version of object_define and object_declare since the state_change() function is changed as an exported function instead of a virtual function in later patch. - Move the introduction of RamBlockAttribute field to this patch and rename it to ram_shared. (Alexey) - call the exit() when register/unregister failed. (Zhao) - Add the ram-block-attribute.c to Memory API related part in MAINTAINERS. Changes in v4: - Change the name from memory-attribute-manager to ram-block-attribute. - Implement the newly-introduced PrivateSharedManager instead of RamDiscardManager and change related commit message. - Define the new object in ramblock.h instead of adding a new file. Changes in v3: - Some rename (bitmap_size->shared_bitmap_size, first_one/zero_bit->first_bit, etc.) - Change shared_bitmap_size from uint32_t to unsigned - Return mgr->mr->ram_block->page_size in get_block_size() - Move set_ram_discard_manager() up to avoid a g_free() in failure case. - Add const for the memory_attribute_manager_get_block_size() - Unify the ReplayRamPopulate and ReplayRamDiscard and related callback. Changes in v2: - Rename the object name to MemoryAttributeManager - Rename the bitmap to shared_bitmap to make it more clear. - Remove block_size field and get it from a helper. In future, we can get the page_size from RAMBlock if necessary. - Remove the unncessary "struct" before GuestMemfdReplayData - Remove the unncessary g_free() for the bitmap - Add some error report when the callback failure for populated/discarded section. - Move the realize()/unrealize() definition to this patch. --- MAINTAINERS | 1 + include/system/ramblock.h | 20 +++ system/meson.build | 1 + system/ram-block-attribute.c | 311 +++++++++++++++++++++++++++++++++++ 4 files changed, 333 insertions(+) create mode 100644 system/ram-block-attribute.c diff --git a/MAINTAINERS b/MAINTAINERS index 6dacd6d004..3b4947dc74 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3149,6 +3149,7 @@ F: system/memory.c F: system/memory_mapping.c F: system/physmem.c F: system/memory-internal.h +F: system/ram-block-attribute.c F: scripts/coccinelle/memory-region-housekeeping.cocci =20 Memory devices diff --git a/include/system/ramblock.h b/include/system/ramblock.h index d8a116ba99..09255e8495 100644 --- a/include/system/ramblock.h +++ b/include/system/ramblock.h @@ -22,6 +22,10 @@ #include "exec/cpu-common.h" #include "qemu/rcu.h" #include "exec/ramlist.h" +#include "system/hostmem.h" + +#define TYPE_RAM_BLOCK_ATTRIBUTE "ram-block-attribute" +OBJECT_DECLARE_SIMPLE_TYPE(RamBlockAttribute, RAM_BLOCK_ATTRIBUTE) =20 struct RAMBlock { struct rcu_head rcu; @@ -42,6 +46,8 @@ struct RAMBlock { int fd; uint64_t fd_offset; int guest_memfd; + /* 1-setting of the bitmap in ram_shared represents ram is shared */ + RamBlockAttribute *ram_shared; size_t page_size; /* dirty bitmap used during migration */ unsigned long *bmap; @@ -91,4 +97,18 @@ struct RAMBlock { ram_addr_t postcopy_length; }; =20 +struct RamBlockAttribute { + Object parent; + + MemoryRegion *mr; + + unsigned bitmap_size; + unsigned long *bitmap; + + QLIST_HEAD(, RamDiscardListener) rdl_list; +}; + +RamBlockAttribute *ram_block_attribute_create(MemoryRegion *mr); +void ram_block_attribute_destroy(RamBlockAttribute *attr); + #endif diff --git a/system/meson.build b/system/meson.build index c2f0082766..107596ce86 100644 --- a/system/meson.build +++ b/system/meson.build @@ -17,6 +17,7 @@ libsystem_ss.add(files( 'dma-helpers.c', 'globals.c', 'ioport.c', + 'ram-block-attribute.c', 'memory_mapping.c', 'memory.c', 'physmem.c', diff --git a/system/ram-block-attribute.c b/system/ram-block-attribute.c new file mode 100644 index 0000000000..8d4a24738c --- /dev/null +++ b/system/ram-block-attribute.c @@ -0,0 +1,311 @@ +/* + * QEMU ram block attribute + * + * Copyright Intel + * + * Author: + * Chenyi Qiang + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory + * + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "system/ramblock.h" + +OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(RamBlockAttribute, + ram_block_attribute, + RAM_BLOCK_ATTRIBUTE, + OBJECT, + { TYPE_RAM_DISCARD_MANAGER }, + { }) + +static size_t ram_block_attribute_get_block_size(const RamBlockAttribute *= attr) +{ + /* + * Because page conversion could be manipulated in the size of at leas= t 4K + * or 4K aligned, Use the host page size as the granularity to track t= he + * memory attribute. + */ + g_assert(attr && attr->mr && attr->mr->ram_block); + g_assert(attr->mr->ram_block->page_size =3D=3D qemu_real_host_page_siz= e()); + return attr->mr->ram_block->page_size; +} + + +static bool +ram_block_attribute_rdm_is_populated(const RamDiscardManager *rdm, + const MemoryRegionSection *section) +{ + const RamBlockAttribute *attr =3D RAM_BLOCK_ATTRIBUTE(rdm); + const int block_size =3D ram_block_attribute_get_block_size(attr); + uint64_t first_bit =3D section->offset_within_region / block_size; + uint64_t last_bit =3D first_bit + int128_get64(section->size) / block_= size - 1; + unsigned long first_discard_bit; + + first_discard_bit =3D find_next_zero_bit(attr->bitmap, last_bit + 1, + first_bit); + return first_discard_bit > last_bit; +} + +typedef int (*ram_block_attribute_section_cb)(MemoryRegionSection *s, + void *arg); + +static int ram_block_attribute_notify_populate_cb(MemoryRegionSection *sec= tion, + void *arg) +{ + RamDiscardListener *rdl =3D arg; + + return rdl->notify_populate(rdl, section); +} + +static int ram_block_attribute_notify_discard_cb(MemoryRegionSection *sect= ion, + void *arg) +{ + RamDiscardListener *rdl =3D arg; + + rdl->notify_discard(rdl, section); + return 0; +} + +static int +ram_block_attribute_for_each_populated_section(const RamBlockAttribute *at= tr, + MemoryRegionSection *sectio= n, + void *arg, + ram_block_attribute_section= _cb cb) +{ + unsigned long first_bit, last_bit; + uint64_t offset, size; + const int block_size =3D ram_block_attribute_get_block_size(attr); + int ret =3D 0; + + first_bit =3D section->offset_within_region / block_size; + first_bit =3D find_next_bit(attr->bitmap, attr->bitmap_size, + first_bit); + + while (first_bit < attr->bitmap_size) { + MemoryRegionSection tmp =3D *section; + + offset =3D first_bit * block_size; + last_bit =3D find_next_zero_bit(attr->bitmap, attr->bitmap_size, + first_bit + 1) - 1; + size =3D (last_bit - first_bit + 1) * block_size; + + if (!memory_region_section_intersect_range(&tmp, offset, size)) { + break; + } + + ret =3D cb(&tmp, arg); + if (ret) { + error_report("%s: Failed to notify RAM discard listener: %s", + __func__, strerror(-ret)); + break; + } + + first_bit =3D find_next_bit(attr->bitmap, attr->bitmap_size, + last_bit + 2); + } + + return ret; +} + +static int +ram_block_attribute_for_each_discard_section(const RamBlockAttribute *attr, + MemoryRegionSection *section, + void *arg, + ram_block_attribute_section_c= b cb) +{ + unsigned long first_bit, last_bit; + uint64_t offset, size; + const int block_size =3D ram_block_attribute_get_block_size(attr); + int ret =3D 0; + + first_bit =3D section->offset_within_region / block_size; + first_bit =3D find_next_zero_bit(attr->bitmap, attr->bitmap_size, + first_bit); + + while (first_bit < attr->bitmap_size) { + MemoryRegionSection tmp =3D *section; + + offset =3D first_bit * block_size; + last_bit =3D find_next_bit(attr->bitmap, attr->bitmap_size, + first_bit + 1) - 1; + size =3D (last_bit - first_bit + 1) * block_size; + + if (!memory_region_section_intersect_range(&tmp, offset, size)) { + break; + } + + ret =3D cb(&tmp, arg); + if (ret) { + error_report("%s: Failed to notify RAM discard listener: %s", + __func__, strerror(-ret)); + break; + } + + first_bit =3D find_next_zero_bit(attr->bitmap, + attr->bitmap_size, + last_bit + 2); + } + + return ret; +} + +static uint64_t +ram_block_attribute_rdm_get_min_granularity(const RamDiscardManager *rdm, + const MemoryRegion *mr) +{ + const RamBlockAttribute *attr =3D RAM_BLOCK_ATTRIBUTE(rdm); + + g_assert(mr =3D=3D attr->mr); + return ram_block_attribute_get_block_size(attr); +} + +static void +ram_block_attribute_rdm_register_listener(RamDiscardManager *rdm, + RamDiscardListener *rdl, + MemoryRegionSection *section) +{ + RamBlockAttribute *attr =3D RAM_BLOCK_ATTRIBUTE(rdm); + int ret; + + g_assert(section->mr =3D=3D attr->mr); + rdl->section =3D memory_region_section_new_copy(section); + + QLIST_INSERT_HEAD(&attr->rdl_list, rdl, next); + + ret =3D ram_block_attribute_for_each_populated_section(attr, section, = rdl, + ram_block_attribute_notify_populate_cb= ); + if (ret) { + error_report("%s: Failed to register RAM discard listener: %s", + __func__, strerror(-ret)); + exit(1); + } +} + +static void +ram_block_attribute_rdm_unregister_listener(RamDiscardManager *rdm, + RamDiscardListener *rdl) +{ + RamBlockAttribute *attr =3D RAM_BLOCK_ATTRIBUTE(rdm); + int ret; + + g_assert(rdl->section); + g_assert(rdl->section->mr =3D=3D attr->mr); + + if (rdl->double_discard_supported) { + rdl->notify_discard(rdl, rdl->section); + } else { + ret =3D ram_block_attribute_for_each_populated_section(attr, + rdl->section, rdl, ram_block_attribute_notify_discard_cb); + if (ret) { + error_report("%s: Failed to unregister RAM discard listener: %= s", + __func__, strerror(-ret)); + exit(1); + } + } + + memory_region_section_free_copy(rdl->section); + rdl->section =3D NULL; + QLIST_REMOVE(rdl, next); +} + +typedef struct RamBlockAttributeReplayData { + ReplayRamDiscardState fn; + void *opaque; +} RamBlockAttributeReplayData; + +static int ram_block_attribute_rdm_replay_cb(MemoryRegionSection *section, + void *arg) +{ + RamBlockAttributeReplayData *data =3D arg; + + return data->fn(section, data->opaque); +} + +static int +ram_block_attribute_rdm_replay_populated(const RamDiscardManager *rdm, + MemoryRegionSection *section, + ReplayRamDiscardState replay_fn, + void *opaque) +{ + RamBlockAttribute *attr =3D RAM_BLOCK_ATTRIBUTE(rdm); + RamBlockAttributeReplayData data =3D { .fn =3D replay_fn, .opaque =3D = opaque }; + + g_assert(section->mr =3D=3D attr->mr); + return ram_block_attribute_for_each_populated_section(attr, section, &= data, + ram_block_attribute_rdm_replay= _cb); +} + +static int +ram_block_attribute_rdm_replay_discard(const RamDiscardManager *rdm, + MemoryRegionSection *section, + ReplayRamDiscardState replay_fn, + void *opaque) +{ + RamBlockAttribute *attr =3D RAM_BLOCK_ATTRIBUTE(rdm); + RamBlockAttributeReplayData data =3D { .fn =3D replay_fn, .opaque =3D = opaque }; + + g_assert(section->mr =3D=3D attr->mr); + return ram_block_attribute_for_each_discard_section(attr, section, &da= ta, + ram_block_attribute_rdm_replay= _cb); +} + +RamBlockAttribute *ram_block_attribute_create(MemoryRegion *mr) +{ + uint64_t bitmap_size; + const int block_size =3D qemu_real_host_page_size(); + RamBlockAttribute *attr; + int ret; + + attr =3D RAM_BLOCK_ATTRIBUTE(object_new(TYPE_RAM_BLOCK_ATTRIBUTE)); + + attr->mr =3D mr; + ret =3D memory_region_set_ram_discard_manager(mr, RAM_DISCARD_MANAGER(= attr)); + if (ret) { + object_unref(OBJECT(attr)); + return NULL; + } + bitmap_size =3D ROUND_UP(mr->size, block_size) / block_size; + attr->bitmap_size =3D bitmap_size; + attr->bitmap =3D bitmap_new(bitmap_size); + + return attr; +} + +void ram_block_attribute_destroy(RamBlockAttribute *attr) +{ + if (!attr) { + return; + } + + g_free(attr->bitmap); + memory_region_set_ram_discard_manager(attr->mr, NULL); + object_unref(OBJECT(attr)); +} + +static void ram_block_attribute_init(Object *obj) +{ + RamBlockAttribute *attr =3D RAM_BLOCK_ATTRIBUTE(obj); + + QLIST_INIT(&attr->rdl_list); +} + +static void ram_block_attribute_finalize(Object *obj) +{ +} + +static void ram_block_attribute_class_init(ObjectClass *klass, + const void *data) +{ + RamDiscardManagerClass *rdmc =3D RAM_DISCARD_MANAGER_CLASS(klass); + + rdmc->get_min_granularity =3D ram_block_attribute_rdm_get_min_granular= ity; + rdmc->register_listener =3D ram_block_attribute_rdm_register_listener; + rdmc->unregister_listener =3D ram_block_attribute_rdm_unregister_liste= ner; + rdmc->is_populated =3D ram_block_attribute_rdm_is_populated; + rdmc->replay_populated =3D ram_block_attribute_rdm_replay_populated; + rdmc->replay_discarded =3D ram_block_attribute_rdm_replay_discard; +} --=20 2.43.5 From nobody Sat Nov 15 20:50:02 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1747737293; cv=none; d=zohomail.com; s=zohoarc; b=DRhV0SVDWWqdla2CUN9QwUcjhXOhvq7r+x97Ui2VhPA/Xqy3JNYq01H9q918WzHdauzs8+ovRxHRKq4GyN9Nv5EEqHTBSz4VGf+nVG/6/iWAn0586XInjWp59jfI+IYANHw16IqlE42Z6lQuZvD6jvzjHHWkiMbzpQ8neoH/xIY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1747737293; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=nPV1y9LcVC+9/a762RgbeSBqDYj+Del8OfGJBFq986Q=; b=ixZU2y1UKIo+7VTjeIHEuH0oOWciAP9nU+wGnAWIK6VuggQquxvBUO9axH4UehwMeXiJGwy43Vk2m0ElvYHbHteztBx/8TS1cfVdT2VUSXuBIhACyu8PLQoUlDJSSzSgcjJcNoGiqxj7mXwLmQrE+8JJLYz2HCFz+tlK5VS4DPk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1747737293938884.463546614705; Tue, 20 May 2025 03:34:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHKDz-0004kw-0E; Tue, 20 May 2025 06:29:31 -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 1uHKDv-0004hE-TS for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:28 -0400 Received: from mgamail.intel.com ([198.175.65.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uHKDs-0004hJ-Il for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:27 -0400 Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:23 -0700 Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:19 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747736965; x=1779272965; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xjsSyyH/vKZhnfoKeplftZcDafjUAYrMzMyTUKLznE8=; b=lWmdQWxvxS+TbNqdDd11iSL0EkipB1RW9Yv7PAGFEbET1cgDaR1YL1uW vdOqWowkihjlmj1o0fhbyT78CUMbrfYHMgcOGDEuiL6cMQn0jhHV1Sc3O w8NV4q9gEWA8lgJpE7CXq2AF+NlIQHX0AstB2OnFV6BRZTTBVDXtfKPjD Rlg8f2U2S+yjhyZifJAet0lRzyxoAkHHFacbJJb2tcvpFem0DisFh1A7L 89Qf3KtMULRye6iQIQjd3H2O8VmYDpfRmeKtlpMGvNUFRTPA+glOVNm2l fqg+Tp2Sofr3Zfu3MA9axJ20Mt7xfHN5DacnWLx0A9SwvE+wkyIOCLOdu A==; X-CSE-ConnectionGUID: pCEouSRHTJ6sup4l4SPq4Q== X-CSE-MsgGUID: qj+XW3upRUqc/LoZTa8C7A== X-IronPort-AV: E=McAfee;i="6700,10204,11438"; a="49566661" X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="49566661" X-CSE-ConnectionGUID: Lph/xiMcRAauSxFu6majOw== X-CSE-MsgGUID: gmuyuwicRxWHnua84DPXKA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="144905255" From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Gupta Pankaj , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Zhao Liu , Baolu Lu , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v5 05/10] ram-block-attribute: Introduce a helper to notify shared/private state changes Date: Tue, 20 May 2025 18:28:45 +0800 Message-ID: <20250520102856.132417-6-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250520102856.132417-1-chenyi.qiang@intel.com> References: <20250520102856.132417-1-chenyi.qiang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.21; envelope-from=chenyi.qiang@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.13, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1747737295513116600 Content-Type: text/plain; charset="utf-8" A new state_change() helper is introduced for RamBlockAttribute to efficiently notify all registered RamDiscardListeners, including VFIO listeners, about memory conversion events in guest_memfd. The VFIO listener can dynamically DMA map/unmap shared pages based on conversion types: - For conversions from shared to private, the VFIO system ensures the discarding of shared mapping from the IOMMU. - For conversions from private to shared, it triggers the population of the shared mapping into the IOMMU. Currently, memory conversion failures cause QEMU to quit instead of resuming the guest or retrying the operation. It would be a future work to add more error handling or rollback mechanisms once conversion failures are allowed. For example, in-place conversion of guest_memfd could retry the unmap operation during the conversion from shared to private. However, for now, keep the complex error handling out of the picture as it is not required: - If a conversion request is made for a page already in the desired state, the helper simply returns success. - For requests involving a range partially in the desired state, there is no such scenario in practice at present. Simply return error. - If a conversion request is declined by other systems, such as a failure from VFIO during notify_to_populated(), the failure is returned directly. As for notify_to_discard(), VFIO cannot fail unmap/unpin, so no error is returned. Note that the bitmap status is updated before callbacks, allowing listeners to handle memory based on the latest status. Signed-off-by: Chenyi Qiang --- Change in v5: - Move the state_change() back to a helper instead of a callback of the class since there's no child for the RamBlockAttributeClass. - Remove the error handling and move them to an individual patch for simple management. Changes in v4: - Add the state_change() callback in PrivateSharedManagerClass instead of the RamBlockAttribute. Changes in v3: - Move the bitmap update before notifier callbacks. - Call the notifier callbacks directly in notify_discard/populate() with the expectation that the request memory range is in the desired attribute. - For the case that only partial range in the desire status, handle the range with block_size granularity for ease of rollback (https://lore.kernel.org/qemu-devel/812768d7-a02d-4b29-95f3-fb7a125cf= 54e@redhat.com/) Changes in v2: - Do the alignment changes due to the rename to MemoryAttributeManager - Move the state_change() helper definition in this patch. --- include/system/ramblock.h | 2 + system/ram-block-attribute.c | 134 +++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) diff --git a/include/system/ramblock.h b/include/system/ramblock.h index 09255e8495..270dffb2f3 100644 --- a/include/system/ramblock.h +++ b/include/system/ramblock.h @@ -108,6 +108,8 @@ struct RamBlockAttribute { QLIST_HEAD(, RamDiscardListener) rdl_list; }; =20 +int ram_block_attribute_state_change(RamBlockAttribute *attr, uint64_t off= set, + uint64_t size, bool to_private); RamBlockAttribute *ram_block_attribute_create(MemoryRegion *mr); void ram_block_attribute_destroy(RamBlockAttribute *attr); =20 diff --git a/system/ram-block-attribute.c b/system/ram-block-attribute.c index 8d4a24738c..f12dd4b881 100644 --- a/system/ram-block-attribute.c +++ b/system/ram-block-attribute.c @@ -253,6 +253,140 @@ ram_block_attribute_rdm_replay_discard(const RamDisca= rdManager *rdm, ram_block_attribute_rdm_replay= _cb); } =20 +static bool ram_block_attribute_is_valid_range(RamBlockAttribute *attr, + uint64_t offset, uint64_t s= ize) +{ + MemoryRegion *mr =3D attr->mr; + + g_assert(mr); + + uint64_t region_size =3D memory_region_size(mr); + int block_size =3D ram_block_attribute_get_block_size(attr); + + if (!QEMU_IS_ALIGNED(offset, block_size)) { + return false; + } + if (offset + size < offset || !size) { + return false; + } + if (offset >=3D region_size || offset + size > region_size) { + return false; + } + return true; +} + +static void ram_block_attribute_notify_to_discard(RamBlockAttribute *attr, + uint64_t offset, + uint64_t size) +{ + RamDiscardListener *rdl; + + QLIST_FOREACH(rdl, &attr->rdl_list, next) { + MemoryRegionSection tmp =3D *rdl->section; + + if (!memory_region_section_intersect_range(&tmp, offset, size)) { + continue; + } + rdl->notify_discard(rdl, &tmp); + } +} + +static int +ram_block_attribute_notify_to_populated(RamBlockAttribute *attr, + uint64_t offset, uint64_t size) +{ + RamDiscardListener *rdl; + int ret =3D 0; + + QLIST_FOREACH(rdl, &attr->rdl_list, next) { + MemoryRegionSection tmp =3D *rdl->section; + + if (!memory_region_section_intersect_range(&tmp, offset, size)) { + continue; + } + ret =3D rdl->notify_populate(rdl, &tmp); + if (ret) { + break; + } + } + + return ret; +} + +static bool ram_block_attribute_is_range_populated(RamBlockAttribute *attr, + uint64_t offset, + uint64_t size) +{ + const int block_size =3D ram_block_attribute_get_block_size(attr); + const unsigned long first_bit =3D offset / block_size; + const unsigned long last_bit =3D first_bit + (size / block_size) - 1; + unsigned long found_bit; + + /* We fake a shorter bitmap to avoid searching too far. */ + found_bit =3D find_next_zero_bit(attr->bitmap, last_bit + 1, + first_bit); + return found_bit > last_bit; +} + +static bool +ram_block_attribute_is_range_discard(RamBlockAttribute *attr, + uint64_t offset, uint64_t size) +{ + const int block_size =3D ram_block_attribute_get_block_size(attr); + const unsigned long first_bit =3D offset / block_size; + const unsigned long last_bit =3D first_bit + (size / block_size) - 1; + unsigned long found_bit; + + /* We fake a shorter bitmap to avoid searching too far. */ + found_bit =3D find_next_bit(attr->bitmap, last_bit + 1, first_bit); + return found_bit > last_bit; +} + +int ram_block_attribute_state_change(RamBlockAttribute *attr, uint64_t off= set, + uint64_t size, bool to_private) +{ + const int block_size =3D ram_block_attribute_get_block_size(attr); + const unsigned long first_bit =3D offset / block_size; + const unsigned long nbits =3D size / block_size; + int ret =3D 0; + + if (!ram_block_attribute_is_valid_range(attr, offset, size)) { + error_report("%s, invalid range: offset 0x%lx, size 0x%lx", + __func__, offset, size); + return -1; + } + + /* Already discard/populated */ + if ((ram_block_attribute_is_range_discard(attr, offset, size) && + to_private) || + (ram_block_attribute_is_range_populated(attr, offset, size) && + !to_private)) { + return 0; + } + + /* Unexpected mixture */ + if ((!ram_block_attribute_is_range_populated(attr, offset, size) && + to_private) || + (!ram_block_attribute_is_range_discard(attr, offset, size) && + !to_private)) { + error_report("%s, the range is not all in the desired state: " + "(offset 0x%lx, size 0x%lx), %s", + __func__, offset, size, + to_private ? "private" : "shared"); + return -1; + } + + if (to_private) { + bitmap_clear(attr->bitmap, first_bit, nbits); + ram_block_attribute_notify_to_discard(attr, offset, size); + } else { + bitmap_set(attr->bitmap, first_bit, nbits); + ret =3D ram_block_attribute_notify_to_populated(attr, offset, size= ); + } + + return ret; +} + RamBlockAttribute *ram_block_attribute_create(MemoryRegion *mr) { uint64_t bitmap_size; --=20 2.43.5 From nobody Sat Nov 15 20:50:02 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1747737256; cv=none; d=zohomail.com; s=zohoarc; b=QOSxWkFw495PbHFinHDEcG+SVooe6wOf1Ytk/fJZZ8UbO1IrUEGqWHU6QPekbEJB0tsoMBIXnaluyuksHuno0xxAhJAeEJ5FyrwHP/JHy7YEFRKWFehfnjfgKI8H5f1WMHmXKS9KTFfF39NwFakm1QSn8zRwU8L0nnMYFoDtq7Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1747737256; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=8tVeY/8uunQGr6ombvp+C7gQx1BExLGFiZuMYbOG5IU=; b=Yv1qUkXFGbGRjI6bhn6SoOwQrysxJbCsEVUV3KGOaE9wss0n27nR5oEmzeEdmI7rPctDEO99Wn1bLLPYbMToYceelhhTZr/JxIkQY32MHSYNiEDo/nd3XvuWEeWRjGgTnj7VV52EG0NJ21dfBnuoDVb/wi7iGbrCQ5szRecshE8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1747737256316766.7122379859668; Tue, 20 May 2025 03:34:16 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHKDz-0004l1-Qe; Tue, 20 May 2025 06:29:31 -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 1uHKDx-0004jb-I7 for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:29 -0400 Received: from mgamail.intel.com ([198.175.65.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uHKDv-0004gB-CQ for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:29 -0400 Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:26 -0700 Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:22 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747736968; x=1779272968; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ZTijY9Sdopl8+Dse6K2gwMX4Z7V1NW/c8Gpa+JnYhEs=; b=Q4jvl9XCnKSl1a0qvVWN6KvhazYIsdUC7qS3yTvKnA34kAxXw+RG0fRE azOb1wO2ISAJ2DMUmLPYWCy3wDRdqePPGYm9AOPm/tu4TqXOUzEwLxqJy TrrFecbEIQpEEZkcXEehzYPpEXWyUttOCiHn6FrJipo4SlL5c/XpO3V3Y U/H77e2A3kFkxwqfqnh5XSZzhgh3DOM02BN5kV9UxY2z60CR+IXLivnYU nECv2lb53+9lRsSqz8/EQ8bzlAPNalthOSfiw+nbMTJA5r4DPmj4/D74R cAPLJgjGmxDIhfcrdmbAAic/R7wln56t6zPRjCAcpx/3t7zRIwR8IAVCT A==; X-CSE-ConnectionGUID: dGEZMmW3Q9ikvPD0tCc4Wg== X-CSE-MsgGUID: egUJm4yLT4GcXxrY8m4Dcg== X-IronPort-AV: E=McAfee;i="6700,10204,11438"; a="49566668" X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="49566668" X-CSE-ConnectionGUID: qH/3r4eJRWqXLyP4ArAIjw== X-CSE-MsgGUID: Dn1CjrlUSPixRMIoLxJdBw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="144905270" From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Gupta Pankaj , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Zhao Liu , Baolu Lu , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v5 06/10] memory: Attach RamBlockAttribute to guest_memfd-backed RAMBlocks Date: Tue, 20 May 2025 18:28:46 +0800 Message-ID: <20250520102856.132417-7-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250520102856.132417-1-chenyi.qiang@intel.com> References: <20250520102856.132417-1-chenyi.qiang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.21; envelope-from=chenyi.qiang@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.13, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1747737257077116600 Content-Type: text/plain; charset="utf-8" A new field, ram_shared, was introduced in RAMBlock to link to a RamBlockAttribute object, which centralizes all guest_memfd state information (such as fd and shared_bitmap) within a RAMBlock. Create and initialize the RamBlockAttribute object upon ram_block_add(). Meanwhile, register the object in the target RAMBlock's MemoryRegion. After that, guest_memfd-backed RAMBlock is associated with the RamDiscardManager interface, and the users will execute RamDiscardManager specific handling. For example, VFIO will register the RamDiscardListener as expected. The live migration path needs to be avoided since it is not supported yet in confidential VMs. Additionally, use the ram_block_attribute_state_change() helper to notify the registered RamDiscardListener of these changes. Signed-off-by: Chenyi Qiang --- Changes in v5: - Revert to use RamDiscardManager interface. - Move the object_new() into the ram_block_attribute_create() helper. - Add some check in migration path. Changes in v4: - Remove the replay operations for attribute changes which will be handled in a listener in following patches. - Add some comment in the error path of realize() to remind the future development of the unified error path. Changes in v3: - Use ram_discard_manager_reply_populated/discarded() to set the memory attribute and add the undo support if state_change() failed. - Didn't add Reviewed-by from Alexey due to the new changes in this commit. Changes in v2: - Introduce a new field memory_attribute_manager in RAMBlock. - Move the state_change() handling during page conversion in this patch. - Undo what we did if it fails to set. - Change the order of close(guest_memfd) and memory_attribute_manager c= leanup. --- accel/kvm/kvm-all.c | 9 +++++++++ migration/ram.c | 28 ++++++++++++++++++++++++++++ system/physmem.c | 14 ++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 51526d301b..2d7ecaeb6a 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3089,6 +3089,15 @@ int kvm_convert_memory(hwaddr start, hwaddr size, bo= ol to_private) addr =3D memory_region_get_ram_ptr(mr) + section.offset_within_region; rb =3D qemu_ram_block_from_host(addr, false, &offset); =20 + ret =3D ram_block_attribute_state_change(RAM_BLOCK_ATTRIBUTE(mr->rdm), + offset, size, to_private); + if (ret) { + error_report("Failed to notify the listener the state change of " + "(0x%"HWADDR_PRIx" + 0x%"HWADDR_PRIx") to %s", + start, size, to_private ? "private" : "shared"); + goto out_unref; + } + if (to_private) { if (rb->page_size !=3D qemu_real_host_page_size()) { /* diff --git a/migration/ram.c b/migration/ram.c index c004f37060..69c9a42f16 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -890,6 +890,13 @@ static uint64_t ramblock_dirty_bitmap_clear_discarded_= pages(RAMBlock *rb) =20 if (rb->mr && rb->bmap && memory_region_has_ram_discard_manager(rb->mr= )) { RamDiscardManager *rdm =3D memory_region_get_ram_discard_manager(r= b->mr); + + if (object_dynamic_cast(OBJECT(rdm), TYPE_RAM_BLOCK_ATTRIBUTE)) { + error_report("%s: Live migration for confidential VM is not " + "supported yet.", __func__); + exit(1); + } + MemoryRegionSection section =3D { .mr =3D rb->mr, .offset_within_region =3D 0, @@ -913,6 +920,13 @@ bool ramblock_page_is_discarded(RAMBlock *rb, ram_addr= _t start) { if (rb->mr && memory_region_has_ram_discard_manager(rb->mr)) { RamDiscardManager *rdm =3D memory_region_get_ram_discard_manager(r= b->mr); + + if (object_dynamic_cast(OBJECT(rdm), TYPE_RAM_BLOCK_ATTRIBUTE)) { + error_report("%s: Live migration for confidential VM is not " + "supported yet.", __func__); + exit(1); + } + MemoryRegionSection section =3D { .mr =3D rb->mr, .offset_within_region =3D start, @@ -1552,6 +1566,13 @@ static void ram_block_populate_read(RAMBlock *rb) */ if (rb->mr && memory_region_has_ram_discard_manager(rb->mr)) { RamDiscardManager *rdm =3D memory_region_get_ram_discard_manager(r= b->mr); + + if (object_dynamic_cast(OBJECT(rdm), TYPE_RAM_BLOCK_ATTRIBUTE)) { + error_report("%s: Live migration for confidential VM is not " + "supported yet.", __func__); + exit(1); + } + MemoryRegionSection section =3D { .mr =3D rb->mr, .offset_within_region =3D 0, @@ -1611,6 +1632,13 @@ static int ram_block_uffd_protect(RAMBlock *rb, int = uffd_fd) /* See ram_block_populate_read() */ if (rb->mr && memory_region_has_ram_discard_manager(rb->mr)) { RamDiscardManager *rdm =3D memory_region_get_ram_discard_manager(r= b->mr); + + if (object_dynamic_cast(OBJECT(rdm), TYPE_RAM_BLOCK_ATTRIBUTE)) { + error_report("%s: Live migration for confidential VM is not " + "supported yet.", __func__); + exit(1); + } + MemoryRegionSection section =3D { .mr =3D rb->mr, .offset_within_region =3D 0, diff --git a/system/physmem.c b/system/physmem.c index a8a9ca309e..f05f7ff09a 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -1931,6 +1931,19 @@ static void ram_block_add(RAMBlock *new_block, Error= **errp) goto out_free; } =20 + new_block->ram_shared =3D ram_block_attribute_create(new_block->mr= ); + if (!new_block->ram_shared) { + error_setg(errp, "Failed to create ram block attribute"); + /* + * The error path could be unified if the rest of ram_block_ad= d() + * ever develops a need to check for errors. + */ + close(new_block->guest_memfd); + ram_block_discard_require(false); + qemu_mutex_unlock_ramlist(); + goto out_free; + } + /* * Add a specific guest_memfd blocker if a generic one would not be * added by ram_block_add_cpr_blocker. @@ -2287,6 +2300,7 @@ static void reclaim_ramblock(RAMBlock *block) } =20 if (block->guest_memfd >=3D 0) { + ram_block_attribute_destroy(block->ram_shared); close(block->guest_memfd); ram_block_discard_require(false); } --=20 2.43.5 From nobody Sat Nov 15 20:50:02 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1747737272; cv=none; d=zohomail.com; s=zohoarc; b=b0Omw7nVTgej8iVKRauV6tJbp754CaIBLYHvGxYLNXR16XFKzxYIppVxIVCgO+rCIFJ1PCuPx+MoLHG90tYd9dzxKfAwEyCGU2lIsfFtC9Qw+TjVFQszpx+vgegRgV/Ck35+Thknrb2gu9pD9/Qpxq025fE2BOB50ruI/a8TL8c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1747737272; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=ws8yn2XK+FGIMloHmvQcv5p2n+MNV90sLCXg1J7bgKU=; b=LZiphVZ9vPcGsPcLzgO6JmRWBIq+q4qEhh9c+1P4H+O7nbpmvSFhBt8hEtuaU05OGaYA0ya2p7jPG+rs3N5cHpr9PrOFDlpFnlJocRLyF1kWmL3M946Hl6Jb8DiQYkdQGPaGoFhNVn1xqVngNeETNYP8R+WAFmfC2k51x/v39vU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1747737272797270.17667737277634; Tue, 20 May 2025 03:34:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHKE1-0004lu-Ml; Tue, 20 May 2025 06:29:33 -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 1uHKE0-0004lH-BI for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:32 -0400 Received: from mgamail.intel.com ([198.175.65.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uHKDy-0004gB-AW for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:31 -0400 Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:30 -0700 Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:26 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747736971; x=1779272971; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=OSuErpkqUJGssDM/2HKZwtfnarun4vbCQ+Y6deq9Hhs=; b=L0iuRGqCQW+CbkK1poDl2PKmnqRaCHcMhESyW44DbEJbLL6tIf8DW7XA kxgnC1SwfpYMH9nA3Ll0sHBtHiGK86a1I1iyHDithA7DWEn0U8HXeS5bn IMUOezIwMgElztEvAi3URAbszQhf0VXgC0hlhVUj2qCJ/ayE0yXXAYKsg p9Jl0P0LXUHdIOuzSqqbT905c3w2wZONEMU/HX1HwaX+CxPvNPQ8PdkGW UkzxCTWbrfByRxpt09VHfWUxemDNFDIS91eHBiSLfDVi2ZKgcKsCesOs/ eiH4VyFkCeAbji7WqsUBJ0PN7bCK45Ltq6PgcKsp8kvOpuXrK6fBTyRw0 Q==; X-CSE-ConnectionGUID: FaK9ZBqPQyee3EWrEJXV8Q== X-CSE-MsgGUID: fAwAET9lTN+r4fOO2e/TPQ== X-IronPort-AV: E=McAfee;i="6700,10204,11438"; a="49566675" X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="49566675" X-CSE-ConnectionGUID: TGNIopkFRjSHPyy6DQtU4A== X-CSE-MsgGUID: dLLYEA9gQ6iB4ii9cFAFGA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="144905289" From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Gupta Pankaj , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Zhao Liu , Baolu Lu , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v5 07/10] RAMBlock: Make guest_memfd require coordinate discard Date: Tue, 20 May 2025 18:28:47 +0800 Message-ID: <20250520102856.132417-8-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250520102856.132417-1-chenyi.qiang@intel.com> References: <20250520102856.132417-1-chenyi.qiang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.21; envelope-from=chenyi.qiang@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.13, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1747737274976116600 Content-Type: text/plain; charset="utf-8" As guest_memfd is now managed by RamBlockAttribute with RamDiscardManager, only block uncoordinated discard. Signed-off-by: Chenyi Qiang --- Changes in v5: - Revert to use RamDiscardManager. Changes in v4: - Modify commit message (RamDiscardManager->PrivateSharedManager). Changes in v3: - No change. Changes in v2: - Change the ram_block_discard_require(false) to ram_block_coordinated_discard_require(false). --- system/physmem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/physmem.c b/system/physmem.c index f05f7ff09a..58b7614660 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -1916,7 +1916,7 @@ static void ram_block_add(RAMBlock *new_block, Error = **errp) } assert(new_block->guest_memfd < 0); =20 - ret =3D ram_block_discard_require(true); + ret =3D ram_block_coordinated_discard_require(true); if (ret < 0) { error_setg_errno(errp, -ret, "cannot set up private guest memory: discard = currently blocked"); @@ -1939,7 +1939,7 @@ static void ram_block_add(RAMBlock *new_block, Error = **errp) * ever develops a need to check for errors. */ close(new_block->guest_memfd); - ram_block_discard_require(false); + ram_block_coordinated_discard_require(false); qemu_mutex_unlock_ramlist(); goto out_free; } @@ -2302,7 +2302,7 @@ static void reclaim_ramblock(RAMBlock *block) if (block->guest_memfd >=3D 0) { ram_block_attribute_destroy(block->ram_shared); close(block->guest_memfd); - ram_block_discard_require(false); + ram_block_coordinated_discard_require(false); } =20 g_free(block); --=20 2.43.5 From nobody Sat Nov 15 20:50:02 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1747737029; cv=none; d=zohomail.com; s=zohoarc; b=F2yClSjc90rO619JWQbLF9xqDFC23aD/IGJP4qnuu1Kg1mP38zV/O3RlB/LoGf+5domfAKkwrFkm/AuoK95bIngyaTTFa8vUBAP/xwnjMb0JzTDksRzbLrTyN7eIR+MHTa0qUCse1GlBvT/RnHrnCk5/DihlywXJikmiXCUFy1Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1747737029; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Fxn3ciiAnXGKExAIk1dESgiMFUyTmgo2M7wa5Rye64U=; b=ZvtQ/mUngjVk4CD4wB8kdOoHM2gqxDl0XpMW52dOVjt2SP1K98FFyfaRJB37DolF+4R9fPP5x44boTt1ZTOSSeT7oeH2nTx++JA4ZHvLZnAXUbT/UeNWOYlTOonicS52b9lt2pw5ULvPUoxVDurlo8gAOSVF94hIKFqfW/nUYfQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1747737029987173.13123493534454; Tue, 20 May 2025 03:30:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHKE5-0004mx-G3; Tue, 20 May 2025 06:29:37 -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 1uHKE3-0004mk-Sm for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:35 -0400 Received: from mgamail.intel.com ([198.175.65.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uHKE1-0004gB-US for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:35 -0400 Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:34 -0700 Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:30 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747736974; x=1779272974; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=OTa0g2q+m0xONAZ985oRQ8DaRJiUFsfwCwbWIOiPDSE=; b=io881stpj2+Cy1W8gnutmmBl3XYWq4Ato45kSPl68AtVEzeJCFv2zEh5 kZQHmWcv0idcOOsQ4DOCydbeEr+QrCgPv0YuW5P1xPMmyKzJd+7PESw76 1OGItSc34l1Lp2lpjBIs8zNhBSTgdKmDNh+KEf9oZ2TQE+96SONknRSoR uM23QwVbEWhWhWwNLmLJ5GRIqg5E0WM0wsOB0UZWFboFS/ikcvdzciYUc Jko15nRP9GQvuIEXft5y8AHH0WiKOk1nb6+XHlLBaMfR3+u82GTYupKaP dVyDY24nccKqa6FQSLy1xrYubvPMV6f+Lo9COrTlOiO4jvRtTR9kdfydo A==; X-CSE-ConnectionGUID: lcx5nT/+RoOlCK93G0AcxA== X-CSE-MsgGUID: nwDYdWHrQiOIUK+BmlQjPA== X-IronPort-AV: E=McAfee;i="6700,10204,11438"; a="49566681" X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="49566681" X-CSE-ConnectionGUID: j9eFD9hUQnubW4cm6fpS2Q== X-CSE-MsgGUID: Vyb9SCSARHefsgMJnbyKSg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="144905299" From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Gupta Pankaj , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Zhao Liu , Baolu Lu , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v5 08/10] memory: Change NotifyRamDiscard() definition to return the result Date: Tue, 20 May 2025 18:28:48 +0800 Message-ID: <20250520102856.132417-9-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250520102856.132417-1-chenyi.qiang@intel.com> References: <20250520102856.132417-1-chenyi.qiang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.21; envelope-from=chenyi.qiang@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.13, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1747737034409116600 Content-Type: text/plain; charset="utf-8" So that the caller can check the result of NotifyRamDiscard() handler if the operation fails. Signed-off-by: Chenyi Qiang --- Changes in v5: - Revert to use of NotifyRamDiscard() Changes in v4: - Newly added. --- hw/vfio/listener.c | 6 ++++-- include/system/memory.h | 4 ++-- system/ram-block-attribute.c | 3 +-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/vfio/listener.c b/hw/vfio/listener.c index bfacb3d8d9..06454e0584 100644 --- a/hw/vfio/listener.c +++ b/hw/vfio/listener.c @@ -190,8 +190,8 @@ out: rcu_read_unlock(); } =20 -static void vfio_ram_discard_notify_discard(RamDiscardListener *rdl, - MemoryRegionSection *section) +static int vfio_ram_discard_notify_discard(RamDiscardListener *rdl, + MemoryRegionSection *section) { VFIORamDiscardListener *vrdl =3D container_of(rdl, VFIORamDiscardListe= ner, listener); @@ -206,6 +206,8 @@ static void vfio_ram_discard_notify_discard(RamDiscardL= istener *rdl, error_report("%s: vfio_container_dma_unmap() failed: %s", __func__, strerror(-ret)); } + + return ret; } =20 static int vfio_ram_discard_notify_populate(RamDiscardListener *rdl, diff --git a/include/system/memory.h b/include/system/memory.h index 83b28551c4..e5155120d9 100644 --- a/include/system/memory.h +++ b/include/system/memory.h @@ -518,8 +518,8 @@ struct IOMMUMemoryRegionClass { typedef struct RamDiscardListener RamDiscardListener; typedef int (*NotifyRamPopulate)(RamDiscardListener *rdl, MemoryRegionSection *section); -typedef void (*NotifyRamDiscard)(RamDiscardListener *rdl, - MemoryRegionSection *section); +typedef int (*NotifyRamDiscard)(RamDiscardListener *rdl, + MemoryRegionSection *section); =20 struct RamDiscardListener { /* diff --git a/system/ram-block-attribute.c b/system/ram-block-attribute.c index f12dd4b881..896c3d7543 100644 --- a/system/ram-block-attribute.c +++ b/system/ram-block-attribute.c @@ -66,8 +66,7 @@ static int ram_block_attribute_notify_discard_cb(MemoryRe= gionSection *section, { RamDiscardListener *rdl =3D arg; =20 - rdl->notify_discard(rdl, section); - return 0; + return rdl->notify_discard(rdl, section); } =20 static int --=20 2.43.5 From nobody Sat Nov 15 20:50:02 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1747737271; cv=none; d=zohomail.com; s=zohoarc; b=k3P47+YmM3sqCC3JJt2CTXItLxgqUK3cjdh2u9C6vM+lJzYr2dq6alIDBKXHjxnXpQaWmx71U/kfQPxQ0pq6rIEhC1yMOFNh2A9JgDg69qC7A2X17JKp/mpjLMtzLnF2m5aXNEPbvf7kvzpXgiKv2VgTfYnf4WqEA7rUm9ncMz4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1747737271; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=y+kMbcaCdRxqZSE1phWfd3EeqpMQsqgCqG0LJ4Zy1bE=; b=DtLzrweX6RQVY4asmMQ5RC8dV+9IT80uDLN56QWhaw8pM30EJkDvPe60xihlfjfWZnVORZJ6iCDshjBBmYh4QoEeha/E8Qw0s9wKCqhzrptcLJiFpL/F6gZRdqFeVdmGlEo1ZA4OJecKXLCdJHvtzgj+tANhgYCvnnmHY4D1oV8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1747737271500779.6799000595345; Tue, 20 May 2025 03:34:31 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHKEA-0004qt-9V; Tue, 20 May 2025 06:29:42 -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 1uHKE7-0004pZ-Sr for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:39 -0400 Received: from mgamail.intel.com ([198.175.65.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uHKE5-0004gB-QL for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:39 -0400 Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:37 -0700 Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:33 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747736978; x=1779272978; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=c1N/BnhvtWYzXYP3VrcMDboLZ9zphs865jcPHhFi2sw=; b=j3yp81sZtCNrJPpnxhOXMV4cm9zzvitcYB4a4h7fSMjC2ywXJmWwtQcK DfOJsMgO2dxrTs+Oisdtco3VfyXSn5SJcZpfFAkFoyg3/7PVMau2vfXiR v/Z3HaT1vuJKZC5JMFtqugHlmiWYJEtc8MhnXxWIHG6ie118VxxKKab/X qff4g8bDrlCoBIS99ZdFtib/CPdWkWDpol/R26y36eTTsQJDTwdKOX7v6 fAEbwm65b4Ug2SgbYuZduQYPzBGN7hrUIzNYAnB8mq8lpi/fCq3bKW5MQ IeOIQjpSphd1mOAdTDY8ZdmdvluZaErEfmg5p+TFk/b9GpI1Omjj/N/M3 Q==; X-CSE-ConnectionGUID: iv8TTyPMQwaUEqcOAZKzdQ== X-CSE-MsgGUID: rVEt6u2LT6qU/QAS2ahFOw== X-IronPort-AV: E=McAfee;i="6700,10204,11438"; a="49566690" X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="49566690" X-CSE-ConnectionGUID: etzM7wjhSOe99UPkIIO2gw== X-CSE-MsgGUID: /6/2X7WJQ7yE34EU3CQX6Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="144905316" From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Gupta Pankaj , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Zhao Liu , Baolu Lu , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v5 09/10] KVM: Introduce RamDiscardListener for attribute changes during memory conversions Date: Tue, 20 May 2025 18:28:49 +0800 Message-ID: <20250520102856.132417-10-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250520102856.132417-1-chenyi.qiang@intel.com> References: <20250520102856.132417-1-chenyi.qiang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.21; envelope-from=chenyi.qiang@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.13, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1747737273187116600 Content-Type: text/plain; charset="utf-8" With the introduction of the RamBlockAttribute object to manage RAMBlocks with guest_memfd, it is more elegant to move KVM set attribute into a RamDiscardListener. The KVM attribute change RamDiscardListener is registered/unregistered for each memory region section during kvm_region_add/del(). The listener handler performs attribute change upon receiving notifications from ram_block_attribute_state_change() calls. After this change, the operations in kvm_convert_memory() can be removed. Note that, errors can be returned in ram_block_attribute_notify_to_discard() by KVM attribute changes, although it is currently unlikely to happen. With in-place conversion guest_memfd in the future, it would be more likely to encounter errors and require error handling. For now, simply return the result, and kvm_convert_memory() will cause QEMU to quit if any issue arises. Signed-off-by: Chenyi Qiang --- Changes in v5: - Revert to use RamDiscardListener Changes in v4: - Newly added. --- accel/kvm/kvm-all.c | 72 ++++++++++++++++++--- include/system/confidential-guest-support.h | 9 +++ system/ram-block-attribute.c | 16 +++-- target/i386/kvm/tdx.c | 1 + target/i386/sev.c | 1 + 5 files changed, 85 insertions(+), 14 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 2d7ecaeb6a..ca4ef8062b 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -49,6 +49,7 @@ #include "kvm-cpus.h" #include "system/dirtylimit.h" #include "qemu/range.h" +#include "system/confidential-guest-support.h" =20 #include "hw/boards.h" #include "system/stats.h" @@ -1689,28 +1690,90 @@ static int kvm_dirty_ring_init(KVMState *s) return 0; } =20 +static int kvm_private_shared_notify(RamDiscardListener *rdl, + MemoryRegionSection *section, + bool to_private) +{ + hwaddr start =3D section->offset_within_address_space; + hwaddr size =3D section->size; + + if (to_private) { + return kvm_set_memory_attributes_private(start, size); + } else { + return kvm_set_memory_attributes_shared(start, size); + } +} + +static int kvm_ram_discard_notify_to_shared(RamDiscardListener *rdl, + MemoryRegionSection *section) +{ + return kvm_private_shared_notify(rdl, section, false); +} + +static int kvm_ram_discard_notify_to_private(RamDiscardListener *rdl, + MemoryRegionSection *section) +{ + return kvm_private_shared_notify(rdl, section, true); +} + static void kvm_region_add(MemoryListener *listener, MemoryRegionSection *section) { KVMMemoryListener *kml =3D container_of(listener, KVMMemoryListener, l= istener); + ConfidentialGuestSupport *cgs =3D MACHINE(qdev_get_machine())->cgs; + RamDiscardManager *rdm =3D memory_region_get_ram_discard_manager(secti= on->mr); KVMMemoryUpdate *update; + CGSRamDiscardListener *crdl; + RamDiscardListener *rdl; + =20 update =3D g_new0(KVMMemoryUpdate, 1); update->section =3D *section; =20 QSIMPLEQ_INSERT_TAIL(&kml->transaction_add, update, next); + + if (!memory_region_has_guest_memfd(section->mr) || !rdm) { + return; + } + + crdl =3D g_new0(CGSRamDiscardListener, 1); + crdl->mr =3D section->mr; + crdl->offset_within_address_space =3D section->offset_within_address_s= pace; + rdl =3D &crdl->listener; + QLIST_INSERT_HEAD(&cgs->cgs_rdl_list, crdl, next); + ram_discard_listener_init(rdl, kvm_ram_discard_notify_to_shared, + kvm_ram_discard_notify_to_private, true); + ram_discard_manager_register_listener(rdm, rdl, section); } =20 static void kvm_region_del(MemoryListener *listener, MemoryRegionSection *section) { KVMMemoryListener *kml =3D container_of(listener, KVMMemoryListener, l= istener); + ConfidentialGuestSupport *cgs =3D MACHINE(qdev_get_machine())->cgs; + RamDiscardManager *rdm =3D memory_region_get_ram_discard_manager(secti= on->mr); KVMMemoryUpdate *update; + CGSRamDiscardListener *crdl; + RamDiscardListener *rdl; =20 update =3D g_new0(KVMMemoryUpdate, 1); update->section =3D *section; =20 QSIMPLEQ_INSERT_TAIL(&kml->transaction_del, update, next); + if (!memory_region_has_guest_memfd(section->mr) || !rdm) { + return; + } + + QLIST_FOREACH(crdl, &cgs->cgs_rdl_list, next) { + if (crdl->mr =3D=3D section->mr && + crdl->offset_within_address_space =3D=3D section->offset_withi= n_address_space) { + rdl =3D &crdl->listener; + ram_discard_manager_unregister_listener(rdm, rdl); + QLIST_REMOVE(crdl, next); + g_free(crdl); + break; + } + } } =20 static void kvm_region_commit(MemoryListener *listener) @@ -3077,15 +3140,6 @@ int kvm_convert_memory(hwaddr start, hwaddr size, bo= ol to_private) goto out_unref; } =20 - if (to_private) { - ret =3D kvm_set_memory_attributes_private(start, size); - } else { - ret =3D kvm_set_memory_attributes_shared(start, size); - } - if (ret) { - goto out_unref; - } - addr =3D memory_region_get_ram_ptr(mr) + section.offset_within_region; rb =3D qemu_ram_block_from_host(addr, false, &offset); =20 diff --git a/include/system/confidential-guest-support.h b/include/system/c= onfidential-guest-support.h index ea46b50c56..974abdbf6b 100644 --- a/include/system/confidential-guest-support.h +++ b/include/system/confidential-guest-support.h @@ -19,12 +19,19 @@ #define QEMU_CONFIDENTIAL_GUEST_SUPPORT_H =20 #include "qom/object.h" +#include "system/memory.h" =20 #define TYPE_CONFIDENTIAL_GUEST_SUPPORT "confidential-guest-support" OBJECT_DECLARE_TYPE(ConfidentialGuestSupport, ConfidentialGuestSupportClass, CONFIDENTIAL_GUEST_SUPPORT) =20 +typedef struct CGSRamDiscardListener { + MemoryRegion *mr; + hwaddr offset_within_address_space; + RamDiscardListener listener; + QLIST_ENTRY(CGSRamDiscardListener) next; +} CGSRamDiscardListener; =20 struct ConfidentialGuestSupport { Object parent; @@ -34,6 +41,8 @@ struct ConfidentialGuestSupport { */ bool require_guest_memfd; =20 + QLIST_HEAD(, CGSRamDiscardListener) cgs_rdl_list; + /* * ready: flag set by CGS initialization code once it's ready to * start executing instructions in a potentially-secure diff --git a/system/ram-block-attribute.c b/system/ram-block-attribute.c index 896c3d7543..387501b569 100644 --- a/system/ram-block-attribute.c +++ b/system/ram-block-attribute.c @@ -274,11 +274,12 @@ static bool ram_block_attribute_is_valid_range(RamBlo= ckAttribute *attr, return true; } =20 -static void ram_block_attribute_notify_to_discard(RamBlockAttribute *attr, - uint64_t offset, - uint64_t size) +static int ram_block_attribute_notify_to_discard(RamBlockAttribute *attr, + uint64_t offset, + uint64_t size) { RamDiscardListener *rdl; + int ret =3D 0; =20 QLIST_FOREACH(rdl, &attr->rdl_list, next) { MemoryRegionSection tmp =3D *rdl->section; @@ -286,8 +287,13 @@ static void ram_block_attribute_notify_to_discard(RamB= lockAttribute *attr, if (!memory_region_section_intersect_range(&tmp, offset, size)) { continue; } - rdl->notify_discard(rdl, &tmp); + ret =3D rdl->notify_discard(rdl, &tmp); + if (ret) { + break; + } } + + return ret; } =20 static int @@ -377,7 +383,7 @@ int ram_block_attribute_state_change(RamBlockAttribute = *attr, uint64_t offset, =20 if (to_private) { bitmap_clear(attr->bitmap, first_bit, nbits); - ram_block_attribute_notify_to_discard(attr, offset, size); + ret =3D ram_block_attribute_notify_to_discard(attr, offset, size); } else { bitmap_set(attr->bitmap, first_bit, nbits); ret =3D ram_block_attribute_notify_to_populated(attr, offset, size= ); diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c index 7ef49690bd..17b360059c 100644 --- a/target/i386/kvm/tdx.c +++ b/target/i386/kvm/tdx.c @@ -1492,6 +1492,7 @@ static void tdx_guest_init(Object *obj) qemu_mutex_init(&tdx->lock); =20 cgs->require_guest_memfd =3D true; + QLIST_INIT(&cgs->cgs_rdl_list); tdx->attributes =3D TDX_TD_ATTRIBUTES_SEPT_VE_DISABLE; =20 object_property_add_uint64_ptr(obj, "attributes", &tdx->attributes, diff --git a/target/i386/sev.c b/target/i386/sev.c index adf787797e..f1b9c35fc3 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -2430,6 +2430,7 @@ sev_snp_guest_instance_init(Object *obj) SevSnpGuestState *sev_snp_guest =3D SEV_SNP_GUEST(obj); =20 cgs->require_guest_memfd =3D true; + QLIST_INIT(&cgs->cgs_rdl_list); =20 /* default init/start/finish params for kvm */ sev_snp_guest->kvm_start_conf.policy =3D DEFAULT_SEV_SNP_POLICY; --=20 2.43.5 From nobody Sat Nov 15 20:50:02 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1747737040; cv=none; d=zohomail.com; s=zohoarc; b=GGLgDe7UGULRrtfp9stO0OtDof6UeyDvsTbTnQYVZglPXujrfOKHW4blKMce1hvBglFyHBqH3PO1udcP4a5nDtMNoxZiGjxtq+LSGZo78buHsH0Sj3flfudTZ9WHxjVKA7jCxkJE+fLpW2CMOeHrYoZLgA0q/ANup2iO3nlyr6o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1747737040; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=v/IEN/ihBc3umsKkYasbLdNymWK5PGcpsmNSVdhx/ho=; b=WF1cFRQGR4hvX1rf7WXlN5LbeU2aYkS/2Qtk9aaeRbb3Wsxphn7QafTGHdsCLpK1NWiFdU+wg6QS0CU0CCkqNK0NLBa6uP0gws/0SQY/uLhSRmouwaYYAcTr4Pyv1rcapYQxBnTcAkT3EsCpO5Wjm2nZuIpQ5HnRK4FwUpM6n8s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1747737040423682.3236667812306; Tue, 20 May 2025 03:30:40 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHKED-0004sG-A1; Tue, 20 May 2025 06:29:45 -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 1uHKEB-0004ri-Gi for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:43 -0400 Received: from mgamail.intel.com ([198.175.65.21]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uHKE9-0004gB-EL for qemu-devel@nongnu.org; Tue, 20 May 2025 06:29:43 -0400 Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:41 -0700 Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2025 03:29:37 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1747736982; x=1779272982; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=QVe4ZfDlF+KN1Ku+/Uhd92OOHuL5O75EpmRDC6Ka9Vw=; b=BeJw6H15kfjwYQ/pZ2EbLDv2BQUpF4Cj6xyqzFy+berkTGk8BFkw7hhd A/7tn+YaII0g4OZf90NqYpTsqQMJz4iCHq+p6uRfGOMGqP5fxYaN+gprC uvDB1+eCZvYn4VTj4nP+an36ZpTxWDLp+1nX9LXKlzxp7y5lnXqlmu/ZN GnBLOab5wkd4uyt4YDrXmx51BI8Xky3X+iotScLGrXT5nZdiJj3299F7I v2X4fuCDkqpxX0+TWjducKRV0OzHJmXt3i51pbe1LCGVv8aJXZJ1V1T1J TmrycVpFqI1TeYYKYai41Y16Nwzhxoa8jggMT9Y9iImYVFHALt3ibrI3v g==; X-CSE-ConnectionGUID: OdftwBB7Svq2Gc+Dr9TL2Q== X-CSE-MsgGUID: SHvZauM3Qqy9PBum6iA4ZQ== X-IronPort-AV: E=McAfee;i="6700,10204,11438"; a="49566697" X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="49566697" X-CSE-ConnectionGUID: HXt5MnjgSyC7CFljN6GtVg== X-CSE-MsgGUID: SuPLIgPaTYODvzo/5Z8fdQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,302,1739865600"; d="scan'208";a="144905325" From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Gupta Pankaj , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Zhao Liu , Baolu Lu , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v5 10/10] ram-block-attribute: Add more error handling during state changes Date: Tue, 20 May 2025 18:28:50 +0800 Message-ID: <20250520102856.132417-11-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250520102856.132417-1-chenyi.qiang@intel.com> References: <20250520102856.132417-1-chenyi.qiang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=198.175.65.21; envelope-from=chenyi.qiang@intel.com; helo=mgamail.intel.com X-Spam_score_int: -44 X-Spam_score: -4.5 X-Spam_bar: ---- X-Spam_report: (-4.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.13, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1747737042558116600 Content-Type: text/plain; charset="utf-8" The current error handling is simple with the following assumption: - QEMU will quit instead of resuming the guest if kvm_convert_memory() fails, thus no need to do rollback. - The convert range is required to be in the desired state. It is not allowed to handle the mixture case. - The conversion from shared to private is a non-failure operation. This is sufficient for now as complext error handling is not required. For future extension, add some potential error handling. - For private to shared conversion, do the rollback operation if ram_block_attribute_notify_to_populated() fails. - For shared to private conversion, still assert it as a non-failure operation for now. It could be an easy fail path with in-place conversion, which will likely have to retry the conversion until it works in the future. - For mixture case, process individual blocks for ease of rollback. Signed-off-by: Chenyi Qiang --- system/ram-block-attribute.c | 116 +++++++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 26 deletions(-) diff --git a/system/ram-block-attribute.c b/system/ram-block-attribute.c index 387501b569..0af3396aa4 100644 --- a/system/ram-block-attribute.c +++ b/system/ram-block-attribute.c @@ -289,7 +289,12 @@ static int ram_block_attribute_notify_to_discard(RamBl= ockAttribute *attr, } ret =3D rdl->notify_discard(rdl, &tmp); if (ret) { - break; + /* + * The current to_private listeners (VFIO dma_unmap and + * KVM set_attribute_private) are non-failing operations. + * TODO: add rollback operations if it is allowed to fail. + */ + g_assert(ret); } } =20 @@ -300,7 +305,7 @@ static int ram_block_attribute_notify_to_populated(RamBlockAttribute *attr, uint64_t offset, uint64_t size) { - RamDiscardListener *rdl; + RamDiscardListener *rdl, *rdl2; int ret =3D 0; =20 QLIST_FOREACH(rdl, &attr->rdl_list, next) { @@ -315,6 +320,20 @@ ram_block_attribute_notify_to_populated(RamBlockAttrib= ute *attr, } } =20 + if (ret) { + /* Notify all already-notified listeners. */ + QLIST_FOREACH(rdl2, &attr->rdl_list, next) { + MemoryRegionSection tmp =3D *rdl2->section; + + if (rdl =3D=3D rdl2) { + break; + } + if (!memory_region_section_intersect_range(&tmp, offset, size)= ) { + continue; + } + rdl2->notify_discard(rdl2, &tmp); + } + } return ret; } =20 @@ -353,6 +372,9 @@ int ram_block_attribute_state_change(RamBlockAttribute = *attr, uint64_t offset, const int block_size =3D ram_block_attribute_get_block_size(attr); const unsigned long first_bit =3D offset / block_size; const unsigned long nbits =3D size / block_size; + const uint64_t end =3D offset + size; + unsigned long bit; + uint64_t cur; int ret =3D 0; =20 if (!ram_block_attribute_is_valid_range(attr, offset, size)) { @@ -361,32 +383,74 @@ int ram_block_attribute_state_change(RamBlockAttribut= e *attr, uint64_t offset, return -1; } =20 - /* Already discard/populated */ - if ((ram_block_attribute_is_range_discard(attr, offset, size) && - to_private) || - (ram_block_attribute_is_range_populated(attr, offset, size) && - !to_private)) { - return 0; - } - - /* Unexpected mixture */ - if ((!ram_block_attribute_is_range_populated(attr, offset, size) && - to_private) || - (!ram_block_attribute_is_range_discard(attr, offset, size) && - !to_private)) { - error_report("%s, the range is not all in the desired state: " - "(offset 0x%lx, size 0x%lx), %s", - __func__, offset, size, - to_private ? "private" : "shared"); - return -1; - } - if (to_private) { - bitmap_clear(attr->bitmap, first_bit, nbits); - ret =3D ram_block_attribute_notify_to_discard(attr, offset, size); + if (ram_block_attribute_is_range_discard(attr, offset, size)) { + /* Already private */ + } else if (!ram_block_attribute_is_range_populated(attr, offset, + size)) { + /* Unexpected mixture: process individual blocks */ + for (cur =3D offset; cur < end; cur +=3D block_size) { + bit =3D cur / block_size; + if (!test_bit(bit, attr->bitmap)) { + continue; + } + clear_bit(bit, attr->bitmap); + ram_block_attribute_notify_to_discard(attr, cur, block_siz= e); + } + } else { + /* Completely shared */ + bitmap_clear(attr->bitmap, first_bit, nbits); + ram_block_attribute_notify_to_discard(attr, offset, size); + } } else { - bitmap_set(attr->bitmap, first_bit, nbits); - ret =3D ram_block_attribute_notify_to_populated(attr, offset, size= ); + if (ram_block_attribute_is_range_populated(attr, offset, size)) { + /* Already shared */ + } else if (!ram_block_attribute_is_range_discard(attr, offset, siz= e)) { + /* Unexpected mixture: process individual blocks */ + unsigned long *modified_bitmap =3D bitmap_new(nbits); + + for (cur =3D offset; cur < end; cur +=3D block_size) { + bit =3D cur / block_size; + if (test_bit(bit, attr->bitmap)) { + continue; + } + set_bit(bit, attr->bitmap); + ret =3D ram_block_attribute_notify_to_populated(attr, cur, + block_size); + if (!ret) { + set_bit(bit - first_bit, modified_bitmap); + continue; + } + clear_bit(bit, attr->bitmap); + break; + } + + if (ret) { + /* + * Very unexpected: something went wrong. Revert to the old + * state, marking only the blocks as private that we conve= rted + * to shared. + */ + for (cur =3D offset; cur < end; cur +=3D block_size) { + bit =3D cur / block_size; + if (!test_bit(bit - first_bit, modified_bitmap)) { + continue; + } + assert(test_bit(bit, attr->bitmap)); + clear_bit(bit, attr->bitmap); + ram_block_attribute_notify_to_discard(attr, cur, + block_size); + } + } + g_free(modified_bitmap); + } else { + /* Complete private */ + bitmap_set(attr->bitmap, first_bit, nbits); + ret =3D ram_block_attribute_notify_to_populated(attr, offset, = size); + if (ret) { + bitmap_clear(attr->bitmap, first_bit, nbits); + } + } } =20 return ret; --=20 2.43.5