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