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