qemu

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

hostmem-file.c (6547B)


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