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