aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChenyi Qiang <chenyi.qiang@intel.com>2025-06-12 16:27:46 +0800
committerPeter Xu <peterx@redhat.com>2025-06-23 16:03:59 -0400
commit2fde3fb916079ee0ff0fc26d9446c813b1d5cc28 (patch)
tree27ffec7704fa6ab01c8b84de5b705d65855274af
parent5d6483edaa9232d8f3709f68c8eab4bc2033fb70 (diff)
downloadqemu-2fde3fb916079ee0ff0fc26d9446c813b1d5cc28.zip
qemu-2fde3fb916079ee0ff0fc26d9446c813b1d5cc28.tar.gz
qemu-2fde3fb916079ee0ff0fc26d9446c813b1d5cc28.tar.bz2
physmem: Support coordinated discarding of RAM with guest_memfd
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 status 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. Tested-by: Alexey Kardashevskiy <aik@amd.com> Reviewed-by: Alexey Kardashevskiy <aik@amd.com> Acked-by: David Hildenbrand <david@redhat.com> Signed-off-by: Chenyi Qiang <chenyi.qiang@intel.com> Link: https://lore.kernel.org/r/20250612082747.51539-6-chenyi.qiang@intel.com Signed-off-by: Peter Xu <peterx@redhat.com>
-rw-r--r--accel/kvm/kvm-all.c9
-rw-r--r--include/system/ramblock.h1
-rw-r--r--system/physmem.c23
3 files changed, 31 insertions, 2 deletions
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index a317783..d095d1b 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -3091,6 +3091,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 1bab9e2..87e847e 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 a8a9ca3..ff0ca40 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");
@@ -1932,6 +1932,24 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
}
/*
+ * The attribute bitmap of the RamBlockAttributes is default to
+ * discarded, which mimics the behavior of kvm_set_phys_mem() when it
+ * calls kvm_set_memory_attributes_private(). This leads to a brief
+ * period of inconsistency between the creation of the RAMBlock and its
+ * mapping into the physical address space. However, this is not
+ * problematic, as no users rely on the attribute status to perform
+ * any actions during this interval.
+ */
+ new_block->attributes = ram_block_attributes_create(new_block);
+ if (!new_block->attributes) {
+ error_setg(errp, "Failed to create ram block attribute");
+ 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 +2305,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);