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 56*605d0a94SPaolo Bonzini static bool host_memory_backend_get_merge(Object *obj, Error **errp) 57*605d0a94SPaolo Bonzini { 58*605d0a94SPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 59*605d0a94SPaolo Bonzini 60*605d0a94SPaolo Bonzini return backend->merge; 61*605d0a94SPaolo Bonzini } 62*605d0a94SPaolo Bonzini 63*605d0a94SPaolo Bonzini static void host_memory_backend_set_merge(Object *obj, bool value, Error **errp) 64*605d0a94SPaolo Bonzini { 65*605d0a94SPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 66*605d0a94SPaolo Bonzini 67*605d0a94SPaolo Bonzini if (!memory_region_size(&backend->mr)) { 68*605d0a94SPaolo Bonzini backend->merge = value; 69*605d0a94SPaolo Bonzini return; 70*605d0a94SPaolo Bonzini } 71*605d0a94SPaolo Bonzini 72*605d0a94SPaolo Bonzini if (value != backend->merge) { 73*605d0a94SPaolo Bonzini void *ptr = memory_region_get_ram_ptr(&backend->mr); 74*605d0a94SPaolo Bonzini uint64_t sz = memory_region_size(&backend->mr); 75*605d0a94SPaolo Bonzini 76*605d0a94SPaolo Bonzini qemu_madvise(ptr, sz, 77*605d0a94SPaolo Bonzini value ? QEMU_MADV_MERGEABLE : QEMU_MADV_UNMERGEABLE); 78*605d0a94SPaolo Bonzini backend->merge = value; 79*605d0a94SPaolo Bonzini } 80*605d0a94SPaolo Bonzini } 81*605d0a94SPaolo Bonzini 82*605d0a94SPaolo Bonzini static bool host_memory_backend_get_dump(Object *obj, Error **errp) 83*605d0a94SPaolo Bonzini { 84*605d0a94SPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 85*605d0a94SPaolo Bonzini 86*605d0a94SPaolo Bonzini return backend->dump; 87*605d0a94SPaolo Bonzini } 88*605d0a94SPaolo Bonzini 89*605d0a94SPaolo Bonzini static void host_memory_backend_set_dump(Object *obj, bool value, Error **errp) 90*605d0a94SPaolo Bonzini { 91*605d0a94SPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 92*605d0a94SPaolo Bonzini 93*605d0a94SPaolo Bonzini if (!memory_region_size(&backend->mr)) { 94*605d0a94SPaolo Bonzini backend->dump = value; 95*605d0a94SPaolo Bonzini return; 96*605d0a94SPaolo Bonzini } 97*605d0a94SPaolo Bonzini 98*605d0a94SPaolo Bonzini if (value != backend->dump) { 99*605d0a94SPaolo Bonzini void *ptr = memory_region_get_ram_ptr(&backend->mr); 100*605d0a94SPaolo Bonzini uint64_t sz = memory_region_size(&backend->mr); 101*605d0a94SPaolo Bonzini 102*605d0a94SPaolo Bonzini qemu_madvise(ptr, sz, 103*605d0a94SPaolo Bonzini value ? QEMU_MADV_DODUMP : QEMU_MADV_DONTDUMP); 104*605d0a94SPaolo Bonzini backend->dump = value; 105*605d0a94SPaolo Bonzini } 106*605d0a94SPaolo Bonzini } 107*605d0a94SPaolo Bonzini 10858f4662cSHu Tao static void host_memory_backend_init(Object *obj) 1091f070489SIgor Mammedov { 110*605d0a94SPaolo Bonzini HostMemoryBackend *backend = MEMORY_BACKEND(obj); 111*605d0a94SPaolo Bonzini 112*605d0a94SPaolo Bonzini backend->merge = qemu_opt_get_bool(qemu_get_machine_opts(), 113*605d0a94SPaolo Bonzini "mem-merge", true); 114*605d0a94SPaolo Bonzini backend->dump = qemu_opt_get_bool(qemu_get_machine_opts(), 115*605d0a94SPaolo Bonzini "dump-guest-core", true); 116*605d0a94SPaolo Bonzini 117*605d0a94SPaolo Bonzini object_property_add_bool(obj, "merge", 118*605d0a94SPaolo Bonzini host_memory_backend_get_merge, 119*605d0a94SPaolo Bonzini host_memory_backend_set_merge, NULL); 120*605d0a94SPaolo Bonzini object_property_add_bool(obj, "dump", 121*605d0a94SPaolo Bonzini host_memory_backend_get_dump, 122*605d0a94SPaolo Bonzini host_memory_backend_set_dump, NULL); 1231f070489SIgor Mammedov object_property_add(obj, "size", "int", 12458f4662cSHu Tao host_memory_backend_get_size, 12558f4662cSHu Tao host_memory_backend_set_size, NULL, NULL, NULL); 1261f070489SIgor Mammedov } 1271f070489SIgor Mammedov 12858f4662cSHu Tao static void host_memory_backend_finalize(Object *obj) 1291f070489SIgor Mammedov { 1301f070489SIgor Mammedov HostMemoryBackend *backend = MEMORY_BACKEND(obj); 1311f070489SIgor Mammedov 1321f070489SIgor Mammedov if (memory_region_size(&backend->mr)) { 1331f070489SIgor Mammedov memory_region_destroy(&backend->mr); 1341f070489SIgor Mammedov } 1351f070489SIgor Mammedov } 1361f070489SIgor Mammedov 1371f070489SIgor Mammedov MemoryRegion * 1381f070489SIgor Mammedov host_memory_backend_get_memory(HostMemoryBackend *backend, Error **errp) 1391f070489SIgor Mammedov { 1401f070489SIgor Mammedov return memory_region_size(&backend->mr) ? &backend->mr : NULL; 1411f070489SIgor Mammedov } 1421f070489SIgor Mammedov 143bd9262d9SHu Tao static void 144bd9262d9SHu Tao host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) 145bd9262d9SHu Tao { 146bd9262d9SHu Tao HostMemoryBackend *backend = MEMORY_BACKEND(uc); 147bd9262d9SHu Tao HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc); 148*605d0a94SPaolo Bonzini Error *local_err = NULL; 149*605d0a94SPaolo Bonzini void *ptr; 150*605d0a94SPaolo Bonzini uint64_t sz; 151bd9262d9SHu Tao 152bd9262d9SHu Tao if (bc->alloc) { 153*605d0a94SPaolo Bonzini bc->alloc(backend, &local_err); 154*605d0a94SPaolo Bonzini if (local_err) { 155*605d0a94SPaolo Bonzini error_propagate(errp, local_err); 156*605d0a94SPaolo Bonzini return; 157*605d0a94SPaolo Bonzini } 158*605d0a94SPaolo Bonzini 159*605d0a94SPaolo Bonzini ptr = memory_region_get_ram_ptr(&backend->mr); 160*605d0a94SPaolo Bonzini sz = memory_region_size(&backend->mr); 161*605d0a94SPaolo Bonzini 162*605d0a94SPaolo Bonzini if (backend->merge) { 163*605d0a94SPaolo Bonzini qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE); 164*605d0a94SPaolo Bonzini } 165*605d0a94SPaolo Bonzini if (!backend->dump) { 166*605d0a94SPaolo Bonzini qemu_madvise(ptr, sz, QEMU_MADV_DONTDUMP); 167*605d0a94SPaolo Bonzini } 168bd9262d9SHu Tao } 169bd9262d9SHu Tao } 170bd9262d9SHu Tao 171bd9262d9SHu Tao static void 172bd9262d9SHu Tao host_memory_backend_class_init(ObjectClass *oc, void *data) 173bd9262d9SHu Tao { 174bd9262d9SHu Tao UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); 175bd9262d9SHu Tao 176bd9262d9SHu Tao ucc->complete = host_memory_backend_memory_complete; 177bd9262d9SHu Tao } 178bd9262d9SHu Tao 17958f4662cSHu Tao static const TypeInfo host_memory_backend_info = { 1801f070489SIgor Mammedov .name = TYPE_MEMORY_BACKEND, 1811f070489SIgor Mammedov .parent = TYPE_OBJECT, 1821f070489SIgor Mammedov .abstract = true, 1831f070489SIgor Mammedov .class_size = sizeof(HostMemoryBackendClass), 184bd9262d9SHu Tao .class_init = host_memory_backend_class_init, 1851f070489SIgor Mammedov .instance_size = sizeof(HostMemoryBackend), 18658f4662cSHu Tao .instance_init = host_memory_backend_init, 18758f4662cSHu Tao .instance_finalize = host_memory_backend_finalize, 1881f070489SIgor Mammedov .interfaces = (InterfaceInfo[]) { 1891f070489SIgor Mammedov { TYPE_USER_CREATABLE }, 1901f070489SIgor Mammedov { } 1911f070489SIgor Mammedov } 1921f070489SIgor Mammedov }; 1931f070489SIgor Mammedov 1941f070489SIgor Mammedov static void register_types(void) 1951f070489SIgor Mammedov { 19658f4662cSHu Tao type_register_static(&host_memory_backend_info); 1971f070489SIgor Mammedov } 1981f070489SIgor Mammedov 1991f070489SIgor Mammedov type_init(register_types); 200