1 /* 2 * QEMU Machine 3 * 4 * Copyright (C) 2014 Red Hat Inc 5 * 6 * Authors: 7 * Marcel Apfelbaum <marcel.a@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "hw/boards.h" 15 #include "qapi/error.h" 16 #include "qapi-visit.h" 17 #include "qapi/visitor.h" 18 #include "hw/sysbus.h" 19 #include "sysemu/sysemu.h" 20 #include "sysemu/numa.h" 21 #include "qemu/error-report.h" 22 #include "qemu/cutils.h" 23 24 static char *machine_get_accel(Object *obj, Error **errp) 25 { 26 MachineState *ms = MACHINE(obj); 27 28 return g_strdup(ms->accel); 29 } 30 31 static void machine_set_accel(Object *obj, const char *value, Error **errp) 32 { 33 MachineState *ms = MACHINE(obj); 34 35 g_free(ms->accel); 36 ms->accel = g_strdup(value); 37 } 38 39 static void machine_set_kernel_irqchip(Object *obj, Visitor *v, 40 const char *name, void *opaque, 41 Error **errp) 42 { 43 Error *err = NULL; 44 MachineState *ms = MACHINE(obj); 45 OnOffSplit mode; 46 47 visit_type_OnOffSplit(v, name, &mode, &err); 48 if (err) { 49 error_propagate(errp, err); 50 return; 51 } else { 52 switch (mode) { 53 case ON_OFF_SPLIT_ON: 54 ms->kernel_irqchip_allowed = true; 55 ms->kernel_irqchip_required = true; 56 ms->kernel_irqchip_split = false; 57 break; 58 case ON_OFF_SPLIT_OFF: 59 ms->kernel_irqchip_allowed = false; 60 ms->kernel_irqchip_required = false; 61 ms->kernel_irqchip_split = false; 62 break; 63 case ON_OFF_SPLIT_SPLIT: 64 ms->kernel_irqchip_allowed = true; 65 ms->kernel_irqchip_required = true; 66 ms->kernel_irqchip_split = true; 67 break; 68 default: 69 /* The value was checked in visit_type_OnOffSplit() above. If 70 * we get here, then something is wrong in QEMU. 71 */ 72 abort(); 73 } 74 } 75 } 76 77 static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v, 78 const char *name, void *opaque, 79 Error **errp) 80 { 81 MachineState *ms = MACHINE(obj); 82 int64_t value = ms->kvm_shadow_mem; 83 84 visit_type_int(v, name, &value, errp); 85 } 86 87 static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v, 88 const char *name, void *opaque, 89 Error **errp) 90 { 91 MachineState *ms = MACHINE(obj); 92 Error *error = NULL; 93 int64_t value; 94 95 visit_type_int(v, name, &value, &error); 96 if (error) { 97 error_propagate(errp, error); 98 return; 99 } 100 101 ms->kvm_shadow_mem = value; 102 } 103 104 static char *machine_get_kernel(Object *obj, Error **errp) 105 { 106 MachineState *ms = MACHINE(obj); 107 108 return g_strdup(ms->kernel_filename); 109 } 110 111 static void machine_set_kernel(Object *obj, const char *value, Error **errp) 112 { 113 MachineState *ms = MACHINE(obj); 114 115 g_free(ms->kernel_filename); 116 ms->kernel_filename = g_strdup(value); 117 } 118 119 static char *machine_get_initrd(Object *obj, Error **errp) 120 { 121 MachineState *ms = MACHINE(obj); 122 123 return g_strdup(ms->initrd_filename); 124 } 125 126 static void machine_set_initrd(Object *obj, const char *value, Error **errp) 127 { 128 MachineState *ms = MACHINE(obj); 129 130 g_free(ms->initrd_filename); 131 ms->initrd_filename = g_strdup(value); 132 } 133 134 static char *machine_get_append(Object *obj, Error **errp) 135 { 136 MachineState *ms = MACHINE(obj); 137 138 return g_strdup(ms->kernel_cmdline); 139 } 140 141 static void machine_set_append(Object *obj, const char *value, Error **errp) 142 { 143 MachineState *ms = MACHINE(obj); 144 145 g_free(ms->kernel_cmdline); 146 ms->kernel_cmdline = g_strdup(value); 147 } 148 149 static char *machine_get_dtb(Object *obj, Error **errp) 150 { 151 MachineState *ms = MACHINE(obj); 152 153 return g_strdup(ms->dtb); 154 } 155 156 static void machine_set_dtb(Object *obj, const char *value, Error **errp) 157 { 158 MachineState *ms = MACHINE(obj); 159 160 g_free(ms->dtb); 161 ms->dtb = g_strdup(value); 162 } 163 164 static char *machine_get_dumpdtb(Object *obj, Error **errp) 165 { 166 MachineState *ms = MACHINE(obj); 167 168 return g_strdup(ms->dumpdtb); 169 } 170 171 static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp) 172 { 173 MachineState *ms = MACHINE(obj); 174 175 g_free(ms->dumpdtb); 176 ms->dumpdtb = g_strdup(value); 177 } 178 179 static void machine_get_phandle_start(Object *obj, Visitor *v, 180 const char *name, void *opaque, 181 Error **errp) 182 { 183 MachineState *ms = MACHINE(obj); 184 int64_t value = ms->phandle_start; 185 186 visit_type_int(v, name, &value, errp); 187 } 188 189 static void machine_set_phandle_start(Object *obj, Visitor *v, 190 const char *name, void *opaque, 191 Error **errp) 192 { 193 MachineState *ms = MACHINE(obj); 194 Error *error = NULL; 195 int64_t value; 196 197 visit_type_int(v, name, &value, &error); 198 if (error) { 199 error_propagate(errp, error); 200 return; 201 } 202 203 ms->phandle_start = value; 204 } 205 206 static char *machine_get_dt_compatible(Object *obj, Error **errp) 207 { 208 MachineState *ms = MACHINE(obj); 209 210 return g_strdup(ms->dt_compatible); 211 } 212 213 static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp) 214 { 215 MachineState *ms = MACHINE(obj); 216 217 g_free(ms->dt_compatible); 218 ms->dt_compatible = g_strdup(value); 219 } 220 221 static bool machine_get_dump_guest_core(Object *obj, Error **errp) 222 { 223 MachineState *ms = MACHINE(obj); 224 225 return ms->dump_guest_core; 226 } 227 228 static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp) 229 { 230 MachineState *ms = MACHINE(obj); 231 232 ms->dump_guest_core = value; 233 } 234 235 static bool machine_get_mem_merge(Object *obj, Error **errp) 236 { 237 MachineState *ms = MACHINE(obj); 238 239 return ms->mem_merge; 240 } 241 242 static void machine_set_mem_merge(Object *obj, bool value, Error **errp) 243 { 244 MachineState *ms = MACHINE(obj); 245 246 ms->mem_merge = value; 247 } 248 249 static bool machine_get_usb(Object *obj, Error **errp) 250 { 251 MachineState *ms = MACHINE(obj); 252 253 return ms->usb; 254 } 255 256 static void machine_set_usb(Object *obj, bool value, Error **errp) 257 { 258 MachineState *ms = MACHINE(obj); 259 260 ms->usb = value; 261 ms->usb_disabled = !value; 262 } 263 264 static bool machine_get_graphics(Object *obj, Error **errp) 265 { 266 MachineState *ms = MACHINE(obj); 267 268 return ms->enable_graphics; 269 } 270 271 static void machine_set_graphics(Object *obj, bool value, Error **errp) 272 { 273 MachineState *ms = MACHINE(obj); 274 275 ms->enable_graphics = value; 276 } 277 278 static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp) 279 { 280 MachineState *ms = MACHINE(obj); 281 282 return ms->igd_gfx_passthru; 283 } 284 285 static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp) 286 { 287 MachineState *ms = MACHINE(obj); 288 289 ms->igd_gfx_passthru = value; 290 } 291 292 static char *machine_get_firmware(Object *obj, Error **errp) 293 { 294 MachineState *ms = MACHINE(obj); 295 296 return g_strdup(ms->firmware); 297 } 298 299 static void machine_set_firmware(Object *obj, const char *value, Error **errp) 300 { 301 MachineState *ms = MACHINE(obj); 302 303 g_free(ms->firmware); 304 ms->firmware = g_strdup(value); 305 } 306 307 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp) 308 { 309 MachineState *ms = MACHINE(obj); 310 311 ms->suppress_vmdesc = value; 312 } 313 314 static bool machine_get_suppress_vmdesc(Object *obj, Error **errp) 315 { 316 MachineState *ms = MACHINE(obj); 317 318 return ms->suppress_vmdesc; 319 } 320 321 static void machine_set_enforce_config_section(Object *obj, bool value, 322 Error **errp) 323 { 324 MachineState *ms = MACHINE(obj); 325 326 ms->enforce_config_section = value; 327 } 328 329 static bool machine_get_enforce_config_section(Object *obj, Error **errp) 330 { 331 MachineState *ms = MACHINE(obj); 332 333 return ms->enforce_config_section; 334 } 335 336 static void error_on_sysbus_device(SysBusDevice *sbdev, void *opaque) 337 { 338 error_report("Option '-device %s' cannot be handled by this machine", 339 object_class_get_name(object_get_class(OBJECT(sbdev)))); 340 exit(1); 341 } 342 343 static void machine_init_notify(Notifier *notifier, void *data) 344 { 345 Object *machine = qdev_get_machine(); 346 ObjectClass *oc = object_get_class(machine); 347 MachineClass *mc = MACHINE_CLASS(oc); 348 349 if (mc->has_dynamic_sysbus) { 350 /* Our machine can handle dynamic sysbus devices, we're all good */ 351 return; 352 } 353 354 /* 355 * Loop through all dynamically created devices and check whether there 356 * are sysbus devices among them. If there are, error out. 357 */ 358 foreach_dynamic_sysbus_device(error_on_sysbus_device, NULL); 359 } 360 361 HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine) 362 { 363 int i; 364 Object *cpu; 365 HotpluggableCPUList *head = NULL; 366 const char *cpu_type; 367 368 cpu = machine->possible_cpus->cpus[0].cpu; 369 assert(cpu); /* Boot cpu is always present */ 370 cpu_type = object_get_typename(cpu); 371 for (i = 0; i < machine->possible_cpus->len; i++) { 372 HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1); 373 HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1); 374 375 cpu_item->type = g_strdup(cpu_type); 376 cpu_item->vcpus_count = machine->possible_cpus->cpus[i].vcpus_count; 377 cpu_item->props = g_memdup(&machine->possible_cpus->cpus[i].props, 378 sizeof(*cpu_item->props)); 379 380 cpu = machine->possible_cpus->cpus[i].cpu; 381 if (cpu) { 382 cpu_item->has_qom_path = true; 383 cpu_item->qom_path = object_get_canonical_path(cpu); 384 } 385 list_item->value = cpu_item; 386 list_item->next = head; 387 head = list_item; 388 } 389 return head; 390 } 391 392 static void machine_class_init(ObjectClass *oc, void *data) 393 { 394 MachineClass *mc = MACHINE_CLASS(oc); 395 396 /* Default 128 MB as guest ram size */ 397 mc->default_ram_size = 128 * M_BYTE; 398 mc->rom_file_has_mr = true; 399 400 /* numa node memory size aligned on 8MB by default. 401 * On Linux, each node's border has to be 8MB aligned 402 */ 403 mc->numa_mem_align_shift = 23; 404 mc->numa_auto_assign_ram = numa_default_auto_assign_ram; 405 406 object_class_property_add_str(oc, "accel", 407 machine_get_accel, machine_set_accel, &error_abort); 408 object_class_property_set_description(oc, "accel", 409 "Accelerator list", &error_abort); 410 411 object_class_property_add(oc, "kernel-irqchip", "OnOffSplit", 412 NULL, machine_set_kernel_irqchip, 413 NULL, NULL, &error_abort); 414 object_class_property_set_description(oc, "kernel-irqchip", 415 "Configure KVM in-kernel irqchip", &error_abort); 416 417 object_class_property_add(oc, "kvm-shadow-mem", "int", 418 machine_get_kvm_shadow_mem, machine_set_kvm_shadow_mem, 419 NULL, NULL, &error_abort); 420 object_class_property_set_description(oc, "kvm-shadow-mem", 421 "KVM shadow MMU size", &error_abort); 422 423 object_class_property_add_str(oc, "kernel", 424 machine_get_kernel, machine_set_kernel, &error_abort); 425 object_class_property_set_description(oc, "kernel", 426 "Linux kernel image file", &error_abort); 427 428 object_class_property_add_str(oc, "initrd", 429 machine_get_initrd, machine_set_initrd, &error_abort); 430 object_class_property_set_description(oc, "initrd", 431 "Linux initial ramdisk file", &error_abort); 432 433 object_class_property_add_str(oc, "append", 434 machine_get_append, machine_set_append, &error_abort); 435 object_class_property_set_description(oc, "append", 436 "Linux kernel command line", &error_abort); 437 438 object_class_property_add_str(oc, "dtb", 439 machine_get_dtb, machine_set_dtb, &error_abort); 440 object_class_property_set_description(oc, "dtb", 441 "Linux kernel device tree file", &error_abort); 442 443 object_class_property_add_str(oc, "dumpdtb", 444 machine_get_dumpdtb, machine_set_dumpdtb, &error_abort); 445 object_class_property_set_description(oc, "dumpdtb", 446 "Dump current dtb to a file and quit", &error_abort); 447 448 object_class_property_add(oc, "phandle-start", "int", 449 machine_get_phandle_start, machine_set_phandle_start, 450 NULL, NULL, &error_abort); 451 object_class_property_set_description(oc, "phandle-start", 452 "The first phandle ID we may generate dynamically", &error_abort); 453 454 object_class_property_add_str(oc, "dt-compatible", 455 machine_get_dt_compatible, machine_set_dt_compatible, &error_abort); 456 object_class_property_set_description(oc, "dt-compatible", 457 "Overrides the \"compatible\" property of the dt root node", 458 &error_abort); 459 460 object_class_property_add_bool(oc, "dump-guest-core", 461 machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort); 462 object_class_property_set_description(oc, "dump-guest-core", 463 "Include guest memory in a core dump", &error_abort); 464 465 object_class_property_add_bool(oc, "mem-merge", 466 machine_get_mem_merge, machine_set_mem_merge, &error_abort); 467 object_class_property_set_description(oc, "mem-merge", 468 "Enable/disable memory merge support", &error_abort); 469 470 object_class_property_add_bool(oc, "usb", 471 machine_get_usb, machine_set_usb, &error_abort); 472 object_class_property_set_description(oc, "usb", 473 "Set on/off to enable/disable usb", &error_abort); 474 475 object_class_property_add_bool(oc, "graphics", 476 machine_get_graphics, machine_set_graphics, &error_abort); 477 object_class_property_set_description(oc, "graphics", 478 "Set on/off to enable/disable graphics emulation", &error_abort); 479 480 object_class_property_add_bool(oc, "igd-passthru", 481 machine_get_igd_gfx_passthru, machine_set_igd_gfx_passthru, 482 &error_abort); 483 object_class_property_set_description(oc, "igd-passthru", 484 "Set on/off to enable/disable igd passthrou", &error_abort); 485 486 object_class_property_add_str(oc, "firmware", 487 machine_get_firmware, machine_set_firmware, 488 &error_abort); 489 object_class_property_set_description(oc, "firmware", 490 "Firmware image", &error_abort); 491 492 object_class_property_add_bool(oc, "suppress-vmdesc", 493 machine_get_suppress_vmdesc, machine_set_suppress_vmdesc, 494 &error_abort); 495 object_class_property_set_description(oc, "suppress-vmdesc", 496 "Set on to disable self-describing migration", &error_abort); 497 498 object_class_property_add_bool(oc, "enforce-config-section", 499 machine_get_enforce_config_section, machine_set_enforce_config_section, 500 &error_abort); 501 object_class_property_set_description(oc, "enforce-config-section", 502 "Set on to enforce configuration section migration", &error_abort); 503 } 504 505 static void machine_class_base_init(ObjectClass *oc, void *data) 506 { 507 if (!object_class_is_abstract(oc)) { 508 MachineClass *mc = MACHINE_CLASS(oc); 509 const char *cname = object_class_get_name(oc); 510 assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX)); 511 mc->name = g_strndup(cname, 512 strlen(cname) - strlen(TYPE_MACHINE_SUFFIX)); 513 } 514 } 515 516 static void machine_initfn(Object *obj) 517 { 518 MachineState *ms = MACHINE(obj); 519 520 ms->kernel_irqchip_allowed = true; 521 ms->kvm_shadow_mem = -1; 522 ms->dump_guest_core = true; 523 ms->mem_merge = true; 524 ms->enable_graphics = true; 525 526 /* Register notifier when init is done for sysbus sanity checks */ 527 ms->sysbus_notifier.notify = machine_init_notify; 528 qemu_add_machine_init_done_notifier(&ms->sysbus_notifier); 529 } 530 531 static void machine_finalize(Object *obj) 532 { 533 MachineState *ms = MACHINE(obj); 534 535 g_free(ms->accel); 536 g_free(ms->kernel_filename); 537 g_free(ms->initrd_filename); 538 g_free(ms->kernel_cmdline); 539 g_free(ms->dtb); 540 g_free(ms->dumpdtb); 541 g_free(ms->dt_compatible); 542 g_free(ms->firmware); 543 } 544 545 bool machine_usb(MachineState *machine) 546 { 547 return machine->usb; 548 } 549 550 bool machine_kernel_irqchip_allowed(MachineState *machine) 551 { 552 return machine->kernel_irqchip_allowed; 553 } 554 555 bool machine_kernel_irqchip_required(MachineState *machine) 556 { 557 return machine->kernel_irqchip_required; 558 } 559 560 bool machine_kernel_irqchip_split(MachineState *machine) 561 { 562 return machine->kernel_irqchip_split; 563 } 564 565 int machine_kvm_shadow_mem(MachineState *machine) 566 { 567 return machine->kvm_shadow_mem; 568 } 569 570 int machine_phandle_start(MachineState *machine) 571 { 572 return machine->phandle_start; 573 } 574 575 bool machine_dump_guest_core(MachineState *machine) 576 { 577 return machine->dump_guest_core; 578 } 579 580 bool machine_mem_merge(MachineState *machine) 581 { 582 return machine->mem_merge; 583 } 584 585 static void machine_class_finalize(ObjectClass *klass, void *data) 586 { 587 MachineClass *mc = MACHINE_CLASS(klass); 588 589 if (mc->compat_props) { 590 g_array_free(mc->compat_props, true); 591 } 592 g_free(mc->name); 593 } 594 595 static void register_compat_prop(const char *driver, 596 const char *property, 597 const char *value) 598 { 599 GlobalProperty *p = g_new0(GlobalProperty, 1); 600 /* Machine compat_props must never cause errors: */ 601 p->errp = &error_abort; 602 p->driver = driver; 603 p->property = property; 604 p->value = value; 605 qdev_prop_register_global(p); 606 } 607 608 static void machine_register_compat_for_subclass(ObjectClass *oc, void *opaque) 609 { 610 GlobalProperty *p = opaque; 611 register_compat_prop(object_class_get_name(oc), p->property, p->value); 612 } 613 614 void machine_register_compat_props(MachineState *machine) 615 { 616 MachineClass *mc = MACHINE_GET_CLASS(machine); 617 int i; 618 GlobalProperty *p; 619 ObjectClass *oc; 620 621 if (!mc->compat_props) { 622 return; 623 } 624 625 for (i = 0; i < mc->compat_props->len; i++) { 626 p = g_array_index(mc->compat_props, GlobalProperty *, i); 627 oc = object_class_by_name(p->driver); 628 if (oc && object_class_is_abstract(oc)) { 629 /* temporary hack to make sure we do not override 630 * globals set explicitly on -global: if an abstract class 631 * is on compat_props, register globals for all its 632 * non-abstract subtypes instead. 633 * 634 * This doesn't solve the problem for cases where 635 * a non-abstract typename mentioned on compat_props 636 * has subclasses, like spapr-pci-host-bridge. 637 */ 638 object_class_foreach(machine_register_compat_for_subclass, 639 p->driver, false, p); 640 } else { 641 register_compat_prop(p->driver, p->property, p->value); 642 } 643 } 644 } 645 646 static const TypeInfo machine_info = { 647 .name = TYPE_MACHINE, 648 .parent = TYPE_OBJECT, 649 .abstract = true, 650 .class_size = sizeof(MachineClass), 651 .class_init = machine_class_init, 652 .class_base_init = machine_class_base_init, 653 .class_finalize = machine_class_finalize, 654 .instance_size = sizeof(MachineState), 655 .instance_init = machine_initfn, 656 .instance_finalize = machine_finalize, 657 }; 658 659 static void machine_register_types(void) 660 { 661 type_register_static(&machine_info); 662 } 663 664 type_init(machine_register_types) 665