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