It's used for discarding opposite memory after memory conversion, for confidential guest. When page is converted from shared to private, the original shared memory can be discarded via ram_block_discard_range(); When page is converted from private to shared, the original private memory is back'ed by guest_memfd. Introduce ram_block_discard_guest_memfd_range() for discarding memory in guest_memfd. Originally-from: Isaku Yamahata <isaku.yamahata@xxxxxxxxx> Codeveloped-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx> Signed-off-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx> --- include/exec/cpu-common.h | 2 ++ system/physmem.c | 50 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 41115d891940..de728a18eef2 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -175,6 +175,8 @@ typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque); int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque); int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length); +int ram_block_convert_range(RAMBlock *rb, uint64_t start, size_t length, + bool shared_to_private); #endif diff --git a/system/physmem.c b/system/physmem.c index ddfecddefcd6..cd6008fa09ad 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -3641,6 +3641,29 @@ err: return ret; } +static int ram_block_discard_guest_memfd_range(RAMBlock *rb, uint64_t start, + size_t length) +{ + int ret = -1; + +#ifdef CONFIG_FALLOCATE_PUNCH_HOLE + ret = fallocate(rb->guest_memfd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + start, length); + + if (ret) { + ret = -errno; + error_report("%s: Failed to fallocate %s:%" PRIx64 " +%zx (%d)", + __func__, rb->idstr, start, length, ret); + } +#else + ret = -ENOSYS; + error_report("%s: fallocate not available %s:%" PRIx64 " +%zx (%d)", + __func__, rb->idstr, start, length, ret); +#endif + + return ret; +} + bool ramblock_is_pmem(RAMBlock *rb) { return rb->flags & RAM_PMEM; @@ -3828,3 +3851,30 @@ bool ram_block_discard_is_required(void) return qatomic_read(&ram_block_discard_required_cnt) || qatomic_read(&ram_block_coordinated_discard_required_cnt); } + +int ram_block_convert_range(RAMBlock *rb, uint64_t start, size_t length, + bool shared_to_private) +{ + if (!rb || rb->guest_memfd < 0) { + return -1; + } + + if (!QEMU_PTR_IS_ALIGNED(start, qemu_host_page_size) || + !QEMU_PTR_IS_ALIGNED(length, qemu_host_page_size)) { + return -1; + } + + if (!length) { + return -1; + } + + if (start + length > rb->max_length) { + return -1; + } + + if (shared_to_private) { + return ram_block_discard_range(rb, start, length); + } else { + return ram_block_discard_guest_memfd_range(rb, start, length); + } +} -- 2.34.1