qemu/backends/hostmem-file.c
<<
>>
Prefs
   1/*
   2 * QEMU Host Memory Backend for hugetlbfs
   3 *
   4 * Copyright (C) 2013-2014 Red Hat Inc
   5 *
   6 * Authors:
   7 *   Paolo Bonzini <pbonzini@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 "qapi/error.h"
  14#include "qemu-common.h"
  15#include "sysemu/hostmem.h"
  16#include "sysemu/sysemu.h"
  17#include "qom/object_interfaces.h"
  18
  19/* hostmem-file.c */
  20/**
  21 * @TYPE_MEMORY_BACKEND_FILE:
  22 * name of backend that uses mmap on a file descriptor
  23 */
  24#define TYPE_MEMORY_BACKEND_FILE "memory-backend-file"
  25
  26#define MEMORY_BACKEND_FILE(obj) \
  27    OBJECT_CHECK(HostMemoryBackendFile, (obj), TYPE_MEMORY_BACKEND_FILE)
  28
  29typedef struct HostMemoryBackendFile HostMemoryBackendFile;
  30
  31struct HostMemoryBackendFile {
  32    HostMemoryBackend parent_obj;
  33
  34    bool discard_data;
  35    char *mem_path;
  36    uint64_t align;
  37};
  38
  39static void
  40file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
  41{
  42    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend);
  43
  44    if (!backend->size) {
  45        error_setg(errp, "can't create backend with size 0");
  46        return;
  47    }
  48    if (!fb->mem_path) {
  49        error_setg(errp, "mem-path property not set");
  50        return;
  51    }
  52#ifndef CONFIG_LINUX
  53    error_setg(errp, "-mem-path not supported on this host");
  54#else
  55    if (!host_memory_backend_mr_inited(backend)) {
  56        gchar *path;
  57        backend->force_prealloc = mem_prealloc;
  58        path = object_get_canonical_path(OBJECT(backend));
  59        memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
  60                                 path,
  61                                 backend->size, fb->align, backend->share,
  62                                 fb->mem_path, errp);
  63        g_free(path);
  64    }
  65#endif
  66}
  67
  68static char *get_mem_path(Object *o, Error **errp)
  69{
  70    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
  71
  72    return g_strdup(fb->mem_path);
  73}
  74
  75static void set_mem_path(Object *o, const char *str, Error **errp)
  76{
  77    HostMemoryBackend *backend = MEMORY_BACKEND(o);
  78    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
  79
  80    if (host_memory_backend_mr_inited(backend)) {
  81        error_setg(errp, "cannot change property value");
  82        return;
  83    }
  84    g_free(fb->mem_path);
  85    fb->mem_path = g_strdup(str);
  86}
  87
  88static bool file_memory_backend_get_discard_data(Object *o, Error **errp)
  89{
  90    return MEMORY_BACKEND_FILE(o)->discard_data;
  91}
  92
  93static void file_memory_backend_set_discard_data(Object *o, bool value,
  94                                               Error **errp)
  95{
  96    MEMORY_BACKEND_FILE(o)->discard_data = value;
  97}
  98
  99static void file_memory_backend_get_align(Object *o, Visitor *v,
 100                                          const char *name, void *opaque,
 101                                          Error **errp)
 102{
 103    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 104    uint64_t val = fb->align;
 105
 106    visit_type_size(v, name, &val, errp);
 107}
 108
 109static void file_memory_backend_set_align(Object *o, Visitor *v,
 110                                          const char *name, void *opaque,
 111                                          Error **errp)
 112{
 113    HostMemoryBackend *backend = MEMORY_BACKEND(o);
 114    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 115    Error *local_err = NULL;
 116    uint64_t val;
 117
 118    if (host_memory_backend_mr_inited(backend)) {
 119        error_setg(&local_err, "cannot change property value");
 120        goto out;
 121    }
 122
 123    visit_type_size(v, name, &val, &local_err);
 124    if (local_err) {
 125        goto out;
 126    }
 127    fb->align = val;
 128
 129 out:
 130    error_propagate(errp, local_err);
 131}
 132
 133static void file_backend_unparent(Object *obj)
 134{
 135    HostMemoryBackend *backend = MEMORY_BACKEND(obj);
 136    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(obj);
 137
 138    if (host_memory_backend_mr_inited(backend) && fb->discard_data) {
 139        void *ptr = memory_region_get_ram_ptr(&backend->mr);
 140        uint64_t sz = memory_region_size(&backend->mr);
 141
 142        qemu_madvise(ptr, sz, QEMU_MADV_REMOVE);
 143    }
 144}
 145
 146static void
 147file_backend_class_init(ObjectClass *oc, void *data)
 148{
 149    HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
 150
 151    bc->alloc = file_backend_memory_alloc;
 152    oc->unparent = file_backend_unparent;
 153
 154    object_class_property_add_bool(oc, "discard-data",
 155        file_memory_backend_get_discard_data, file_memory_backend_set_discard_data,
 156        &error_abort);
 157    object_class_property_add_str(oc, "mem-path",
 158        get_mem_path, set_mem_path,
 159        &error_abort);
 160    object_class_property_add(oc, "align", "int",
 161        file_memory_backend_get_align,
 162        file_memory_backend_set_align,
 163        NULL, NULL, &error_abort);
 164}
 165
 166static void file_backend_instance_finalize(Object *o)
 167{
 168    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 169
 170    g_free(fb->mem_path);
 171}
 172
 173static const TypeInfo file_backend_info = {
 174    .name = TYPE_MEMORY_BACKEND_FILE,
 175    .parent = TYPE_MEMORY_BACKEND,
 176    .class_init = file_backend_class_init,
 177    .instance_finalize = file_backend_instance_finalize,
 178    .instance_size = sizeof(HostMemoryBackendFile),
 179};
 180
 181static void register_types(void)
 182{
 183    type_register_static(&file_backend_info);
 184}
 185
 186type_init(register_types);
 187