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
  13#include "qemu/osdep.h"
  14#include "qapi/error.h"
  15#include "qemu/error-report.h"
  16#include "qemu/module.h"
  17#include "sysemu/hostmem.h"
  18#include "sysemu/sysemu.h"
  19#include "qom/object_interfaces.h"
  20#include "qom/object.h"
  21
  22OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendFile, MEMORY_BACKEND_FILE)
  23
  24
  25struct HostMemoryBackendFile {
  26    HostMemoryBackend parent_obj;
  27
  28    char *mem_path;
  29    uint64_t align;
  30    bool discard_data;
  31    bool is_pmem;
  32    bool readonly;
  33};
  34
  35static void
  36file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
  37{
  38#ifndef CONFIG_POSIX
  39    error_setg(errp, "backend '%s' not supported on this host",
  40               object_get_typename(OBJECT(backend)));
  41#else
  42    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend);
  43    gchar *name;
  44
  45    if (!backend->size) {
  46        error_setg(errp, "can't create backend with size 0");
  47        return;
  48    }
  49    if (!fb->mem_path) {
  50        error_setg(errp, "mem-path property not set");
  51        return;
  52    }
  53
  54    name = host_memory_backend_get_name(backend);
  55    memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
  56                                     name,
  57                                     backend->size, fb->align,
  58                                     (backend->share ? RAM_SHARED : 0) |
  59                                     (fb->is_pmem ? RAM_PMEM : 0),
  60                                     fb->mem_path, fb->readonly, errp);
  61    g_free(name);
  62#endif
  63}
  64
  65static char *get_mem_path(Object *o, Error **errp)
  66{
  67    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
  68
  69    return g_strdup(fb->mem_path);
  70}
  71
  72static void set_mem_path(Object *o, const char *str, Error **errp)
  73{
  74    HostMemoryBackend *backend = MEMORY_BACKEND(o);
  75    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
  76
  77    if (host_memory_backend_mr_inited(backend)) {
  78        error_setg(errp, "cannot change property 'mem-path' of %s",
  79                   object_get_typename(o));
  80        return;
  81    }
  82    g_free(fb->mem_path);
  83    fb->mem_path = g_strdup(str);
  84}
  85
  86static bool file_memory_backend_get_discard_data(Object *o, Error **errp)
  87{
  88    return MEMORY_BACKEND_FILE(o)->discard_data;
  89}
  90
  91static void file_memory_backend_set_discard_data(Object *o, bool value,
  92                                               Error **errp)
  93{
  94    MEMORY_BACKEND_FILE(o)->discard_data = value;
  95}
  96
  97static void file_memory_backend_get_align(Object *o, Visitor *v,
  98                                          const char *name, void *opaque,
  99                                          Error **errp)
 100{
 101    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 102    uint64_t val = fb->align;
 103
 104    visit_type_size(v, name, &val, errp);
 105}
 106
 107static void file_memory_backend_set_align(Object *o, Visitor *v,
 108                                          const char *name, void *opaque,
 109                                          Error **errp)
 110{
 111    HostMemoryBackend *backend = MEMORY_BACKEND(o);
 112    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 113    uint64_t val;
 114
 115    if (host_memory_backend_mr_inited(backend)) {
 116        error_setg(errp, "cannot change property '%s' of %s", name,
 117                   object_get_typename(o));
 118        return;
 119    }
 120
 121    if (!visit_type_size(v, name, &val, errp)) {
 122        return;
 123    }
 124    fb->align = val;
 125}
 126
 127#ifdef CONFIG_LIBPMEM
 128static bool file_memory_backend_get_pmem(Object *o, Error **errp)
 129{
 130    return MEMORY_BACKEND_FILE(o)->is_pmem;
 131}
 132
 133static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp)
 134{
 135    HostMemoryBackend *backend = MEMORY_BACKEND(o);
 136    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 137
 138    if (host_memory_backend_mr_inited(backend)) {
 139        error_setg(errp, "cannot change property 'pmem' of %s.",
 140                   object_get_typename(o));
 141        return;
 142    }
 143
 144    fb->is_pmem = value;
 145}
 146#endif /* CONFIG_LIBPMEM */
 147
 148static bool file_memory_backend_get_readonly(Object *obj, Error **errp)
 149{
 150    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(obj);
 151
 152    return fb->readonly;
 153}
 154
 155static void file_memory_backend_set_readonly(Object *obj, bool value,
 156                                             Error **errp)
 157{
 158    HostMemoryBackend *backend = MEMORY_BACKEND(obj);
 159    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(obj);
 160
 161    if (host_memory_backend_mr_inited(backend)) {
 162        error_setg(errp, "cannot change property 'readonly' of %s.",
 163                   object_get_typename(obj));
 164        return;
 165    }
 166
 167    fb->readonly = value;
 168}
 169
 170static void file_backend_unparent(Object *obj)
 171{
 172    HostMemoryBackend *backend = MEMORY_BACKEND(obj);
 173    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(obj);
 174
 175    if (host_memory_backend_mr_inited(backend) && fb->discard_data) {
 176        void *ptr = memory_region_get_ram_ptr(&backend->mr);
 177        uint64_t sz = memory_region_size(&backend->mr);
 178
 179        qemu_madvise(ptr, sz, QEMU_MADV_REMOVE);
 180    }
 181}
 182
 183static void
 184file_backend_class_init(ObjectClass *oc, void *data)
 185{
 186    HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
 187
 188    bc->alloc = file_backend_memory_alloc;
 189    oc->unparent = file_backend_unparent;
 190
 191    object_class_property_add_bool(oc, "discard-data",
 192        file_memory_backend_get_discard_data, file_memory_backend_set_discard_data);
 193    object_class_property_add_str(oc, "mem-path",
 194        get_mem_path, set_mem_path);
 195    object_class_property_add(oc, "align", "int",
 196        file_memory_backend_get_align,
 197        file_memory_backend_set_align,
 198        NULL, NULL);
 199#ifdef CONFIG_LIBPMEM
 200    object_class_property_add_bool(oc, "pmem",
 201        file_memory_backend_get_pmem, file_memory_backend_set_pmem);
 202#endif
 203    object_class_property_add_bool(oc, "readonly",
 204        file_memory_backend_get_readonly,
 205        file_memory_backend_set_readonly);
 206}
 207
 208static void file_backend_instance_finalize(Object *o)
 209{
 210    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
 211
 212    g_free(fb->mem_path);
 213}
 214
 215static const TypeInfo file_backend_info = {
 216    .name = TYPE_MEMORY_BACKEND_FILE,
 217    .parent = TYPE_MEMORY_BACKEND,
 218    .class_init = file_backend_class_init,
 219    .instance_finalize = file_backend_instance_finalize,
 220    .instance_size = sizeof(HostMemoryBackendFile),
 221};
 222
 223static void register_types(void)
 224{
 225    type_register_static(&file_backend_info);
 226}
 227
 228type_init(register_types);
 229