qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

hostmem-memfd.c (4904B)


      1 /*
      2  * QEMU host memfd memory backend
      3  *
      4  * Copyright (C) 2018 Red Hat Inc
      5  *
      6  * Authors:
      7  *   Marc-André Lureau <marcandre.lureau@redhat.com>
      8  *
      9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10  * See the COPYING file in the top-level directory.
     11  */
     12 
     13 #include "qemu/osdep.h"
     14 #include "sysemu/hostmem.h"
     15 #include "qom/object_interfaces.h"
     16 #include "qemu/memfd.h"
     17 #include "qemu/module.h"
     18 #include "qapi/error.h"
     19 #include "qom/object.h"
     20 
     21 #define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
     22 
     23 OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendMemfd, MEMORY_BACKEND_MEMFD)
     24 
     25 
     26 struct HostMemoryBackendMemfd {
     27     HostMemoryBackend parent_obj;
     28 
     29     bool hugetlb;
     30     uint64_t hugetlbsize;
     31     bool seal;
     32 };
     33 
     34 static void
     35 memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
     36 {
     37     HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(backend);
     38     uint32_t ram_flags;
     39     char *name;
     40     int fd;
     41 
     42     if (!backend->size) {
     43         error_setg(errp, "can't create backend with size 0");
     44         return;
     45     }
     46 
     47     fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD, backend->size,
     48                            m->hugetlb, m->hugetlbsize, m->seal ?
     49                            F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL : 0,
     50                            errp);
     51     if (fd == -1) {
     52         return;
     53     }
     54 
     55     name = host_memory_backend_get_name(backend);
     56     ram_flags = backend->share ? RAM_SHARED : 0;
     57     ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
     58     memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
     59                                    backend->size, ram_flags, fd, 0, errp);
     60     g_free(name);
     61 }
     62 
     63 static bool
     64 memfd_backend_get_hugetlb(Object *o, Error **errp)
     65 {
     66     return MEMORY_BACKEND_MEMFD(o)->hugetlb;
     67 }
     68 
     69 static void
     70 memfd_backend_set_hugetlb(Object *o, bool value, Error **errp)
     71 {
     72     MEMORY_BACKEND_MEMFD(o)->hugetlb = value;
     73 }
     74 
     75 static void
     76 memfd_backend_set_hugetlbsize(Object *obj, Visitor *v, const char *name,
     77                               void *opaque, Error **errp)
     78 {
     79     HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
     80     uint64_t value;
     81 
     82     if (host_memory_backend_mr_inited(MEMORY_BACKEND(obj))) {
     83         error_setg(errp, "cannot change property value");
     84         return;
     85     }
     86 
     87     if (!visit_type_size(v, name, &value, errp)) {
     88         return;
     89     }
     90     if (!value) {
     91         error_setg(errp, "Property '%s.%s' doesn't take value '%" PRIu64 "'",
     92                    object_get_typename(obj), name, value);
     93         return;
     94     }
     95     m->hugetlbsize = value;
     96 }
     97 
     98 static void
     99 memfd_backend_get_hugetlbsize(Object *obj, Visitor *v, const char *name,
    100                               void *opaque, Error **errp)
    101 {
    102     HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
    103     uint64_t value = m->hugetlbsize;
    104 
    105     visit_type_size(v, name, &value, errp);
    106 }
    107 
    108 static bool
    109 memfd_backend_get_seal(Object *o, Error **errp)
    110 {
    111     return MEMORY_BACKEND_MEMFD(o)->seal;
    112 }
    113 
    114 static void
    115 memfd_backend_set_seal(Object *o, bool value, Error **errp)
    116 {
    117     MEMORY_BACKEND_MEMFD(o)->seal = value;
    118 }
    119 
    120 static void
    121 memfd_backend_instance_init(Object *obj)
    122 {
    123     HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
    124 
    125     /* default to sealed file */
    126     m->seal = true;
    127     MEMORY_BACKEND(m)->share = true;
    128 }
    129 
    130 static void
    131 memfd_backend_class_init(ObjectClass *oc, void *data)
    132 {
    133     HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
    134 
    135     bc->alloc = memfd_backend_memory_alloc;
    136 
    137     if (qemu_memfd_check(MFD_HUGETLB)) {
    138         object_class_property_add_bool(oc, "hugetlb",
    139                                        memfd_backend_get_hugetlb,
    140                                        memfd_backend_set_hugetlb);
    141         object_class_property_set_description(oc, "hugetlb",
    142                                               "Use huge pages");
    143         object_class_property_add(oc, "hugetlbsize", "int",
    144                                   memfd_backend_get_hugetlbsize,
    145                                   memfd_backend_set_hugetlbsize,
    146                                   NULL, NULL);
    147         object_class_property_set_description(oc, "hugetlbsize",
    148                                               "Huge pages size (ex: 2M, 1G)");
    149     }
    150     object_class_property_add_bool(oc, "seal",
    151                                    memfd_backend_get_seal,
    152                                    memfd_backend_set_seal);
    153     object_class_property_set_description(oc, "seal",
    154                                           "Seal growing & shrinking");
    155 }
    156 
    157 static const TypeInfo memfd_backend_info = {
    158     .name = TYPE_MEMORY_BACKEND_MEMFD,
    159     .parent = TYPE_MEMORY_BACKEND,
    160     .instance_init = memfd_backend_instance_init,
    161     .class_init = memfd_backend_class_init,
    162     .instance_size = sizeof(HostMemoryBackendMemfd),
    163 };
    164 
    165 static void register_types(void)
    166 {
    167     if (qemu_memfd_check(MFD_ALLOW_SEALING)) {
    168         type_register_static(&memfd_backend_info);
    169     }
    170 }
    171 
    172 type_init(register_types);