From: Chenyi Qiang <chenyi.qiang@intel.com>
To: "David Hildenbrand" <david@redhat.com>,
"Alexey Kardashevskiy" <aik@amd.com>,
"Peter Xu" <peterx@redhat.com>,
"Gupta Pankaj" <pankaj.gupta@amd.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Michael Roth" <michael.roth@amd.com>
Cc: Chenyi Qiang <chenyi.qiang@intel.com>,
qemu-devel@nongnu.org, kvm@vger.kernel.org,
Williams Dan J <dan.j.williams@intel.com>,
Peng Chao P <chao.p.peng@intel.com>,
Gao Chao <chao.gao@intel.com>, Xu Yilun <yilun.xu@intel.com>,
Li Xiaoyao <xiaoyao.li@intel.com>
Subject: [PATCH v4 06/13] vfio: Add the support for PrivateSharedManager Interface
Date: Mon, 7 Apr 2025 15:49:26 +0800 [thread overview]
Message-ID: <20250407074939.18657-7-chenyi.qiang@intel.com> (raw)
In-Reply-To: <20250407074939.18657-1-chenyi.qiang@intel.com>
Subsystems like VFIO previously disabled ram block discard and only
allowed coordinated discarding via RamDiscardManager. However,
guest_memfd in confidential VMs relies on discard operations for 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. With the introduction of PrivateSharedManager
interface to manage private and shared states and being distinct from
RamDiscardManager, include PrivateSharedManager in coordinated RAM
discard and add related support in VFIO.
Currently, migration support for confidential VMs is not available, so
vfio_sync_dirty_bitmap() handling for PrivateSharedListener can be
ignored. The register/unregister of PrivateSharedListener is necessary
during vfio_listener_region_add/del(). The listener callbacks are
similar between RamDiscardListener and PrivateSharedListener, allowing
for extraction of common parts opportunisticlly.
Signed-off-by: Chenyi Qiang <chenyi.qiang@intel.com>
---
Changes in v4
- Newly added.
---
hw/vfio/common.c | 104 +++++++++++++++++++++++---
hw/vfio/container-base.c | 1 +
include/hw/vfio/vfio-container-base.h | 10 +++
3 files changed, 105 insertions(+), 10 deletions(-)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 3172d877cc..48468a12c3 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -335,13 +335,9 @@ out:
rcu_read_unlock();
}
-static void vfio_ram_discard_notify_discard(StateChangeListener *scl,
- MemoryRegionSection *section)
+static void vfio_state_change_notify_to_state_clear(VFIOContainerBase *bcontainer,
+ MemoryRegionSection *section)
{
- RamDiscardListener *rdl = container_of(scl, RamDiscardListener, scl);
- VFIORamDiscardListener *vrdl = container_of(rdl, VFIORamDiscardListener,
- listener);
- VFIOContainerBase *bcontainer = vrdl->bcontainer;
const hwaddr size = int128_get64(section->size);
const hwaddr iova = section->offset_within_address_space;
int ret;
@@ -354,13 +350,28 @@ static void vfio_ram_discard_notify_discard(StateChangeListener *scl,
}
}
-static int vfio_ram_discard_notify_populate(StateChangeListener *scl,
+static void vfio_ram_discard_notify_discard(StateChangeListener *scl,
MemoryRegionSection *section)
{
RamDiscardListener *rdl = container_of(scl, RamDiscardListener, scl);
VFIORamDiscardListener *vrdl = container_of(rdl, VFIORamDiscardListener,
listener);
- VFIOContainerBase *bcontainer = vrdl->bcontainer;
+ vfio_state_change_notify_to_state_clear(vrdl->bcontainer, section);
+}
+
+static void vfio_private_shared_notify_to_private(StateChangeListener *scl,
+ MemoryRegionSection *section)
+{
+ PrivateSharedListener *psl = container_of(scl, PrivateSharedListener, scl);
+ VFIOPrivateSharedListener *vpsl = container_of(psl, VFIOPrivateSharedListener,
+ listener);
+ vfio_state_change_notify_to_state_clear(vpsl->bcontainer, section);
+}
+
+static int vfio_state_change_notify_to_state_set(VFIOContainerBase *bcontainer,
+ MemoryRegionSection *section,
+ uint64_t granularity)
+{
const hwaddr end = section->offset_within_region +
int128_get64(section->size);
hwaddr start, next, iova;
@@ -372,7 +383,7 @@ static int vfio_ram_discard_notify_populate(StateChangeListener *scl,
* unmap in minimum granularity later.
*/
for (start = section->offset_within_region; start < end; start = next) {
- next = ROUND_UP(start + 1, vrdl->granularity);
+ next = ROUND_UP(start + 1, granularity);
next = MIN(next, end);
iova = start - section->offset_within_region +
@@ -383,13 +394,33 @@ static int vfio_ram_discard_notify_populate(StateChangeListener *scl,
vaddr, section->readonly);
if (ret) {
/* Rollback */
- vfio_ram_discard_notify_discard(scl, section);
+ vfio_state_change_notify_to_state_clear(bcontainer, section);
return ret;
}
}
return 0;
}
+static int vfio_ram_discard_notify_populate(StateChangeListener *scl,
+ MemoryRegionSection *section)
+{
+ RamDiscardListener *rdl = container_of(scl, RamDiscardListener, scl);
+ VFIORamDiscardListener *vrdl = container_of(rdl, VFIORamDiscardListener,
+ listener);
+ return vfio_state_change_notify_to_state_set(vrdl->bcontainer, section,
+ vrdl->granularity);
+}
+
+static int vfio_private_shared_notify_to_shared(StateChangeListener *scl,
+ MemoryRegionSection *section)
+{
+ PrivateSharedListener *psl = container_of(scl, PrivateSharedListener, scl);
+ VFIOPrivateSharedListener *vpsl = container_of(psl, VFIOPrivateSharedListener,
+ listener);
+ return vfio_state_change_notify_to_state_set(vpsl->bcontainer, section,
+ vpsl->granularity);
+}
+
static void vfio_register_ram_discard_listener(VFIOContainerBase *bcontainer,
MemoryRegionSection *section)
{
@@ -466,6 +497,27 @@ static void vfio_register_ram_discard_listener(VFIOContainerBase *bcontainer,
}
}
+static void vfio_register_private_shared_listener(VFIOContainerBase *bcontainer,
+ MemoryRegionSection *section)
+{
+ GenericStateManager *gsm = memory_region_get_generic_state_manager(section->mr);
+ VFIOPrivateSharedListener *vpsl;
+ PrivateSharedListener *psl;
+
+ vpsl = g_new0(VFIOPrivateSharedListener, 1);
+ vpsl->bcontainer = bcontainer;
+ vpsl->mr = section->mr;
+ vpsl->offset_within_address_space = section->offset_within_address_space;
+ vpsl->granularity = generic_state_manager_get_min_granularity(gsm,
+ section->mr);
+
+ psl = &vpsl->listener;
+ private_shared_listener_init(psl, vfio_private_shared_notify_to_shared,
+ vfio_private_shared_notify_to_private);
+ generic_state_manager_register_listener(gsm, &psl->scl, section);
+ QLIST_INSERT_HEAD(&bcontainer->vpsl_list, vpsl, next);
+}
+
static void vfio_unregister_ram_discard_listener(VFIOContainerBase *bcontainer,
MemoryRegionSection *section)
{
@@ -491,6 +543,31 @@ static void vfio_unregister_ram_discard_listener(VFIOContainerBase *bcontainer,
g_free(vrdl);
}
+static void vfio_unregister_private_shared_listener(VFIOContainerBase *bcontainer,
+ MemoryRegionSection *section)
+{
+ GenericStateManager *gsm = memory_region_get_generic_state_manager(section->mr);
+ VFIOPrivateSharedListener *vpsl = NULL;
+ PrivateSharedListener *psl;
+
+ QLIST_FOREACH(vpsl, &bcontainer->vpsl_list, next) {
+ if (vpsl->mr == section->mr &&
+ vpsl->offset_within_address_space ==
+ section->offset_within_address_space) {
+ break;
+ }
+ }
+
+ if (!vpsl) {
+ hw_error("vfio: Trying to unregister missing RAM discard listener");
+ }
+
+ psl = &vpsl->listener;
+ generic_state_manager_unregister_listener(gsm, &psl->scl);
+ QLIST_REMOVE(vpsl, next);
+ g_free(vpsl);
+}
+
static bool vfio_known_safe_misalignment(MemoryRegionSection *section)
{
MemoryRegion *mr = section->mr;
@@ -644,6 +721,9 @@ static void vfio_listener_region_add(MemoryListener *listener,
if (memory_region_has_ram_discard_manager(section->mr)) {
vfio_register_ram_discard_listener(bcontainer, section);
return;
+ } else if (memory_region_has_private_shared_manager(section->mr)) {
+ vfio_register_private_shared_listener(bcontainer, section);
+ return;
}
vaddr = memory_region_get_ram_ptr(section->mr) +
@@ -764,6 +844,10 @@ static void vfio_listener_region_del(MemoryListener *listener,
vfio_unregister_ram_discard_listener(bcontainer, section);
/* Unregistering will trigger an unmap. */
try_unmap = false;
+ } else if (memory_region_has_private_shared_manager(section->mr)) {
+ vfio_unregister_private_shared_listener(bcontainer, section);
+ /* Unregistering will trigger an unmap. */
+ try_unmap = false;
}
if (try_unmap) {
diff --git a/hw/vfio/container-base.c b/hw/vfio/container-base.c
index 749a3fd29d..ff5df925c2 100644
--- a/hw/vfio/container-base.c
+++ b/hw/vfio/container-base.c
@@ -135,6 +135,7 @@ static void vfio_container_instance_init(Object *obj)
bcontainer->iova_ranges = NULL;
QLIST_INIT(&bcontainer->giommu_list);
QLIST_INIT(&bcontainer->vrdl_list);
+ QLIST_INIT(&bcontainer->vpsl_list);
}
static const TypeInfo types[] = {
diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h
index 4cff9943ab..8d7c0b1179 100644
--- a/include/hw/vfio/vfio-container-base.h
+++ b/include/hw/vfio/vfio-container-base.h
@@ -47,6 +47,7 @@ typedef struct VFIOContainerBase {
bool dirty_pages_started; /* Protected by BQL */
QLIST_HEAD(, VFIOGuestIOMMU) giommu_list;
QLIST_HEAD(, VFIORamDiscardListener) vrdl_list;
+ QLIST_HEAD(, VFIOPrivateSharedListener) vpsl_list;
QLIST_ENTRY(VFIOContainerBase) next;
QLIST_HEAD(, VFIODevice) device_list;
GList *iova_ranges;
@@ -71,6 +72,15 @@ typedef struct VFIORamDiscardListener {
QLIST_ENTRY(VFIORamDiscardListener) next;
} VFIORamDiscardListener;
+typedef struct VFIOPrivateSharedListener {
+ VFIOContainerBase *bcontainer;
+ MemoryRegion *mr;
+ hwaddr offset_within_address_space;
+ uint64_t granularity;
+ PrivateSharedListener listener;
+ QLIST_ENTRY(VFIOPrivateSharedListener) next;
+} VFIOPrivateSharedListener;
+
int vfio_container_dma_map(VFIOContainerBase *bcontainer,
hwaddr iova, ram_addr_t size,
void *vaddr, bool readonly);
--
2.43.5
next prev parent reply other threads:[~2025-04-07 7:51 UTC|newest]
Thread overview: 67+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-07 7:49 [PATCH v4 00/13] Enable shared device assignment Chenyi Qiang
2025-04-07 7:49 ` [PATCH v4 01/13] memory: Export a helper to get intersection of a MemoryRegionSection with a given range Chenyi Qiang
2025-04-09 2:47 ` Alexey Kardashevskiy
2025-04-09 6:26 ` Chenyi Qiang
2025-04-09 6:45 ` Alexey Kardashevskiy
2025-04-09 7:38 ` Chenyi Qiang
2025-05-12 3:24 ` Zhao Liu
2025-04-07 7:49 ` [PATCH v4 02/13] memory: Change memory_region_set_ram_discard_manager() to return the result Chenyi Qiang
2025-04-07 9:53 ` Xiaoyao Li
2025-04-08 0:50 ` Chenyi Qiang
2025-04-09 5:35 ` Alexey Kardashevskiy
2025-04-09 5:52 ` Chenyi Qiang
2025-04-25 12:35 ` David Hildenbrand
2025-04-07 7:49 ` [PATCH v4 03/13] memory: Unify the definiton of ReplayRamPopulate() and ReplayRamDiscard() Chenyi Qiang
2025-04-09 5:43 ` Alexey Kardashevskiy
2025-04-09 6:56 ` Chenyi Qiang
2025-04-25 12:44 ` David Hildenbrand
2025-04-25 12:42 ` David Hildenbrand
2025-04-27 2:13 ` Chenyi Qiang
2025-04-07 7:49 ` [PATCH v4 04/13] memory: Introduce generic state change parent class for RamDiscardManager Chenyi Qiang
2025-04-09 9:56 ` Alexey Kardashevskiy
2025-04-09 12:57 ` Chenyi Qiang
2025-04-10 0:11 ` Alexey Kardashevskiy
2025-04-10 1:44 ` Chenyi Qiang
2025-04-16 3:32 ` Chenyi Qiang
2025-04-17 23:10 ` Alexey Kardashevskiy
2025-04-18 3:49 ` Chenyi Qiang
2025-04-25 12:54 ` David Hildenbrand
2025-04-25 12:49 ` David Hildenbrand
2025-04-27 1:33 ` Chenyi Qiang
2025-04-07 7:49 ` [PATCH v4 05/13] memory: Introduce PrivateSharedManager Interface as child of GenericStateManager Chenyi Qiang
2025-04-09 9:56 ` Alexey Kardashevskiy
2025-04-10 3:47 ` Chenyi Qiang
2025-04-25 12:57 ` David Hildenbrand
2025-04-27 1:40 ` Chenyi Qiang
2025-04-29 10:01 ` David Hildenbrand
2025-04-07 7:49 ` Chenyi Qiang [this message]
2025-04-09 9:58 ` [PATCH v4 06/13] vfio: Add the support for PrivateSharedManager Interface Alexey Kardashevskiy
2025-04-10 5:53 ` Chenyi Qiang
2025-04-07 7:49 ` [PATCH v4 07/13] ram-block-attribute: Introduce RamBlockAttribute to manage RAMBLock with guest_memfd Chenyi Qiang
2025-04-09 9:57 ` Alexey Kardashevskiy
2025-04-10 7:37 ` Chenyi Qiang
2025-05-09 6:41 ` Baolu Lu
2025-05-09 7:55 ` Chenyi Qiang
2025-05-09 8:18 ` David Hildenbrand
2025-05-09 10:37 ` Chenyi Qiang
2025-05-12 8:07 ` Zhao Liu
2025-05-12 9:43 ` Chenyi Qiang
2025-05-13 8:31 ` Zhao Liu
2025-05-14 1:39 ` Chenyi Qiang
2025-04-07 7:49 ` [PATCH v4 08/13] ram-block-attribute: Introduce a callback to notify shared/private state changes Chenyi Qiang
2025-04-07 7:49 ` [PATCH v4 09/13] memory: Attach RamBlockAttribute to guest_memfd-backed RAMBlocks Chenyi Qiang
2025-04-07 7:49 ` [PATCH v4 10/13] memory: Change NotifyStateClear() definition to return the result Chenyi Qiang
2025-04-27 2:26 ` Chenyi Qiang
2025-05-09 2:38 ` Chao Gao
2025-05-09 8:20 ` David Hildenbrand
2025-05-09 9:19 ` Chenyi Qiang
2025-05-09 8:22 ` Baolu Lu
2025-05-09 10:04 ` Chenyi Qiang
2025-05-12 7:54 ` David Hildenbrand
2025-04-07 7:49 ` [PATCH v4 11/13] KVM: Introduce CVMPrivateSharedListener for attribute changes during page conversions Chenyi Qiang
2025-05-09 9:03 ` Baolu Lu
2025-05-12 3:18 ` Chenyi Qiang
2025-04-07 7:49 ` [PATCH v4 12/13] ram-block-attribute: Add priority listener support for PrivateSharedListener Chenyi Qiang
2025-05-09 9:23 ` Baolu Lu
2025-05-09 9:39 ` Chenyi Qiang
2025-04-07 7:49 ` [PATCH v4 13/13] RAMBlock: Make guest_memfd require coordinate discard Chenyi Qiang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250407074939.18657-7-chenyi.qiang@intel.com \
--to=chenyi.qiang@intel.com \
--cc=aik@amd.com \
--cc=chao.gao@intel.com \
--cc=chao.p.peng@intel.com \
--cc=dan.j.williams@intel.com \
--cc=david@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=michael.roth@amd.com \
--cc=pankaj.gupta@amd.com \
--cc=pbonzini@redhat.com \
--cc=peterx@redhat.com \
--cc=philmd@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=xiaoyao.li@intel.com \
--cc=yilun.xu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).