On 2/24/2022 12:56 PM, Dr. David Alan Gilbert wrote: > * Steve Sistare (steven.sist...@oracle.com) wrote: >> Allocate anonymous memory using memfd_create if the memfd-alloc machine >> option is set. >> >> Signed-off-by: Steve Sistare <steven.sist...@oracle.com> > > So other than the minor error nit that Guoyi spotted, I think this is > pretty good, one other comment below: > >> --- >> hw/core/machine.c | 19 +++++++++++++++++++ >> include/hw/boards.h | 1 + >> qemu-options.hx | 6 ++++++ >> softmmu/physmem.c | 47 ++++++++++++++++++++++++++++++++++++++--------- >> softmmu/vl.c | 1 + >> trace-events | 1 + >> util/qemu-config.c | 4 ++++ >> 7 files changed, 70 insertions(+), 9 deletions(-) >> >> diff --git a/hw/core/machine.c b/hw/core/machine.c >> index 53a99ab..7739d88 100644 >> --- a/hw/core/machine.c >> +++ b/hw/core/machine.c >> @@ -392,6 +392,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); >> @@ -829,6 +843,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", >> diff --git a/include/hw/boards.h b/include/hw/boards.h >> index 9c1c190..a57d7a0 100644 >> --- a/include/hw/boards.h >> +++ b/include/hw/boards.h >> @@ -327,6 +327,7 @@ struct MachineState { >> char *dt_compatible; >> bool dump_guest_core; >> bool mem_merge; >> + bool memfd_alloc; >> bool usb; >> bool usb_disabled; >> char *firmware; >> diff --git a/qemu-options.hx b/qemu-options.hx >> index 7d47510..33c8173 100644 >> --- a/qemu-options.hx >> +++ b/qemu-options.hx >> @@ -30,6 +30,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" >> @@ -76,6 +77,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 >> diff --git a/softmmu/physmem.c b/softmmu/physmem.c >> index 3524c04..95e2b49 100644 >> --- a/softmmu/physmem.c >> +++ b/softmmu/physmem.c >> @@ -41,6 +41,7 @@ >> #include "qemu/config-file.h" >> #include "qemu/error-report.h" >> #include "qemu/qemu-print.h" >> +#include "qemu/memfd.h" >> #include "exec/memory.h" >> #include "exec/ioport.h" >> #include "sysemu/dma.h" >> @@ -1964,35 +1965,63 @@ static void ram_block_add(RAMBlock *new_block, Error >> **errp) >> const bool shared = qemu_ram_is_shared(new_block); >> RAMBlock *block; >> RAMBlock *last_block = NULL; >> + struct MemoryRegion *mr = new_block->mr; >> ram_addr_t old_ram_size, new_ram_size; >> Error *err = NULL; >> + const char *name; >> + void *addr = 0; >> + size_t maxlen; > > You could move some of these down to the top of the block you're using > them.
Will do. One question: I added this to shorten lines and make my code additions more readable: size_t maxlen; maxlen = new_block->max_length; However, I did not change new_block->max_length to maxlen in the second half of the function which I did not modify, to avoid noise in the patch that is unrelated to cpr. Making those changes would shorten a few multi-liners. What is your preference -- make those changes or not? - Steve >> + MachineState *ms = MACHINE(qdev_get_machine()); >> >> old_ram_size = last_ram_page(); >> >> qemu_mutex_lock_ramlist(); >> - new_block->offset = find_ram_offset(new_block->max_length); >> + maxlen = new_block->max_length; >> + new_block->offset = find_ram_offset(maxlen); >> >> if (!new_block->host) { >> if (xen_enabled()) { >> - xen_ram_alloc(new_block->offset, new_block->max_length, >> - new_block->mr, &err); >> + xen_ram_alloc(new_block->offset, maxlen, new_block->mr, &err); >> if (err) { >> error_propagate(errp, err); >> qemu_mutex_unlock_ramlist(); >> return; >> } >> } else { >> - new_block->host = qemu_anon_ram_alloc(new_block->max_length, >> - &new_block->mr->align, >> - shared, noreserve); >> - if (!new_block->host) { >> + name = memory_region_name(mr); >> + if (ms->memfd_alloc) { >> + Object *parent = &mr->parent_obj; >> + int mfd = -1; /* placeholder until next patch */ >> + mr->align = QEMU_VMALLOC_ALIGN; >> + if (mfd < 0) { >> + mfd = qemu_memfd_create(name, maxlen + mr->align, >> + 0, 0, 0, &err); >> + if (mfd < 0) { >> + return; >> + } >> + } >> + qemu_set_cloexec(mfd); >> + /* The memory backend already set its desired flags. */ >> + if (!object_dynamic_cast(parent, TYPE_MEMORY_BACKEND)) { >> + new_block->flags |= RAM_SHARED; >> + } >> + addr = file_ram_alloc(new_block, maxlen, mfd, >> + false, false, 0, errp); >> + trace_anon_memfd_alloc(name, maxlen, addr, mfd); >> + } else { >> + addr = qemu_anon_ram_alloc(maxlen, &mr->align, >> + shared, noreserve); >> + } >> + >> + if (!addr) { >> error_setg_errno(errp, errno, >> "cannot set up guest memory '%s'", >> - memory_region_name(new_block->mr)); >> + name); >> qemu_mutex_unlock_ramlist(); >> return; >> } >> - memory_try_enable_merging(new_block->host, >> new_block->max_length); >> + memory_try_enable_merging(addr, maxlen); >> + new_block->host = addr; >> } >> } >> >> diff --git a/softmmu/vl.c b/softmmu/vl.c >> index 620a1f1..ab3648a 100644 >> --- a/softmmu/vl.c >> +++ b/softmmu/vl.c >> @@ -2440,6 +2440,7 @@ static void create_default_memdev(MachineState *ms, >> const char *path) >> object_property_set_str(obj, "mem-path", path, &error_fatal); >> } >> object_property_set_int(obj, "size", ms->ram_size, &error_fatal); >> + object_property_set_bool(obj, "share", ms->memfd_alloc, &error_fatal); >> 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 */ >> diff --git a/trace-events b/trace-events >> index a637a61..770a9ac 100644 >> --- a/trace-events >> +++ b/trace-events >> @@ -45,6 +45,7 @@ ram_block_discard_range(const char *rbname, void *hva, >> size_t length, bool need_ >> # accel/tcg/cputlb.c >> memory_notdirty_write_access(uint64_t vaddr, uint64_t ram_addr, unsigned >> size) "0x%" PRIx64 " ram_addr 0x%" PRIx64 " size %u" >> memory_notdirty_set_dirty(uint64_t vaddr) "0x%" PRIx64 >> +anon_memfd_alloc(const char *name, size_t size, void *ptr, int fd) "%s size >> %zu ptr %p fd %d" >> >> # gdbstub.c >> gdbstub_op_start(const char *device) "Starting gdbstub using device %s" >> diff --git a/util/qemu-config.c b/util/qemu-config.c >> index 436ab63..3606e5c 100644 >> --- a/util/qemu-config.c >> +++ b/util/qemu-config.c >> @@ -207,6 +207,10 @@ static QemuOptsList machine_opts = { >> .type = QEMU_OPT_BOOL, >> .help = "enable/disable memory merge support", >> },{ >> + .name = "memfd-alloc", >> + .type = QEMU_OPT_BOOL, >> + .help = "enable/disable memfd_create for anonymous memory", >> + },{ >> .name = "usb", >> .type = QEMU_OPT_BOOL, >> .help = "Set on/off to enable/disable usb", >> -- >> 1.8.3.1 >>