]> git.proxmox.com Git - mirror_qemu.git/blame - hw/core/machine.c
numa: equally distribute memory on nodes
[mirror_qemu.git] / hw / core / machine.c
CommitLineData
36d20cb2
MA
1/*
2 * QEMU Machine
3 *
4 * Copyright (C) 2014 Red Hat Inc
5 *
6 * Authors:
7 * Marcel Apfelbaum <marcel.a@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
18c86e2b 13#include "qemu/osdep.h"
36d20cb2 14#include "hw/boards.h"
da34e65c 15#include "qapi/error.h"
32c18a2d 16#include "qapi-visit.h"
6b1b1440 17#include "qapi/visitor.h"
33cd52b5
AG
18#include "hw/sysbus.h"
19#include "sysemu/sysemu.h"
3bfe5716 20#include "sysemu/numa.h"
33cd52b5 21#include "qemu/error-report.h"
f348b6d1 22#include "qemu/cutils.h"
6b1b1440
MA
23
24static char *machine_get_accel(Object *obj, Error **errp)
25{
26 MachineState *ms = MACHINE(obj);
27
28 return g_strdup(ms->accel);
29}
30
31static void machine_set_accel(Object *obj, const char *value, Error **errp)
32{
33 MachineState *ms = MACHINE(obj);
34
556068ee 35 g_free(ms->accel);
6b1b1440
MA
36 ms->accel = g_strdup(value);
37}
38
32c18a2d 39static void machine_set_kernel_irqchip(Object *obj, Visitor *v,
d7bce999 40 const char *name, void *opaque,
32c18a2d 41 Error **errp)
6b1b1440 42{
32c18a2d 43 Error *err = NULL;
6b1b1440 44 MachineState *ms = MACHINE(obj);
32c18a2d 45 OnOffSplit mode;
6b1b1440 46
51e72bc1 47 visit_type_OnOffSplit(v, name, &mode, &err);
32c18a2d
MG
48 if (err) {
49 error_propagate(errp, err);
50 return;
51 } else {
52 switch (mode) {
53 case ON_OFF_SPLIT_ON:
54 ms->kernel_irqchip_allowed = true;
55 ms->kernel_irqchip_required = true;
56 ms->kernel_irqchip_split = false;
57 break;
58 case ON_OFF_SPLIT_OFF:
59 ms->kernel_irqchip_allowed = false;
60 ms->kernel_irqchip_required = false;
61 ms->kernel_irqchip_split = false;
62 break;
63 case ON_OFF_SPLIT_SPLIT:
64 ms->kernel_irqchip_allowed = true;
65 ms->kernel_irqchip_required = true;
66 ms->kernel_irqchip_split = true;
67 break;
68 default:
78a39306
GK
69 /* The value was checked in visit_type_OnOffSplit() above. If
70 * we get here, then something is wrong in QEMU.
71 */
32c18a2d
MG
72 abort();
73 }
74 }
6b1b1440
MA
75}
76
77static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v,
d7bce999 78 const char *name, void *opaque,
6b1b1440
MA
79 Error **errp)
80{
81 MachineState *ms = MACHINE(obj);
82 int64_t value = ms->kvm_shadow_mem;
83
51e72bc1 84 visit_type_int(v, name, &value, errp);
6b1b1440
MA
85}
86
87static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v,
d7bce999 88 const char *name, void *opaque,
6b1b1440
MA
89 Error **errp)
90{
91 MachineState *ms = MACHINE(obj);
92 Error *error = NULL;
93 int64_t value;
94
51e72bc1 95 visit_type_int(v, name, &value, &error);
6b1b1440
MA
96 if (error) {
97 error_propagate(errp, error);
98 return;
99 }
100
101 ms->kvm_shadow_mem = value;
102}
103
104static char *machine_get_kernel(Object *obj, Error **errp)
105{
106 MachineState *ms = MACHINE(obj);
107
108 return g_strdup(ms->kernel_filename);
109}
110
111static void machine_set_kernel(Object *obj, const char *value, Error **errp)
112{
113 MachineState *ms = MACHINE(obj);
114
556068ee 115 g_free(ms->kernel_filename);
6b1b1440
MA
116 ms->kernel_filename = g_strdup(value);
117}
118
119static char *machine_get_initrd(Object *obj, Error **errp)
120{
121 MachineState *ms = MACHINE(obj);
122
123 return g_strdup(ms->initrd_filename);
124}
125
126static void machine_set_initrd(Object *obj, const char *value, Error **errp)
127{
128 MachineState *ms = MACHINE(obj);
129
556068ee 130 g_free(ms->initrd_filename);
6b1b1440
MA
131 ms->initrd_filename = g_strdup(value);
132}
133
134static char *machine_get_append(Object *obj, Error **errp)
135{
136 MachineState *ms = MACHINE(obj);
137
138 return g_strdup(ms->kernel_cmdline);
139}
140
141static void machine_set_append(Object *obj, const char *value, Error **errp)
142{
143 MachineState *ms = MACHINE(obj);
144
556068ee 145 g_free(ms->kernel_cmdline);
6b1b1440
MA
146 ms->kernel_cmdline = g_strdup(value);
147}
148
149static char *machine_get_dtb(Object *obj, Error **errp)
150{
151 MachineState *ms = MACHINE(obj);
152
153 return g_strdup(ms->dtb);
154}
155
156static void machine_set_dtb(Object *obj, const char *value, Error **errp)
157{
158 MachineState *ms = MACHINE(obj);
159
556068ee 160 g_free(ms->dtb);
6b1b1440
MA
161 ms->dtb = g_strdup(value);
162}
163
164static char *machine_get_dumpdtb(Object *obj, Error **errp)
165{
166 MachineState *ms = MACHINE(obj);
167
168 return g_strdup(ms->dumpdtb);
169}
170
171static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
172{
173 MachineState *ms = MACHINE(obj);
174
556068ee 175 g_free(ms->dumpdtb);
6b1b1440
MA
176 ms->dumpdtb = g_strdup(value);
177}
178
179static void machine_get_phandle_start(Object *obj, Visitor *v,
d7bce999
EB
180 const char *name, void *opaque,
181 Error **errp)
6b1b1440
MA
182{
183 MachineState *ms = MACHINE(obj);
184 int64_t value = ms->phandle_start;
185
51e72bc1 186 visit_type_int(v, name, &value, errp);
6b1b1440
MA
187}
188
189static void machine_set_phandle_start(Object *obj, Visitor *v,
d7bce999
EB
190 const char *name, void *opaque,
191 Error **errp)
6b1b1440
MA
192{
193 MachineState *ms = MACHINE(obj);
194 Error *error = NULL;
195 int64_t value;
196
51e72bc1 197 visit_type_int(v, name, &value, &error);
6b1b1440
MA
198 if (error) {
199 error_propagate(errp, error);
200 return;
201 }
202
203 ms->phandle_start = value;
204}
205
206static char *machine_get_dt_compatible(Object *obj, Error **errp)
207{
208 MachineState *ms = MACHINE(obj);
209
210 return g_strdup(ms->dt_compatible);
211}
212
213static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp)
214{
215 MachineState *ms = MACHINE(obj);
216
556068ee 217 g_free(ms->dt_compatible);
6b1b1440
MA
218 ms->dt_compatible = g_strdup(value);
219}
220
221static bool machine_get_dump_guest_core(Object *obj, Error **errp)
222{
223 MachineState *ms = MACHINE(obj);
224
225 return ms->dump_guest_core;
226}
227
228static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp)
229{
230 MachineState *ms = MACHINE(obj);
231
232 ms->dump_guest_core = value;
233}
234
235static bool machine_get_mem_merge(Object *obj, Error **errp)
236{
237 MachineState *ms = MACHINE(obj);
238
239 return ms->mem_merge;
240}
241
242static void machine_set_mem_merge(Object *obj, bool value, Error **errp)
243{
244 MachineState *ms = MACHINE(obj);
245
246 ms->mem_merge = value;
247}
248
249static bool machine_get_usb(Object *obj, Error **errp)
250{
251 MachineState *ms = MACHINE(obj);
252
253 return ms->usb;
254}
255
256static void machine_set_usb(Object *obj, bool value, Error **errp)
257{
258 MachineState *ms = MACHINE(obj);
259
260 ms->usb = value;
c6e76503 261 ms->usb_disabled = !value;
6b1b1440
MA
262}
263
cfc58cf3
EH
264static bool machine_get_graphics(Object *obj, Error **errp)
265{
266 MachineState *ms = MACHINE(obj);
267
268 return ms->enable_graphics;
269}
270
271static void machine_set_graphics(Object *obj, bool value, Error **errp)
272{
273 MachineState *ms = MACHINE(obj);
274
275 ms->enable_graphics = value;
276}
277
79814179
TC
278static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
279{
280 MachineState *ms = MACHINE(obj);
281
282 return ms->igd_gfx_passthru;
283}
284
285static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
286{
287 MachineState *ms = MACHINE(obj);
288
289 ms->igd_gfx_passthru = value;
290}
291
6b1b1440
MA
292static char *machine_get_firmware(Object *obj, Error **errp)
293{
294 MachineState *ms = MACHINE(obj);
295
296 return g_strdup(ms->firmware);
297}
298
299static void machine_set_firmware(Object *obj, const char *value, Error **errp)
300{
301 MachineState *ms = MACHINE(obj);
302
556068ee 303 g_free(ms->firmware);
6b1b1440
MA
304 ms->firmware = g_strdup(value);
305}
306
9850c604
AG
307static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
308{
309 MachineState *ms = MACHINE(obj);
310
311 ms->suppress_vmdesc = value;
312}
313
314static bool machine_get_suppress_vmdesc(Object *obj, Error **errp)
315{
316 MachineState *ms = MACHINE(obj);
317
318 return ms->suppress_vmdesc;
319}
320
902c053d
GK
321static void machine_set_enforce_config_section(Object *obj, bool value,
322 Error **errp)
323{
324 MachineState *ms = MACHINE(obj);
325
326 ms->enforce_config_section = value;
327}
328
329static bool machine_get_enforce_config_section(Object *obj, Error **errp)
330{
331 MachineState *ms = MACHINE(obj);
332
333 return ms->enforce_config_section;
334}
335
4f01a637 336static void error_on_sysbus_device(SysBusDevice *sbdev, void *opaque)
33cd52b5
AG
337{
338 error_report("Option '-device %s' cannot be handled by this machine",
339 object_class_get_name(object_get_class(OBJECT(sbdev))));
340 exit(1);
341}
342
343static void machine_init_notify(Notifier *notifier, void *data)
344{
345 Object *machine = qdev_get_machine();
346 ObjectClass *oc = object_get_class(machine);
347 MachineClass *mc = MACHINE_CLASS(oc);
348
349 if (mc->has_dynamic_sysbus) {
350 /* Our machine can handle dynamic sysbus devices, we're all good */
351 return;
352 }
353
354 /*
355 * Loop through all dynamically created devices and check whether there
356 * are sysbus devices among them. If there are, error out.
357 */
358 foreach_dynamic_sysbus_device(error_on_sysbus_device, NULL);
359}
360
f2d672c2
IM
361HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
362{
363 int i;
364 Object *cpu;
365 HotpluggableCPUList *head = NULL;
366 const char *cpu_type;
367
368 cpu = machine->possible_cpus->cpus[0].cpu;
369 assert(cpu); /* Boot cpu is always present */
370 cpu_type = object_get_typename(cpu);
371 for (i = 0; i < machine->possible_cpus->len; i++) {
372 HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
373 HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
374
375 cpu_item->type = g_strdup(cpu_type);
376 cpu_item->vcpus_count = machine->possible_cpus->cpus[i].vcpus_count;
377 cpu_item->props = g_memdup(&machine->possible_cpus->cpus[i].props,
378 sizeof(*cpu_item->props));
379
380 cpu = machine->possible_cpus->cpus[i].cpu;
381 if (cpu) {
382 cpu_item->has_qom_path = true;
383 cpu_item->qom_path = object_get_canonical_path(cpu);
384 }
385 list_item->value = cpu_item;
386 list_item->next = head;
387 head = list_item;
388 }
389 return head;
390}
391
076b35b5
ND
392static void machine_class_init(ObjectClass *oc, void *data)
393{
394 MachineClass *mc = MACHINE_CLASS(oc);
395
396 /* Default 128 MB as guest ram size */
397 mc->default_ram_size = 128 * M_BYTE;
71ae9e94 398 mc->rom_file_has_mr = true;
26b81df4 399
55641213
LV
400 /* numa node memory size aligned on 8MB by default.
401 * On Linux, each node's border has to be 8MB aligned
402 */
403 mc->numa_mem_align_shift = 23;
3bfe5716 404 mc->numa_auto_assign_ram = numa_default_auto_assign_ram;
55641213 405
26b81df4
EH
406 object_class_property_add_str(oc, "accel",
407 machine_get_accel, machine_set_accel, &error_abort);
408 object_class_property_set_description(oc, "accel",
409 "Accelerator list", &error_abort);
410
411 object_class_property_add(oc, "kernel-irqchip", "OnOffSplit",
412 NULL, machine_set_kernel_irqchip,
413 NULL, NULL, &error_abort);
414 object_class_property_set_description(oc, "kernel-irqchip",
415 "Configure KVM in-kernel irqchip", &error_abort);
416
417 object_class_property_add(oc, "kvm-shadow-mem", "int",
418 machine_get_kvm_shadow_mem, machine_set_kvm_shadow_mem,
419 NULL, NULL, &error_abort);
420 object_class_property_set_description(oc, "kvm-shadow-mem",
421 "KVM shadow MMU size", &error_abort);
422
423 object_class_property_add_str(oc, "kernel",
424 machine_get_kernel, machine_set_kernel, &error_abort);
425 object_class_property_set_description(oc, "kernel",
426 "Linux kernel image file", &error_abort);
427
428 object_class_property_add_str(oc, "initrd",
429 machine_get_initrd, machine_set_initrd, &error_abort);
430 object_class_property_set_description(oc, "initrd",
431 "Linux initial ramdisk file", &error_abort);
432
433 object_class_property_add_str(oc, "append",
434 machine_get_append, machine_set_append, &error_abort);
435 object_class_property_set_description(oc, "append",
436 "Linux kernel command line", &error_abort);
437
438 object_class_property_add_str(oc, "dtb",
439 machine_get_dtb, machine_set_dtb, &error_abort);
440 object_class_property_set_description(oc, "dtb",
441 "Linux kernel device tree file", &error_abort);
442
443 object_class_property_add_str(oc, "dumpdtb",
444 machine_get_dumpdtb, machine_set_dumpdtb, &error_abort);
445 object_class_property_set_description(oc, "dumpdtb",
446 "Dump current dtb to a file and quit", &error_abort);
447
448 object_class_property_add(oc, "phandle-start", "int",
449 machine_get_phandle_start, machine_set_phandle_start,
450 NULL, NULL, &error_abort);
451 object_class_property_set_description(oc, "phandle-start",
452 "The first phandle ID we may generate dynamically", &error_abort);
453
454 object_class_property_add_str(oc, "dt-compatible",
455 machine_get_dt_compatible, machine_set_dt_compatible, &error_abort);
456 object_class_property_set_description(oc, "dt-compatible",
457 "Overrides the \"compatible\" property of the dt root node",
458 &error_abort);
459
460 object_class_property_add_bool(oc, "dump-guest-core",
461 machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort);
462 object_class_property_set_description(oc, "dump-guest-core",
463 "Include guest memory in a core dump", &error_abort);
464
465 object_class_property_add_bool(oc, "mem-merge",
466 machine_get_mem_merge, machine_set_mem_merge, &error_abort);
467 object_class_property_set_description(oc, "mem-merge",
468 "Enable/disable memory merge support", &error_abort);
469
470 object_class_property_add_bool(oc, "usb",
471 machine_get_usb, machine_set_usb, &error_abort);
472 object_class_property_set_description(oc, "usb",
473 "Set on/off to enable/disable usb", &error_abort);
474
475 object_class_property_add_bool(oc, "graphics",
476 machine_get_graphics, machine_set_graphics, &error_abort);
477 object_class_property_set_description(oc, "graphics",
478 "Set on/off to enable/disable graphics emulation", &error_abort);
479
480 object_class_property_add_bool(oc, "igd-passthru",
481 machine_get_igd_gfx_passthru, machine_set_igd_gfx_passthru,
482 &error_abort);
483 object_class_property_set_description(oc, "igd-passthru",
484 "Set on/off to enable/disable igd passthrou", &error_abort);
485
486 object_class_property_add_str(oc, "firmware",
487 machine_get_firmware, machine_set_firmware,
488 &error_abort);
489 object_class_property_set_description(oc, "firmware",
490 "Firmware image", &error_abort);
491
492 object_class_property_add_bool(oc, "suppress-vmdesc",
493 machine_get_suppress_vmdesc, machine_set_suppress_vmdesc,
494 &error_abort);
495 object_class_property_set_description(oc, "suppress-vmdesc",
496 "Set on to disable self-describing migration", &error_abort);
497
498 object_class_property_add_bool(oc, "enforce-config-section",
499 machine_get_enforce_config_section, machine_set_enforce_config_section,
500 &error_abort);
501 object_class_property_set_description(oc, "enforce-config-section",
502 "Set on to enforce configuration section migration", &error_abort);
076b35b5
ND
503}
504
dcb3d601
EH
505static void machine_class_base_init(ObjectClass *oc, void *data)
506{
507 if (!object_class_is_abstract(oc)) {
98cec76a 508 MachineClass *mc = MACHINE_CLASS(oc);
dcb3d601
EH
509 const char *cname = object_class_get_name(oc);
510 assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX));
98cec76a
EH
511 mc->name = g_strndup(cname,
512 strlen(cname) - strlen(TYPE_MACHINE_SUFFIX));
dcb3d601
EH
513 }
514}
515
6b1b1440
MA
516static void machine_initfn(Object *obj)
517{
33cd52b5
AG
518 MachineState *ms = MACHINE(obj);
519
d8870d02 520 ms->kernel_irqchip_allowed = true;
4689b77b 521 ms->kvm_shadow_mem = -1;
47c8ca53 522 ms->dump_guest_core = true;
75cc7f01 523 ms->mem_merge = true;
cfc58cf3 524 ms->enable_graphics = true;
d8870d02 525
33cd52b5
AG
526 /* Register notifier when init is done for sysbus sanity checks */
527 ms->sysbus_notifier.notify = machine_init_notify;
528 qemu_add_machine_init_done_notifier(&ms->sysbus_notifier);
6b1b1440
MA
529}
530
531static void machine_finalize(Object *obj)
532{
533 MachineState *ms = MACHINE(obj);
534
535 g_free(ms->accel);
536 g_free(ms->kernel_filename);
537 g_free(ms->initrd_filename);
538 g_free(ms->kernel_cmdline);
539 g_free(ms->dtb);
540 g_free(ms->dumpdtb);
541 g_free(ms->dt_compatible);
542 g_free(ms->firmware);
543}
36d20cb2 544
5e97b623
MA
545bool machine_usb(MachineState *machine)
546{
547 return machine->usb;
548}
549
d8870d02
MA
550bool machine_kernel_irqchip_allowed(MachineState *machine)
551{
552 return machine->kernel_irqchip_allowed;
553}
554
555bool machine_kernel_irqchip_required(MachineState *machine)
556{
557 return machine->kernel_irqchip_required;
558}
559
32c18a2d
MG
560bool machine_kernel_irqchip_split(MachineState *machine)
561{
562 return machine->kernel_irqchip_split;
563}
564
4689b77b
MA
565int machine_kvm_shadow_mem(MachineState *machine)
566{
567 return machine->kvm_shadow_mem;
568}
569
6cabe7fa
MA
570int machine_phandle_start(MachineState *machine)
571{
572 return machine->phandle_start;
573}
574
47c8ca53
MA
575bool machine_dump_guest_core(MachineState *machine)
576{
577 return machine->dump_guest_core;
578}
579
75cc7f01
MA
580bool machine_mem_merge(MachineState *machine)
581{
582 return machine->mem_merge;
583}
584
bacc344c
IM
585static void machine_class_finalize(ObjectClass *klass, void *data)
586{
587 MachineClass *mc = MACHINE_CLASS(klass);
588
589 if (mc->compat_props) {
590 g_array_free(mc->compat_props, true);
591 }
8ea75371 592 g_free(mc->name);
bacc344c
IM
593}
594
0bcba41f
EH
595static void register_compat_prop(const char *driver,
596 const char *property,
597 const char *value)
598{
599 GlobalProperty *p = g_new0(GlobalProperty, 1);
600 /* Machine compat_props must never cause errors: */
601 p->errp = &error_abort;
602 p->driver = driver;
603 p->property = property;
604 p->value = value;
605 qdev_prop_register_global(p);
606}
607
608static void machine_register_compat_for_subclass(ObjectClass *oc, void *opaque)
609{
610 GlobalProperty *p = opaque;
611 register_compat_prop(object_class_get_name(oc), p->property, p->value);
612}
613
39a3b377
EH
614void machine_register_compat_props(MachineState *machine)
615{
616 MachineClass *mc = MACHINE_GET_CLASS(machine);
617 int i;
618 GlobalProperty *p;
0bcba41f 619 ObjectClass *oc;
39a3b377
EH
620
621 if (!mc->compat_props) {
622 return;
623 }
624
625 for (i = 0; i < mc->compat_props->len; i++) {
626 p = g_array_index(mc->compat_props, GlobalProperty *, i);
0bcba41f
EH
627 oc = object_class_by_name(p->driver);
628 if (oc && object_class_is_abstract(oc)) {
629 /* temporary hack to make sure we do not override
630 * globals set explicitly on -global: if an abstract class
631 * is on compat_props, register globals for all its
632 * non-abstract subtypes instead.
633 *
634 * This doesn't solve the problem for cases where
635 * a non-abstract typename mentioned on compat_props
636 * has subclasses, like spapr-pci-host-bridge.
637 */
638 object_class_foreach(machine_register_compat_for_subclass,
639 p->driver, false, p);
640 } else {
641 register_compat_prop(p->driver, p->property, p->value);
642 }
39a3b377
EH
643 }
644}
645
36d20cb2
MA
646static const TypeInfo machine_info = {
647 .name = TYPE_MACHINE,
648 .parent = TYPE_OBJECT,
649 .abstract = true,
650 .class_size = sizeof(MachineClass),
076b35b5 651 .class_init = machine_class_init,
dcb3d601 652 .class_base_init = machine_class_base_init,
bacc344c 653 .class_finalize = machine_class_finalize,
36d20cb2 654 .instance_size = sizeof(MachineState),
6b1b1440
MA
655 .instance_init = machine_initfn,
656 .instance_finalize = machine_finalize,
36d20cb2
MA
657};
658
659static void machine_register_types(void)
660{
661 type_register_static(&machine_info);
662}
663
664type_init(machine_register_types)