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 int 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 static void machine_class_init(ObjectClass *oc, void *data) 361 { 362 MachineClass *mc = MACHINE_CLASS(oc); 363 364 /* Default 128 MB as guest ram size */ 365 mc->default_ram_size = 128 * M_BYTE; 366 mc->rom_file_has_mr = true; 367 } 368 369 static void machine_class_base_init(ObjectClass *oc, void *data) 370 { 371 if (!object_class_is_abstract(oc)) { 372 MachineClass *mc = MACHINE_CLASS(oc); 373 const char *cname = object_class_get_name(oc); 374 assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX)); 375 mc->name = g_strndup(cname, 376 strlen(cname) - strlen(TYPE_MACHINE_SUFFIX)); 377 } 378 } 379 380 static void machine_initfn(Object *obj) 381 { 382 MachineState *ms = MACHINE(obj); 383 384 ms->kernel_irqchip_allowed = true; 385 ms->kvm_shadow_mem = -1; 386 ms->dump_guest_core = true; 387 ms->mem_merge = true; 388 ms->enable_graphics = true; 389 390 object_property_add_str(obj, "accel", 391 machine_get_accel, machine_set_accel, NULL); 392 object_property_set_description(obj, "accel", 393 "Accelerator list", 394 NULL); 395 object_property_add(obj, "kernel-irqchip", "OnOffSplit", 396 NULL, 397 machine_set_kernel_irqchip, 398 NULL, NULL, NULL); 399 object_property_set_description(obj, "kernel-irqchip", 400 "Configure KVM in-kernel irqchip", 401 NULL); 402 object_property_add(obj, "kvm-shadow-mem", "int", 403 machine_get_kvm_shadow_mem, 404 machine_set_kvm_shadow_mem, 405 NULL, NULL, NULL); 406 object_property_set_description(obj, "kvm-shadow-mem", 407 "KVM shadow MMU size", 408 NULL); 409 object_property_add_str(obj, "kernel", 410 machine_get_kernel, machine_set_kernel, NULL); 411 object_property_set_description(obj, "kernel", 412 "Linux kernel image file", 413 NULL); 414 object_property_add_str(obj, "initrd", 415 machine_get_initrd, machine_set_initrd, NULL); 416 object_property_set_description(obj, "initrd", 417 "Linux initial ramdisk file", 418 NULL); 419 object_property_add_str(obj, "append", 420 machine_get_append, machine_set_append, NULL); 421 object_property_set_description(obj, "append", 422 "Linux kernel command line", 423 NULL); 424 object_property_add_str(obj, "dtb", 425 machine_get_dtb, machine_set_dtb, NULL); 426 object_property_set_description(obj, "dtb", 427 "Linux kernel device tree file", 428 NULL); 429 object_property_add_str(obj, "dumpdtb", 430 machine_get_dumpdtb, machine_set_dumpdtb, NULL); 431 object_property_set_description(obj, "dumpdtb", 432 "Dump current dtb to a file and quit", 433 NULL); 434 object_property_add(obj, "phandle-start", "int", 435 machine_get_phandle_start, 436 machine_set_phandle_start, 437 NULL, NULL, NULL); 438 object_property_set_description(obj, "phandle-start", 439 "The first phandle ID we may generate dynamically", 440 NULL); 441 object_property_add_str(obj, "dt-compatible", 442 machine_get_dt_compatible, 443 machine_set_dt_compatible, 444 NULL); 445 object_property_set_description(obj, "dt-compatible", 446 "Overrides the \"compatible\" property of the dt root node", 447 NULL); 448 object_property_add_bool(obj, "dump-guest-core", 449 machine_get_dump_guest_core, 450 machine_set_dump_guest_core, 451 NULL); 452 object_property_set_description(obj, "dump-guest-core", 453 "Include guest memory in a core dump", 454 NULL); 455 object_property_add_bool(obj, "mem-merge", 456 machine_get_mem_merge, 457 machine_set_mem_merge, NULL); 458 object_property_set_description(obj, "mem-merge", 459 "Enable/disable memory merge support", 460 NULL); 461 object_property_add_bool(obj, "usb", 462 machine_get_usb, 463 machine_set_usb, NULL); 464 object_property_set_description(obj, "usb", 465 "Set on/off to enable/disable usb", 466 NULL); 467 object_property_add_bool(obj, "graphics", 468 machine_get_graphics, 469 machine_set_graphics, NULL); 470 object_property_set_description(obj, "graphics", 471 "Set on/off to enable/disable graphics emulation", 472 NULL); 473 object_property_add_bool(obj, "igd-passthru", 474 machine_get_igd_gfx_passthru, 475 machine_set_igd_gfx_passthru, NULL); 476 object_property_set_description(obj, "igd-passthru", 477 "Set on/off to enable/disable igd passthrou", 478 NULL); 479 object_property_add_str(obj, "firmware", 480 machine_get_firmware, 481 machine_set_firmware, NULL); 482 object_property_set_description(obj, "firmware", 483 "Firmware image", 484 NULL); 485 object_property_add_bool(obj, "suppress-vmdesc", 486 machine_get_suppress_vmdesc, 487 machine_set_suppress_vmdesc, NULL); 488 object_property_set_description(obj, "suppress-vmdesc", 489 "Set on to disable self-describing migration", 490 NULL); 491 object_property_add_bool(obj, "enforce-config-section", 492 machine_get_enforce_config_section, 493 machine_set_enforce_config_section, NULL); 494 object_property_set_description(obj, "enforce-config-section", 495 "Set on to enforce configuration section migration", 496 NULL); 497 498 /* Register notifier when init is done for sysbus sanity checks */ 499 ms->sysbus_notifier.notify = machine_init_notify; 500 qemu_add_machine_init_done_notifier(&ms->sysbus_notifier); 501 } 502 503 static void machine_finalize(Object *obj) 504 { 505 MachineState *ms = MACHINE(obj); 506 507 g_free(ms->accel); 508 g_free(ms->kernel_filename); 509 g_free(ms->initrd_filename); 510 g_free(ms->kernel_cmdline); 511 g_free(ms->dtb); 512 g_free(ms->dumpdtb); 513 g_free(ms->dt_compatible); 514 g_free(ms->firmware); 515 } 516 517 bool machine_usb(MachineState *machine) 518 { 519 return machine->usb; 520 } 521 522 bool machine_kernel_irqchip_allowed(MachineState *machine) 523 { 524 return machine->kernel_irqchip_allowed; 525 } 526 527 bool machine_kernel_irqchip_required(MachineState *machine) 528 { 529 return machine->kernel_irqchip_required; 530 } 531 532 bool machine_kernel_irqchip_split(MachineState *machine) 533 { 534 return machine->kernel_irqchip_split; 535 } 536 537 int machine_kvm_shadow_mem(MachineState *machine) 538 { 539 return machine->kvm_shadow_mem; 540 } 541 542 int machine_phandle_start(MachineState *machine) 543 { 544 return machine->phandle_start; 545 } 546 547 bool machine_dump_guest_core(MachineState *machine) 548 { 549 return machine->dump_guest_core; 550 } 551 552 bool machine_mem_merge(MachineState *machine) 553 { 554 return machine->mem_merge; 555 } 556 557 static void machine_class_finalize(ObjectClass *klass, void *data) 558 { 559 MachineClass *mc = MACHINE_CLASS(klass); 560 561 if (mc->compat_props) { 562 g_array_free(mc->compat_props, true); 563 } 564 g_free(mc->name); 565 } 566 567 void machine_register_compat_props(MachineState *machine) 568 { 569 MachineClass *mc = MACHINE_GET_CLASS(machine); 570 int i; 571 GlobalProperty *p; 572 573 if (!mc->compat_props) { 574 return; 575 } 576 577 for (i = 0; i < mc->compat_props->len; i++) { 578 p = g_array_index(mc->compat_props, GlobalProperty *, i); 579 /* Machine compat_props must never cause errors: */ 580 p->errp = &error_abort; 581 qdev_prop_register_global(p); 582 } 583 } 584 585 static const TypeInfo machine_info = { 586 .name = TYPE_MACHINE, 587 .parent = TYPE_OBJECT, 588 .abstract = true, 589 .class_size = sizeof(MachineClass), 590 .class_init = machine_class_init, 591 .class_base_init = machine_class_base_init, 592 .class_finalize = machine_class_finalize, 593 .instance_size = sizeof(MachineState), 594 .instance_init = machine_initfn, 595 .instance_finalize = machine_finalize, 596 }; 597 598 static void machine_register_types(void) 599 { 600 type_register_static(&machine_info); 601 } 602 603 type_init(machine_register_types) 604