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