xref: /qemu/backends/hostmem.c (revision 605d0a945d020e3024aa7faf8a0e8b471371d8ff)
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