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#include "qemu/osdep.h"
  13#include "qemu-common.h"
  14#include "sysemu/hostmem.h"
  15#include "sysemu/sysemu.h"
  16#include "qom/object_interfaces.h"
  17#include "qemu/memfd.h"
  18#include "qapi/error.h"
  19
  20#define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
  21
  22#define MEMORY_BACKEND_MEMFD(obj)                                        \
  23    OBJECT_CHECK(HostMemoryBackendMemfd, (obj), TYPE_MEMORY_BACKEND_MEMFD)
  24
  25typedef struct HostMemoryBackendMemfd HostMemoryBackendMemfd;
  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    if (host_memory_backend_mr_inited(backend)) {
  48        return;
  49    }
  50
  51    backend->force_prealloc = mem_prealloc;
  52    fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD, backend->size,
  53                           m->hugetlb, m->hugetlbsize, m->seal ?
  54                           F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL : 0,
  55                           errp);
  56    if (fd == -1) {
  57        return;
  58    }
  59
  60    name = object_get_canonical_path(OBJECT(backend));
  61    memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
  62                                   name, backend->size, true, fd, errp);
  63    g_free(name);
  64}
  65
  66static bool
  67memfd_backend_get_hugetlb(Object *o, Error **errp)
  68{
  69    return MEMORY_BACKEND_MEMFD(o)->hugetlb;
  70}
  71
  72static void
  73memfd_backend_set_hugetlb(Object *o, bool value, Error **errp)
  74{
  75    MEMORY_BACKEND_MEMFD(o)->hugetlb = value;
  76}
  77
  78static void
  79memfd_backend_set_hugetlbsize(Object *obj, Visitor *v, const char *name,
  80                              void *opaque, Error **errp)
  81{
  82    HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
  83    Error *local_err = NULL;
  84    uint64_t value;
  85
  86    if (host_memory_backend_mr_inited(MEMORY_BACKEND(obj))) {
  87        error_setg(&local_err, "cannot change property value");
  88        goto out;
  89    }
  90
  91    visit_type_size(v, name, &value, &local_err);
  92    if (local_err) {
  93        goto out;
  94    }
  95    if (!value) {
  96        error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
  97                   PRIu64 "'", object_get_typename(obj), name, value);
  98        goto out;
  99    }
 100    m->hugetlbsize = value;
 101out:
 102    error_propagate(errp, local_err);
 103}
 104
 105static void
 106memfd_backend_get_hugetlbsize(Object *obj, Visitor *v, const char *name,
 107                              void *opaque, Error **errp)
 108{
 109    HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
 110    uint64_t value = m->hugetlbsize;
 111
 112    visit_type_size(v, name, &value, errp);
 113}
 114
 115static bool
 116memfd_backend_get_seal(Object *o, Error **errp)
 117{
 118    return MEMORY_BACKEND_MEMFD(o)->seal;
 119}
 120
 121static void
 122memfd_backend_set_seal(Object *o, bool value, Error **errp)
 123{
 124    MEMORY_BACKEND_MEMFD(o)->seal = value;
 125}
 126
 127static void
 128memfd_backend_instance_init(Object *obj)
 129{
 130    HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(obj);
 131
 132    /* default to sealed file */
 133    m->seal = true;
 134}
 135
 136static void
 137memfd_backend_class_init(ObjectClass *oc, void *data)
 138{
 139    HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
 140
 141    bc->alloc = memfd_backend_memory_alloc;
 142
 143    object_class_property_add_bool(oc, "hugetlb",
 144                                   memfd_backend_get_hugetlb,
 145                                   memfd_backend_set_hugetlb,
 146                                   &error_abort);
 147    object_class_property_add(oc, "hugetlbsize", "int",
 148                              memfd_backend_get_hugetlbsize,
 149                              memfd_backend_set_hugetlbsize,
 150                              NULL, NULL, &error_abort);
 151    object_class_property_add_bool(oc, "seal",
 152                                   memfd_backend_get_seal,
 153                                   memfd_backend_set_seal,
 154                                   &error_abort);
 155}
 156
 157static 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
 165static void register_types(void)
 166{
 167    type_register_static(&memfd_backend_info);
 168}
 169
 170type_init(register_types);
 171