11f070489SIgor Mammedov /* 21f070489SIgor Mammedov * QEMU Host Memory Backend 31f070489SIgor Mammedov * 41f070489SIgor Mammedov * Copyright (C) 2013-2014 Red Hat Inc 51f070489SIgor Mammedov * 61f070489SIgor Mammedov * Authors: 71f070489SIgor Mammedov * Igor Mammedov <imammedo@redhat.com> 81f070489SIgor Mammedov * 91f070489SIgor Mammedov * This work is licensed under the terms of the GNU GPL, version 2 or later. 101f070489SIgor Mammedov * See the COPYING file in the top-level directory. 111f070489SIgor Mammedov */ 121f070489SIgor Mammedov #include "sysemu/hostmem.h" 131f070489SIgor Mammedov #include "sysemu/sysemu.h" 141f070489SIgor Mammedov #include "qapi/visitor.h" 151f070489SIgor Mammedov #include "qapi/qmp/qerror.h" 161f070489SIgor Mammedov #include "qemu/config-file.h" 171f070489SIgor Mammedov #include "qom/object_interfaces.h" 181f070489SIgor Mammedov 191f070489SIgor Mammedov static void 2058f4662cSHu Tao host_memory_backend_get_size(Object *obj, Visitor *v, void *opaque, 211f070489SIgor Mammedov const char *name, Error **errp) 221f070489SIgor Mammedov { 231f070489SIgor Mammedov HostMemoryBackend *backend = MEMORY_BACKEND(obj); 241f070489SIgor Mammedov uint64_t value = backend->size; 251f070489SIgor Mammedov 261f070489SIgor Mammedov visit_type_size(v, &value, name, errp); 271f070489SIgor Mammedov } 281f070489SIgor Mammedov 291f070489SIgor Mammedov static void 3058f4662cSHu Tao host_memory_backend_set_size(Object *obj, Visitor *v, void *opaque, 311f070489SIgor Mammedov const char *name, Error **errp) 321f070489SIgor Mammedov { 331f070489SIgor Mammedov HostMemoryBackend *backend = MEMORY_BACKEND(obj); 341f070489SIgor Mammedov Error *local_err = NULL; 351f070489SIgor Mammedov uint64_t value; 361f070489SIgor Mammedov 371f070489SIgor Mammedov if (memory_region_size(&backend->mr)) { 381f070489SIgor Mammedov error_setg(&local_err, "cannot change property value"); 391f070489SIgor Mammedov goto out; 401f070489SIgor Mammedov } 411f070489SIgor Mammedov 421f070489SIgor Mammedov visit_type_size(v, &value, name, &local_err); 431f070489SIgor Mammedov if (local_err) { 441f070489SIgor Mammedov goto out; 451f070489SIgor Mammedov } 461f070489SIgor Mammedov if (!value) { 471f070489SIgor Mammedov error_setg(&local_err, "Property '%s.%s' doesn't take value '%" 481f070489SIgor Mammedov PRIu64 "'", object_get_typename(obj), name, value); 491f070489SIgor Mammedov goto out; 501f070489SIgor Mammedov } 511f070489SIgor Mammedov backend->size = value; 521f070489SIgor Mammedov out: 531f070489SIgor Mammedov error_propagate(errp, local_err); 541f070489SIgor Mammedov } 551f070489SIgor Mammedov 56605d0a94SPaolo Bonzini static bool host_memory_backend_get_merge(Object *obj, Error **errp) 57605d0a94SPaolo Bonzini { 58605d0a94SPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 59605d0a94SPaolo Bonzini 60605d0a94SPaolo Bonzini return backend->merge; 61605d0a94SPaolo Bonzini } 62605d0a94SPaolo Bonzini 63605d0a94SPaolo Bonzini static void host_memory_backend_set_merge(Object *obj, bool value, Error **errp) 64605d0a94SPaolo Bonzini { 65605d0a94SPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 66605d0a94SPaolo Bonzini 67605d0a94SPaolo Bonzini if (!memory_region_size(&backend->mr)) { 68605d0a94SPaolo Bonzini backend->merge = value; 69605d0a94SPaolo Bonzini return; 70605d0a94SPaolo Bonzini } 71605d0a94SPaolo Bonzini 72605d0a94SPaolo Bonzini if (value != backend->merge) { 73605d0a94SPaolo Bonzini void *ptr = memory_region_get_ram_ptr(&backend->mr); 74605d0a94SPaolo Bonzini uint64_t sz = memory_region_size(&backend->mr); 75605d0a94SPaolo Bonzini 76605d0a94SPaolo Bonzini qemu_madvise(ptr, sz, 77605d0a94SPaolo Bonzini value ? QEMU_MADV_MERGEABLE : QEMU_MADV_UNMERGEABLE); 78605d0a94SPaolo Bonzini backend->merge = value; 79605d0a94SPaolo Bonzini } 80605d0a94SPaolo Bonzini } 81605d0a94SPaolo Bonzini 82605d0a94SPaolo Bonzini static bool host_memory_backend_get_dump(Object *obj, Error **errp) 83605d0a94SPaolo Bonzini { 84605d0a94SPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 85605d0a94SPaolo Bonzini 86605d0a94SPaolo Bonzini return backend->dump; 87605d0a94SPaolo Bonzini } 88605d0a94SPaolo Bonzini 89605d0a94SPaolo Bonzini static void host_memory_backend_set_dump(Object *obj, bool value, Error **errp) 90605d0a94SPaolo Bonzini { 91605d0a94SPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 92605d0a94SPaolo Bonzini 93605d0a94SPaolo Bonzini if (!memory_region_size(&backend->mr)) { 94605d0a94SPaolo Bonzini backend->dump = value; 95605d0a94SPaolo Bonzini return; 96605d0a94SPaolo Bonzini } 97605d0a94SPaolo Bonzini 98605d0a94SPaolo Bonzini if (value != backend->dump) { 99605d0a94SPaolo Bonzini void *ptr = memory_region_get_ram_ptr(&backend->mr); 100605d0a94SPaolo Bonzini uint64_t sz = memory_region_size(&backend->mr); 101605d0a94SPaolo Bonzini 102605d0a94SPaolo Bonzini qemu_madvise(ptr, sz, 103605d0a94SPaolo Bonzini value ? QEMU_MADV_DODUMP : QEMU_MADV_DONTDUMP); 104605d0a94SPaolo Bonzini backend->dump = value; 105605d0a94SPaolo Bonzini } 106605d0a94SPaolo Bonzini } 107605d0a94SPaolo Bonzini 108*a35ba7beSPaolo Bonzini static bool host_memory_backend_get_prealloc(Object *obj, Error **errp) 109*a35ba7beSPaolo Bonzini { 110*a35ba7beSPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 111*a35ba7beSPaolo Bonzini 112*a35ba7beSPaolo Bonzini return backend->prealloc || backend->force_prealloc; 113*a35ba7beSPaolo Bonzini } 114*a35ba7beSPaolo Bonzini 115*a35ba7beSPaolo Bonzini static void host_memory_backend_set_prealloc(Object *obj, bool value, 116*a35ba7beSPaolo Bonzini Error **errp) 117*a35ba7beSPaolo Bonzini { 118*a35ba7beSPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 119*a35ba7beSPaolo Bonzini 120*a35ba7beSPaolo Bonzini if (backend->force_prealloc) { 121*a35ba7beSPaolo Bonzini if (value) { 122*a35ba7beSPaolo Bonzini error_setg(errp, 123*a35ba7beSPaolo Bonzini "remove -mem-prealloc to use the prealloc property"); 124*a35ba7beSPaolo Bonzini return; 125*a35ba7beSPaolo Bonzini } 126*a35ba7beSPaolo Bonzini } 127*a35ba7beSPaolo Bonzini 128*a35ba7beSPaolo Bonzini if (!memory_region_size(&backend->mr)) { 129*a35ba7beSPaolo Bonzini backend->prealloc = value; 130*a35ba7beSPaolo Bonzini return; 131*a35ba7beSPaolo Bonzini } 132*a35ba7beSPaolo Bonzini 133*a35ba7beSPaolo Bonzini if (value && !backend->prealloc) { 134*a35ba7beSPaolo Bonzini int fd = memory_region_get_fd(&backend->mr); 135*a35ba7beSPaolo Bonzini void *ptr = memory_region_get_ram_ptr(&backend->mr); 136*a35ba7beSPaolo Bonzini uint64_t sz = memory_region_size(&backend->mr); 137*a35ba7beSPaolo Bonzini 138*a35ba7beSPaolo Bonzini os_mem_prealloc(fd, ptr, sz); 139*a35ba7beSPaolo Bonzini backend->prealloc = true; 140*a35ba7beSPaolo Bonzini } 141*a35ba7beSPaolo Bonzini } 142*a35ba7beSPaolo Bonzini 14358f4662cSHu Tao static void host_memory_backend_init(Object *obj) 1441f070489SIgor Mammedov { 145605d0a94SPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 146605d0a94SPaolo Bonzini 147605d0a94SPaolo Bonzini backend->merge = qemu_opt_get_bool(qemu_get_machine_opts(), 148605d0a94SPaolo Bonzini "mem-merge", true); 149605d0a94SPaolo Bonzini backend->dump = qemu_opt_get_bool(qemu_get_machine_opts(), 150605d0a94SPaolo Bonzini "dump-guest-core", true); 151*a35ba7beSPaolo Bonzini backend->prealloc = mem_prealloc; 152605d0a94SPaolo Bonzini 153605d0a94SPaolo Bonzini object_property_add_bool(obj, "merge", 154605d0a94SPaolo Bonzini host_memory_backend_get_merge, 155605d0a94SPaolo Bonzini host_memory_backend_set_merge, NULL); 156605d0a94SPaolo Bonzini object_property_add_bool(obj, "dump", 157605d0a94SPaolo Bonzini host_memory_backend_get_dump, 158605d0a94SPaolo Bonzini host_memory_backend_set_dump, NULL); 159*a35ba7beSPaolo Bonzini object_property_add_bool(obj, "prealloc", 160*a35ba7beSPaolo Bonzini host_memory_backend_get_prealloc, 161*a35ba7beSPaolo Bonzini host_memory_backend_set_prealloc, NULL); 1621f070489SIgor Mammedov object_property_add(obj, "size", "int", 16358f4662cSHu Tao host_memory_backend_get_size, 16458f4662cSHu Tao host_memory_backend_set_size, NULL, NULL, NULL); 1651f070489SIgor Mammedov } 1661f070489SIgor Mammedov 16758f4662cSHu Tao static void host_memory_backend_finalize(Object *obj) 1681f070489SIgor Mammedov { 1691f070489SIgor Mammedov HostMemoryBackend *backend = MEMORY_BACKEND(obj); 1701f070489SIgor Mammedov 1711f070489SIgor Mammedov if (memory_region_size(&backend->mr)) { 1721f070489SIgor Mammedov memory_region_destroy(&backend->mr); 1731f070489SIgor Mammedov } 1741f070489SIgor Mammedov } 1751f070489SIgor Mammedov 1761f070489SIgor Mammedov MemoryRegion * 1771f070489SIgor Mammedov host_memory_backend_get_memory(HostMemoryBackend *backend, Error **errp) 1781f070489SIgor Mammedov { 1791f070489SIgor Mammedov return memory_region_size(&backend->mr) ? &backend->mr : NULL; 1801f070489SIgor Mammedov } 1811f070489SIgor Mammedov 182bd9262d9SHu Tao static void 183bd9262d9SHu Tao host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) 184bd9262d9SHu Tao { 185bd9262d9SHu Tao HostMemoryBackend *backend = MEMORY_BACKEND(uc); 186bd9262d9SHu Tao HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc); 187605d0a94SPaolo Bonzini Error *local_err = NULL; 188605d0a94SPaolo Bonzini void *ptr; 189605d0a94SPaolo Bonzini uint64_t sz; 190bd9262d9SHu Tao 191bd9262d9SHu Tao if (bc->alloc) { 192605d0a94SPaolo Bonzini bc->alloc(backend, &local_err); 193605d0a94SPaolo Bonzini if (local_err) { 194605d0a94SPaolo Bonzini error_propagate(errp, local_err); 195605d0a94SPaolo Bonzini return; 196605d0a94SPaolo Bonzini } 197605d0a94SPaolo Bonzini 198605d0a94SPaolo Bonzini ptr = memory_region_get_ram_ptr(&backend->mr); 199605d0a94SPaolo Bonzini sz = memory_region_size(&backend->mr); 200605d0a94SPaolo Bonzini 201605d0a94SPaolo Bonzini if (backend->merge) { 202605d0a94SPaolo Bonzini qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE); 203605d0a94SPaolo Bonzini } 204605d0a94SPaolo Bonzini if (!backend->dump) { 205605d0a94SPaolo Bonzini qemu_madvise(ptr, sz, QEMU_MADV_DONTDUMP); 206605d0a94SPaolo Bonzini } 207*a35ba7beSPaolo Bonzini if (backend->prealloc) { 208*a35ba7beSPaolo Bonzini os_mem_prealloc(memory_region_get_fd(&backend->mr), ptr, sz); 209*a35ba7beSPaolo Bonzini } 210bd9262d9SHu Tao } 211bd9262d9SHu Tao } 212bd9262d9SHu Tao 213bd9262d9SHu Tao static void 214bd9262d9SHu Tao host_memory_backend_class_init(ObjectClass *oc, void *data) 215bd9262d9SHu Tao { 216bd9262d9SHu Tao UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); 217bd9262d9SHu Tao 218bd9262d9SHu Tao ucc->complete = host_memory_backend_memory_complete; 219bd9262d9SHu Tao } 220bd9262d9SHu Tao 22158f4662cSHu Tao static const TypeInfo host_memory_backend_info = { 2221f070489SIgor Mammedov .name = TYPE_MEMORY_BACKEND, 2231f070489SIgor Mammedov .parent = TYPE_OBJECT, 2241f070489SIgor Mammedov .abstract = true, 2251f070489SIgor Mammedov .class_size = sizeof(HostMemoryBackendClass), 226bd9262d9SHu Tao .class_init = host_memory_backend_class_init, 2271f070489SIgor Mammedov .instance_size = sizeof(HostMemoryBackend), 22858f4662cSHu Tao .instance_init = host_memory_backend_init, 22958f4662cSHu Tao .instance_finalize = host_memory_backend_finalize, 2301f070489SIgor Mammedov .interfaces = (InterfaceInfo[]) { 2311f070489SIgor Mammedov { TYPE_USER_CREATABLE }, 2321f070489SIgor Mammedov { } 2331f070489SIgor Mammedov } 2341f070489SIgor Mammedov }; 2351f070489SIgor Mammedov 2361f070489SIgor Mammedov static void register_types(void) 2371f070489SIgor Mammedov { 23858f4662cSHu Tao type_register_static(&host_memory_backend_info); 2391f070489SIgor Mammedov } 2401f070489SIgor Mammedov 2411f070489SIgor Mammedov type_init(register_types); 242