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 "qemu-common.h" 14 #include "sysemu/hostmem.h" 15 #include "sysemu/sysemu.h" 16 #include "qom/object_interfaces.h" 17 18 /* hostmem-file.c */ 19 /** 20 * @TYPE_MEMORY_BACKEND_FILE: 21 * name of backend that uses mmap on a file descriptor 22 */ 23 #define TYPE_MEMORY_BACKEND_FILE "memory-backend-file" 24 25 #define MEMORY_BACKEND_FILE(obj) \ 26 OBJECT_CHECK(HostMemoryBackendFile, (obj), TYPE_MEMORY_BACKEND_FILE) 27 28 typedef struct HostMemoryBackendFile HostMemoryBackendFile; 29 30 struct HostMemoryBackendFile { 31 HostMemoryBackend parent_obj; 32 33 bool share; 34 char *mem_path; 35 }; 36 37 static void 38 file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp) 39 { 40 HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend); 41 42 if (!backend->size) { 43 error_setg(errp, "can't create backend with size 0"); 44 return; 45 } 46 if (!fb->mem_path) { 47 error_setg(errp, "mem-path property not set"); 48 return; 49 } 50 #ifndef CONFIG_LINUX 51 error_setg(errp, "-mem-path not supported on this host"); 52 #else 53 if (!memory_region_size(&backend->mr)) { 54 backend->force_prealloc = mem_prealloc; 55 memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), 56 object_get_canonical_path(OBJECT(backend)), 57 backend->size, fb->share, 58 fb->mem_path, errp); 59 } 60 #endif 61 } 62 63 static void 64 file_backend_class_init(ObjectClass *oc, void *data) 65 { 66 HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc); 67 68 bc->alloc = file_backend_memory_alloc; 69 } 70 71 static char *get_mem_path(Object *o, Error **errp) 72 { 73 HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o); 74 75 return g_strdup(fb->mem_path); 76 } 77 78 static void set_mem_path(Object *o, const char *str, Error **errp) 79 { 80 HostMemoryBackend *backend = MEMORY_BACKEND(o); 81 HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o); 82 83 if (memory_region_size(&backend->mr)) { 84 error_setg(errp, "cannot change property value"); 85 return; 86 } 87 g_free(fb->mem_path); 88 fb->mem_path = g_strdup(str); 89 } 90 91 static bool file_memory_backend_get_share(Object *o, Error **errp) 92 { 93 HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o); 94 95 return fb->share; 96 } 97 98 static void file_memory_backend_set_share(Object *o, bool value, Error **errp) 99 { 100 HostMemoryBackend *backend = MEMORY_BACKEND(o); 101 HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o); 102 103 if (memory_region_size(&backend->mr)) { 104 error_setg(errp, "cannot change property value"); 105 return; 106 } 107 fb->share = value; 108 } 109 110 static void 111 file_backend_instance_init(Object *o) 112 { 113 object_property_add_bool(o, "share", 114 file_memory_backend_get_share, 115 file_memory_backend_set_share, NULL); 116 object_property_add_str(o, "mem-path", get_mem_path, 117 set_mem_path, NULL); 118 } 119 120 static const TypeInfo file_backend_info = { 121 .name = TYPE_MEMORY_BACKEND_FILE, 122 .parent = TYPE_MEMORY_BACKEND, 123 .class_init = file_backend_class_init, 124 .instance_init = file_backend_instance_init, 125 .instance_size = sizeof(HostMemoryBackendFile), 126 }; 127 128 static void register_types(void) 129 { 130 type_register_static(&file_backend_info); 131 } 132 133 type_init(register_types); 134