From: Chao Peng <chao.p.peng@xxxxxxxxxxxxxxx> This new routine adds support for memory conversion between shared/private memory for gmem fd based private ram_block. Signed-off-by: Chao Peng <chao.p.peng@xxxxxxxxxxxxxxx> Signed-off-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx> --- include/exec/cpu-common.h | 2 ++ softmmu/physmem.c | 61 ++++++++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 87dc9a752c9a..558684b9f246 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -157,6 +157,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/softmmu/physmem.c b/softmmu/physmem.c index 05c981e5c18e..2acc8bee5b33 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -3415,15 +3415,9 @@ int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque) return ret; } -/* - * Unmap pages of memory from start to start+length such that - * they a) read as 0, b) Trigger whatever fault mechanism - * the OS provides for postcopy. - * The pages must be unmapped by the end of the function. - * Returns: 0 on success, none-0 on failure - * - */ -int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length) +static int ram_block_discard_range_fd(RAMBlock *rb, uint64_t start, + size_t length, int fd) + { int ret = -1; @@ -3449,8 +3443,8 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length) * fallocate works on hugepages and shmem * shared anonymous memory requires madvise REMOVE */ - need_madvise = (rb->page_size == qemu_host_page_size); - need_fallocate = rb->fd != -1; + need_madvise = (rb->page_size == qemu_host_page_size) && (rb->fd == fd); + need_fallocate = fd != -1; if (need_fallocate) { /* For a file, this causes the area of the file to be zero'd * if read, and for hugetlbfs also causes it to be unmapped @@ -3475,7 +3469,7 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length) " users of the file", __func__); } - ret = fallocate(rb->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + ret = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, start, length); if (ret) { ret = -errno; @@ -3498,7 +3492,7 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length) * fallocate'd away). */ #if defined(CONFIG_MADVISE) - if (qemu_ram_is_shared(rb) && rb->fd < 0) { + if (qemu_ram_is_shared(rb) && fd < 0) { ret = madvise(host_startaddr, length, QEMU_MADV_REMOVE); } else { ret = madvise(host_startaddr, length, QEMU_MADV_DONTNEED); @@ -3528,6 +3522,20 @@ err: return ret; } +/* + * Unmap pages of memory from start to start+length such that + * they a) read as 0, b) Trigger whatever fault mechanism + * the OS provides for postcopy. + * + * The pages must be unmapped by the end of the function. + * Returns: 0 on success, none-0 on failure. + */ +int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length) +{ + return ram_block_discard_range_fd(rb, start, length, rb->fd); +} + + bool ramblock_is_pmem(RAMBlock *rb) { return rb->flags & RAM_PMEM; @@ -3715,3 +3723,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) +{ + int fd; + + if (!rb || rb->gmem_fd < 0) { + return -1; + } + + if (!QEMU_PTR_IS_ALIGNED(start, rb->page_size) || + !QEMU_PTR_IS_ALIGNED(length, rb->page_size)) { + return -1; + } + + if (length > rb->max_length) { + return -1; + } + + if (shared_to_private) { + fd = rb->fd; + } else { + fd = rb->gmem_fd; + } + + return ram_block_discard_range_fd(rb, start, length, fd); +} -- 2.34.1