1
2
3
4
5
6
7
8
9
10
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#include "sysemu/numa.h"
24#include "sysemu/qtest.h"
25
26static char *machine_get_accel(Object *obj, Error **errp)
27{
28 MachineState *ms = MACHINE(obj);
29
30 return g_strdup(ms->accel);
31}
32
33static void machine_set_accel(Object *obj, const char *value, Error **errp)
34{
35 MachineState *ms = MACHINE(obj);
36
37 g_free(ms->accel);
38 ms->accel = g_strdup(value);
39}
40
41static void machine_set_kernel_irqchip(Object *obj, Visitor *v,
42 const char *name, void *opaque,
43 Error **errp)
44{
45 Error *err = NULL;
46 MachineState *ms = MACHINE(obj);
47 OnOffSplit mode;
48
49 visit_type_OnOffSplit(v, name, &mode, &err);
50 if (err) {
51 error_propagate(errp, err);
52 return;
53 } else {
54 switch (mode) {
55 case ON_OFF_SPLIT_ON:
56 ms->kernel_irqchip_allowed = true;
57 ms->kernel_irqchip_required = true;
58 ms->kernel_irqchip_split = false;
59 break;
60 case ON_OFF_SPLIT_OFF:
61 ms->kernel_irqchip_allowed = false;
62 ms->kernel_irqchip_required = false;
63 ms->kernel_irqchip_split = false;
64 break;
65 case ON_OFF_SPLIT_SPLIT:
66 ms->kernel_irqchip_allowed = true;
67 ms->kernel_irqchip_required = true;
68 ms->kernel_irqchip_split = true;
69 break;
70 default:
71
72
73
74 abort();
75 }
76 }
77}
78
79static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v,
80 const char *name, void *opaque,
81 Error **errp)
82{
83 MachineState *ms = MACHINE(obj);
84 int64_t value = ms->kvm_shadow_mem;
85
86 visit_type_int(v, name, &value, errp);
87}
88
89static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v,
90 const char *name, void *opaque,
91 Error **errp)
92{
93 MachineState *ms = MACHINE(obj);
94 Error *error = NULL;
95 int64_t value;
96
97 visit_type_int(v, name, &value, &error);
98 if (error) {
99 error_propagate(errp, error);
100 return;
101 }
102
103 ms->kvm_shadow_mem = value;
104}
105
106static char *machine_get_kernel(Object *obj, Error **errp)
107{
108 MachineState *ms = MACHINE(obj);
109
110 return g_strdup(ms->kernel_filename);
111}
112
113static void machine_set_kernel(Object *obj, const char *value, Error **errp)
114{
115 MachineState *ms = MACHINE(obj);
116
117 g_free(ms->kernel_filename);
118 ms->kernel_filename = g_strdup(value);
119}
120
121static char *machine_get_initrd(Object *obj, Error **errp)
122{
123 MachineState *ms = MACHINE(obj);
124
125 return g_strdup(ms->initrd_filename);
126}
127
128static void machine_set_initrd(Object *obj, const char *value, Error **errp)
129{
130 MachineState *ms = MACHINE(obj);
131
132 g_free(ms->initrd_filename);
133 ms->initrd_filename = g_strdup(value);
134}
135
136static char *machine_get_append(Object *obj, Error **errp)
137{
138 MachineState *ms = MACHINE(obj);
139
140 return g_strdup(ms->kernel_cmdline);
141}
142
143static void machine_set_append(Object *obj, const char *value, Error **errp)
144{
145 MachineState *ms = MACHINE(obj);
146
147 g_free(ms->kernel_cmdline);
148 ms->kernel_cmdline = g_strdup(value);
149}
150
151static char *machine_get_dtb(Object *obj, Error **errp)
152{
153 MachineState *ms = MACHINE(obj);
154
155 return g_strdup(ms->dtb);
156}
157
158static void machine_set_dtb(Object *obj, const char *value, Error **errp)
159{
160 MachineState *ms = MACHINE(obj);
161
162 g_free(ms->dtb);
163 ms->dtb = g_strdup(value);
164}
165
166static char *machine_get_hw_dtb(Object *obj, Error **errp)
167{
168 MachineState *ms = MACHINE(obj);
169
170 return g_strdup(ms->hw_dtb);
171}
172
173static void machine_set_hw_dtb(Object *obj, const char *value, Error **errp)
174{
175 MachineState *ms = MACHINE(obj);
176
177 ms->hw_dtb = g_strdup(value);
178}
179
180static char *machine_get_dumpdtb(Object *obj, Error **errp)
181{
182 MachineState *ms = MACHINE(obj);
183
184 return g_strdup(ms->dumpdtb);
185}
186
187static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
188{
189 MachineState *ms = MACHINE(obj);
190
191 g_free(ms->dumpdtb);
192 ms->dumpdtb = g_strdup(value);
193}
194
195static void machine_get_phandle_start(Object *obj, Visitor *v,
196 const char *name, void *opaque,
197 Error **errp)
198{
199 MachineState *ms = MACHINE(obj);
200 int64_t value = ms->phandle_start;
201
202 visit_type_int(v, name, &value, errp);
203}
204
205static void machine_set_phandle_start(Object *obj, Visitor *v,
206 const char *name, void *opaque,
207 Error **errp)
208{
209 MachineState *ms = MACHINE(obj);
210 Error *error = NULL;
211 int64_t value;
212
213 visit_type_int(v, name, &value, &error);
214 if (error) {
215 error_propagate(errp, error);
216 return;
217 }
218
219 ms->phandle_start = value;
220}
221
222static char *machine_get_dt_compatible(Object *obj, Error **errp)
223{
224 MachineState *ms = MACHINE(obj);
225
226 return g_strdup(ms->dt_compatible);
227}
228
229static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp)
230{
231 MachineState *ms = MACHINE(obj);
232
233 g_free(ms->dt_compatible);
234 ms->dt_compatible = g_strdup(value);
235}
236
237static bool machine_get_dump_guest_core(Object *obj, Error **errp)
238{
239 MachineState *ms = MACHINE(obj);
240
241 return ms->dump_guest_core;
242}
243
244static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp)
245{
246 MachineState *ms = MACHINE(obj);
247
248 ms->dump_guest_core = value;
249}
250
251
252static bool machine_get_linux(Object *obj, Error **errp)
253{
254 MachineState *ms = MACHINE(obj);
255
256 return ms->is_linux;
257}
258
259static void machine_set_linux(Object *obj, bool value, Error **errp)
260{
261 MachineState *ms = MACHINE(obj);
262
263 ms->is_linux = value;
264}
265
266static bool machine_get_mem_merge(Object *obj, Error **errp)
267{
268 MachineState *ms = MACHINE(obj);
269
270 return ms->mem_merge;
271}
272
273static void machine_set_mem_merge(Object *obj, bool value, Error **errp)
274{
275 MachineState *ms = MACHINE(obj);
276
277 ms->mem_merge = value;
278}
279
280static bool machine_get_usb(Object *obj, Error **errp)
281{
282 MachineState *ms = MACHINE(obj);
283
284 return ms->usb;
285}
286
287static void machine_set_usb(Object *obj, bool value, Error **errp)
288{
289 MachineState *ms = MACHINE(obj);
290
291 ms->usb = value;
292 ms->usb_disabled = !value;
293}
294
295static bool machine_get_graphics(Object *obj, Error **errp)
296{
297 MachineState *ms = MACHINE(obj);
298
299 return ms->enable_graphics;
300}
301
302static void machine_set_graphics(Object *obj, bool value, Error **errp)
303{
304 MachineState *ms = MACHINE(obj);
305
306 ms->enable_graphics = value;
307}
308
309static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
310{
311 MachineState *ms = MACHINE(obj);
312
313 return ms->igd_gfx_passthru;
314}
315
316static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
317{
318 MachineState *ms = MACHINE(obj);
319
320 ms->igd_gfx_passthru = value;
321}
322
323static char *machine_get_firmware(Object *obj, Error **errp)
324{
325 MachineState *ms = MACHINE(obj);
326
327 return g_strdup(ms->firmware);
328}
329
330static void machine_set_firmware(Object *obj, const char *value, Error **errp)
331{
332 MachineState *ms = MACHINE(obj);
333
334 g_free(ms->firmware);
335 ms->firmware = g_strdup(value);
336}
337
338static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
339{
340 MachineState *ms = MACHINE(obj);
341
342 ms->suppress_vmdesc = value;
343}
344
345static bool machine_get_suppress_vmdesc(Object *obj, Error **errp)
346{
347 MachineState *ms = MACHINE(obj);
348
349 return ms->suppress_vmdesc;
350}
351
352static void machine_set_enforce_config_section(Object *obj, bool value,
353 Error **errp)
354{
355 MachineState *ms = MACHINE(obj);
356
357 ms->enforce_config_section = value;
358}
359
360static bool machine_get_enforce_config_section(Object *obj, Error **errp)
361{
362 MachineState *ms = MACHINE(obj);
363
364 return ms->enforce_config_section;
365}
366
367static void error_on_sysbus_device(SysBusDevice *sbdev, void *opaque)
368{
369 error_report("Option '-device %s' cannot be handled by this machine",
370 object_class_get_name(object_get_class(OBJECT(sbdev))));
371 exit(1);
372}
373
374static void machine_init_notify(Notifier *notifier, void *data)
375{
376 Object *machine = qdev_get_machine();
377 ObjectClass *oc = object_get_class(machine);
378 MachineClass *mc = MACHINE_CLASS(oc);
379
380 if (mc->has_dynamic_sysbus) {
381
382 return;
383 }
384
385
386
387
388
389 foreach_dynamic_sysbus_device(error_on_sysbus_device, NULL);
390}
391
392HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
393{
394 int i;
395 Object *cpu;
396 HotpluggableCPUList *head = NULL;
397 const char *cpu_type;
398
399 cpu = machine->possible_cpus->cpus[0].cpu;
400 assert(cpu);
401 cpu_type = object_get_typename(cpu);
402 for (i = 0; i < machine->possible_cpus->len; i++) {
403 HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
404 HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
405
406 cpu_item->type = g_strdup(cpu_type);
407 cpu_item->vcpus_count = machine->possible_cpus->cpus[i].vcpus_count;
408 cpu_item->props = g_memdup(&machine->possible_cpus->cpus[i].props,
409 sizeof(*cpu_item->props));
410
411 cpu = machine->possible_cpus->cpus[i].cpu;
412 if (cpu) {
413 cpu_item->has_qom_path = true;
414 cpu_item->qom_path = object_get_canonical_path(cpu);
415 }
416 list_item->value = cpu_item;
417 list_item->next = head;
418 head = list_item;
419 }
420 return head;
421}
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448void machine_set_cpu_numa_node(MachineState *machine,
449 const CpuInstanceProperties *props, Error **errp)
450{
451 MachineClass *mc = MACHINE_GET_CLASS(machine);
452 bool match = false;
453 int i;
454
455 if (!mc->possible_cpu_arch_ids) {
456 error_setg(errp, "mapping of CPUs to NUMA node is not supported");
457 return;
458 }
459
460
461 assert(props->has_node_id);
462
463
464 mc->possible_cpu_arch_ids(machine);
465
466 for (i = 0; i < machine->possible_cpus->len; i++) {
467 CPUArchId *slot = &machine->possible_cpus->cpus[i];
468
469
470 if (props->has_thread_id && !slot->props.has_thread_id) {
471 error_setg(errp, "thread-id is not supported");
472 return;
473 }
474
475 if (props->has_core_id && !slot->props.has_core_id) {
476 error_setg(errp, "core-id is not supported");
477 return;
478 }
479
480 if (props->has_socket_id && !slot->props.has_socket_id) {
481 error_setg(errp, "socket-id is not supported");
482 return;
483 }
484
485
486 if (props->has_thread_id && props->thread_id != slot->props.thread_id) {
487 continue;
488 }
489
490 if (props->has_core_id && props->core_id != slot->props.core_id) {
491 continue;
492 }
493
494 if (props->has_socket_id && props->socket_id != slot->props.socket_id) {
495 continue;
496 }
497
498
499
500
501 if (slot->props.has_node_id &&
502 slot->props.node_id != props->node_id) {
503 error_setg(errp, "CPU is already assigned to node-id: %" PRId64,
504 slot->props.node_id);
505 return;
506 }
507
508
509 match = true;
510 slot->props.node_id = props->node_id;
511 slot->props.has_node_id = props->has_node_id;
512 }
513
514 if (!match) {
515 error_setg(errp, "no match found");
516 }
517}
518
519static void machine_class_init(ObjectClass *oc, void *data)
520{
521 MachineClass *mc = MACHINE_CLASS(oc);
522
523
524 mc->default_ram_size = 128 * M_BYTE;
525 mc->rom_file_has_mr = true;
526
527
528
529
530 mc->numa_mem_align_shift = 23;
531 mc->numa_auto_assign_ram = numa_default_auto_assign_ram;
532
533 object_class_property_add_str(oc, "accel",
534 machine_get_accel, machine_set_accel, &error_abort);
535 object_class_property_set_description(oc, "accel",
536 "Accelerator list", &error_abort);
537
538 object_class_property_add(oc, "kernel-irqchip", "OnOffSplit",
539 NULL, machine_set_kernel_irqchip,
540 NULL, NULL, &error_abort);
541 object_class_property_set_description(oc, "kernel-irqchip",
542 "Configure KVM in-kernel irqchip", &error_abort);
543
544 object_class_property_add(oc, "kvm-shadow-mem", "int",
545 machine_get_kvm_shadow_mem, machine_set_kvm_shadow_mem,
546 NULL, NULL, &error_abort);
547 object_class_property_set_description(oc, "kvm-shadow-mem",
548 "KVM shadow MMU size", &error_abort);
549
550 object_class_property_add_str(oc, "kernel",
551 machine_get_kernel, machine_set_kernel, &error_abort);
552 object_class_property_set_description(oc, "kernel",
553 "Linux kernel image file", &error_abort);
554
555 object_class_property_add_str(oc, "initrd",
556 machine_get_initrd, machine_set_initrd, &error_abort);
557 object_class_property_set_description(oc, "initrd",
558 "Linux initial ramdisk file", &error_abort);
559
560 object_class_property_add_str(oc, "append",
561 machine_get_append, machine_set_append, &error_abort);
562 object_class_property_set_description(oc, "append",
563 "Linux kernel command line", &error_abort);
564
565 object_class_property_add_str(oc, "dtb",
566 machine_get_dtb, machine_set_dtb, &error_abort);
567 object_class_property_set_description(oc, "dtb",
568 "Linux kernel device tree file", &error_abort);
569
570 object_class_property_add_str(oc, "dumpdtb",
571 machine_get_dumpdtb, machine_set_dumpdtb, &error_abort);
572 object_class_property_set_description(oc, "dumpdtb",
573 "Dump current dtb to a file and quit", &error_abort);
574
575 object_class_property_add(oc, "phandle-start", "int",
576 machine_get_phandle_start, machine_set_phandle_start,
577 NULL, NULL, &error_abort);
578 object_class_property_set_description(oc, "phandle-start",
579 "The first phandle ID we may generate dynamically", &error_abort);
580
581 object_class_property_add_str(oc, "dt-compatible",
582 machine_get_dt_compatible, machine_set_dt_compatible, &error_abort);
583 object_class_property_set_description(oc, "dt-compatible",
584 "Overrides the \"compatible\" property of the dt root node",
585 &error_abort);
586
587 object_class_property_add_bool(oc, "dump-guest-core",
588 machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort);
589 object_class_property_set_description(oc, "dump-guest-core",
590 "Include guest memory in a core dump", &error_abort);
591
592 object_class_property_add_bool(oc, "mem-merge",
593 machine_get_mem_merge, machine_set_mem_merge, &error_abort);
594 object_class_property_set_description(oc, "mem-merge",
595 "Enable/disable memory merge support", &error_abort);
596
597 object_class_property_add_bool(oc, "usb",
598 machine_get_usb, machine_set_usb, &error_abort);
599 object_class_property_set_description(oc, "usb",
600 "Set on/off to enable/disable usb", &error_abort);
601
602 object_class_property_add_bool(oc, "graphics",
603 machine_get_graphics, machine_set_graphics, &error_abort);
604 object_class_property_set_description(oc, "graphics",
605 "Set on/off to enable/disable graphics emulation", &error_abort);
606
607 object_class_property_add_bool(oc, "igd-passthru",
608 machine_get_igd_gfx_passthru, machine_set_igd_gfx_passthru,
609 &error_abort);
610 object_class_property_set_description(oc, "igd-passthru",
611 "Set on/off to enable/disable igd passthrou", &error_abort);
612
613 object_class_property_add_str(oc, "firmware",
614 machine_get_firmware, machine_set_firmware,
615 &error_abort);
616 object_class_property_set_description(oc, "firmware",
617 "Firmware image", &error_abort);
618
619 object_class_property_add_bool(oc, "suppress-vmdesc",
620 machine_get_suppress_vmdesc, machine_set_suppress_vmdesc,
621 &error_abort);
622 object_class_property_set_description(oc, "suppress-vmdesc",
623 "Set on to disable self-describing migration", &error_abort);
624
625 object_class_property_add_bool(oc, "enforce-config-section",
626 machine_get_enforce_config_section, machine_set_enforce_config_section,
627 &error_abort);
628 object_class_property_set_description(oc, "enforce-config-section",
629 "Set on to enforce configuration section migration", &error_abort);
630}
631
632static void machine_class_base_init(ObjectClass *oc, void *data)
633{
634 if (!object_class_is_abstract(oc)) {
635 MachineClass *mc = MACHINE_CLASS(oc);
636 const char *cname = object_class_get_name(oc);
637 assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX));
638 mc->name = g_strndup(cname,
639 strlen(cname) - strlen(TYPE_MACHINE_SUFFIX));
640 }
641}
642
643static void machine_initfn(Object *obj)
644{
645 MachineState *ms = MACHINE(obj);
646
647 ms->kernel_irqchip_allowed = true;
648 ms->kvm_shadow_mem = -1;
649 ms->dump_guest_core = true;
650 ms->mem_merge = true;
651 ms->enable_graphics = true;
652
653 object_property_add_str(obj, "hw-dtb",
654 machine_get_hw_dtb, machine_set_hw_dtb, NULL);
655 object_property_set_description(obj, "hw-dtb",
656 "A device tree used to describe the hardware to QEMU.",
657 NULL);
658 object_property_add_bool(obj, "linux",
659 machine_get_linux, machine_set_linux, NULL);
660 object_property_set_description(obj, "linux",
661 "Force a Linux style boot",
662 NULL);
663
664
665 ms->sysbus_notifier.notify = machine_init_notify;
666 qemu_add_machine_init_done_notifier(&ms->sysbus_notifier);
667}
668
669static void machine_finalize(Object *obj)
670{
671 MachineState *ms = MACHINE(obj);
672
673 g_free(ms->accel);
674 g_free(ms->kernel_filename);
675 g_free(ms->initrd_filename);
676 g_free(ms->kernel_cmdline);
677 g_free(ms->dtb);
678 g_free(ms->dumpdtb);
679 g_free(ms->dt_compatible);
680 g_free(ms->firmware);
681}
682
683bool machine_usb(MachineState *machine)
684{
685 return machine->usb;
686}
687
688bool machine_kernel_irqchip_allowed(MachineState *machine)
689{
690 return machine->kernel_irqchip_allowed;
691}
692
693bool machine_kernel_irqchip_required(MachineState *machine)
694{
695 return machine->kernel_irqchip_required;
696}
697
698bool machine_kernel_irqchip_split(MachineState *machine)
699{
700 return machine->kernel_irqchip_split;
701}
702
703int machine_kvm_shadow_mem(MachineState *machine)
704{
705 return machine->kvm_shadow_mem;
706}
707
708int machine_phandle_start(MachineState *machine)
709{
710 return machine->phandle_start;
711}
712
713bool machine_dump_guest_core(MachineState *machine)
714{
715 return machine->dump_guest_core;
716}
717
718bool machine_mem_merge(MachineState *machine)
719{
720 return machine->mem_merge;
721}
722
723static char *cpu_slot_to_string(const CPUArchId *cpu)
724{
725 GString *s = g_string_new(NULL);
726 if (cpu->props.has_socket_id) {
727 g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id);
728 }
729 if (cpu->props.has_core_id) {
730 if (s->len) {
731 g_string_append_printf(s, ", ");
732 }
733 g_string_append_printf(s, "core-id: %"PRId64, cpu->props.core_id);
734 }
735 if (cpu->props.has_thread_id) {
736 if (s->len) {
737 g_string_append_printf(s, ", ");
738 }
739 g_string_append_printf(s, "thread-id: %"PRId64, cpu->props.thread_id);
740 }
741 return g_string_free(s, false);
742}
743
744static void machine_numa_finish_init(MachineState *machine)
745{
746 int i;
747 bool default_mapping;
748 GString *s = g_string_new(NULL);
749 MachineClass *mc = MACHINE_GET_CLASS(machine);
750 const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(machine);
751
752 assert(nb_numa_nodes);
753 for (i = 0; i < possible_cpus->len; i++) {
754 if (possible_cpus->cpus[i].props.has_node_id) {
755 break;
756 }
757 }
758 default_mapping = (i == possible_cpus->len);
759
760 for (i = 0; i < possible_cpus->len; i++) {
761 const CPUArchId *cpu_slot = &possible_cpus->cpus[i];
762
763 if (!cpu_slot->props.has_node_id) {
764
765 CpuInstanceProperties props = cpu_slot->props;
766
767 props.node_id = mc->get_default_cpu_node_id(machine, i);
768 if (!default_mapping) {
769
770
771 char *cpu_str = cpu_slot_to_string(cpu_slot);
772 g_string_append_printf(s, "%sCPU %d [%s]",
773 s->len ? ", " : "", i, cpu_str);
774 g_free(cpu_str);
775
776
777 props.node_id = 0;
778 }
779
780 props.has_node_id = true;
781 machine_set_cpu_numa_node(machine, &props, &error_fatal);
782 }
783 }
784 if (s->len && !qtest_enabled()) {
785 warn_report("CPU(s) not present in any NUMA nodes: %s",
786 s->str);
787 warn_report("All CPU(s) up to maxcpus should be described "
788 "in NUMA config, ability to start up with partial NUMA "
789 "mappings is obsoleted and will be removed in future");
790 }
791 g_string_free(s, true);
792}
793
794void machine_run_board_init(MachineState *machine)
795{
796 MachineClass *machine_class = MACHINE_GET_CLASS(machine);
797
798 if (nb_numa_nodes) {
799 machine_numa_finish_init(machine);
800 }
801
802
803
804
805 if (machine_class->valid_cpu_types && machine->cpu_type) {
806 ObjectClass *class = object_class_by_name(machine->cpu_type);
807 int i;
808
809 for (i = 0; machine_class->valid_cpu_types[i]; i++) {
810 if (object_class_dynamic_cast(class,
811 machine_class->valid_cpu_types[i])) {
812
813
814
815 break;
816 }
817 }
818
819 if (!machine_class->valid_cpu_types[i]) {
820
821 error_report("Invalid CPU type: %s", machine->cpu_type);
822 error_printf("The valid types are: %s",
823 machine_class->valid_cpu_types[0]);
824 for (i = 1; machine_class->valid_cpu_types[i]; i++) {
825 error_printf(", %s", machine_class->valid_cpu_types[i]);
826 }
827 error_printf("\n");
828
829 exit(1);
830 }
831 }
832
833 machine_class->init(machine);
834}
835
836static void machine_class_finalize(ObjectClass *klass, void *data)
837{
838 MachineClass *mc = MACHINE_CLASS(klass);
839
840 if (mc->compat_props) {
841 g_array_free(mc->compat_props, true);
842 }
843 g_free(mc->name);
844}
845
846void machine_register_compat_props(MachineState *machine)
847{
848 MachineClass *mc = MACHINE_GET_CLASS(machine);
849 int i;
850 GlobalProperty *p;
851
852 if (!mc->compat_props) {
853 return;
854 }
855
856 for (i = 0; i < mc->compat_props->len; i++) {
857 p = g_array_index(mc->compat_props, GlobalProperty *, i);
858
859 p->errp = &error_abort;
860 qdev_prop_register_global(p);
861 }
862}
863
864static const TypeInfo machine_info = {
865 .name = TYPE_MACHINE,
866 .parent = TYPE_OBJECT,
867 .abstract = true,
868 .class_size = sizeof(MachineClass),
869 .class_init = machine_class_init,
870 .class_base_init = machine_class_base_init,
871 .class_finalize = machine_class_finalize,
872 .instance_size = sizeof(MachineState),
873 .instance_init = machine_initfn,
874 .instance_finalize = machine_finalize,
875};
876
877static void machine_register_types(void)
878{
879 type_register_static(&machine_info);
880}
881
882type_init(machine_register_types)
883