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_igd_gfx_passthru(Object *obj, Error **errp) 261 { 262 MachineState *ms = MACHINE(obj); 263 264 return ms->igd_gfx_passthru; 265 } 266 267 static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp) 268 { 269 MachineState *ms = MACHINE(obj); 270 271 ms->igd_gfx_passthru = value; 272 } 273 274 static char *machine_get_firmware(Object *obj, Error **errp) 275 { 276 MachineState *ms = MACHINE(obj); 277 278 return g_strdup(ms->firmware); 279 } 280 281 static void machine_set_firmware(Object *obj, const char *value, Error **errp) 282 { 283 MachineState *ms = MACHINE(obj); 284 285 g_free(ms->firmware); 286 ms->firmware = g_strdup(value); 287 } 288 289 static bool machine_get_iommu(Object *obj, Error **errp) 290 { 291 MachineState *ms = MACHINE(obj); 292 293 return ms->iommu; 294 } 295 296 static void machine_set_iommu(Object *obj, bool value, Error **errp) 297 { 298 MachineState *ms = MACHINE(obj); 299 300 ms->iommu = value; 301 } 302 303 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp) 304 { 305 MachineState *ms = MACHINE(obj); 306 307 ms->suppress_vmdesc = value; 308 } 309 310 static bool machine_get_suppress_vmdesc(Object *obj, Error **errp) 311 { 312 MachineState *ms = MACHINE(obj); 313 314 return ms->suppress_vmdesc; 315 } 316 317 static void machine_set_enforce_config_section(Object *obj, bool value, 318 Error **errp) 319 { 320 MachineState *ms = MACHINE(obj); 321 322 ms->enforce_config_section = value; 323 } 324 325 static bool machine_get_enforce_config_section(Object *obj, Error **errp) 326 { 327 MachineState *ms = MACHINE(obj); 328 329 return ms->enforce_config_section; 330 } 331 332 static int error_on_sysbus_device(SysBusDevice *sbdev, void *opaque) 333 { 334 error_report("Option '-device %s' cannot be handled by this machine", 335 object_class_get_name(object_get_class(OBJECT(sbdev)))); 336 exit(1); 337 } 338 339 static void machine_init_notify(Notifier *notifier, void *data) 340 { 341 Object *machine = qdev_get_machine(); 342 ObjectClass *oc = object_get_class(machine); 343 MachineClass *mc = MACHINE_CLASS(oc); 344 345 if (mc->has_dynamic_sysbus) { 346 /* Our machine can handle dynamic sysbus devices, we're all good */ 347 return; 348 } 349 350 /* 351 * Loop through all dynamically created devices and check whether there 352 * are sysbus devices among them. If there are, error out. 353 */ 354 foreach_dynamic_sysbus_device(error_on_sysbus_device, NULL); 355 } 356 357 static void machine_class_init(ObjectClass *oc, void *data) 358 { 359 MachineClass *mc = MACHINE_CLASS(oc); 360 361 /* Default 128 MB as guest ram size */ 362 mc->default_ram_size = 128 * M_BYTE; 363 mc->rom_file_has_mr = true; 364 } 365 366 static void machine_class_base_init(ObjectClass *oc, void *data) 367 { 368 if (!object_class_is_abstract(oc)) { 369 MachineClass *mc = MACHINE_CLASS(oc); 370 const char *cname = object_class_get_name(oc); 371 assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX)); 372 mc->name = g_strndup(cname, 373 strlen(cname) - strlen(TYPE_MACHINE_SUFFIX)); 374 } 375 } 376 377 static void machine_initfn(Object *obj) 378 { 379 MachineState *ms = MACHINE(obj); 380 381 ms->kernel_irqchip_allowed = true; 382 ms->kvm_shadow_mem = -1; 383 ms->dump_guest_core = true; 384 ms->mem_merge = true; 385 386 object_property_add_str(obj, "accel", 387 machine_get_accel, machine_set_accel, NULL); 388 object_property_set_description(obj, "accel", 389 "Accelerator list", 390 NULL); 391 object_property_add(obj, "kernel-irqchip", "OnOffSplit", 392 NULL, 393 machine_set_kernel_irqchip, 394 NULL, NULL, NULL); 395 object_property_set_description(obj, "kernel-irqchip", 396 "Configure KVM in-kernel irqchip", 397 NULL); 398 object_property_add(obj, "kvm-shadow-mem", "int", 399 machine_get_kvm_shadow_mem, 400 machine_set_kvm_shadow_mem, 401 NULL, NULL, NULL); 402 object_property_set_description(obj, "kvm-shadow-mem", 403 "KVM shadow MMU size", 404 NULL); 405 object_property_add_str(obj, "kernel", 406 machine_get_kernel, machine_set_kernel, NULL); 407 object_property_set_description(obj, "kernel", 408 "Linux kernel image file", 409 NULL); 410 object_property_add_str(obj, "initrd", 411 machine_get_initrd, machine_set_initrd, NULL); 412 object_property_set_description(obj, "initrd", 413 "Linux initial ramdisk file", 414 NULL); 415 object_property_add_str(obj, "append", 416 machine_get_append, machine_set_append, NULL); 417 object_property_set_description(obj, "append", 418 "Linux kernel command line", 419 NULL); 420 object_property_add_str(obj, "dtb", 421 machine_get_dtb, machine_set_dtb, NULL); 422 object_property_set_description(obj, "dtb", 423 "Linux kernel device tree file", 424 NULL); 425 object_property_add_str(obj, "dumpdtb", 426 machine_get_dumpdtb, machine_set_dumpdtb, NULL); 427 object_property_set_description(obj, "dumpdtb", 428 "Dump current dtb to a file and quit", 429 NULL); 430 object_property_add(obj, "phandle-start", "int", 431 machine_get_phandle_start, 432 machine_set_phandle_start, 433 NULL, NULL, NULL); 434 object_property_set_description(obj, "phandle-start", 435 "The first phandle ID we may generate dynamically", 436 NULL); 437 object_property_add_str(obj, "dt-compatible", 438 machine_get_dt_compatible, 439 machine_set_dt_compatible, 440 NULL); 441 object_property_set_description(obj, "dt-compatible", 442 "Overrides the \"compatible\" property of the dt root node", 443 NULL); 444 object_property_add_bool(obj, "dump-guest-core", 445 machine_get_dump_guest_core, 446 machine_set_dump_guest_core, 447 NULL); 448 object_property_set_description(obj, "dump-guest-core", 449 "Include guest memory in a core dump", 450 NULL); 451 object_property_add_bool(obj, "mem-merge", 452 machine_get_mem_merge, 453 machine_set_mem_merge, NULL); 454 object_property_set_description(obj, "mem-merge", 455 "Enable/disable memory merge support", 456 NULL); 457 object_property_add_bool(obj, "usb", 458 machine_get_usb, 459 machine_set_usb, NULL); 460 object_property_set_description(obj, "usb", 461 "Set on/off to enable/disable usb", 462 NULL); 463 object_property_add_bool(obj, "igd-passthru", 464 machine_get_igd_gfx_passthru, 465 machine_set_igd_gfx_passthru, NULL); 466 object_property_set_description(obj, "igd-passthru", 467 "Set on/off to enable/disable igd passthrou", 468 NULL); 469 object_property_add_str(obj, "firmware", 470 machine_get_firmware, 471 machine_set_firmware, NULL); 472 object_property_set_description(obj, "firmware", 473 "Firmware image", 474 NULL); 475 object_property_add_bool(obj, "iommu", 476 machine_get_iommu, 477 machine_set_iommu, NULL); 478 object_property_set_description(obj, "iommu", 479 "Set on/off to enable/disable Intel IOMMU (VT-d)", 480 NULL); 481 object_property_add_bool(obj, "suppress-vmdesc", 482 machine_get_suppress_vmdesc, 483 machine_set_suppress_vmdesc, NULL); 484 object_property_set_description(obj, "suppress-vmdesc", 485 "Set on to disable self-describing migration", 486 NULL); 487 object_property_add_bool(obj, "enforce-config-section", 488 machine_get_enforce_config_section, 489 machine_set_enforce_config_section, NULL); 490 object_property_set_description(obj, "enforce-config-section", 491 "Set on to enforce configuration section migration", 492 NULL); 493 494 /* Register notifier when init is done for sysbus sanity checks */ 495 ms->sysbus_notifier.notify = machine_init_notify; 496 qemu_add_machine_init_done_notifier(&ms->sysbus_notifier); 497 } 498 499 static void machine_finalize(Object *obj) 500 { 501 MachineState *ms = MACHINE(obj); 502 503 g_free(ms->accel); 504 g_free(ms->kernel_filename); 505 g_free(ms->initrd_filename); 506 g_free(ms->kernel_cmdline); 507 g_free(ms->dtb); 508 g_free(ms->dumpdtb); 509 g_free(ms->dt_compatible); 510 g_free(ms->firmware); 511 } 512 513 bool machine_usb(MachineState *machine) 514 { 515 return machine->usb; 516 } 517 518 bool machine_kernel_irqchip_allowed(MachineState *machine) 519 { 520 return machine->kernel_irqchip_allowed; 521 } 522 523 bool machine_kernel_irqchip_required(MachineState *machine) 524 { 525 return machine->kernel_irqchip_required; 526 } 527 528 bool machine_kernel_irqchip_split(MachineState *machine) 529 { 530 return machine->kernel_irqchip_split; 531 } 532 533 int machine_kvm_shadow_mem(MachineState *machine) 534 { 535 return machine->kvm_shadow_mem; 536 } 537 538 int machine_phandle_start(MachineState *machine) 539 { 540 return machine->phandle_start; 541 } 542 543 bool machine_dump_guest_core(MachineState *machine) 544 { 545 return machine->dump_guest_core; 546 } 547 548 bool machine_mem_merge(MachineState *machine) 549 { 550 return machine->mem_merge; 551 } 552 553 static const TypeInfo machine_info = { 554 .name = TYPE_MACHINE, 555 .parent = TYPE_OBJECT, 556 .abstract = true, 557 .class_size = sizeof(MachineClass), 558 .class_init = machine_class_init, 559 .class_base_init = machine_class_base_init, 560 .instance_size = sizeof(MachineState), 561 .instance_init = machine_initfn, 562 .instance_finalize = machine_finalize, 563 }; 564 565 static void machine_register_types(void) 566 { 567 type_register_static(&machine_info); 568 } 569 570 type_init(machine_register_types) 571