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