On 30/5/25 18:32, Chenyi Qiang wrote:
A new field, attributes, was introduced in RAMBlock to link to a
RamBlockAttributes object, which centralizes all guest_memfd related
information (such as fd and shared bitmap) within a RAMBlock.

Create and initialize the RamBlockAttributes 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 can execute RamDiscardManager
specific handling. For example, VFIO will register the
RamDiscardListener and get notifications when the state_change() helper
invokes.

As coordinate discarding of RAM with guest_memfd is now supported, only
block uncoordinated discard.

Signed-off-by: Chenyi Qiang <chenyi.qi...@intel.com>


Tested-by: Alexey Kardashevskiy <a...@amd.com>
Reviewed-by: Alexey Kardashevskiy <a...@amd.com>


---
Changes in v6:
     - Squash the unblocking of cooridnate discard into this commit.
     - Remove the checks in migration path.

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.
---
  accel/kvm/kvm-all.c       |  9 +++++++++
  include/system/ramblock.h |  1 +
  system/physmem.c          | 18 ++++++++++++++++--
  3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 51526d301b..3b390bbb09 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, bool 
to_private)
      addr = memory_region_get_ram_ptr(mr) + section.offset_within_region;
      rb = qemu_ram_block_from_host(addr, false, &offset);
+ ret = ram_block_attributes_state_change(RAM_BLOCK_ATTRIBUTES(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 != qemu_real_host_page_size()) {
              /*
diff --git a/include/system/ramblock.h b/include/system/ramblock.h
index 1bab9e2dac..87e847e184 100644
--- a/include/system/ramblock.h
+++ b/include/system/ramblock.h
@@ -46,6 +46,7 @@ struct RAMBlock {
      int fd;
      uint64_t fd_offset;
      int guest_memfd;
+    RamBlockAttributes *attributes;
      size_t page_size;
      /* dirty bitmap used during migration */
      unsigned long *bmap;
diff --git a/system/physmem.c b/system/physmem.c
index a8a9ca309e..1f1217fa0a 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);
- 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");
@@ -1931,6 +1931,19 @@ static void ram_block_add(RAMBlock *new_block, Error 
**errp)
              goto out_free;
          }
+ new_block->attributes = ram_block_attributes_create(new_block);
+        if (!new_block->attributes) {
+            error_setg(errp, "Failed to create ram block attribute");
+            /*
+             * The error path could be unified if the rest of ram_block_add()
+             * ever develops a need to check for errors.
+             */
+            close(new_block->guest_memfd);
+            ram_block_coordinated_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,8 +2300,9 @@ static void reclaim_ramblock(RAMBlock *block)
      }
if (block->guest_memfd >= 0) {
+        ram_block_attributes_destroy(block->attributes);
          close(block->guest_memfd);
-        ram_block_discard_require(false);
+        ram_block_coordinated_discard_require(false);
      }
g_free(block);

--
Alexey


Reply via email to