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 "qemu/units.h" 15 #include "hw/boards.h" 16 #include "qapi/error.h" 17 #include "qapi/qapi-visit-common.h" 18 #include "qapi/visitor.h" 19 #include "hw/sysbus.h" 20 #include "sysemu/sysemu.h" 21 #include "sysemu/numa.h" 22 #include "qemu/error-report.h" 23 #include "sysemu/qtest.h" 24 25 GlobalProperty hw_compat_3_1[] = { 26 { 27 .driver = "pcie-root-port", 28 .property = "x-speed", 29 .value = "2_5", 30 },{ 31 .driver = "pcie-root-port", 32 .property = "x-width", 33 .value = "1", 34 }, 35 }; 36 const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1); 37 38 GlobalProperty hw_compat_3_0[] = {}; 39 const size_t hw_compat_3_0_len = G_N_ELEMENTS(hw_compat_3_0); 40 41 GlobalProperty hw_compat_2_12[] = { 42 { 43 .driver = "migration", 44 .property = "decompress-error-check", 45 .value = "off", 46 },{ 47 .driver = "hda-audio", 48 .property = "use-timer", 49 .value = "false", 50 },{ 51 .driver = "cirrus-vga", 52 .property = "global-vmstate", 53 .value = "true", 54 },{ 55 .driver = "VGA", 56 .property = "global-vmstate", 57 .value = "true", 58 },{ 59 .driver = "vmware-svga", 60 .property = "global-vmstate", 61 .value = "true", 62 },{ 63 .driver = "qxl-vga", 64 .property = "global-vmstate", 65 .value = "true", 66 }, 67 }; 68 const size_t hw_compat_2_12_len = G_N_ELEMENTS(hw_compat_2_12); 69 70 GlobalProperty hw_compat_2_11[] = { 71 { 72 .driver = "hpet", 73 .property = "hpet-offset-saved", 74 .value = "false", 75 },{ 76 .driver = "virtio-blk-pci", 77 .property = "vectors", 78 .value = "2", 79 },{ 80 .driver = "vhost-user-blk-pci", 81 .property = "vectors", 82 .value = "2", 83 },{ 84 .driver = "e1000", 85 .property = "migrate_tso_props", 86 .value = "off", 87 }, 88 }; 89 const size_t hw_compat_2_11_len = G_N_ELEMENTS(hw_compat_2_11); 90 91 GlobalProperty hw_compat_2_10[] = { 92 { 93 .driver = "virtio-mouse-device", 94 .property = "wheel-axis", 95 .value = "false", 96 },{ 97 .driver = "virtio-tablet-device", 98 .property = "wheel-axis", 99 .value = "false", 100 }, 101 }; 102 const size_t hw_compat_2_10_len = G_N_ELEMENTS(hw_compat_2_10); 103 104 GlobalProperty hw_compat_2_9[] = { 105 { 106 .driver = "pci-bridge", 107 .property = "shpc", 108 .value = "off", 109 },{ 110 .driver = "intel-iommu", 111 .property = "pt", 112 .value = "off", 113 },{ 114 .driver = "virtio-net-device", 115 .property = "x-mtu-bypass-backend", 116 .value = "off", 117 },{ 118 .driver = "pcie-root-port", 119 .property = "x-migrate-msix", 120 .value = "false", 121 }, 122 }; 123 const size_t hw_compat_2_9_len = G_N_ELEMENTS(hw_compat_2_9); 124 125 static char *machine_get_accel(Object *obj, Error **errp) 126 { 127 MachineState *ms = MACHINE(obj); 128 129 return g_strdup(ms->accel); 130 } 131 132 static void machine_set_accel(Object *obj, const char *value, Error **errp) 133 { 134 MachineState *ms = MACHINE(obj); 135 136 g_free(ms->accel); 137 ms->accel = g_strdup(value); 138 } 139 140 static void machine_set_kernel_irqchip(Object *obj, Visitor *v, 141 const char *name, void *opaque, 142 Error **errp) 143 { 144 Error *err = NULL; 145 MachineState *ms = MACHINE(obj); 146 OnOffSplit mode; 147 148 visit_type_OnOffSplit(v, name, &mode, &err); 149 if (err) { 150 error_propagate(errp, err); 151 return; 152 } else { 153 switch (mode) { 154 case ON_OFF_SPLIT_ON: 155 ms->kernel_irqchip_allowed = true; 156 ms->kernel_irqchip_required = true; 157 ms->kernel_irqchip_split = false; 158 break; 159 case ON_OFF_SPLIT_OFF: 160 ms->kernel_irqchip_allowed = false; 161 ms->kernel_irqchip_required = false; 162 ms->kernel_irqchip_split = false; 163 break; 164 case ON_OFF_SPLIT_SPLIT: 165 ms->kernel_irqchip_allowed = true; 166 ms->kernel_irqchip_required = true; 167 ms->kernel_irqchip_split = true; 168 break; 169 default: 170 /* The value was checked in visit_type_OnOffSplit() above. If 171 * we get here, then something is wrong in QEMU. 172 */ 173 abort(); 174 } 175 } 176 } 177 178 static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v, 179 const char *name, void *opaque, 180 Error **errp) 181 { 182 MachineState *ms = MACHINE(obj); 183 int64_t value = ms->kvm_shadow_mem; 184 185 visit_type_int(v, name, &value, errp); 186 } 187 188 static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v, 189 const char *name, void *opaque, 190 Error **errp) 191 { 192 MachineState *ms = MACHINE(obj); 193 Error *error = NULL; 194 int64_t value; 195 196 visit_type_int(v, name, &value, &error); 197 if (error) { 198 error_propagate(errp, error); 199 return; 200 } 201 202 ms->kvm_shadow_mem = value; 203 } 204 205 static char *machine_get_kernel(Object *obj, Error **errp) 206 { 207 MachineState *ms = MACHINE(obj); 208 209 return g_strdup(ms->kernel_filename); 210 } 211 212 static void machine_set_kernel(Object *obj, const char *value, Error **errp) 213 { 214 MachineState *ms = MACHINE(obj); 215 216 g_free(ms->kernel_filename); 217 ms->kernel_filename = g_strdup(value); 218 } 219 220 static char *machine_get_initrd(Object *obj, Error **errp) 221 { 222 MachineState *ms = MACHINE(obj); 223 224 return g_strdup(ms->initrd_filename); 225 } 226 227 static void machine_set_initrd(Object *obj, const char *value, Error **errp) 228 { 229 MachineState *ms = MACHINE(obj); 230 231 g_free(ms->initrd_filename); 232 ms->initrd_filename = g_strdup(value); 233 } 234 235 static char *machine_get_append(Object *obj, Error **errp) 236 { 237 MachineState *ms = MACHINE(obj); 238 239 return g_strdup(ms->kernel_cmdline); 240 } 241 242 static void machine_set_append(Object *obj, const char *value, Error **errp) 243 { 244 MachineState *ms = MACHINE(obj); 245 246 g_free(ms->kernel_cmdline); 247 ms->kernel_cmdline = g_strdup(value); 248 } 249 250 static char *machine_get_dtb(Object *obj, Error **errp) 251 { 252 MachineState *ms = MACHINE(obj); 253 254 return g_strdup(ms->dtb); 255 } 256 257 static void machine_set_dtb(Object *obj, const char *value, Error **errp) 258 { 259 MachineState *ms = MACHINE(obj); 260 261 g_free(ms->dtb); 262 ms->dtb = g_strdup(value); 263 } 264 265 static char *machine_get_dumpdtb(Object *obj, Error **errp) 266 { 267 MachineState *ms = MACHINE(obj); 268 269 return g_strdup(ms->dumpdtb); 270 } 271 272 static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp) 273 { 274 MachineState *ms = MACHINE(obj); 275 276 g_free(ms->dumpdtb); 277 ms->dumpdtb = g_strdup(value); 278 } 279 280 static void machine_get_phandle_start(Object *obj, Visitor *v, 281 const char *name, void *opaque, 282 Error **errp) 283 { 284 MachineState *ms = MACHINE(obj); 285 int64_t value = ms->phandle_start; 286 287 visit_type_int(v, name, &value, errp); 288 } 289 290 static void machine_set_phandle_start(Object *obj, Visitor *v, 291 const char *name, void *opaque, 292 Error **errp) 293 { 294 MachineState *ms = MACHINE(obj); 295 Error *error = NULL; 296 int64_t value; 297 298 visit_type_int(v, name, &value, &error); 299 if (error) { 300 error_propagate(errp, error); 301 return; 302 } 303 304 ms->phandle_start = value; 305 } 306 307 static char *machine_get_dt_compatible(Object *obj, Error **errp) 308 { 309 MachineState *ms = MACHINE(obj); 310 311 return g_strdup(ms->dt_compatible); 312 } 313 314 static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp) 315 { 316 MachineState *ms = MACHINE(obj); 317 318 g_free(ms->dt_compatible); 319 ms->dt_compatible = g_strdup(value); 320 } 321 322 static bool machine_get_dump_guest_core(Object *obj, Error **errp) 323 { 324 MachineState *ms = MACHINE(obj); 325 326 return ms->dump_guest_core; 327 } 328 329 static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp) 330 { 331 MachineState *ms = MACHINE(obj); 332 333 ms->dump_guest_core = value; 334 } 335 336 static bool machine_get_mem_merge(Object *obj, Error **errp) 337 { 338 MachineState *ms = MACHINE(obj); 339 340 return ms->mem_merge; 341 } 342 343 static void machine_set_mem_merge(Object *obj, bool value, Error **errp) 344 { 345 MachineState *ms = MACHINE(obj); 346 347 ms->mem_merge = value; 348 } 349 350 static bool machine_get_usb(Object *obj, Error **errp) 351 { 352 MachineState *ms = MACHINE(obj); 353 354 return ms->usb; 355 } 356 357 static void machine_set_usb(Object *obj, bool value, Error **errp) 358 { 359 MachineState *ms = MACHINE(obj); 360 361 ms->usb = value; 362 ms->usb_disabled = !value; 363 } 364 365 static bool machine_get_graphics(Object *obj, Error **errp) 366 { 367 MachineState *ms = MACHINE(obj); 368 369 return ms->enable_graphics; 370 } 371 372 static void machine_set_graphics(Object *obj, bool value, Error **errp) 373 { 374 MachineState *ms = MACHINE(obj); 375 376 ms->enable_graphics = value; 377 } 378 379 static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp) 380 { 381 MachineState *ms = MACHINE(obj); 382 383 return ms->igd_gfx_passthru; 384 } 385 386 static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp) 387 { 388 MachineState *ms = MACHINE(obj); 389 390 ms->igd_gfx_passthru = value; 391 } 392 393 static char *machine_get_firmware(Object *obj, Error **errp) 394 { 395 MachineState *ms = MACHINE(obj); 396 397 return g_strdup(ms->firmware); 398 } 399 400 static void machine_set_firmware(Object *obj, const char *value, Error **errp) 401 { 402 MachineState *ms = MACHINE(obj); 403 404 g_free(ms->firmware); 405 ms->firmware = g_strdup(value); 406 } 407 408 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp) 409 { 410 MachineState *ms = MACHINE(obj); 411 412 ms->suppress_vmdesc = value; 413 } 414 415 static bool machine_get_suppress_vmdesc(Object *obj, Error **errp) 416 { 417 MachineState *ms = MACHINE(obj); 418 419 return ms->suppress_vmdesc; 420 } 421 422 static void machine_set_enforce_config_section(Object *obj, bool value, 423 Error **errp) 424 { 425 MachineState *ms = MACHINE(obj); 426 427 warn_report("enforce-config-section is deprecated, please use " 428 "-global migration.send-configuration=on|off instead"); 429 430 ms->enforce_config_section = value; 431 } 432 433 static bool machine_get_enforce_config_section(Object *obj, Error **errp) 434 { 435 MachineState *ms = MACHINE(obj); 436 437 return ms->enforce_config_section; 438 } 439 440 static char *machine_get_memory_encryption(Object *obj, Error **errp) 441 { 442 MachineState *ms = MACHINE(obj); 443 444 return g_strdup(ms->memory_encryption); 445 } 446 447 static void machine_set_memory_encryption(Object *obj, const char *value, 448 Error **errp) 449 { 450 MachineState *ms = MACHINE(obj); 451 452 g_free(ms->memory_encryption); 453 ms->memory_encryption = g_strdup(value); 454 } 455 456 void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type) 457 { 458 strList *item = g_new0(strList, 1); 459 460 item->value = g_strdup(type); 461 item->next = mc->allowed_dynamic_sysbus_devices; 462 mc->allowed_dynamic_sysbus_devices = item; 463 } 464 465 static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque) 466 { 467 MachineState *machine = opaque; 468 MachineClass *mc = MACHINE_GET_CLASS(machine); 469 bool allowed = false; 470 strList *wl; 471 472 for (wl = mc->allowed_dynamic_sysbus_devices; 473 !allowed && wl; 474 wl = wl->next) { 475 allowed |= !!object_dynamic_cast(OBJECT(sbdev), wl->value); 476 } 477 478 if (!allowed) { 479 error_report("Option '-device %s' cannot be handled by this machine", 480 object_class_get_name(object_get_class(OBJECT(sbdev)))); 481 exit(1); 482 } 483 } 484 485 static void machine_init_notify(Notifier *notifier, void *data) 486 { 487 MachineState *machine = MACHINE(qdev_get_machine()); 488 489 /* 490 * Loop through all dynamically created sysbus devices and check if they are 491 * all allowed. If a device is not allowed, error out. 492 */ 493 foreach_dynamic_sysbus_device(validate_sysbus_device, machine); 494 } 495 496 HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine) 497 { 498 int i; 499 HotpluggableCPUList *head = NULL; 500 MachineClass *mc = MACHINE_GET_CLASS(machine); 501 502 /* force board to initialize possible_cpus if it hasn't been done yet */ 503 mc->possible_cpu_arch_ids(machine); 504 505 for (i = 0; i < machine->possible_cpus->len; i++) { 506 Object *cpu; 507 HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1); 508 HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1); 509 510 cpu_item->type = g_strdup(machine->possible_cpus->cpus[i].type); 511 cpu_item->vcpus_count = machine->possible_cpus->cpus[i].vcpus_count; 512 cpu_item->props = g_memdup(&machine->possible_cpus->cpus[i].props, 513 sizeof(*cpu_item->props)); 514 515 cpu = machine->possible_cpus->cpus[i].cpu; 516 if (cpu) { 517 cpu_item->has_qom_path = true; 518 cpu_item->qom_path = object_get_canonical_path(cpu); 519 } 520 list_item->value = cpu_item; 521 list_item->next = head; 522 head = list_item; 523 } 524 return head; 525 } 526 527 /** 528 * machine_set_cpu_numa_node: 529 * @machine: machine object to modify 530 * @props: specifies which cpu objects to assign to 531 * numa node specified by @props.node_id 532 * @errp: if an error occurs, a pointer to an area to store the error 533 * 534 * Associate NUMA node specified by @props.node_id with cpu slots that 535 * match socket/core/thread-ids specified by @props. It's recommended to use 536 * query-hotpluggable-cpus.props values to specify affected cpu slots, 537 * which would lead to exact 1:1 mapping of cpu slots to NUMA node. 538 * 539 * However for CLI convenience it's possible to pass in subset of properties, 540 * which would affect all cpu slots that match it. 541 * Ex for pc machine: 542 * -smp 4,cores=2,sockets=2 -numa node,nodeid=0 -numa node,nodeid=1 \ 543 * -numa cpu,node-id=0,socket_id=0 \ 544 * -numa cpu,node-id=1,socket_id=1 545 * will assign all child cores of socket 0 to node 0 and 546 * of socket 1 to node 1. 547 * 548 * On attempt of reassigning (already assigned) cpu slot to another NUMA node, 549 * return error. 550 * Empty subset is disallowed and function will return with error in this case. 551 */ 552 void machine_set_cpu_numa_node(MachineState *machine, 553 const CpuInstanceProperties *props, Error **errp) 554 { 555 MachineClass *mc = MACHINE_GET_CLASS(machine); 556 bool match = false; 557 int i; 558 559 if (!mc->possible_cpu_arch_ids) { 560 error_setg(errp, "mapping of CPUs to NUMA node is not supported"); 561 return; 562 } 563 564 /* disabling node mapping is not supported, forbid it */ 565 assert(props->has_node_id); 566 567 /* force board to initialize possible_cpus if it hasn't been done yet */ 568 mc->possible_cpu_arch_ids(machine); 569 570 for (i = 0; i < machine->possible_cpus->len; i++) { 571 CPUArchId *slot = &machine->possible_cpus->cpus[i]; 572 573 /* reject unsupported by board properties */ 574 if (props->has_thread_id && !slot->props.has_thread_id) { 575 error_setg(errp, "thread-id is not supported"); 576 return; 577 } 578 579 if (props->has_core_id && !slot->props.has_core_id) { 580 error_setg(errp, "core-id is not supported"); 581 return; 582 } 583 584 if (props->has_socket_id && !slot->props.has_socket_id) { 585 error_setg(errp, "socket-id is not supported"); 586 return; 587 } 588 589 /* skip slots with explicit mismatch */ 590 if (props->has_thread_id && props->thread_id != slot->props.thread_id) { 591 continue; 592 } 593 594 if (props->has_core_id && props->core_id != slot->props.core_id) { 595 continue; 596 } 597 598 if (props->has_socket_id && props->socket_id != slot->props.socket_id) { 599 continue; 600 } 601 602 /* reject assignment if slot is already assigned, for compatibility 603 * of legacy cpu_index mapping with SPAPR core based mapping do not 604 * error out if cpu thread and matched core have the same node-id */ 605 if (slot->props.has_node_id && 606 slot->props.node_id != props->node_id) { 607 error_setg(errp, "CPU is already assigned to node-id: %" PRId64, 608 slot->props.node_id); 609 return; 610 } 611 612 /* assign slot to node as it's matched '-numa cpu' key */ 613 match = true; 614 slot->props.node_id = props->node_id; 615 slot->props.has_node_id = props->has_node_id; 616 } 617 618 if (!match) { 619 error_setg(errp, "no match found"); 620 } 621 } 622 623 static void machine_class_init(ObjectClass *oc, void *data) 624 { 625 MachineClass *mc = MACHINE_CLASS(oc); 626 627 /* Default 128 MB as guest ram size */ 628 mc->default_ram_size = 128 * MiB; 629 mc->rom_file_has_mr = true; 630 631 /* numa node memory size aligned on 8MB by default. 632 * On Linux, each node's border has to be 8MB aligned 633 */ 634 mc->numa_mem_align_shift = 23; 635 mc->numa_auto_assign_ram = numa_default_auto_assign_ram; 636 637 object_class_property_add_str(oc, "accel", 638 machine_get_accel, machine_set_accel, &error_abort); 639 object_class_property_set_description(oc, "accel", 640 "Accelerator list", &error_abort); 641 642 object_class_property_add(oc, "kernel-irqchip", "on|off|split", 643 NULL, machine_set_kernel_irqchip, 644 NULL, NULL, &error_abort); 645 object_class_property_set_description(oc, "kernel-irqchip", 646 "Configure KVM in-kernel irqchip", &error_abort); 647 648 object_class_property_add(oc, "kvm-shadow-mem", "int", 649 machine_get_kvm_shadow_mem, machine_set_kvm_shadow_mem, 650 NULL, NULL, &error_abort); 651 object_class_property_set_description(oc, "kvm-shadow-mem", 652 "KVM shadow MMU size", &error_abort); 653 654 object_class_property_add_str(oc, "kernel", 655 machine_get_kernel, machine_set_kernel, &error_abort); 656 object_class_property_set_description(oc, "kernel", 657 "Linux kernel image file", &error_abort); 658 659 object_class_property_add_str(oc, "initrd", 660 machine_get_initrd, machine_set_initrd, &error_abort); 661 object_class_property_set_description(oc, "initrd", 662 "Linux initial ramdisk file", &error_abort); 663 664 object_class_property_add_str(oc, "append", 665 machine_get_append, machine_set_append, &error_abort); 666 object_class_property_set_description(oc, "append", 667 "Linux kernel command line", &error_abort); 668 669 object_class_property_add_str(oc, "dtb", 670 machine_get_dtb, machine_set_dtb, &error_abort); 671 object_class_property_set_description(oc, "dtb", 672 "Linux kernel device tree file", &error_abort); 673 674 object_class_property_add_str(oc, "dumpdtb", 675 machine_get_dumpdtb, machine_set_dumpdtb, &error_abort); 676 object_class_property_set_description(oc, "dumpdtb", 677 "Dump current dtb to a file and quit", &error_abort); 678 679 object_class_property_add(oc, "phandle-start", "int", 680 machine_get_phandle_start, machine_set_phandle_start, 681 NULL, NULL, &error_abort); 682 object_class_property_set_description(oc, "phandle-start", 683 "The first phandle ID we may generate dynamically", &error_abort); 684 685 object_class_property_add_str(oc, "dt-compatible", 686 machine_get_dt_compatible, machine_set_dt_compatible, &error_abort); 687 object_class_property_set_description(oc, "dt-compatible", 688 "Overrides the \"compatible\" property of the dt root node", 689 &error_abort); 690 691 object_class_property_add_bool(oc, "dump-guest-core", 692 machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort); 693 object_class_property_set_description(oc, "dump-guest-core", 694 "Include guest memory in a core dump", &error_abort); 695 696 object_class_property_add_bool(oc, "mem-merge", 697 machine_get_mem_merge, machine_set_mem_merge, &error_abort); 698 object_class_property_set_description(oc, "mem-merge", 699 "Enable/disable memory merge support", &error_abort); 700 701 object_class_property_add_bool(oc, "usb", 702 machine_get_usb, machine_set_usb, &error_abort); 703 object_class_property_set_description(oc, "usb", 704 "Set on/off to enable/disable usb", &error_abort); 705 706 object_class_property_add_bool(oc, "graphics", 707 machine_get_graphics, machine_set_graphics, &error_abort); 708 object_class_property_set_description(oc, "graphics", 709 "Set on/off to enable/disable graphics emulation", &error_abort); 710 711 object_class_property_add_bool(oc, "igd-passthru", 712 machine_get_igd_gfx_passthru, machine_set_igd_gfx_passthru, 713 &error_abort); 714 object_class_property_set_description(oc, "igd-passthru", 715 "Set on/off to enable/disable igd passthrou", &error_abort); 716 717 object_class_property_add_str(oc, "firmware", 718 machine_get_firmware, machine_set_firmware, 719 &error_abort); 720 object_class_property_set_description(oc, "firmware", 721 "Firmware image", &error_abort); 722 723 object_class_property_add_bool(oc, "suppress-vmdesc", 724 machine_get_suppress_vmdesc, machine_set_suppress_vmdesc, 725 &error_abort); 726 object_class_property_set_description(oc, "suppress-vmdesc", 727 "Set on to disable self-describing migration", &error_abort); 728 729 object_class_property_add_bool(oc, "enforce-config-section", 730 machine_get_enforce_config_section, machine_set_enforce_config_section, 731 &error_abort); 732 object_class_property_set_description(oc, "enforce-config-section", 733 "Set on to enforce configuration section migration", &error_abort); 734 735 object_class_property_add_str(oc, "memory-encryption", 736 machine_get_memory_encryption, machine_set_memory_encryption, 737 &error_abort); 738 object_class_property_set_description(oc, "memory-encryption", 739 "Set memory encryption object to use", &error_abort); 740 } 741 742 static void machine_class_base_init(ObjectClass *oc, void *data) 743 { 744 if (!object_class_is_abstract(oc)) { 745 MachineClass *mc = MACHINE_CLASS(oc); 746 const char *cname = object_class_get_name(oc); 747 assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX)); 748 mc->name = g_strndup(cname, 749 strlen(cname) - strlen(TYPE_MACHINE_SUFFIX)); 750 mc->compat_props = g_ptr_array_new(); 751 } 752 } 753 754 static void machine_initfn(Object *obj) 755 { 756 MachineState *ms = MACHINE(obj); 757 MachineClass *mc = MACHINE_GET_CLASS(obj); 758 759 ms->kernel_irqchip_allowed = true; 760 ms->kernel_irqchip_split = mc->default_kernel_irqchip_split; 761 ms->kvm_shadow_mem = -1; 762 ms->dump_guest_core = true; 763 ms->mem_merge = true; 764 ms->enable_graphics = true; 765 766 /* Register notifier when init is done for sysbus sanity checks */ 767 ms->sysbus_notifier.notify = machine_init_notify; 768 qemu_add_machine_init_done_notifier(&ms->sysbus_notifier); 769 } 770 771 static void machine_finalize(Object *obj) 772 { 773 MachineState *ms = MACHINE(obj); 774 775 g_free(ms->accel); 776 g_free(ms->kernel_filename); 777 g_free(ms->initrd_filename); 778 g_free(ms->kernel_cmdline); 779 g_free(ms->dtb); 780 g_free(ms->dumpdtb); 781 g_free(ms->dt_compatible); 782 g_free(ms->firmware); 783 g_free(ms->device_memory); 784 } 785 786 bool machine_usb(MachineState *machine) 787 { 788 return machine->usb; 789 } 790 791 bool machine_kernel_irqchip_allowed(MachineState *machine) 792 { 793 return machine->kernel_irqchip_allowed; 794 } 795 796 bool machine_kernel_irqchip_required(MachineState *machine) 797 { 798 return machine->kernel_irqchip_required; 799 } 800 801 bool machine_kernel_irqchip_split(MachineState *machine) 802 { 803 return machine->kernel_irqchip_split; 804 } 805 806 int machine_kvm_shadow_mem(MachineState *machine) 807 { 808 return machine->kvm_shadow_mem; 809 } 810 811 int machine_phandle_start(MachineState *machine) 812 { 813 return machine->phandle_start; 814 } 815 816 bool machine_dump_guest_core(MachineState *machine) 817 { 818 return machine->dump_guest_core; 819 } 820 821 bool machine_mem_merge(MachineState *machine) 822 { 823 return machine->mem_merge; 824 } 825 826 static char *cpu_slot_to_string(const CPUArchId *cpu) 827 { 828 GString *s = g_string_new(NULL); 829 if (cpu->props.has_socket_id) { 830 g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id); 831 } 832 if (cpu->props.has_core_id) { 833 if (s->len) { 834 g_string_append_printf(s, ", "); 835 } 836 g_string_append_printf(s, "core-id: %"PRId64, cpu->props.core_id); 837 } 838 if (cpu->props.has_thread_id) { 839 if (s->len) { 840 g_string_append_printf(s, ", "); 841 } 842 g_string_append_printf(s, "thread-id: %"PRId64, cpu->props.thread_id); 843 } 844 return g_string_free(s, false); 845 } 846 847 static void machine_numa_finish_cpu_init(MachineState *machine) 848 { 849 int i; 850 bool default_mapping; 851 GString *s = g_string_new(NULL); 852 MachineClass *mc = MACHINE_GET_CLASS(machine); 853 const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(machine); 854 855 assert(nb_numa_nodes); 856 for (i = 0; i < possible_cpus->len; i++) { 857 if (possible_cpus->cpus[i].props.has_node_id) { 858 break; 859 } 860 } 861 default_mapping = (i == possible_cpus->len); 862 863 for (i = 0; i < possible_cpus->len; i++) { 864 const CPUArchId *cpu_slot = &possible_cpus->cpus[i]; 865 866 if (!cpu_slot->props.has_node_id) { 867 /* fetch default mapping from board and enable it */ 868 CpuInstanceProperties props = cpu_slot->props; 869 870 props.node_id = mc->get_default_cpu_node_id(machine, i); 871 if (!default_mapping) { 872 /* record slots with not set mapping, 873 * TODO: make it hard error in future */ 874 char *cpu_str = cpu_slot_to_string(cpu_slot); 875 g_string_append_printf(s, "%sCPU %d [%s]", 876 s->len ? ", " : "", i, cpu_str); 877 g_free(cpu_str); 878 879 /* non mapped cpus used to fallback to node 0 */ 880 props.node_id = 0; 881 } 882 883 props.has_node_id = true; 884 machine_set_cpu_numa_node(machine, &props, &error_fatal); 885 } 886 } 887 if (s->len && !qtest_enabled()) { 888 warn_report("CPU(s) not present in any NUMA nodes: %s", 889 s->str); 890 warn_report("All CPU(s) up to maxcpus should be described " 891 "in NUMA config, ability to start up with partial NUMA " 892 "mappings is obsoleted and will be removed in future"); 893 } 894 g_string_free(s, true); 895 } 896 897 void machine_run_board_init(MachineState *machine) 898 { 899 MachineClass *machine_class = MACHINE_GET_CLASS(machine); 900 901 numa_complete_configuration(machine); 902 if (nb_numa_nodes) { 903 machine_numa_finish_cpu_init(machine); 904 } 905 906 /* If the machine supports the valid_cpu_types check and the user 907 * specified a CPU with -cpu check here that the user CPU is supported. 908 */ 909 if (machine_class->valid_cpu_types && machine->cpu_type) { 910 ObjectClass *class = object_class_by_name(machine->cpu_type); 911 int i; 912 913 for (i = 0; machine_class->valid_cpu_types[i]; i++) { 914 if (object_class_dynamic_cast(class, 915 machine_class->valid_cpu_types[i])) { 916 /* The user specificed CPU is in the valid field, we are 917 * good to go. 918 */ 919 break; 920 } 921 } 922 923 if (!machine_class->valid_cpu_types[i]) { 924 /* The user specified CPU is not valid */ 925 error_report("Invalid CPU type: %s", machine->cpu_type); 926 error_printf("The valid types are: %s", 927 machine_class->valid_cpu_types[0]); 928 for (i = 1; machine_class->valid_cpu_types[i]; i++) { 929 error_printf(", %s", machine_class->valid_cpu_types[i]); 930 } 931 error_printf("\n"); 932 933 exit(1); 934 } 935 } 936 937 machine_class->init(machine); 938 } 939 940 static const TypeInfo machine_info = { 941 .name = TYPE_MACHINE, 942 .parent = TYPE_OBJECT, 943 .abstract = true, 944 .class_size = sizeof(MachineClass), 945 .class_init = machine_class_init, 946 .class_base_init = machine_class_base_init, 947 .instance_size = sizeof(MachineState), 948 .instance_init = machine_initfn, 949 .instance_finalize = machine_finalize, 950 }; 951 952 static void machine_register_types(void) 953 { 954 type_register_static(&machine_info); 955 } 956 957 type_init(machine_register_types) 958