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