@@ -443,6 +443,20 @@ static void machine_set_mem_merge(Object *obj, bool value, Error **errp)
ms->mem_merge = value;
}
+static bool machine_get_memfd_alloc(Object *obj, Error **errp)
+{
+ MachineState *ms = MACHINE(obj);
+
+ return ms->memfd_alloc;
+}
+
+static void machine_set_memfd_alloc(Object *obj, bool value, Error **errp)
+{
+ MachineState *ms = MACHINE(obj);
+
+ ms->memfd_alloc = value;
+}
+
static bool machine_get_usb(Object *obj, Error **errp)
{
MachineState *ms = MACHINE(obj);
@@ -1044,6 +1058,11 @@ static void machine_class_init(ObjectClass *oc, void *data)
object_class_property_set_description(oc, "mem-merge",
"Enable/disable memory merge support");
+ object_class_property_add_bool(oc, "memfd-alloc",
+ machine_get_memfd_alloc, machine_set_memfd_alloc);
+ object_class_property_set_description(oc, "memfd-alloc",
+ "Enable/disable allocating anonymous memory using memfd_create");
+
object_class_property_add_bool(oc, "usb",
machine_get_usb, machine_set_usb);
object_class_property_set_description(oc, "usb",
@@ -1387,6 +1406,9 @@ static bool create_default_memdev(MachineState *ms, const char *path, Error **er
if (!object_property_set_int(obj, "size", ms->ram_size, errp)) {
goto out;
}
+ if (!object_property_set_bool(obj, "share", ms->memfd_alloc, errp)) {
+ goto out;
+ }
object_property_add_child(object_get_objects_root(), mc->default_ram_id,
obj);
/* Ensure backend's memory region name is equal to mc->default_ram_id */
@@ -372,6 +372,7 @@ struct MachineState {
bool dump_guest_core;
bool mem_merge;
bool require_guest_memfd;
+ bool memfd_alloc;
bool usb;
bool usb_disabled;
char *firmware;
@@ -32,6 +32,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
" vmport=on|off|auto controls emulation of vmport (default: auto)\n"
" dump-guest-core=on|off include guest memory in a core dump (default=on)\n"
" mem-merge=on|off controls memory merge support (default: on)\n"
+ " memfd-alloc=on|off controls allocating anonymous guest RAM using memfd_create (default: off)\n"
" aes-key-wrap=on|off controls support for AES key wrapping (default=on)\n"
" dea-key-wrap=on|off controls support for DEA key wrapping (default=on)\n"
" suppress-vmdesc=on|off disables self-describing migration (default=off)\n"
@@ -79,6 +80,11 @@ SRST
supported by the host, de-duplicates identical memory pages
among VMs instances (enabled by default).
+ ``memfd-alloc=on|off``
+ Enables or disables allocation of anonymous guest RAM using
+ memfd_create. Any associated memory-backend objects are created with
+ share=on. The memfd-alloc default is off.
+
``aes-key-wrap=on|off``
Enables or disables AES key wrapping support on s390-ccw hosts.
This feature controls whether AES wrapping keys will be created
@@ -1552,8 +1552,9 @@ bool memory_region_init_ram_nomigrate(MemoryRegion *mr,
uint64_t size,
Error **errp)
{
+ uint32_t flags = current_machine->memfd_alloc ? RAM_SHARED : 0;
return memory_region_init_ram_flags_nomigrate(mr, owner, name,
- size, 0, errp);
+ size, flags, errp);
}
bool memory_region_init_ram_flags_nomigrate(MemoryRegion *mr,
@@ -1713,8 +1714,9 @@ bool memory_region_init_rom_nomigrate(MemoryRegion *mr,
uint64_t size,
Error **errp)
{
+ uint32_t flags = current_machine->memfd_alloc ? RAM_SHARED : 0;
if (!memory_region_init_ram_flags_nomigrate(mr, owner, name,
- size, 0, errp)) {
+ size, flags, errp)) {
return false;
}
mr->readonly = true;
@@ -1731,6 +1733,7 @@ bool memory_region_init_rom_device_nomigrate(MemoryRegion *mr,
Error **errp)
{
Error *err = NULL;
+ uint32_t flags = current_machine->memfd_alloc ? RAM_SHARED : 0;
assert(ops);
memory_region_init(mr, owner, name, size);
mr->ops = ops;
@@ -1738,7 +1741,7 @@ bool memory_region_init_rom_device_nomigrate(MemoryRegion *mr,
mr->terminates = true;
mr->rom_device = true;
mr->destructor = memory_region_destructor_ram;
- mr->ram_block = qemu_ram_alloc(size, 0, mr, &err);
+ mr->ram_block = qemu_ram_alloc(size, flags, mr, &err);
if (err) {
mr->size = int128_zero();
object_unparent(OBJECT(mr));
@@ -45,6 +45,7 @@
#include "qemu/qemu-print.h"
#include "qemu/log.h"
#include "qemu/memalign.h"
+#include "qemu/memfd.h"
#include "exec/memory.h"
#include "exec/ioport.h"
#include "sysemu/dma.h"
@@ -1825,6 +1826,19 @@ static void *ram_block_alloc_host(RAMBlock *rb, Error **errp)
if (xen_enabled()) {
xen_ram_alloc(rb->offset, rb->max_length, mr, errp);
+ } else if (rb->flags & RAM_SHARED) {
+ if (rb->fd == -1) {
+ mr->align = QEMU_VMALLOC_ALIGN;
+ rb->fd = qemu_memfd_create(rb->idstr, rb->max_length + mr->align,
+ 0, 0, 0, errp);
+ }
+ if (rb->fd >= 0) {
+ int mfd = rb->fd;
+ qemu_set_cloexec(mfd);
+ host = file_ram_alloc(rb, rb->max_length, mfd, false, 0, errp);
+ trace_qemu_anon_memfd_alloc(rb->idstr, rb->max_length, mfd, host);
+ }
+
} else {
host = qemu_anon_ram_alloc(rb->max_length, &mr->align,
qemu_ram_is_shared(rb),
@@ -2106,8 +2120,10 @@ RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t maxsz,
void *host),
MemoryRegion *mr, Error **errp)
{
+ uint32_t flags = current_machine->memfd_alloc ? RAM_SHARED : 0;
+ flags |= RAM_RESIZEABLE;
return qemu_ram_alloc_internal(size, maxsz, resized, NULL,
- RAM_RESIZEABLE, mr, errp);
+ flags, mr, errp);
}
static void reclaim_ramblock(RAMBlock *block)
@@ -41,3 +41,4 @@ dirtylimit_vcpu_execute(int cpu_index, int64_t sleep_time_us) "CPU[%d] sleep %"P
# physmem.c
ram_block_create(const char *name, uint32_t flags, int fd, size_t used_length, size_t max_length, size_t align) "%s, flags %u, fd %d, len %lu, maxlen %lu, align %lu"
+qemu_anon_memfd_alloc(const char *name, size_t size, int fd, void *ptr) "%s size %zu fd %d -> %p"
Allocate anonymous memory using memfd_create if the memfd-alloc machine option is set. Signed-off-by: Steve Sistare <steven.sistare@oracle.com> --- hw/core/machine.c | 22 ++++++++++++++++++++++ include/hw/boards.h | 1 + qemu-options.hx | 6 ++++++ system/memory.c | 9 ++++++--- system/physmem.c | 18 +++++++++++++++++- system/trace-events | 1 + 6 files changed, 53 insertions(+), 4 deletions(-)