From patchwork Mon Feb 17 08:18:20 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chenyi Qiang X-Patchwork-Id: 13977277 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B0293191F68 for ; Mon, 17 Feb 2025 08:18:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780333; cv=none; b=sTTFlMd64n0EQe4FY6xo/8RlT5PNIHv8C2ohZGazA3wP6LM5CoOSoZmAkSbXr9MVpG+9rY20RRbv0mEAjbKtXxx9G6sxA66W9kK4+wqGlff+XgDch/DcxhQSoyIceRKr1j5jqA3uWQm9l49LvzL3fCxP51G9bpakeeX/MXRiu90= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780333; c=relaxed/simple; bh=xqSOLjyi089bY2ndKhL6A+1UkPmyvIO0I3dcjqPvT+Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rO4+ptJNX5Bzm3C0XZywcZ2ZQha1sCiYlP/G5/Y3ecVkJuWelut+CkiHOzQ2+J+nFfieCuBgyjRyRV1M7uO/mHllcnQciy5B4ZupouUNfYbl784qQdXbmxc4MrAQZqv+urpTR7RlOgoJ6x8wj6DUtNbRnkiw2hoGhBsr2hW3aUM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=AM+APp6N; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="AM+APp6N" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1739780331; x=1771316331; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xqSOLjyi089bY2ndKhL6A+1UkPmyvIO0I3dcjqPvT+Q=; b=AM+APp6N8CqrI39hAeLWSIYB7q6/qy83UGdpZ4+Plwec1wW+6QFAnBch 91XJ57pkkW5pGwRaVQ6jIOvV7SJcF5+687fnx1NXx2fHwRZjMMVnbaWWi VDiZOLj3ZJa8QwnSW+WZv7+rYBQO+7goq7fHIuYxa3K1XhzsjIWMYoaqY MfBk59j7TnVHKRee7Uwcy2Uh18VujdUJ11qb5C0+sutBD/HexIeo+tzzk +VQh7rgBmyBTaqnNWZk2UqQVTuo+YqHspVUinruzN5yBRbVYB9kbiNbxX BfInAwchz/Mj5zEFV3cjq9B3JmSW+BteEYk85NT4jLYOM5ZbUeC2buXit Q==; X-CSE-ConnectionGUID: gGLUXB5aRLih0pH038Feiw== X-CSE-MsgGUID: QlPh+ZwKR1qFAFLnewl03g== X-IronPort-AV: E=McAfee;i="6700,10204,11347"; a="50668966" X-IronPort-AV: E=Sophos;i="6.13,292,1732608000"; d="scan'208";a="50668966" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:18:51 -0800 X-CSE-ConnectionGUID: vLkH71JoTcaZPs2UNAiUVA== X-CSE-MsgGUID: 7338LJpHQTO0rKHzS9lRAg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118690172" Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:18:48 -0800 From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Peng Chao P , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v2 1/6] memory: Export a helper to get intersection of a MemoryRegionSection with a given range Date: Mon, 17 Feb 2025 16:18:20 +0800 Message-ID: <20250217081833.21568-2-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250217081833.21568-1-chenyi.qiang@intel.com> References: <20250217081833.21568-1-chenyi.qiang@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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: David Hildenbrand Signed-off-by: Chenyi Qiang --- 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/exec/memory.h | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index b1a003736b..21f16e4912 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; } -/* - * Adjust the memory section to cover the intersection with the given range. - * - * 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 = MAX(s->offset_within_region, offset); - uint64_t end = MIN(s->offset_within_region + int128_get64(s->size), - offset + size); - - if (end <= start) { - return false; - } - - s->offset_within_address_space += start - s->offset_within_region; - s->offset_within_region = start; - s->size = int128_make64(end - start); - return true; -} - typedef int (*virtio_mem_section_cb)(MemoryRegionSection *s, void *arg); static int virtio_mem_for_each_plugged_section(const VirtIOMEM *vmem, @@ -287,7 +265,7 @@ static int virtio_mem_for_each_plugged_section(const VirtIOMEM *vmem, first_bit + 1) - 1; size = (last_bit - first_bit + 1) * vmem->block_size; - if (!virtio_mem_intersect_memory_section(&tmp, offset, size)) { + if (!memory_region_section_intersect_range(&tmp, offset, size)) { break; } ret = cb(&tmp, arg); @@ -319,7 +297,7 @@ static int virtio_mem_for_each_unplugged_section(const VirtIOMEM *vmem, first_bit + 1) - 1; size = (last_bit - first_bit + 1) * vmem->block_size; - if (!virtio_mem_intersect_memory_section(&tmp, offset, size)) { + if (!memory_region_section_intersect_range(&tmp, offset, size)) { break; } ret = cb(&tmp, arg); @@ -355,7 +333,7 @@ static void virtio_mem_notify_unplug(VirtIOMEM *vmem, uint64_t offset, QLIST_FOREACH(rdl, &vmem->rdl_list, next) { MemoryRegionSection tmp = *rdl->section; - 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, uint64_t offset, QLIST_FOREACH(rdl, &vmem->rdl_list, next) { MemoryRegionSection tmp = *rdl->section; - if (!virtio_mem_intersect_memory_section(&tmp, offset, size)) { + if (!memory_region_section_intersect_range(&tmp, offset, size)) { continue; } ret = rdl->notify_populate(rdl, &tmp); @@ -388,7 +366,7 @@ static int virtio_mem_notify_plug(VirtIOMEM *vmem, uint64_t offset, if (rdl2 == 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/exec/memory.h b/include/exec/memory.h index 3ee1901b52..3bebc43d59 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1202,6 +1202,33 @@ MemoryRegionSection *memory_region_section_new_copy(MemoryRegionSection *s); */ void memory_region_section_free_copy(MemoryRegionSection *s); +/** + * memory_region_section_intersect_range: Adjust the memory section to cover + * 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(MemoryRegionSection *s, + uint64_t offset, uint64_t size) +{ + uint64_t start = MAX(s->offset_within_region, offset); + Int128 end = int128_min(int128_add(int128_make64(s->offset_within_region), s->size), + int128_add(int128_make64(offset), int128_make64(size))); + + if (int128_le(end, int128_make64(start))) { + return false; + } + + s->offset_within_address_space += start - s->offset_within_region; + s->offset_within_region = start; + s->size = int128_sub(end, int128_make64(start)); + return true; +} + /** * memory_region_init: Initialize a memory region * From patchwork Mon Feb 17 08:18:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chenyi Qiang X-Patchwork-Id: 13977278 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 072EB1A0731 for ; Mon, 17 Feb 2025 08:18:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780336; cv=none; b=D81efQU3/Vryxkd/L/wwSMOuvEHMPQjGI/igwjI+v+blotPHlQA6D3kal+p8oysD+WyAAYYu+BrH/lIy2HfhwKn05x437mUqjC05uZYu9cTh+kDUNicPOEIEUWlOMfmBDHteeVLs7303WB20Lv+VkAoV0o2UhEQIOP9UTzi+gUw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780336; c=relaxed/simple; bh=aCF+b4RwfnVnsui1hr69IimEOU4HkOAhxYc97Sd88Us=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SyR64zqijjmW9pD/ZTNHrCsNJk8jOoVSCXUrxQXPmMEFEMdiQPV9mCI/3atPc2v3LcZSl58io30R3G72OsNP8fZb4Az8dZV81VDgVduLGOC0UjjR5HqYXp0JKJMyIET7tjtd002R2RH67fJJzuSsyT/KU1aGWvDpAj7GhL8/ZfY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=ncWC0xak; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="ncWC0xak" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1739780335; x=1771316335; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=aCF+b4RwfnVnsui1hr69IimEOU4HkOAhxYc97Sd88Us=; b=ncWC0xakXRS1JMre0c16JiI5FpZKg6wSN/WnlJiaeKYNbF5djvrqO8Xz lb52mc5QtH2hA9wCzYqTabzlHPHEU2RSGvWYGlcZWmdPcKUjsxtckrtC2 8qtw71RxecatqbRm9T9T6Kb82+OJxwBUMufsHtcXYFH1FKrnrDPyPENNo FIImYk15Fjvrkl00yAIa3L0YuW8oySm2SGHXMRw3FfWTeYdiGN+1zYfjV 3OBklvdCTYuaTLg9oGw6zbFtrvvkHFPpacksUnnQTQrCUkT+8bVZLVgbm kds116TZEKQBq71ktAA6seF277C1y1MAjz8NxMykk4dv9425YF2xfnKGq g==; X-CSE-ConnectionGUID: 6UHqtjCiQ0+NLJuXjLdwVA== X-CSE-MsgGUID: IBauHFGMRiGk3cIefuLiNg== X-IronPort-AV: E=McAfee;i="6700,10204,11347"; a="50668973" X-IronPort-AV: E=Sophos;i="6.13,292,1732608000"; d="scan'208";a="50668973" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:18:54 -0800 X-CSE-ConnectionGUID: bJsn2YPTQ6OurDEqgpOlMw== X-CSE-MsgGUID: DYuhebGISKS+FiChk3Xkeg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118690184" Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:18:52 -0800 From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Peng Chao P , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v2 2/6] memory: Change memory_region_set_ram_discard_manager() to return the result Date: Mon, 17 Feb 2025 16:18:21 +0800 Message-ID: <20250217081833.21568-3-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250217081833.21568-1-chenyi.qiang@intel.com> References: <20250217081833.21568-1-chenyi.qiang@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Modify memory_region_set_ram_discard_manager() to return false 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 a MemoryRegion at present. Suggested-by: David Hildenbrand Signed-off-by: Chenyi Qiang --- Changes in v2: - newly added. --- hw/virtio/virtio-mem.c | 30 +++++++++++++++++------------- include/exec/memory.h | 6 +++--- system/memory.c | 11 ++++++++--- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index 21f16e4912..ef818a2cdf 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -1074,6 +1074,18 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp) vmem->block_size; vmem->bitmap = bitmap_new(vmem->bitmap_size); + /* + * 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"); + g_free(vmem->bitmap); + ram_block_coordinated_discard_require(false); + return; + } + virtio_init(vdev, VIRTIO_ID_MEM, sizeof(struct virtio_mem_config)); vmem->vq = virtio_add_queue(vdev, 128, virtio_mem_handle_request); @@ -1124,13 +1136,6 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp) vmem->system_reset = VIRTIO_MEM_SYSTEM_RESET(obj); vmem->system_reset->vmem = 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)); } static void virtio_mem_device_unrealize(DeviceState *dev) @@ -1138,12 +1143,6 @@ static void virtio_mem_device_unrealize(DeviceState *dev) VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOMEM *vmem = VIRTIO_MEM(dev); - /* - * 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)); @@ -1155,6 +1154,11 @@ static void virtio_mem_device_unrealize(DeviceState *dev) host_memory_backend_set_mapped(vmem->memdev, false); virtio_del_queue(vdev, 0); virtio_cleanup(vdev); + /* + * 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); g_free(vmem->bitmap); ram_block_coordinated_discard_require(false); } diff --git a/include/exec/memory.h b/include/exec/memory.h index 3bebc43d59..390477b588 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -2487,13 +2487,13 @@ static inline bool memory_region_has_ram_discard_manager(MemoryRegion *mr) * * This function must not be called for a mapped #MemoryRegion, a #MemoryRegion * 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); /** * memory_region_find: translate an address/size relative to a diff --git a/system/memory.c b/system/memory.c index b17b5538ff..297a3dbcd4 100644 --- a/system/memory.c +++ b/system/memory.c @@ -2115,12 +2115,17 @@ RamDiscardManager *memory_region_get_ram_discard_manager(MemoryRegion *mr) return mr->rdm; } -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 != NULL) { + return -1; + } + + /* !rdm || !mr->rdm */ mr->rdm = rdm; + return 0; } uint64_t ram_discard_manager_get_min_granularity(const RamDiscardManager *rdm, From patchwork Mon Feb 17 08:18:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chenyi Qiang X-Patchwork-Id: 13977279 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 79CAD194C77 for ; Mon, 17 Feb 2025 08:18:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780340; cv=none; b=GVXK7VtzMcQXrlmM2CQtoE2G+Ow2HFVZWViVEJfnXJUoh5V4pKClp2bBGrDNMb9alilpYuhz3PCAYKZVKimd5xgnmJ8cmAz1/L8CP8WyeqOMOJbiB6pyASpv/hsYGyslcAZFJfmPb5uM7WG18oOZMMo66UBxVILe/R9350i8OnY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780340; c=relaxed/simple; bh=s6pqC5vUpmDBSKOPqcIdeYtY5SKjjfh0VkIpfTUsAwE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TK8h/ajl59DWffyLPLbhJHB2nxRLE0HqjrG8hHdOJZp5muguNx7yAg3YKJIXO7w36bj5CLRhUj+i0UbvAYeyxWRawDlSdMhczix3drkKD2v2D4Feu3XlfRApdWhrLCRPIjLsUt+Sgp9yvPy6u5NEeY06msA+XDX9lfGnD5EnFXU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Vw+ICf6V; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Vw+ICf6V" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1739780338; x=1771316338; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=s6pqC5vUpmDBSKOPqcIdeYtY5SKjjfh0VkIpfTUsAwE=; b=Vw+ICf6VUdUOxbmrMR4AzCy73v342Q+y9QRmdDqRZGMeuuNGTnyZDRJs 8SUcR1VjoFhrFIInczC91HNVFHY8XRdnUU3fCbJBOJZvyTYssK6pNlOAN Hez7C+Kz7qkXGPar9MILaoM3yIUxetmvji0jBYShVYuxCJ2LbKGfGOUO1 Cjn7D0xcH5wGnsf+XD2vUqT8RW7iuL7De/GXMvjVBRUV0Bug1wQ9qMhbs DM4bFmsHNl3mCCqNYdFCyz0S3+texbNHEqHhjtogum605rNjEetJfpDcs poyQrvzsr8GuCsPS8XhgfypiPMYgyrSx5usIPvjkeZN3mwydCw0t+u5y8 Q==; X-CSE-ConnectionGUID: xf8jjdh9QdmWxb62ZjoCow== X-CSE-MsgGUID: LDKuOge2SMKKRLK/sU2hIA== X-IronPort-AV: E=McAfee;i="6700,10204,11347"; a="50668983" X-IronPort-AV: E=Sophos;i="6.13,292,1732608000"; d="scan'208";a="50668983" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:18:58 -0800 X-CSE-ConnectionGUID: d/k2H8RBTby5fb9aR2w1yA== X-CSE-MsgGUID: +c31eibPQwKxlZJH4fjoJw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118690199" Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:18:55 -0800 From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Peng Chao P , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v2 3/6] memory-attribute-manager: Introduce MemoryAttributeManager to manage RAMBLock with guest_memfd Date: Mon, 17 Feb 2025 16:18:22 +0800 Message-ID: <20250217081833.21568-4-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250217081833.21568-1-chenyi.qiang@intel.com> References: <20250217081833.21568-1-chenyi.qiang@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 As the commit 852f0048f3 ("RAMBlock: make guest_memfd require uncoordinated discard") highlighted, some subsystems like VFIO may disable ram block discard. However, guest_memfd relies on the discard operation to perform page conversion between private and shared memory. This can lead to stale IOMMU mapping issue when assigning a hardware device to a confidential VM via shared memory. To address this, it is crucial to ensure systems like VFIO refresh its IOMMU mappings. RamDiscardManager is an existing concept (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. One potential attempt is to implement it in HostMemoryBackend. This is not appropriate because guest_memfd is per RAMBlock. Some RAMBlocks have a memory backend but others do not. In particular, the ones like virtual BIOS calling memory_region_init_ram_guest_memfd() do not. To manage the RAMBlocks with guest_memfd, define a new object named MemoryAttributeManager to implement the RamDiscardManager interface. The object stores guest_memfd information such as shared_bitmap, and handles page conversion notification. Using the name of MemoryAttributeManager is aimed to make it more generic. The term "Memory" emcompasses not only RAM but also private MMIO in TEE I/O, which might rely on this object/interface to handle page conversion events in the future. The term "Attribute" allows for the management of various attributes beyond shared and private. For instance, it could support scenarios where discard vs. populated and shared vs. private states co-exists, such as supporting virtio-mem or something similar in the future. In the current context, MemoryAttributeManager signifies discarded state as private and populated state as shared. Memory state is tracked at the host page size granularity, as the 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, e.g. conversion happens on a small region within a large region. To prevent such invalid cases and until cut_mapping operation support is introduced, all operations are performed with 4K granularity. Signed-off-by: Chenyi Qiang --- 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. --- include/system/memory-attribute-manager.h | 42 ++++ system/memory-attribute-manager.c | 292 ++++++++++++++++++++++ system/meson.build | 1 + 3 files changed, 335 insertions(+) create mode 100644 include/system/memory-attribute-manager.h create mode 100644 system/memory-attribute-manager.c diff --git a/include/system/memory-attribute-manager.h b/include/system/memory-attribute-manager.h new file mode 100644 index 0000000000..72adc0028e --- /dev/null +++ b/include/system/memory-attribute-manager.h @@ -0,0 +1,42 @@ +/* + * QEMU memory attribute manager + * + * Copyright Intel + * + * Author: + * Chenyi Qiang + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory + * + */ + +#ifndef SYSTEM_MEMORY_ATTRIBUTE_MANAGER_H +#define SYSTEM_MEMORY_ATTRIBUTE_MANAGER_H + +#include "system/hostmem.h" + +#define TYPE_MEMORY_ATTRIBUTE_MANAGER "memory-attribute-manager" + +OBJECT_DECLARE_TYPE(MemoryAttributeManager, MemoryAttributeManagerClass, MEMORY_ATTRIBUTE_MANAGER) + +struct MemoryAttributeManager { + Object parent; + + MemoryRegion *mr; + + /* 1-setting of the bit represents the memory is populated (shared) */ + int32_t bitmap_size; + unsigned long *shared_bitmap; + + QLIST_HEAD(, RamDiscardListener) rdl_list; +}; + +struct MemoryAttributeManagerClass { + ObjectClass parent_class; +}; + +int memory_attribute_manager_realize(MemoryAttributeManager *mgr, MemoryRegion *mr); +void memory_attribute_manager_unrealize(MemoryAttributeManager *mgr); + +#endif diff --git a/system/memory-attribute-manager.c b/system/memory-attribute-manager.c new file mode 100644 index 0000000000..ed97e43dd0 --- /dev/null +++ b/system/memory-attribute-manager.c @@ -0,0 +1,292 @@ +/* + * QEMU memory attribute manager + * + * Copyright Intel + * + * Author: + * Chenyi Qiang + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory + * + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "system/memory-attribute-manager.h" + +OBJECT_DEFINE_TYPE_WITH_INTERFACES(MemoryAttributeManager, + memory_attribute_manager, + MEMORY_ATTRIBUTE_MANAGER, + OBJECT, + { TYPE_RAM_DISCARD_MANAGER }, + { }) + +static int memory_attribute_manager_get_block_size(const MemoryAttributeManager *mgr) +{ + /* + * Because page conversion could be manipulated in the size of at least 4K or 4K aligned, + * Use the host page size as the granularity to track the memory attribute. + * TODO: if necessary, switch to get the page_size from RAMBlock. + * i.e. mgr->mr->ram_block->page_size. + */ + return qemu_real_host_page_size(); +} + + +static bool memory_attribute_rdm_is_populated(const RamDiscardManager *rdm, + const MemoryRegionSection *section) +{ + const MemoryAttributeManager *mgr = MEMORY_ATTRIBUTE_MANAGER(rdm); + int block_size = memory_attribute_manager_get_block_size(mgr); + uint64_t first_bit = section->offset_within_region / block_size; + uint64_t last_bit = first_bit + int128_get64(section->size) / block_size - 1; + unsigned long first_discard_bit; + + first_discard_bit = find_next_zero_bit(mgr->shared_bitmap, last_bit + 1, first_bit); + return first_discard_bit > last_bit; +} + +typedef int (*memory_attribute_section_cb)(MemoryRegionSection *s, void *arg); + +static int memory_attribute_notify_populate_cb(MemoryRegionSection *section, void *arg) +{ + RamDiscardListener *rdl = arg; + + return rdl->notify_populate(rdl, section); +} + +static int memory_attribute_notify_discard_cb(MemoryRegionSection *section, void *arg) +{ + RamDiscardListener *rdl = arg; + + rdl->notify_discard(rdl, section); + + return 0; +} + +static int memory_attribute_for_each_populated_section(const MemoryAttributeManager *mgr, + MemoryRegionSection *section, + void *arg, + memory_attribute_section_cb cb) +{ + unsigned long first_one_bit, last_one_bit; + uint64_t offset, size; + int block_size = memory_attribute_manager_get_block_size(mgr); + int ret = 0; + + first_one_bit = section->offset_within_region / block_size; + first_one_bit = find_next_bit(mgr->shared_bitmap, mgr->bitmap_size, first_one_bit); + + while (first_one_bit < mgr->bitmap_size) { + MemoryRegionSection tmp = *section; + + offset = first_one_bit * block_size; + last_one_bit = find_next_zero_bit(mgr->shared_bitmap, mgr->bitmap_size, + first_one_bit + 1) - 1; + size = (last_one_bit - first_one_bit + 1) * block_size; + + if (!memory_region_section_intersect_range(&tmp, offset, size)) { + break; + } + + ret = cb(&tmp, arg); + if (ret) { + error_report("%s: Failed to notify RAM discard listener: %s", __func__, + strerror(-ret)); + break; + } + + first_one_bit = find_next_bit(mgr->shared_bitmap, mgr->bitmap_size, + last_one_bit + 2); + } + + return ret; +} + +static int memory_attribute_for_each_discarded_section(const MemoryAttributeManager *mgr, + MemoryRegionSection *section, + void *arg, + memory_attribute_section_cb cb) +{ + unsigned long first_zero_bit, last_zero_bit; + uint64_t offset, size; + int block_size = memory_attribute_manager_get_block_size(mgr); + int ret = 0; + + first_zero_bit = section->offset_within_region / block_size; + first_zero_bit = find_next_zero_bit(mgr->shared_bitmap, mgr->bitmap_size, + first_zero_bit); + + while (first_zero_bit < mgr->bitmap_size) { + MemoryRegionSection tmp = *section; + + offset = first_zero_bit * block_size; + last_zero_bit = find_next_bit(mgr->shared_bitmap, mgr->bitmap_size, + first_zero_bit + 1) - 1; + size = (last_zero_bit - first_zero_bit + 1) * block_size; + + if (!memory_region_section_intersect_range(&tmp, offset, size)) { + break; + } + + ret = cb(&tmp, arg); + if (ret) { + error_report("%s: Failed to notify RAM discard listener: %s", __func__, + strerror(-ret)); + break; + } + + first_zero_bit = find_next_zero_bit(mgr->shared_bitmap, mgr->bitmap_size, + last_zero_bit + 2); + } + + return ret; +} + +static uint64_t memory_attribute_rdm_get_min_granularity(const RamDiscardManager *rdm, + const MemoryRegion *mr) +{ + MemoryAttributeManager *mgr = MEMORY_ATTRIBUTE_MANAGER(rdm); + + g_assert(mr == mgr->mr); + return memory_attribute_manager_get_block_size(mgr); +} + +static void memory_attribute_rdm_register_listener(RamDiscardManager *rdm, + RamDiscardListener *rdl, + MemoryRegionSection *section) +{ + MemoryAttributeManager *mgr = MEMORY_ATTRIBUTE_MANAGER(rdm); + int ret; + + g_assert(section->mr == mgr->mr); + rdl->section = memory_region_section_new_copy(section); + + QLIST_INSERT_HEAD(&mgr->rdl_list, rdl, next); + + ret = memory_attribute_for_each_populated_section(mgr, section, rdl, + memory_attribute_notify_populate_cb); + if (ret) { + error_report("%s: Failed to register RAM discard listener: %s", __func__, + strerror(-ret)); + } +} + +static void memory_attribute_rdm_unregister_listener(RamDiscardManager *rdm, + RamDiscardListener *rdl) +{ + MemoryAttributeManager *mgr = MEMORY_ATTRIBUTE_MANAGER(rdm); + int ret; + + g_assert(rdl->section); + g_assert(rdl->section->mr == mgr->mr); + + ret = memory_attribute_for_each_populated_section(mgr, rdl->section, rdl, + memory_attribute_notify_discard_cb); + if (ret) { + error_report("%s: Failed to unregister RAM discard listener: %s", __func__, + strerror(-ret)); + } + + memory_region_section_free_copy(rdl->section); + rdl->section = NULL; + QLIST_REMOVE(rdl, next); + +} + +typedef struct MemoryAttributeReplayData { + void *fn; + void *opaque; +} MemoryAttributeReplayData; + +static int memory_attribute_rdm_replay_populated_cb(MemoryRegionSection *section, void *arg) +{ + MemoryAttributeReplayData *data = arg; + + return ((ReplayRamPopulate)data->fn)(section, data->opaque); +} + +static int memory_attribute_rdm_replay_populated(const RamDiscardManager *rdm, + MemoryRegionSection *section, + ReplayRamPopulate replay_fn, + void *opaque) +{ + MemoryAttributeManager *mgr = MEMORY_ATTRIBUTE_MANAGER(rdm); + MemoryAttributeReplayData data = { .fn = replay_fn, .opaque = opaque }; + + g_assert(section->mr == mgr->mr); + return memory_attribute_for_each_populated_section(mgr, section, &data, + memory_attribute_rdm_replay_populated_cb); +} + +static int memory_attribute_rdm_replay_discarded_cb(MemoryRegionSection *section, void *arg) +{ + MemoryAttributeReplayData *data = arg; + + ((ReplayRamDiscard)data->fn)(section, data->opaque); + return 0; +} + +static void memory_attribute_rdm_replay_discarded(const RamDiscardManager *rdm, + MemoryRegionSection *section, + ReplayRamDiscard replay_fn, + void *opaque) +{ + MemoryAttributeManager *mgr = MEMORY_ATTRIBUTE_MANAGER(rdm); + MemoryAttributeReplayData data = { .fn = replay_fn, .opaque = opaque }; + + g_assert(section->mr == mgr->mr); + memory_attribute_for_each_discarded_section(mgr, section, &data, + memory_attribute_rdm_replay_discarded_cb); +} + +int memory_attribute_manager_realize(MemoryAttributeManager *mgr, MemoryRegion *mr) +{ + uint64_t bitmap_size; + int block_size = memory_attribute_manager_get_block_size(mgr); + int ret; + + bitmap_size = ROUND_UP(mr->size, block_size) / block_size; + + mgr->mr = mr; + mgr->bitmap_size = bitmap_size; + mgr->shared_bitmap = bitmap_new(bitmap_size); + + ret = memory_region_set_ram_discard_manager(mgr->mr, RAM_DISCARD_MANAGER(mgr)); + if (ret) { + g_free(mgr->shared_bitmap); + } + + return ret; +} + +void memory_attribute_manager_unrealize(MemoryAttributeManager *mgr) +{ + memory_region_set_ram_discard_manager(mgr->mr, NULL); + + g_free(mgr->shared_bitmap); +} + +static void memory_attribute_manager_init(Object *obj) +{ + MemoryAttributeManager *mgr = MEMORY_ATTRIBUTE_MANAGER(obj); + + QLIST_INIT(&mgr->rdl_list); +} + +static void memory_attribute_manager_finalize(Object *obj) +{ +} + +static void memory_attribute_manager_class_init(ObjectClass *oc, void *data) +{ + RamDiscardManagerClass *rdmc = RAM_DISCARD_MANAGER_CLASS(oc); + + rdmc->get_min_granularity = memory_attribute_rdm_get_min_granularity; + rdmc->register_listener = memory_attribute_rdm_register_listener; + rdmc->unregister_listener = memory_attribute_rdm_unregister_listener; + rdmc->is_populated = memory_attribute_rdm_is_populated; + rdmc->replay_populated = memory_attribute_rdm_replay_populated; + rdmc->replay_discarded = memory_attribute_rdm_replay_discarded; +} diff --git a/system/meson.build b/system/meson.build index 4952f4b2c7..ab07ff1442 100644 --- a/system/meson.build +++ b/system/meson.build @@ -15,6 +15,7 @@ system_ss.add(files( 'dirtylimit.c', 'dma-helpers.c', 'globals.c', + 'memory-attribute-manager.c', 'memory_mapping.c', 'qdev-monitor.c', 'qtest.c', From patchwork Mon Feb 17 08:18:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chenyi Qiang X-Patchwork-Id: 13977280 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B988019EED2 for ; Mon, 17 Feb 2025 08:19:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780343; cv=none; b=Ta+y4R4snQ6Ik0L1xlmyTtn8qLQE8ntVNVkTmMOR4qdD1p9oQ7vTz3g0fYoh/cwqk2js1EudGK2RN8XPE2upXRweHDpZXTpc23pb89OL8vgOHcZIGTqap465ZnRvxuQ1RYCgdaVD/vnS8VKelNBmUzfpLSMjTRFiy23Ygx9Wf2E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780343; c=relaxed/simple; bh=fgikP9pCs5jC0lyoad1drlNUfTByGFH9gXJjN5Ul2t0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hcWz9epMutacqRyXtcqWiIPYJlSA/iJZOuf7gL2godlHT+e36s7RF03z3UeOuYUNvvKVp90GFet50E1FAIhImi28a7sL3ssUr3jQzTuIESKSe/Q01ofn6DWr4ko9EB9v3k8BvSAcpnRIwiSa0Kq2D7SFlpbNW6Y2ONKax6irxtk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=PEM1kJt7; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="PEM1kJt7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1739780341; x=1771316341; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=fgikP9pCs5jC0lyoad1drlNUfTByGFH9gXJjN5Ul2t0=; b=PEM1kJt7Nj4Wr0iAVsQSJZvchDJMzFv4YDaBg8mQBiTpwrOwPPw62d3L Eo6jAXsA8Nunf1aco4ZKJ2R39dqeDP6NBceRnQ1f3PJkWw0ZRnsimffCI k/shqy7tnvjGeQA//gbSs8oL3ERbTruavy7lUX+Ad/pODvBSsF3o6H9Bt hQLlmjwwsHIe0iT1CyLJs2eWIc7DaixkjyUYbQCg2DUG5wG7zuD471liY SyuB8Vna8FX85mbDqttxNsjcyDZb7U2Z8ZF0lEWOsP7GH7qk+4Y3dLGAz EC2t65ntdJRJSAhFv9aaNf6juQVcHZd9xfsJMsU9A3TBN1KQo9IlRzrP6 A==; X-CSE-ConnectionGUID: iFIiAP+tRFC5Wq0dMT/oBw== X-CSE-MsgGUID: 0lJTy72CQRCH5j5bdgajyg== X-IronPort-AV: E=McAfee;i="6700,10204,11347"; a="50668992" X-IronPort-AV: E=Sophos;i="6.13,292,1732608000"; d="scan'208";a="50668992" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:19:01 -0800 X-CSE-ConnectionGUID: 4++vfEfLQc+TGqj/kWLFbw== X-CSE-MsgGUID: nF3NBRcjRM+gJeJNBwQ0gQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118690233" Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:18:58 -0800 From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Peng Chao P , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v2 4/6] memory-attribute-manager: Introduce a callback to notify the shared/private state change Date: Mon, 17 Feb 2025 16:18:23 +0800 Message-ID: <20250217081833.21568-5-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250217081833.21568-1-chenyi.qiang@intel.com> References: <20250217081833.21568-1-chenyi.qiang@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce a new state_change() callback in MemoryAttributeManagerClass to efficiently notify all registered RamDiscardListeners, including VFIO listeners about the memory conversion events in guest_memfd. The existing VFIO listener can dynamically DMA map/unmap the 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. Additionally, there could be some special conversion requests: - When 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, only the necessary segments are converted, ensuring the entire range complies with the request efficiently. - In scenarios where a conversion request is declined by other systems, such as a failure from VFIO during notify_populate(), the helper will roll back the request, maintaining consistency. Opportunistically introduce a helper to trigger the state_change() callback of the class. Signed-off-by: Chenyi Qiang --- Changes in v2: - Do the alignment changes due to the rename to MemoryAttributeManager - Move the state_change() helper definition in this patch. --- include/system/memory-attribute-manager.h | 20 +++ system/memory-attribute-manager.c | 148 ++++++++++++++++++++++ 2 files changed, 168 insertions(+) diff --git a/include/system/memory-attribute-manager.h b/include/system/memory-attribute-manager.h index 72adc0028e..c3dab4e47b 100644 --- a/include/system/memory-attribute-manager.h +++ b/include/system/memory-attribute-manager.h @@ -34,8 +34,28 @@ struct MemoryAttributeManager { struct MemoryAttributeManagerClass { ObjectClass parent_class; + + int (*state_change)(MemoryAttributeManager *mgr, uint64_t offset, uint64_t size, + bool shared_to_private); }; +static inline int memory_attribute_manager_state_change(MemoryAttributeManager *mgr, uint64_t offset, + uint64_t size, bool shared_to_private) +{ + MemoryAttributeManagerClass *klass; + + if (mgr == NULL) { + return 0; + } + + klass = MEMORY_ATTRIBUTE_MANAGER_GET_CLASS(mgr); + if (klass->state_change) { + return klass->state_change(mgr, offset, size, shared_to_private); + } + + return 0; +} + int memory_attribute_manager_realize(MemoryAttributeManager *mgr, MemoryRegion *mr); void memory_attribute_manager_unrealize(MemoryAttributeManager *mgr); diff --git a/system/memory-attribute-manager.c b/system/memory-attribute-manager.c index ed97e43dd0..17c70cf677 100644 --- a/system/memory-attribute-manager.c +++ b/system/memory-attribute-manager.c @@ -241,6 +241,151 @@ static void memory_attribute_rdm_replay_discarded(const RamDiscardManager *rdm, memory_attribute_rdm_replay_discarded_cb); } +static bool memory_attribute_is_valid_range(MemoryAttributeManager *mgr, + uint64_t offset, uint64_t size) +{ + MemoryRegion *mr = mgr->mr; + + g_assert(mr); + + uint64_t region_size = memory_region_size(mr); + int block_size = memory_attribute_manager_get_block_size(mgr); + + if (!QEMU_IS_ALIGNED(offset, block_size)) { + return false; + } + if (offset + size < offset || !size) { + return false; + } + if (offset >= region_size || offset + size > region_size) { + return false; + } + return true; +} + +static void memory_attribute_notify_discard(MemoryAttributeManager *mgr, + uint64_t offset, uint64_t size) +{ + RamDiscardListener *rdl; + + QLIST_FOREACH(rdl, &mgr->rdl_list, next) { + MemoryRegionSection tmp = *rdl->section; + + if (!memory_region_section_intersect_range(&tmp, offset, size)) { + continue; + } + + memory_attribute_for_each_populated_section(mgr, &tmp, rdl, + memory_attribute_notify_discard_cb); + } +} + +static int memory_attribute_notify_populate(MemoryAttributeManager *mgr, + uint64_t offset, uint64_t size) +{ + RamDiscardListener *rdl, *rdl2; + int ret = 0; + + QLIST_FOREACH(rdl, &mgr->rdl_list, next) { + MemoryRegionSection tmp = *rdl->section; + + if (!memory_region_section_intersect_range(&tmp, offset, size)) { + continue; + } + + ret = memory_attribute_for_each_discarded_section(mgr, &tmp, rdl, + memory_attribute_notify_populate_cb); + if (ret) { + break; + } + } + + if (ret) { + /* Notify all already-notified listeners. */ + QLIST_FOREACH(rdl2, &mgr->rdl_list, next) { + MemoryRegionSection tmp = *rdl2->section; + + if (rdl2 == rdl) { + break; + } + if (!memory_region_section_intersect_range(&tmp, offset, size)) { + continue; + } + + memory_attribute_for_each_discarded_section(mgr, &tmp, rdl2, + memory_attribute_notify_discard_cb); + } + } + return ret; +} + +static bool memory_attribute_is_range_populated(MemoryAttributeManager *mgr, + uint64_t offset, uint64_t size) +{ + int block_size = memory_attribute_manager_get_block_size(mgr); + const unsigned long first_bit = offset / block_size; + const unsigned long last_bit = first_bit + (size / block_size) - 1; + unsigned long found_bit; + + /* We fake a shorter bitmap to avoid searching too far. */ + found_bit = find_next_zero_bit(mgr->shared_bitmap, last_bit + 1, first_bit); + return found_bit > last_bit; +} + +static bool memory_attribute_is_range_discarded(MemoryAttributeManager *mgr, + uint64_t offset, uint64_t size) +{ + int block_size = memory_attribute_manager_get_block_size(mgr); + const unsigned long first_bit = offset / block_size; + const unsigned long last_bit = first_bit + (size / block_size) - 1; + unsigned long found_bit; + + /* We fake a shorter bitmap to avoid searching too far. */ + found_bit = find_next_bit(mgr->shared_bitmap, last_bit + 1, first_bit); + return found_bit > last_bit; +} + +static int memory_attribute_state_change(MemoryAttributeManager *mgr, uint64_t offset, + uint64_t size, bool shared_to_private) +{ + int block_size = memory_attribute_manager_get_block_size(mgr); + int ret = 0; + + if (!memory_attribute_is_valid_range(mgr, offset, size)) { + error_report("%s, invalid range: offset 0x%lx, size 0x%lx", + __func__, offset, size); + return -1; + } + + if ((shared_to_private && memory_attribute_is_range_discarded(mgr, offset, size)) || + (!shared_to_private && memory_attribute_is_range_populated(mgr, offset, size))) { + return 0; + } + + if (shared_to_private) { + memory_attribute_notify_discard(mgr, offset, size); + } else { + ret = memory_attribute_notify_populate(mgr, offset, size); + } + + if (!ret) { + unsigned long first_bit = offset / block_size; + unsigned long nbits = size / block_size; + + g_assert((first_bit + nbits) <= mgr->bitmap_size); + + if (shared_to_private) { + bitmap_clear(mgr->shared_bitmap, first_bit, nbits); + } else { + bitmap_set(mgr->shared_bitmap, first_bit, nbits); + } + + return 0; + } + + return ret; +} + int memory_attribute_manager_realize(MemoryAttributeManager *mgr, MemoryRegion *mr) { uint64_t bitmap_size; @@ -281,8 +426,11 @@ static void memory_attribute_manager_finalize(Object *obj) static void memory_attribute_manager_class_init(ObjectClass *oc, void *data) { + MemoryAttributeManagerClass *mamc = MEMORY_ATTRIBUTE_MANAGER_CLASS(oc); RamDiscardManagerClass *rdmc = RAM_DISCARD_MANAGER_CLASS(oc); + mamc->state_change = memory_attribute_state_change; + rdmc->get_min_granularity = memory_attribute_rdm_get_min_granularity; rdmc->register_listener = memory_attribute_rdm_register_listener; rdmc->unregister_listener = memory_attribute_rdm_unregister_listener; From patchwork Mon Feb 17 08:18:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chenyi Qiang X-Patchwork-Id: 13977281 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E1C9C1A2645 for ; Mon, 17 Feb 2025 08:19:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780346; cv=none; b=HDgtpuOpUeViL7A1rRbCCes8X1h7ZTXJaMkmmFiyACbiLZcmE1pIbeSBYgpGibsRRgizi3kJlgHjV+JibUp+BOnjRHcyadTmXDmY8Igsxybt0u/tJ8GnT9iZf1arL3eBiueQEKycAC8LDgam1PEvykpU9e0T6oebF2COv3AHLbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780346; c=relaxed/simple; bh=et457s5gxOACczlEdsQV3JpgBTp1+3xW6hMwzsrYsk0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Zrey6Nc+yMzqqWCmGE4QW1SObk8sWIzaf+5Hm/X/rZFIdJEi+AFNpU+mlRMaBMWAhcPa+Gp76kGHmfNrEk9lFQ9ZfeY5eBqmUkGD/Jl7Mi75KMHSAOa4vtxoIvn7cF8pJ4mhy2Bh5dmAoyCNblfEOK2BYPxWzAc5sus0STXZxlQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Lqx2qodx; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Lqx2qodx" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1739780344; x=1771316344; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=et457s5gxOACczlEdsQV3JpgBTp1+3xW6hMwzsrYsk0=; b=Lqx2qodxEt7eGP97ygA8l95KUxRGrn4DUbs4r0VgrnDDxm9sjFeZGmEJ ntXP29un1UkokVT3Es98yeIMl4MX6GFTxkj3fEFtlrymToyfhVUZQrgPS qRyB8JlK7ZEEFJFfPY60lf21lgy65r9e8JBHzr4kAgWtq45K61ijeqcAP l6qDFhsltIy5JsB7VyfzpKwSHW6kdfSV6R8Pdehamb2PK6lZu6lkwtu4/ xzsieUjVHHxWp3k4xM9++H3WmL1pGSNGAeDvXS6qf95r6MeBR8TZ8EOaS ckLtvrlqHffT6F9bt/g0BR7wKGTxu0D7KBXgTZvC5zK+67cD6KwCdLq/5 A==; X-CSE-ConnectionGUID: H+mn5nH2R0C5h29Y5+fUAw== X-CSE-MsgGUID: P9oYwJLfQ26D9Ulbejm26A== X-IronPort-AV: E=McAfee;i="6700,10204,11347"; a="50669000" X-IronPort-AV: E=Sophos;i="6.13,292,1732608000"; d="scan'208";a="50669000" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:19:04 -0800 X-CSE-ConnectionGUID: l51kerAISVmk9QAqliXkng== X-CSE-MsgGUID: xdV2eWBVTKyB3H50d8XF5Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118690254" Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:19:02 -0800 From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Peng Chao P , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v2 5/6] memory: Attach MemoryAttributeManager to guest_memfd-backed RAMBlocks Date: Mon, 17 Feb 2025 16:18:24 +0800 Message-ID: <20250217081833.21568-6-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250217081833.21568-1-chenyi.qiang@intel.com> References: <20250217081833.21568-1-chenyi.qiang@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce a new field, memory_attribute_manager, in RAMBlock to link to an MemoryAttributeManager object. This change centralizes all guest_memfd state information (like fd and shared_bitmap) within a RAMBlock, making it easier to manage. Use the realize()/unrealize() helpers to initialize/uninitialize the MemoryAttributeManager object. Register/unregister the object in the target RAMBlock's MemoryRegion when creating guest_memfd. Upon memory state changes in kvm_convert_memory(), invoke the memory_attribute_manager_state_change() helper to notify the registered RamDiscardListener. Signed-off-by: Chenyi Qiang Reviewed-by: Alexey Kardashevskiy --- 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 cleanup. --- accel/kvm/kvm-all.c | 9 +++++++++ include/exec/ramblock.h | 2 ++ system/physmem.c | 13 +++++++++++++ 3 files changed, 24 insertions(+) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index c1fea69d58..c0d15c48ad 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -48,6 +48,7 @@ #include "kvm-cpus.h" #include "system/dirtylimit.h" #include "qemu/range.h" +#include "system/memory-attribute-manager.h" #include "hw/boards.h" #include "system/stats.h" @@ -3088,6 +3089,14 @@ int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private) addr = memory_region_get_ram_ptr(mr) + section.offset_within_region; rb = qemu_ram_block_from_host(addr, false, &offset); + ret = memory_attribute_manager_state_change(MEMORY_ATTRIBUTE_MANAGER(mr->rdm), + offset, size, to_private); + if (ret) { + warn_report("Failed to notify the listener the state change of " + "(0x%"HWADDR_PRIx" + 0x%"HWADDR_PRIx") to %s", + start, size, to_private ? "private" : "shared"); + } + if (to_private) { if (rb->page_size != qemu_real_host_page_size()) { /* diff --git a/include/exec/ramblock.h b/include/exec/ramblock.h index 0babd105c0..06fd365326 100644 --- a/include/exec/ramblock.h +++ b/include/exec/ramblock.h @@ -23,6 +23,7 @@ #include "cpu-common.h" #include "qemu/rcu.h" #include "exec/ramlist.h" +#include "system/memory-attribute-manager.h" struct RAMBlock { struct rcu_head rcu; @@ -42,6 +43,7 @@ struct RAMBlock { int fd; uint64_t fd_offset; int guest_memfd; + MemoryAttributeManager *memory_attribute_manager; size_t page_size; /* dirty bitmap used during migration */ unsigned long *bmap; diff --git a/system/physmem.c b/system/physmem.c index c76503aea8..0ed394c5d2 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -54,6 +54,7 @@ #include "system/hostmem.h" #include "system/hw_accel.h" #include "system/xen-mapcache.h" +#include "system/memory-attribute-manager.h" #include "trace.h" #ifdef CONFIG_FALLOCATE_PUNCH_HOLE @@ -1885,6 +1886,16 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) qemu_mutex_unlock_ramlist(); goto out_free; } + + new_block->memory_attribute_manager = MEMORY_ATTRIBUTE_MANAGER(object_new(TYPE_MEMORY_ATTRIBUTE_MANAGER)); + if (memory_attribute_manager_realize(new_block->memory_attribute_manager, new_block->mr)) { + error_setg(errp, "Failed to realize memory attribute manager"); + object_unref(OBJECT(new_block->memory_attribute_manager)); + close(new_block->guest_memfd); + ram_block_discard_require(false); + qemu_mutex_unlock_ramlist(); + goto out_free; + } } ram_size = (new_block->offset + new_block->max_length) >> TARGET_PAGE_BITS; @@ -2138,6 +2149,8 @@ static void reclaim_ramblock(RAMBlock *block) } if (block->guest_memfd >= 0) { + memory_attribute_manager_unrealize(block->memory_attribute_manager); + object_unref(OBJECT(block->memory_attribute_manager)); close(block->guest_memfd); ram_block_discard_require(false); } From patchwork Mon Feb 17 08:18:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chenyi Qiang X-Patchwork-Id: 13977282 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 255181A2645 for ; Mon, 17 Feb 2025 08:19:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780349; cv=none; b=Q9dXbWkP15HxrmDEUuV/wn05ykOZF4Hq1ihU+IHW2HfoBB60ryyheTDnHkwXgDU4DmTE2QLtL+Dc0f9qmxNlKVIX5qJm/lQMZQW7ugPhe9/VJrp35CYMoK/6DZDyxZn5ItwBQJ+QHOC/3+FP0sn6SPEDCjXG6p0CI01CtVYCTFQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739780349; c=relaxed/simple; bh=E5Ngw7fVDUDC+t1CAmd5+sTvqe9bA5/nLMHz0pQXMco=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M/QpQUSwWuH6wd5xu5fGIjjWUx0LG5Q+M3sJfZK2Sr2Ah5NbKc9xvzPAIR4kkcHzqsC1mqhw3Afu8lS1bl8MIjWyEtVdbevQ0ixHBlRGvYcAMd/gxviP8qwLv2ktxWmwQxkIyMlb1/I9AUkf/et/6law1KwSwAxBYGg+SDnltVw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=adTQuEKy; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="adTQuEKy" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1739780348; x=1771316348; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=E5Ngw7fVDUDC+t1CAmd5+sTvqe9bA5/nLMHz0pQXMco=; b=adTQuEKyBJuT/t6wTGBQVhaiOwtiq+YxZyZ66xF9CNzwN5XUrtXFHdlT G8F9FQ6ib7/b56T2vj/CKGrfBcUraYlrleTPXumWV0P5sohZpXLLXqh8h hu3rD6KdJIvwRXgmFg9nts22UsVgje9HLbtIdarMKSYbouAGHWJn3WGFD qTjr8I3cbvbnf5C85Qe8awVIcz+H4RAwi8Y71Ok+g3FTqlIPZbMnbYx8w VCnAzgNtzKLGFoybyQRI8CavJpFf0MKaBesGSgbap6TVKuWflymFMuD2t zxGzWdn+KAmAIUX95B0K8URS2hhbdLyOqVqwiweeUMeGvPrFCUmqkVsNW Q==; X-CSE-ConnectionGUID: JoRCjkBQSCOIes8U6J7ijg== X-CSE-MsgGUID: eSSJYZWiSbKljuGk/kAK2g== X-IronPort-AV: E=McAfee;i="6700,10204,11347"; a="50669012" X-IronPort-AV: E=Sophos;i="6.13,292,1732608000"; d="scan'208";a="50669012" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:19:07 -0800 X-CSE-ConnectionGUID: 3PtVm0eITQy1Op+8wtRspw== X-CSE-MsgGUID: 20dN3Mz6Qqm1GqR+j0/lpA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="118690267" Received: from emr-bkc.sh.intel.com ([10.112.230.82]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 00:19:05 -0800 From: Chenyi Qiang To: David Hildenbrand , Alexey Kardashevskiy , Peter Xu , Paolo Bonzini , =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= , Michael Roth Cc: Chenyi Qiang , qemu-devel@nongnu.org, kvm@vger.kernel.org, Williams Dan J , Peng Chao P , Gao Chao , Xu Yilun , Li Xiaoyao Subject: [PATCH v2 6/6] RAMBlock: Make guest_memfd require coordinate discard Date: Mon, 17 Feb 2025 16:18:25 +0800 Message-ID: <20250217081833.21568-7-chenyi.qiang@intel.com> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250217081833.21568-1-chenyi.qiang@intel.com> References: <20250217081833.21568-1-chenyi.qiang@intel.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 As guest_memfd is now managed by memory_attribute_manager with RamDiscardManager, only block uncoordinated discard. Signed-off-by: Chenyi Qiang --- 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 0ed394c5d2..a30cdd43ee 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -1872,7 +1872,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) assert(kvm_enabled()); assert(new_block->guest_memfd < 0); - ret = ram_block_discard_require(true); + ret = ram_block_coordinated_discard_require(true); if (ret < 0) { error_setg_errno(errp, -ret, "cannot set up private guest memory: discard currently blocked"); @@ -1892,7 +1892,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) error_setg(errp, "Failed to realize memory attribute manager"); object_unref(OBJECT(new_block->memory_attribute_manager)); close(new_block->guest_memfd); - ram_block_discard_require(false); + ram_block_coordinated_discard_require(false); qemu_mutex_unlock_ramlist(); goto out_free; } @@ -2152,7 +2152,7 @@ static void reclaim_ramblock(RAMBlock *block) memory_attribute_manager_unrealize(block->memory_attribute_manager); object_unref(OBJECT(block->memory_attribute_manager)); close(block->guest_memfd); - ram_block_discard_require(false); + ram_block_coordinated_discard_require(false); } g_free(block);