xref: /qemu/hw/core/machine.c (revision 3bfe57165b4bf86a431099078df422f54598f5c6)
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 
13 #include "qemu/osdep.h"
14 #include "hw/boards.h"
15 #include "qapi/error.h"
16 #include "qapi-visit.h"
17 #include "qapi/visitor.h"
18 #include "hw/sysbus.h"
19 #include "sysemu/sysemu.h"
20 #include "sysemu/numa.h"
21 #include "qemu/error-report.h"
22 #include "qemu/cutils.h"
23 
24 static char *machine_get_accel(Object *obj, Error **errp)
25 {
26     MachineState *ms = MACHINE(obj);
27 
28     return g_strdup(ms->accel);
29 }
30 
31 static void machine_set_accel(Object *obj, const char *value, Error **errp)
32 {
33     MachineState *ms = MACHINE(obj);
34 
35     g_free(ms->accel);
36     ms->accel = g_strdup(value);
37 }
38 
39 static void machine_set_kernel_irqchip(Object *obj, Visitor *v,
40                                        const char *name, void *opaque,
41                                        Error **errp)
42 {
43     Error *err = NULL;
44     MachineState *ms = MACHINE(obj);
45     OnOffSplit mode;
46 
47     visit_type_OnOffSplit(v, name, &mode, &err);
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:
69             /* The value was checked in visit_type_OnOffSplit() above. If
70              * we get here, then something is wrong in QEMU.
71              */
72             abort();
73         }
74     }
75 }
76 
77 static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v,
78                                        const char *name, void *opaque,
79                                        Error **errp)
80 {
81     MachineState *ms = MACHINE(obj);
82     int64_t value = ms->kvm_shadow_mem;
83 
84     visit_type_int(v, name, &value, errp);
85 }
86 
87 static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v,
88                                        const char *name, void *opaque,
89                                        Error **errp)
90 {
91     MachineState *ms = MACHINE(obj);
92     Error *error = NULL;
93     int64_t value;
94 
95     visit_type_int(v, name, &value, &error);
96     if (error) {
97         error_propagate(errp, error);
98         return;
99     }
100 
101     ms->kvm_shadow_mem = value;
102 }
103 
104 static char *machine_get_kernel(Object *obj, Error **errp)
105 {
106     MachineState *ms = MACHINE(obj);
107 
108     return g_strdup(ms->kernel_filename);
109 }
110 
111 static void machine_set_kernel(Object *obj, const char *value, Error **errp)
112 {
113     MachineState *ms = MACHINE(obj);
114 
115     g_free(ms->kernel_filename);
116     ms->kernel_filename = g_strdup(value);
117 }
118 
119 static char *machine_get_initrd(Object *obj, Error **errp)
120 {
121     MachineState *ms = MACHINE(obj);
122 
123     return g_strdup(ms->initrd_filename);
124 }
125 
126 static void machine_set_initrd(Object *obj, const char *value, Error **errp)
127 {
128     MachineState *ms = MACHINE(obj);
129 
130     g_free(ms->initrd_filename);
131     ms->initrd_filename = g_strdup(value);
132 }
133 
134 static char *machine_get_append(Object *obj, Error **errp)
135 {
136     MachineState *ms = MACHINE(obj);
137 
138     return g_strdup(ms->kernel_cmdline);
139 }
140 
141 static void machine_set_append(Object *obj, const char *value, Error **errp)
142 {
143     MachineState *ms = MACHINE(obj);
144 
145     g_free(ms->kernel_cmdline);
146     ms->kernel_cmdline = g_strdup(value);
147 }
148 
149 static char *machine_get_dtb(Object *obj, Error **errp)
150 {
151     MachineState *ms = MACHINE(obj);
152 
153     return g_strdup(ms->dtb);
154 }
155 
156 static void machine_set_dtb(Object *obj, const char *value, Error **errp)
157 {
158     MachineState *ms = MACHINE(obj);
159 
160     g_free(ms->dtb);
161     ms->dtb = g_strdup(value);
162 }
163 
164 static char *machine_get_dumpdtb(Object *obj, Error **errp)
165 {
166     MachineState *ms = MACHINE(obj);
167 
168     return g_strdup(ms->dumpdtb);
169 }
170 
171 static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
172 {
173     MachineState *ms = MACHINE(obj);
174 
175     g_free(ms->dumpdtb);
176     ms->dumpdtb = g_strdup(value);
177 }
178 
179 static void machine_get_phandle_start(Object *obj, Visitor *v,
180                                       const char *name, void *opaque,
181                                       Error **errp)
182 {
183     MachineState *ms = MACHINE(obj);
184     int64_t value = ms->phandle_start;
185 
186     visit_type_int(v, name, &value, errp);
187 }
188 
189 static void machine_set_phandle_start(Object *obj, Visitor *v,
190                                       const char *name, void *opaque,
191                                       Error **errp)
192 {
193     MachineState *ms = MACHINE(obj);
194     Error *error = NULL;
195     int64_t value;
196 
197     visit_type_int(v, name, &value, &error);
198     if (error) {
199         error_propagate(errp, error);
200         return;
201     }
202 
203     ms->phandle_start = value;
204 }
205 
206 static 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 
213 static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp)
214 {
215     MachineState *ms = MACHINE(obj);
216 
217     g_free(ms->dt_compatible);
218     ms->dt_compatible = g_strdup(value);
219 }
220 
221 static 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 
228 static 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 
235 static bool machine_get_mem_merge(Object *obj, Error **errp)
236 {
237     MachineState *ms = MACHINE(obj);
238 
239     return ms->mem_merge;
240 }
241 
242 static 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 
249 static bool machine_get_usb(Object *obj, Error **errp)
250 {
251     MachineState *ms = MACHINE(obj);
252 
253     return ms->usb;
254 }
255 
256 static void machine_set_usb(Object *obj, bool value, Error **errp)
257 {
258     MachineState *ms = MACHINE(obj);
259 
260     ms->usb = value;
261     ms->usb_disabled = !value;
262 }
263 
264 static bool machine_get_graphics(Object *obj, Error **errp)
265 {
266     MachineState *ms = MACHINE(obj);
267 
268     return ms->enable_graphics;
269 }
270 
271 static void machine_set_graphics(Object *obj, bool value, Error **errp)
272 {
273     MachineState *ms = MACHINE(obj);
274 
275     ms->enable_graphics = value;
276 }
277 
278 static 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 
285 static 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 
292 static char *machine_get_firmware(Object *obj, Error **errp)
293 {
294     MachineState *ms = MACHINE(obj);
295 
296     return g_strdup(ms->firmware);
297 }
298 
299 static void machine_set_firmware(Object *obj, const char *value, Error **errp)
300 {
301     MachineState *ms = MACHINE(obj);
302 
303     g_free(ms->firmware);
304     ms->firmware = g_strdup(value);
305 }
306 
307 static 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 
314 static bool machine_get_suppress_vmdesc(Object *obj, Error **errp)
315 {
316     MachineState *ms = MACHINE(obj);
317 
318     return ms->suppress_vmdesc;
319 }
320 
321 static 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 
329 static 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 
336 static void error_on_sysbus_device(SysBusDevice *sbdev, void *opaque)
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 
343 static 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 
361 HotpluggableCPUList *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 
392 static 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;
398     mc->rom_file_has_mr = true;
399 
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;
404     mc->numa_auto_assign_ram = numa_default_auto_assign_ram;
405 
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);
503 }
504 
505 static void machine_class_base_init(ObjectClass *oc, void *data)
506 {
507     if (!object_class_is_abstract(oc)) {
508         MachineClass *mc = MACHINE_CLASS(oc);
509         const char *cname = object_class_get_name(oc);
510         assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX));
511         mc->name = g_strndup(cname,
512                             strlen(cname) - strlen(TYPE_MACHINE_SUFFIX));
513     }
514 }
515 
516 static void machine_initfn(Object *obj)
517 {
518     MachineState *ms = MACHINE(obj);
519 
520     ms->kernel_irqchip_allowed = true;
521     ms->kvm_shadow_mem = -1;
522     ms->dump_guest_core = true;
523     ms->mem_merge = true;
524     ms->enable_graphics = true;
525 
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);
529 }
530 
531 static 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 }
544 
545 bool machine_usb(MachineState *machine)
546 {
547     return machine->usb;
548 }
549 
550 bool machine_kernel_irqchip_allowed(MachineState *machine)
551 {
552     return machine->kernel_irqchip_allowed;
553 }
554 
555 bool machine_kernel_irqchip_required(MachineState *machine)
556 {
557     return machine->kernel_irqchip_required;
558 }
559 
560 bool machine_kernel_irqchip_split(MachineState *machine)
561 {
562     return machine->kernel_irqchip_split;
563 }
564 
565 int machine_kvm_shadow_mem(MachineState *machine)
566 {
567     return machine->kvm_shadow_mem;
568 }
569 
570 int machine_phandle_start(MachineState *machine)
571 {
572     return machine->phandle_start;
573 }
574 
575 bool machine_dump_guest_core(MachineState *machine)
576 {
577     return machine->dump_guest_core;
578 }
579 
580 bool machine_mem_merge(MachineState *machine)
581 {
582     return machine->mem_merge;
583 }
584 
585 static 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     }
592     g_free(mc->name);
593 }
594 
595 static 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 
608 static 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 
614 void machine_register_compat_props(MachineState *machine)
615 {
616     MachineClass *mc = MACHINE_GET_CLASS(machine);
617     int i;
618     GlobalProperty *p;
619     ObjectClass *oc;
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);
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         }
643     }
644 }
645 
646 static const TypeInfo machine_info = {
647     .name = TYPE_MACHINE,
648     .parent = TYPE_OBJECT,
649     .abstract = true,
650     .class_size = sizeof(MachineClass),
651     .class_init    = machine_class_init,
652     .class_base_init = machine_class_base_init,
653     .class_finalize = machine_class_finalize,
654     .instance_size = sizeof(MachineState),
655     .instance_init = machine_initfn,
656     .instance_finalize = machine_finalize,
657 };
658 
659 static void machine_register_types(void)
660 {
661     type_register_static(&machine_info);
662 }
663 
664 type_init(machine_register_types)
665