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