mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:17 +00:00
system/physmem: make ram_block_discard_range() handle guest_memfd
Most callers of ram_block_discard_range() want to discard both the shared and guest_memfd backing. Only kvm_convert_memory() intentionally discards a single plane during private/shared conversions. Rename the current implementation to ram_block_discard_shared_range() and make ram_block_discard_range() a composite that also discards guest_memfd when present (rb->guest_memfd >= 0). This ensures callers like virtio-mem, virtio-balloon, hv-balloon, migration.. reclaim private pages on discard. Update kvm_convert_memory() to use the plane-specific ram_block_discard_shared_range() since it only needs to discard the shared backing when converting to private. Likewise, after TDVF image copy, use ram_block_discard_shared_range(). Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Link: https://lore.kernel.org/r/20260604-rdm5-v5-11-5768e6a0943d@redhat.com Signed-off-by: Peter Xu <peterx@redhat.com>
This commit is contained in:
committed by
Peter Xu
parent
c2237aaf6d
commit
1f3241bcae
@@ -3422,7 +3422,7 @@ int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private)
|
||||
*/
|
||||
goto out_unref;
|
||||
}
|
||||
ret = ram_block_discard_range(rb, offset, size);
|
||||
ret = ram_block_discard_shared_range(rb, offset, size);
|
||||
} else {
|
||||
ret = ram_block_discard_guest_memfd_range(rb, offset, size);
|
||||
}
|
||||
|
||||
@@ -103,7 +103,8 @@ struct RamBlockAttributes {
|
||||
|
||||
/* @offset: the offset within the RAMBlock */
|
||||
int ram_block_discard_range(RAMBlock *rb, uint64_t offset, size_t length);
|
||||
/* @offset: the offset within the RAMBlock */
|
||||
int ram_block_discard_shared_range(RAMBlock *rb, uint64_t offset,
|
||||
size_t length);
|
||||
int ram_block_discard_guest_memfd_range(RAMBlock *rb, uint64_t offset,
|
||||
size_t length);
|
||||
|
||||
|
||||
@@ -4093,7 +4093,7 @@ int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque)
|
||||
* Returns: 0 on success, none-0 on failure
|
||||
*
|
||||
*/
|
||||
int ram_block_discard_range(RAMBlock *rb, uint64_t offset, size_t length)
|
||||
int ram_block_discard_shared_range(RAMBlock *rb, uint64_t offset, size_t length)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
@@ -4142,7 +4142,7 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t offset, size_t length)
|
||||
* have a MAP_PRIVATE mapping, possibly messing with other
|
||||
* MAP_PRIVATE/MAP_SHARED mappings. There is no easy way to
|
||||
* change that behavior whithout violating the promised
|
||||
* semantics of ram_block_discard_range().
|
||||
* semantics of ram_block_discard_shared_range().
|
||||
*
|
||||
* Only warn, because it works as long as nobody else uses that
|
||||
* file.
|
||||
@@ -4198,8 +4198,9 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t offset, size_t length)
|
||||
goto err;
|
||||
#endif
|
||||
}
|
||||
trace_ram_block_discard_range(rb->idstr, host_startaddr, length,
|
||||
need_madvise, need_fallocate, ret);
|
||||
trace_ram_block_discard_shared_range(rb->idstr, host_startaddr, length,
|
||||
need_madvise, need_fallocate,
|
||||
ret);
|
||||
} else {
|
||||
error_report("%s: Overrun block '%s' (%" PRIu64 "/%zx/" RAM_ADDR_FMT")",
|
||||
__func__, rb->idstr, offset, length, rb->max_length);
|
||||
@@ -4209,6 +4210,22 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ram_block_discard_range(RAMBlock *rb, uint64_t offset, size_t length)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ram_block_discard_shared_range(rb, offset, length);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rb->guest_memfd >= 0) {
|
||||
ret = ram_block_discard_guest_memfd_range(rb, offset, length);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ram_block_discard_guest_memfd_range(RAMBlock *rb, uint64_t offset,
|
||||
size_t length)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ global_dirty_changed(unsigned int bitmask) "bitmask 0x%"PRIx32
|
||||
address_space_map(void *as, uint64_t addr, uint64_t len, bool is_write, uint32_t attrs) "as:%p addr 0x%"PRIx64":%"PRIx64" write:%d attrs:0x%x"
|
||||
find_ram_offset(uint64_t size, uint64_t offset) "size: 0x%" PRIx64 " @ 0x%" PRIx64
|
||||
find_ram_offset_loop(uint64_t size, uint64_t candidate, uint64_t offset, uint64_t next, uint64_t mingap) "trying size: 0x%" PRIx64 " @ 0x%" PRIx64 ", offset: 0x%" PRIx64" next: 0x%" PRIx64 " mingap: 0x%" PRIx64
|
||||
ram_block_discard_range(const char *rbname, void *hva, size_t length, bool need_madvise, bool need_fallocate, int ret) "%s@%p + 0x%zx: madvise: %d fallocate: %d ret: %d"
|
||||
ram_block_discard_shared_range(const char *rbname, void *hva, size_t length, bool need_madvise, bool need_fallocate, int ret) "%s@%p + 0x%zx: madvise: %d fallocate: %d ret: %d"
|
||||
qemu_ram_alloc_shared(const char *name, size_t size, size_t max_size, int fd, void *host) "%s size %zu max_size %zu fd %d host %p"
|
||||
|
||||
subpage_register(void *subpage, uint32_t start, uint32_t end, int idx, int eidx, uint16_t section) "subpage %p start 0x%08x end 0x%08x idx 0x%08x eidx 0x%08x section %u"
|
||||
|
||||
@@ -385,7 +385,7 @@ static void tdx_finalize_vm(Notifier *notifier, void *unused)
|
||||
* KVM_MEMORY_MAPPING. It becomes useless.
|
||||
*/
|
||||
ram_block = tdx_guest->tdvf_mr->ram_block;
|
||||
ram_block_discard_range(ram_block, 0, ram_block->max_length);
|
||||
ram_block_discard_shared_range(ram_block, 0, ram_block->max_length);
|
||||
|
||||
tdx_vm_ioctl(KVM_TDX_FINALIZE_VM, 0, NULL, &error_fatal);
|
||||
CONFIDENTIAL_GUEST_SUPPORT(tdx_guest)->ready = true;
|
||||
|
||||
Reference in New Issue
Block a user