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 bool machine_get_kernel_irqchip(Object *obj, Error **errp) 35 { 36 MachineState *ms = MACHINE(obj); 37 38 return ms->kernel_irqchip; 39 } 40 41 static void machine_set_kernel_irqchip(Object *obj, bool value, Error **errp) 42 { 43 MachineState *ms = MACHINE(obj); 44 45 ms->kernel_irqchip = value; 46 } 47 48 static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v, 49 void *opaque, const char *name, 50 Error **errp) 51 { 52 MachineState *ms = MACHINE(obj); 53 int64_t value = ms->kvm_shadow_mem; 54 55 visit_type_int(v, &value, name, errp); 56 } 57 58 static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v, 59 void *opaque, const char *name, 60 Error **errp) 61 { 62 MachineState *ms = MACHINE(obj); 63 Error *error = NULL; 64 int64_t value; 65 66 visit_type_int(v, &value, name, &error); 67 if (error) { 68 error_propagate(errp, error); 69 return; 70 } 71 72 ms->kvm_shadow_mem = value; 73 } 74 75 static char *machine_get_kernel(Object *obj, Error **errp) 76 { 77 MachineState *ms = MACHINE(obj); 78 79 return g_strdup(ms->kernel_filename); 80 } 81 82 static void machine_set_kernel(Object *obj, const char *value, Error **errp) 83 { 84 MachineState *ms = MACHINE(obj); 85 86 g_free(ms->kernel_filename); 87 ms->kernel_filename = g_strdup(value); 88 } 89 90 static char *machine_get_initrd(Object *obj, Error **errp) 91 { 92 MachineState *ms = MACHINE(obj); 93 94 return g_strdup(ms->initrd_filename); 95 } 96 97 static void machine_set_initrd(Object *obj, const char *value, Error **errp) 98 { 99 MachineState *ms = MACHINE(obj); 100 101 g_free(ms->initrd_filename); 102 ms->initrd_filename = g_strdup(value); 103 } 104 105 static char *machine_get_append(Object *obj, Error **errp) 106 { 107 MachineState *ms = MACHINE(obj); 108 109 return g_strdup(ms->kernel_cmdline); 110 } 111 112 static void machine_set_append(Object *obj, const char *value, Error **errp) 113 { 114 MachineState *ms = MACHINE(obj); 115 116 g_free(ms->kernel_cmdline); 117 ms->kernel_cmdline = g_strdup(value); 118 } 119 120 static char *machine_get_dtb(Object *obj, Error **errp) 121 { 122 MachineState *ms = MACHINE(obj); 123 124 return g_strdup(ms->dtb); 125 } 126 127 static void machine_set_dtb(Object *obj, const char *value, Error **errp) 128 { 129 MachineState *ms = MACHINE(obj); 130 131 g_free(ms->dtb); 132 ms->dtb = g_strdup(value); 133 } 134 135 static char *machine_get_dumpdtb(Object *obj, Error **errp) 136 { 137 MachineState *ms = MACHINE(obj); 138 139 return g_strdup(ms->dumpdtb); 140 } 141 142 static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp) 143 { 144 MachineState *ms = MACHINE(obj); 145 146 g_free(ms->dumpdtb); 147 ms->dumpdtb = g_strdup(value); 148 } 149 150 static void machine_get_phandle_start(Object *obj, Visitor *v, 151 void *opaque, const char *name, 152 Error **errp) 153 { 154 MachineState *ms = MACHINE(obj); 155 int64_t value = ms->phandle_start; 156 157 visit_type_int(v, &value, name, errp); 158 } 159 160 static void machine_set_phandle_start(Object *obj, Visitor *v, 161 void *opaque, const char *name, 162 Error **errp) 163 { 164 MachineState *ms = MACHINE(obj); 165 Error *error = NULL; 166 int64_t value; 167 168 visit_type_int(v, &value, name, &error); 169 if (error) { 170 error_propagate(errp, error); 171 return; 172 } 173 174 ms->phandle_start = value; 175 } 176 177 static char *machine_get_dt_compatible(Object *obj, Error **errp) 178 { 179 MachineState *ms = MACHINE(obj); 180 181 return g_strdup(ms->dt_compatible); 182 } 183 184 static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp) 185 { 186 MachineState *ms = MACHINE(obj); 187 188 g_free(ms->dt_compatible); 189 ms->dt_compatible = g_strdup(value); 190 } 191 192 static bool machine_get_dump_guest_core(Object *obj, Error **errp) 193 { 194 MachineState *ms = MACHINE(obj); 195 196 return ms->dump_guest_core; 197 } 198 199 static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp) 200 { 201 MachineState *ms = MACHINE(obj); 202 203 ms->dump_guest_core = value; 204 } 205 206 static bool machine_get_mem_merge(Object *obj, Error **errp) 207 { 208 MachineState *ms = MACHINE(obj); 209 210 return ms->mem_merge; 211 } 212 213 static void machine_set_mem_merge(Object *obj, bool value, Error **errp) 214 { 215 MachineState *ms = MACHINE(obj); 216 217 ms->mem_merge = value; 218 } 219 220 static bool machine_get_usb(Object *obj, Error **errp) 221 { 222 MachineState *ms = MACHINE(obj); 223 224 return ms->usb; 225 } 226 227 static void machine_set_usb(Object *obj, bool value, Error **errp) 228 { 229 MachineState *ms = MACHINE(obj); 230 231 ms->usb = value; 232 } 233 234 static char *machine_get_firmware(Object *obj, Error **errp) 235 { 236 MachineState *ms = MACHINE(obj); 237 238 return g_strdup(ms->firmware); 239 } 240 241 static void machine_set_firmware(Object *obj, const char *value, Error **errp) 242 { 243 MachineState *ms = MACHINE(obj); 244 245 g_free(ms->firmware); 246 ms->firmware = g_strdup(value); 247 } 248 249 static bool machine_get_iommu(Object *obj, Error **errp) 250 { 251 MachineState *ms = MACHINE(obj); 252 253 return ms->iommu; 254 } 255 256 static void machine_set_iommu(Object *obj, bool value, Error **errp) 257 { 258 MachineState *ms = MACHINE(obj); 259 260 ms->iommu = value; 261 } 262 263 static int error_on_sysbus_device(SysBusDevice *sbdev, void *opaque) 264 { 265 error_report("Option '-device %s' cannot be handled by this machine", 266 object_class_get_name(object_get_class(OBJECT(sbdev)))); 267 exit(1); 268 } 269 270 static void machine_init_notify(Notifier *notifier, void *data) 271 { 272 Object *machine = qdev_get_machine(); 273 ObjectClass *oc = object_get_class(machine); 274 MachineClass *mc = MACHINE_CLASS(oc); 275 276 if (mc->has_dynamic_sysbus) { 277 /* Our machine can handle dynamic sysbus devices, we're all good */ 278 return; 279 } 280 281 /* 282 * Loop through all dynamically created devices and check whether there 283 * are sysbus devices among them. If there are, error out. 284 */ 285 foreach_dynamic_sysbus_device(error_on_sysbus_device, NULL); 286 } 287 288 static void machine_initfn(Object *obj) 289 { 290 MachineState *ms = MACHINE(obj); 291 292 object_property_add_str(obj, "accel", 293 machine_get_accel, machine_set_accel, NULL); 294 object_property_set_description(obj, "accel", 295 "Accelerator list", 296 NULL); 297 object_property_add_bool(obj, "kernel-irqchip", 298 machine_get_kernel_irqchip, 299 machine_set_kernel_irqchip, 300 NULL); 301 object_property_set_description(obj, "kernel-irqchip", 302 "Use KVM in-kernel irqchip", 303 NULL); 304 object_property_add(obj, "kvm-shadow-mem", "int", 305 machine_get_kvm_shadow_mem, 306 machine_set_kvm_shadow_mem, 307 NULL, NULL, NULL); 308 object_property_set_description(obj, "kvm-shadow-mem", 309 "KVM shadow MMU size", 310 NULL); 311 object_property_add_str(obj, "kernel", 312 machine_get_kernel, machine_set_kernel, NULL); 313 object_property_set_description(obj, "kernel", 314 "Linux kernel image file", 315 NULL); 316 object_property_add_str(obj, "initrd", 317 machine_get_initrd, machine_set_initrd, NULL); 318 object_property_set_description(obj, "initrd", 319 "Linux initial ramdisk file", 320 NULL); 321 object_property_add_str(obj, "append", 322 machine_get_append, machine_set_append, NULL); 323 object_property_set_description(obj, "append", 324 "Linux kernel command line", 325 NULL); 326 object_property_add_str(obj, "dtb", 327 machine_get_dtb, machine_set_dtb, NULL); 328 object_property_set_description(obj, "dtb", 329 "Linux kernel device tree file", 330 NULL); 331 object_property_add_str(obj, "dumpdtb", 332 machine_get_dumpdtb, machine_set_dumpdtb, NULL); 333 object_property_set_description(obj, "dumpdtb", 334 "Dump current dtb to a file and quit", 335 NULL); 336 object_property_add(obj, "phandle-start", "int", 337 machine_get_phandle_start, 338 machine_set_phandle_start, 339 NULL, NULL, NULL); 340 object_property_set_description(obj, "phandle-start", 341 "The first phandle ID we may generate dynamically", 342 NULL); 343 object_property_add_str(obj, "dt-compatible", 344 machine_get_dt_compatible, 345 machine_set_dt_compatible, 346 NULL); 347 object_property_set_description(obj, "dt-compatible", 348 "Overrides the \"compatible\" property of the dt root node", 349 NULL); 350 object_property_add_bool(obj, "dump-guest-core", 351 machine_get_dump_guest_core, 352 machine_set_dump_guest_core, 353 NULL); 354 object_property_set_description(obj, "dump-guest-core", 355 "Include guest memory in a core dump", 356 NULL); 357 object_property_add_bool(obj, "mem-merge", 358 machine_get_mem_merge, 359 machine_set_mem_merge, NULL); 360 object_property_set_description(obj, "mem-merge", 361 "Enable/disable memory merge support", 362 NULL); 363 object_property_add_bool(obj, "usb", 364 machine_get_usb, 365 machine_set_usb, NULL); 366 object_property_set_description(obj, "usb", 367 "Set on/off to enable/disable usb", 368 NULL); 369 object_property_add_str(obj, "firmware", 370 machine_get_firmware, 371 machine_set_firmware, NULL); 372 object_property_set_description(obj, "firmware", 373 "Firmware image", 374 NULL); 375 object_property_add_bool(obj, "iommu", 376 machine_get_iommu, 377 machine_set_iommu, NULL); 378 object_property_set_description(obj, "iommu", 379 "Set on/off to enable/disable Intel IOMMU (VT-d)", 380 NULL); 381 382 /* Register notifier when init is done for sysbus sanity checks */ 383 ms->sysbus_notifier.notify = machine_init_notify; 384 qemu_add_machine_init_done_notifier(&ms->sysbus_notifier); 385 } 386 387 static void machine_finalize(Object *obj) 388 { 389 MachineState *ms = MACHINE(obj); 390 391 g_free(ms->accel); 392 g_free(ms->kernel_filename); 393 g_free(ms->initrd_filename); 394 g_free(ms->kernel_cmdline); 395 g_free(ms->dtb); 396 g_free(ms->dumpdtb); 397 g_free(ms->dt_compatible); 398 g_free(ms->firmware); 399 } 400 401 bool machine_usb(MachineState *machine) 402 { 403 return machine->usb; 404 } 405 406 static const TypeInfo machine_info = { 407 .name = TYPE_MACHINE, 408 .parent = TYPE_OBJECT, 409 .abstract = true, 410 .class_size = sizeof(MachineClass), 411 .instance_size = sizeof(MachineState), 412 .instance_init = machine_initfn, 413 .instance_finalize = machine_finalize, 414 }; 415 416 static void machine_register_types(void) 417 { 418 type_register_static(&machine_info); 419 } 420 421 type_init(machine_register_types) 422