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