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 } 346 347 static void machine_class_base_init(ObjectClass *oc, void *data) 348 { 349 if (!object_class_is_abstract(oc)) { 350 MachineClass *mc = MACHINE_CLASS(oc); 351 const char *cname = object_class_get_name(oc); 352 assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX)); 353 mc->name = g_strndup(cname, 354 strlen(cname) - strlen(TYPE_MACHINE_SUFFIX)); 355 } 356 } 357 358 static void machine_initfn(Object *obj) 359 { 360 MachineState *ms = MACHINE(obj); 361 362 ms->kernel_irqchip_allowed = true; 363 ms->kvm_shadow_mem = -1; 364 ms->dump_guest_core = true; 365 ms->mem_merge = true; 366 367 object_property_add_str(obj, "accel", 368 machine_get_accel, machine_set_accel, NULL); 369 object_property_set_description(obj, "accel", 370 "Accelerator list", 371 NULL); 372 object_property_add(obj, "kernel-irqchip", "OnOffSplit", 373 NULL, 374 machine_set_kernel_irqchip, 375 NULL, NULL, NULL); 376 object_property_set_description(obj, "kernel-irqchip", 377 "Configure KVM in-kernel irqchip", 378 NULL); 379 object_property_add(obj, "kvm-shadow-mem", "int", 380 machine_get_kvm_shadow_mem, 381 machine_set_kvm_shadow_mem, 382 NULL, NULL, NULL); 383 object_property_set_description(obj, "kvm-shadow-mem", 384 "KVM shadow MMU size", 385 NULL); 386 object_property_add_str(obj, "kernel", 387 machine_get_kernel, machine_set_kernel, NULL); 388 object_property_set_description(obj, "kernel", 389 "Linux kernel image file", 390 NULL); 391 object_property_add_str(obj, "initrd", 392 machine_get_initrd, machine_set_initrd, NULL); 393 object_property_set_description(obj, "initrd", 394 "Linux initial ramdisk file", 395 NULL); 396 object_property_add_str(obj, "append", 397 machine_get_append, machine_set_append, NULL); 398 object_property_set_description(obj, "append", 399 "Linux kernel command line", 400 NULL); 401 object_property_add_str(obj, "dtb", 402 machine_get_dtb, machine_set_dtb, NULL); 403 object_property_set_description(obj, "dtb", 404 "Linux kernel device tree file", 405 NULL); 406 object_property_add_str(obj, "dumpdtb", 407 machine_get_dumpdtb, machine_set_dumpdtb, NULL); 408 object_property_set_description(obj, "dumpdtb", 409 "Dump current dtb to a file and quit", 410 NULL); 411 object_property_add(obj, "phandle-start", "int", 412 machine_get_phandle_start, 413 machine_set_phandle_start, 414 NULL, NULL, NULL); 415 object_property_set_description(obj, "phandle-start", 416 "The first phandle ID we may generate dynamically", 417 NULL); 418 object_property_add_str(obj, "dt-compatible", 419 machine_get_dt_compatible, 420 machine_set_dt_compatible, 421 NULL); 422 object_property_set_description(obj, "dt-compatible", 423 "Overrides the \"compatible\" property of the dt root node", 424 NULL); 425 object_property_add_bool(obj, "dump-guest-core", 426 machine_get_dump_guest_core, 427 machine_set_dump_guest_core, 428 NULL); 429 object_property_set_description(obj, "dump-guest-core", 430 "Include guest memory in a core dump", 431 NULL); 432 object_property_add_bool(obj, "mem-merge", 433 machine_get_mem_merge, 434 machine_set_mem_merge, NULL); 435 object_property_set_description(obj, "mem-merge", 436 "Enable/disable memory merge support", 437 NULL); 438 object_property_add_bool(obj, "usb", 439 machine_get_usb, 440 machine_set_usb, NULL); 441 object_property_set_description(obj, "usb", 442 "Set on/off to enable/disable usb", 443 NULL); 444 object_property_add_bool(obj, "igd-passthru", 445 machine_get_igd_gfx_passthru, 446 machine_set_igd_gfx_passthru, NULL); 447 object_property_set_description(obj, "igd-passthru", 448 "Set on/off to enable/disable igd passthrou", 449 NULL); 450 object_property_add_str(obj, "firmware", 451 machine_get_firmware, 452 machine_set_firmware, NULL); 453 object_property_set_description(obj, "firmware", 454 "Firmware image", 455 NULL); 456 object_property_add_bool(obj, "iommu", 457 machine_get_iommu, 458 machine_set_iommu, NULL); 459 object_property_set_description(obj, "iommu", 460 "Set on/off to enable/disable Intel IOMMU (VT-d)", 461 NULL); 462 object_property_add_bool(obj, "suppress-vmdesc", 463 machine_get_suppress_vmdesc, 464 machine_set_suppress_vmdesc, NULL); 465 object_property_set_description(obj, "suppress-vmdesc", 466 "Set on to disable self-describing migration", 467 NULL); 468 469 /* Register notifier when init is done for sysbus sanity checks */ 470 ms->sysbus_notifier.notify = machine_init_notify; 471 qemu_add_machine_init_done_notifier(&ms->sysbus_notifier); 472 } 473 474 static void machine_finalize(Object *obj) 475 { 476 MachineState *ms = MACHINE(obj); 477 478 g_free(ms->accel); 479 g_free(ms->kernel_filename); 480 g_free(ms->initrd_filename); 481 g_free(ms->kernel_cmdline); 482 g_free(ms->dtb); 483 g_free(ms->dumpdtb); 484 g_free(ms->dt_compatible); 485 g_free(ms->firmware); 486 } 487 488 bool machine_usb(MachineState *machine) 489 { 490 return machine->usb; 491 } 492 493 bool machine_kernel_irqchip_allowed(MachineState *machine) 494 { 495 return machine->kernel_irqchip_allowed; 496 } 497 498 bool machine_kernel_irqchip_required(MachineState *machine) 499 { 500 return machine->kernel_irqchip_required; 501 } 502 503 bool machine_kernel_irqchip_split(MachineState *machine) 504 { 505 return machine->kernel_irqchip_split; 506 } 507 508 int machine_kvm_shadow_mem(MachineState *machine) 509 { 510 return machine->kvm_shadow_mem; 511 } 512 513 int machine_phandle_start(MachineState *machine) 514 { 515 return machine->phandle_start; 516 } 517 518 bool machine_dump_guest_core(MachineState *machine) 519 { 520 return machine->dump_guest_core; 521 } 522 523 bool machine_mem_merge(MachineState *machine) 524 { 525 return machine->mem_merge; 526 } 527 528 static const TypeInfo machine_info = { 529 .name = TYPE_MACHINE, 530 .parent = TYPE_OBJECT, 531 .abstract = true, 532 .class_size = sizeof(MachineClass), 533 .class_init = machine_class_init, 534 .class_base_init = machine_class_base_init, 535 .instance_size = sizeof(MachineState), 536 .instance_init = machine_initfn, 537 .instance_finalize = machine_finalize, 538 }; 539 540 static void machine_register_types(void) 541 { 542 type_register_static(&machine_info); 543 } 544 545 type_init(machine_register_types) 546