master
c 605 lines 18.6 KB
Raw
1 /*
2 * QEMU Host Memory Backend
3 *
4 * Copyright (C) 2013-2014 Red Hat Inc
5 *
6 * Authors:
7 * Igor Mammedov <imammedo@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
13 #include "qemu/osdep.h"
14 #include "system/hostmem.h"
15 #include "system/ramblock.h"
16 #include "hw/core/boards.h"
17 #include "qapi/error.h"
18 #include "qapi/qapi-builtin-visit.h"
19 #include "qapi/visitor.h"
20 #include "qemu/config-file.h"
21 #include "qom/compat-properties.h"
22 #include "qom/object_interfaces.h"
23 #include "qemu/mmap-alloc.h"
24 #include "qemu/madvise.h"
25 #include "qemu/cutils.h"
26 #include "hw/core/qdev.h"
27
28 #ifdef CONFIG_NUMA
29 #include <numaif.h>
30 #include <numa.h>
31 QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_DEFAULT != MPOL_DEFAULT);
32 /*
33 * HOST_MEM_POLICY_PREFERRED may either translate to MPOL_PREFERRED or
34 * MPOL_PREFERRED_MANY, see comments further below.
35 */
36 QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_PREFERRED != MPOL_PREFERRED);
37 QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_BIND != MPOL_BIND);
38 QEMU_BUILD_BUG_ON(HOST_MEM_POLICY_INTERLEAVE != MPOL_INTERLEAVE);
39 #endif
40
41 char *
42 host_memory_backend_get_name(HostMemoryBackend *backend)
43 {
44 if (!backend->use_canonical_path) {
45 return g_strdup(object_get_canonical_path_component(OBJECT(backend)));
46 }
47
48 return object_get_canonical_path(OBJECT(backend));
49 }
50
51 static void
52 host_memory_backend_get_size(Object *obj, Visitor *v, const char *name,
53 void *opaque, Error **errp)
54 {
55 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
56 uint64_t value = backend->size;
57
58 visit_type_size(v, name, &value, errp);
59 }
60
61 static void
62 host_memory_backend_set_size(Object *obj, Visitor *v, const char *name,
63 void *opaque, Error **errp)
64 {
65 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
66 uint64_t value;
67
68 if (host_memory_backend_mr_inited(backend)) {
69 error_setg(errp, "cannot change property %s of %s ", name,
70 object_get_typename(obj));
71 return;
72 }
73
74 if (!visit_type_size(v, name, &value, errp)) {
75 return;
76 }
77 if (!value) {
78 error_setg(errp,
79 "property '%s' of %s doesn't take value '%" PRIu64 "'",
80 name, object_get_typename(obj), value);
81 return;
82 }
83 backend->size = value;
84 }
85
86 static void
87 host_memory_backend_get_host_nodes(Object *obj, Visitor *v, const char *name,
88 void *opaque, Error **errp)
89 {
90 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
91 uint16List *host_nodes = NULL;
92 uint16List **tail = &host_nodes;
93 unsigned long value;
94
95 value = find_first_bit(backend->host_nodes, MAX_NODES);
96 if (value == MAX_NODES) {
97 goto ret;
98 }
99
100 QAPI_LIST_APPEND(tail, value);
101
102 do {
103 value = find_next_bit(backend->host_nodes, MAX_NODES, value + 1);
104 if (value == MAX_NODES) {
105 break;
106 }
107
108 QAPI_LIST_APPEND(tail, value);
109 } while (true);
110
111 ret:
112 visit_type_uint16List(v, name, &host_nodes, errp);
113 qapi_free_uint16List(host_nodes);
114 }
115
116 static void
117 host_memory_backend_set_host_nodes(Object *obj, Visitor *v, const char *name,
118 void *opaque, Error **errp)
119 {
120 #ifdef CONFIG_NUMA
121 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
122 uint16List *l, *host_nodes = NULL;
123
124 visit_type_uint16List(v, name, &host_nodes, errp);
125
126 for (l = host_nodes; l; l = l->next) {
127 if (l->value >= MAX_NODES) {
128 error_setg(errp, "Invalid host-nodes value: %d", l->value);
129 goto out;
130 }
131 }
132
133 for (l = host_nodes; l; l = l->next) {
134 bitmap_set(backend->host_nodes, l->value, 1);
135 }
136
137 out:
138 qapi_free_uint16List(host_nodes);
139 #else
140 error_setg(errp, "NUMA node binding are not supported by this QEMU");
141 #endif
142 }
143
144 static int
145 host_memory_backend_get_policy(Object *obj, Error **errp G_GNUC_UNUSED)
146 {
147 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
148 return backend->policy;
149 }
150
151 static void
152 host_memory_backend_set_policy(Object *obj, int policy, Error **errp)
153 {
154 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
155 backend->policy = policy;
156
157 #ifndef CONFIG_NUMA
158 if (policy != HOST_MEM_POLICY_DEFAULT) {
159 error_setg(errp, "NUMA policies are not supported by this QEMU");
160 }
161 #endif
162 }
163
164 static bool host_memory_backend_get_merge(Object *obj, Error **errp)
165 {
166 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
167
168 return backend->merge;
169 }
170
171 static void host_memory_backend_set_merge(Object *obj, bool value, Error **errp)
172 {
173 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
174
175 if (QEMU_MADV_MERGEABLE == QEMU_MADV_INVALID) {
176 if (value) {
177 error_setg(errp, "Memory merging is not supported on this host");
178 }
179 assert(!backend->merge);
180 return;
181 }
182
183 if (host_memory_backend_mr_inited(backend) &&
184 value != backend->merge) {
185 void *ptr = memory_region_get_ram_ptr(&backend->mr);
186 uint64_t sz = memory_region_size(&backend->mr);
187
188 qemu_madvise(ptr, sz,
189 value ? QEMU_MADV_MERGEABLE : QEMU_MADV_UNMERGEABLE);
190 }
191
192 backend->merge = value;
193 }
194
195 static bool host_memory_backend_get_dump(Object *obj, Error **errp)
196 {
197 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
198
199 return backend->dump;
200 }
201
202 static void host_memory_backend_set_dump(Object *obj, bool value, Error **errp)
203 {
204 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
205
206 if (QEMU_MADV_DONTDUMP == QEMU_MADV_INVALID) {
207 if (!value) {
208 error_setg(errp, "Dumping guest memory cannot be disabled on this host");
209 }
210 assert(backend->dump);
211 return;
212 }
213
214 if (host_memory_backend_mr_inited(backend) &&
215 value != backend->dump) {
216 void *ptr = memory_region_get_ram_ptr(&backend->mr);
217 uint64_t sz = memory_region_size(&backend->mr);
218
219 qemu_madvise(ptr, sz,
220 value ? QEMU_MADV_DODUMP : QEMU_MADV_DONTDUMP);
221 }
222
223 backend->dump = value;
224 }
225
226 static bool host_memory_backend_get_prealloc(Object *obj, Error **errp)
227 {
228 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
229
230 return backend->prealloc;
231 }
232
233 static void host_memory_backend_set_prealloc(Object *obj, bool value,
234 Error **errp)
235 {
236 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
237
238 if (!backend->reserve && value) {
239 error_setg(errp, "'prealloc=on' and 'reserve=off' are incompatible");
240 return;
241 }
242
243 if (!host_memory_backend_mr_inited(backend)) {
244 backend->prealloc = value;
245 return;
246 }
247
248 if (value && !backend->prealloc) {
249 int fd = memory_region_get_fd(&backend->mr);
250 void *ptr = memory_region_get_ram_ptr(&backend->mr);
251 uint64_t sz = memory_region_size(&backend->mr);
252
253 if (!qemu_prealloc_mem(fd, ptr, sz, backend->prealloc_threads,
254 backend->prealloc_context, false, errp)) {
255 return;
256 }
257 backend->prealloc = true;
258 }
259 }
260
261 static void host_memory_backend_get_prealloc_threads(Object *obj, Visitor *v,
262 const char *name, void *opaque, Error **errp)
263 {
264 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
265 visit_type_uint32(v, name, &backend->prealloc_threads, errp);
266 }
267
268 static void host_memory_backend_set_prealloc_threads(Object *obj, Visitor *v,
269 const char *name, void *opaque, Error **errp)
270 {
271 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
272 uint32_t value;
273
274 if (!visit_type_uint32(v, name, &value, errp)) {
275 return;
276 }
277 if (value <= 0) {
278 error_setg(errp, "property '%s' of %s doesn't take value '%d'", name,
279 object_get_typename(obj), value);
280 return;
281 }
282 backend->prealloc_threads = value;
283 }
284
285 static void host_memory_backend_init(Object *obj)
286 {
287 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
288 MachineState *machine = MACHINE(qdev_get_machine());
289
290 /* TODO: convert access to globals to compat properties */
291 backend->merge = machine_mem_merge(machine);
292 backend->dump = machine_dump_guest_core(machine);
293 backend->guest_memfd = machine_require_guest_memfd(machine);
294 backend->reserve = true;
295 backend->prealloc_threads = machine->smp.cpus;
296 }
297
298 static void host_memory_backend_post_init(Object *obj)
299 {
300 object_apply_compat_props(obj);
301 }
302
303 bool host_memory_backend_mr_inited(HostMemoryBackend *backend)
304 {
305 /*
306 * NOTE: We forbid zero-length memory backend, so here zero means
307 * "we haven't inited the backend memory region yet".
308 */
309 return memory_region_size(&backend->mr) != 0;
310 }
311
312 MemoryRegion *host_memory_backend_get_memory(HostMemoryBackend *backend)
313 {
314 return host_memory_backend_mr_inited(backend) ? &backend->mr : NULL;
315 }
316
317 void host_memory_backend_set_mapped(HostMemoryBackend *backend, bool mapped)
318 {
319 backend->is_mapped = mapped;
320 }
321
322 bool host_memory_backend_is_mapped(HostMemoryBackend *backend)
323 {
324 return backend->is_mapped;
325 }
326
327 size_t host_memory_backend_pagesize(HostMemoryBackend *memdev)
328 {
329 size_t pagesize = qemu_ram_pagesize(memdev->mr.ram_block);
330 g_assert(pagesize >= qemu_real_host_page_size());
331 return pagesize;
332 }
333
334 static void
335 host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
336 {
337 HostMemoryBackend *backend = MEMORY_BACKEND(uc);
338 HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
339 void *ptr;
340 uint64_t sz;
341 size_t pagesize;
342 bool async = !phase_check(PHASE_LATE_BACKENDS_CREATED);
343
344 if (!bc->alloc) {
345 return;
346 }
347 if (!bc->alloc(backend, errp)) {
348 return;
349 }
350
351 ptr = memory_region_get_ram_ptr(&backend->mr);
352 sz = memory_region_size(&backend->mr);
353 pagesize = qemu_ram_pagesize(backend->mr.ram_block);
354
355 if (backend->aligned && !QEMU_IS_ALIGNED(sz, pagesize)) {
356 g_autofree char *pagesize_str = size_to_str(pagesize);
357 error_setg(errp, "backend '%s' memory size must be multiple of %s",
358 object_get_typename(OBJECT(uc)), pagesize_str);
359 return;
360 }
361
362 if (backend->merge) {
363 qemu_madvise(ptr, sz, QEMU_MADV_MERGEABLE);
364 }
365 if (!backend->dump) {
366 qemu_madvise(ptr, sz, QEMU_MADV_DONTDUMP);
367 }
368 #ifdef CONFIG_NUMA
369 unsigned long lastbit = find_last_bit(backend->host_nodes, MAX_NODES);
370 /* lastbit == MAX_NODES means maxnode = 0 */
371 unsigned long maxnode = (lastbit + 1) % (MAX_NODES + 1);
372 /*
373 * Ensure policy won't be ignored in case memory is preallocated
374 * before mbind(). note: MPOL_MF_STRICT is ignored on hugepages so
375 * this doesn't catch hugepage case.
376 */
377 unsigned flags = MPOL_MF_STRICT | MPOL_MF_MOVE;
378 int mode = backend->policy;
379
380 /* check for invalid host-nodes and policies and give more verbose
381 * error messages than mbind(). */
382 if (maxnode && backend->policy == MPOL_DEFAULT) {
383 error_setg(errp, "host-nodes must be empty for policy default,"
384 " or you should explicitly specify a policy other"
385 " than default");
386 return;
387 } else if (maxnode == 0 && backend->policy != MPOL_DEFAULT) {
388 error_setg(errp, "host-nodes must be set for policy %s",
389 HostMemPolicy_str(backend->policy));
390 return;
391 }
392
393 /*
394 * We can have up to MAX_NODES nodes, but we need to pass maxnode+1
395 * as argument to mbind() due to an old Linux bug (feature?) which
396 * cuts off the last specified node. This means backend->host_nodes
397 * must have MAX_NODES+1 bits available.
398 */
399 assert(sizeof(backend->host_nodes) >=
400 BITS_TO_LONGS(MAX_NODES + 1) * sizeof(unsigned long));
401 assert(maxnode <= MAX_NODES);
402
403 #ifdef HAVE_NUMA_HAS_PREFERRED_MANY
404 if (mode == MPOL_PREFERRED && numa_has_preferred_many() > 0) {
405 /*
406 * Replace with MPOL_PREFERRED_MANY otherwise the mbind() below
407 * silently picks the first node.
408 */
409 mode = MPOL_PREFERRED_MANY;
410 }
411 #endif
412
413 if (maxnode &&
414 mbind(ptr, sz, mode, backend->host_nodes, maxnode + 1, flags)) {
415 if (backend->policy != MPOL_DEFAULT || errno != ENOSYS) {
416 error_setg_errno(errp, errno,
417 "cannot bind memory to host NUMA nodes");
418 return;
419 }
420 }
421 #endif
422 /*
423 * Preallocate memory after the NUMA policy has been instantiated.
424 * This is necessary to guarantee memory is allocated with
425 * specified NUMA policy in place.
426 */
427 if (backend->prealloc && !qemu_prealloc_mem(memory_region_get_fd(&backend->mr),
428 ptr, sz,
429 backend->prealloc_threads,
430 backend->prealloc_context,
431 async, errp)) {
432 return;
433 }
434 }
435
436 static bool
437 host_memory_backend_prepare_delete(UserCreatable *uc, Error **errp)
438 {
439 if (host_memory_backend_is_mapped(MEMORY_BACKEND(uc))) {
440 error_setg(errp,
441 "Cannot delete host memory backend '%s' which is mapped",
442 object_get_canonical_path_component(OBJECT(uc)));
443 return false;
444 } else {
445 return true;
446 }
447 }
448
449 static bool host_memory_backend_get_share(Object *o, Error **errp)
450 {
451 HostMemoryBackend *backend = MEMORY_BACKEND(o);
452
453 return backend->share;
454 }
455
456 static void host_memory_backend_set_share(Object *o, bool value, Error **errp)
457 {
458 HostMemoryBackend *backend = MEMORY_BACKEND(o);
459
460 if (host_memory_backend_mr_inited(backend)) {
461 error_setg(errp, "cannot change property value");
462 return;
463 }
464 backend->share = value;
465 }
466
467 #ifdef CONFIG_LINUX
468 static bool host_memory_backend_get_reserve(Object *o, Error **errp)
469 {
470 HostMemoryBackend *backend = MEMORY_BACKEND(o);
471
472 return backend->reserve;
473 }
474
475 static void host_memory_backend_set_reserve(Object *o, bool value, Error **errp)
476 {
477 HostMemoryBackend *backend = MEMORY_BACKEND(o);
478
479 if (host_memory_backend_mr_inited(backend)) {
480 error_setg(errp, "cannot change property value");
481 return;
482 }
483 if (backend->prealloc && !value) {
484 error_setg(errp, "'prealloc=on' and 'reserve=off' are incompatible");
485 return;
486 }
487 backend->reserve = value;
488 }
489 #endif /* CONFIG_LINUX */
490
491 static bool
492 host_memory_backend_get_use_canonical_path(Object *obj, Error **errp)
493 {
494 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
495
496 return backend->use_canonical_path;
497 }
498
499 static void
500 host_memory_backend_set_use_canonical_path(Object *obj, bool value,
501 Error **errp)
502 {
503 HostMemoryBackend *backend = MEMORY_BACKEND(obj);
504
505 backend->use_canonical_path = value;
506 }
507
508 static void
509 host_memory_backend_class_init(ObjectClass *oc, const void *data)
510 {
511 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
512
513 ucc->complete = host_memory_backend_memory_complete;
514 ucc->prepare_delete = host_memory_backend_prepare_delete;
515
516 object_class_property_add_bool(oc, "merge",
517 host_memory_backend_get_merge,
518 host_memory_backend_set_merge);
519 object_class_property_set_description(oc, "merge",
520 "Mark memory as mergeable");
521 object_class_property_add_bool(oc, "dump",
522 host_memory_backend_get_dump,
523 host_memory_backend_set_dump);
524 object_class_property_set_description(oc, "dump",
525 "Set to 'off' to exclude from core dump");
526 object_class_property_add_bool(oc, "prealloc",
527 host_memory_backend_get_prealloc,
528 host_memory_backend_set_prealloc);
529 object_class_property_set_description(oc, "prealloc",
530 "Preallocate memory");
531 object_class_property_add(oc, "prealloc-threads", "int",
532 host_memory_backend_get_prealloc_threads,
533 host_memory_backend_set_prealloc_threads,
534 NULL, NULL);
535 object_class_property_set_description(oc, "prealloc-threads",
536 "Number of CPU threads to use for prealloc");
537 object_class_property_add_link(oc, "prealloc-context",
538 TYPE_THREAD_CONTEXT, offsetof(HostMemoryBackend, prealloc_context),
539 object_property_allow_set_link, OBJ_PROP_LINK_STRONG);
540 object_class_property_set_description(oc, "prealloc-context",
541 "Context to use for creating CPU threads for preallocation");
542 object_class_property_add(oc, "size", "int",
543 host_memory_backend_get_size,
544 host_memory_backend_set_size,
545 NULL, NULL);
546 object_class_property_set_description(oc, "size",
547 "Size of the memory region (ex: 500M)");
548 object_class_property_add(oc, "host-nodes", "int",
549 host_memory_backend_get_host_nodes,
550 host_memory_backend_set_host_nodes,
551 NULL, NULL);
552 object_class_property_set_description(oc, "host-nodes",
553 "Binds memory to the list of NUMA host nodes");
554 object_class_property_add_enum(oc, "policy", "HostMemPolicy",
555 &HostMemPolicy_lookup,
556 host_memory_backend_get_policy,
557 host_memory_backend_set_policy);
558 object_class_property_set_description(oc, "policy",
559 "Set the NUMA policy");
560 object_class_property_add_bool(oc, "share",
561 host_memory_backend_get_share, host_memory_backend_set_share);
562 object_class_property_set_description(oc, "share",
563 "Mark the memory as private to QEMU or shared");
564 #ifdef CONFIG_LINUX
565 object_class_property_add_bool(oc, "reserve",
566 host_memory_backend_get_reserve, host_memory_backend_set_reserve);
567 object_class_property_set_description(oc, "reserve",
568 "Reserve swap space (or huge pages) if applicable");
569 #endif /* CONFIG_LINUX */
570 /*
571 * Do not delete/rename option. This option must be considered stable
572 * (as if it didn't have the 'x-' prefix including deprecation period) as
573 * long as 4.0 and older machine types exists.
574 * Option will be used by upper layers to override (disable) canonical path
575 * for ramblock-id set by compat properties on old machine types ( <= 4.0),
576 * to keep migration working when backend is used for main RAM with
577 * -machine memory-backend= option (main RAM historically used prefix-less
578 * ramblock-id).
579 */
580 object_class_property_add_bool(oc, "x-use-canonical-path-for-ramblock-id",
581 host_memory_backend_get_use_canonical_path,
582 host_memory_backend_set_use_canonical_path);
583 }
584
585 static const TypeInfo host_memory_backend_info = {
586 .name = TYPE_MEMORY_BACKEND,
587 .parent = TYPE_OBJECT,
588 .abstract = true,
589 .class_size = sizeof(HostMemoryBackendClass),
590 .class_init = host_memory_backend_class_init,
591 .instance_size = sizeof(HostMemoryBackend),
592 .instance_init = host_memory_backend_init,
593 .instance_post_init = host_memory_backend_post_init,
594 .interfaces = (const InterfaceInfo[]) {
595 { TYPE_USER_CREATABLE },
596 { }
597 }
598 };
599
600 static void register_types(void)
601 {
602 type_register_static(&host_memory_backend_info);
603 }
604
605 type_init(register_types);