qemu/backends/hostmem-memfd.c
<<
>>
Prefs
   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 "sysemu/sysemu.h"
  16#include "qom/object_interfaces.h"
  17#include "qemu/memfd.h"
  18#include "qemu/module.h"
  19#include "qapi/error.h"
  20#include "qom/object.h"
  21
  22#define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
  23
  24OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendMemfd, MEMORY_BACKEND_MEMFD)
  25
  26
  27struct HostMemoryBackendMemfd {
  28    HostMemoryBackend parent_obj;
  29
  30    bool hugetlb;
  31    uint64_t hugetlbsize;
  32    bool seal;
  33};
  34
  35static void
  36memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
  37{
  38    HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(backend);
  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    memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
  57                                   name, backend->size,
  58                                   backend->share, fd, 0, errp);
  59    g_free(name);
  60}
  61
  62static bool
  63memfd_backend_get_hugetlb(Object *o, Error **errp)
  64{
  65    return MEMORY_BACKEND_MEMFD(o)->hugetlb;
  66}
  67
  68static void
  69memfd_backend_set_hugetlb(Object *o, bool value, Error **errp)
  70{
  71    MEMORY_BACKEND_MEMFD(o)->hugetlb = value;
  72}
  73
  74static void
  75memfd_backend_set_hugetlbsize(Object *obj, Visitor *v, const char *name,
  76                              void *opaque, Error **errp)
  77{
  78    HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
  79    uint64_t value;
  80
  81    if (host_memory_backend_mr_inited(MEMORY_BACKEND(obj))) {
  82        error_setg(errp, "cannot change property value");
  83        return;
  84    }
  85
  86    if (!visit_type_size(v, name, &value, errp)) {
  87        return;
  88    }
  89    if (!value) {
  90        error_setg(errp, "Property '%s.%s' doesn't take value '%" PRIu64 "'",
  91                   object_get_typename(obj), name, value);
  92        return;
  93    }
  94    m->hugetlbsize = value;
  95}
  96
  97static void
  98memfd_backend_get_hugetlbsize(Object *obj, Visitor *v, const char *name,
  99                              void *opaque, Error **errp)
 100{
 101    HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
 102    uint64_t value = m->hugetlbsize;
 103
 104    visit_type_size(v, name, &value, errp);
 105}
 106
 107static bool
 108memfd_backend_get_seal(Object *o, Error **errp)
 109{
 110    return MEMORY_BACKEND_MEMFD(o)->seal;
 111}
 112
 113static void
 114memfd_backend_set_seal(Object *o, bool value, Error **errp)
 115{
 116    MEMORY_BACKEND_MEMFD(o)->seal = value;
 117}
 118
 119static void
 120memfd_backend_instance_init(Object *obj)
 121{
 122    HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
 123
 124    /* default to sealed file */
 125    m->seal = true;
 126    MEMORY_BACKEND(m)->share = true;
 127}
 128
 129static void
 130memfd_backend_class_init(ObjectClass *oc, void *data)
 131{
 132    HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
 133
 134    bc->alloc = memfd_backend_memory_alloc;
 135
 136    if (qemu_memfd_check(MFD_HUGETLB)) {
 137        object_class_property_add_bool(oc, "hugetlb",
 138                                       memfd_backend_get_hugetlb,
 139                                       memfd_backend_set_hugetlb);
 140        object_class_property_set_description(oc, "hugetlb",
 141                                              "Use huge pages");
 142        object_class_property_add(oc, "hugetlbsize", "int",
 143                                  memfd_backend_get_hugetlbsize,
 144                                  memfd_backend_set_hugetlbsize,
 145                                  NULL, NULL);
 146        object_class_property_set_description(oc, "hugetlbsize",
 147                                              "Huge pages size (ex: 2M, 1G)");
 148    }
 149    object_class_property_add_bool(oc, "seal",
 150                                   memfd_backend_get_seal,
 151                                   memfd_backend_set_seal);
 152    object_class_property_set_description(oc, "seal",
 153                                          "Seal growing & shrinking");
 154}
 155
 156static const TypeInfo memfd_backend_info = {
 157    .name = TYPE_MEMORY_BACKEND_MEMFD,
 158    .parent = TYPE_MEMORY_BACKEND,
 159    .instance_init = memfd_backend_instance_init,
 160    .class_init = memfd_backend_class_init,
 161    .instance_size = sizeof(HostMemoryBackendMemfd),
 162};
 163
 164static void register_types(void)
 165{
 166    if (qemu_memfd_check(MFD_ALLOW_SEALING)) {
 167        type_register_static(&memfd_backend_info);
 168    }
 169}
 170
 171type_init(register_types);
 172