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_add_bool(obj, "kernel-irqchip", 295 machine_get_kernel_irqchip, 296 machine_set_kernel_irqchip, 297 NULL); 298 object_property_add(obj, "kvm-shadow-mem", "int", 299 machine_get_kvm_shadow_mem, 300 machine_set_kvm_shadow_mem, 301 NULL, NULL, NULL); 302 object_property_add_str(obj, "kernel", 303 machine_get_kernel, machine_set_kernel, NULL); 304 object_property_add_str(obj, "initrd", 305 machine_get_initrd, machine_set_initrd, NULL); 306 object_property_add_str(obj, "append", 307 machine_get_append, machine_set_append, NULL); 308 object_property_add_str(obj, "dtb", 309 machine_get_dtb, machine_set_dtb, NULL); 310 object_property_add_str(obj, "dumpdtb", 311 machine_get_dumpdtb, machine_set_dumpdtb, NULL); 312 object_property_add(obj, "phandle-start", "int", 313 machine_get_phandle_start, 314 machine_set_phandle_start, 315 NULL, NULL, NULL); 316 object_property_add_str(obj, "dt-compatible", 317 machine_get_dt_compatible, 318 machine_set_dt_compatible, 319 NULL); 320 object_property_add_bool(obj, "dump-guest-core", 321 machine_get_dump_guest_core, 322 machine_set_dump_guest_core, 323 NULL); 324 object_property_add_bool(obj, "mem-merge", 325 machine_get_mem_merge, 326 machine_set_mem_merge, NULL); 327 object_property_add_bool(obj, "usb", 328 machine_get_usb, 329 machine_set_usb, NULL); 330 object_property_add_str(obj, "firmware", 331 machine_get_firmware, 332 machine_set_firmware, NULL); 333 object_property_add_bool(obj, "iommu", 334 machine_get_iommu, 335 machine_set_iommu, NULL); 336 337 /* Register notifier when init is done for sysbus sanity checks */ 338 ms->sysbus_notifier.notify = machine_init_notify; 339 qemu_add_machine_init_done_notifier(&ms->sysbus_notifier); 340 } 341 342 static void machine_finalize(Object *obj) 343 { 344 MachineState *ms = MACHINE(obj); 345 346 g_free(ms->accel); 347 g_free(ms->kernel_filename); 348 g_free(ms->initrd_filename); 349 g_free(ms->kernel_cmdline); 350 g_free(ms->dtb); 351 g_free(ms->dumpdtb); 352 g_free(ms->dt_compatible); 353 g_free(ms->firmware); 354 } 355 356 static const TypeInfo machine_info = { 357 .name = TYPE_MACHINE, 358 .parent = TYPE_OBJECT, 359 .abstract = true, 360 .class_size = sizeof(MachineClass), 361 .instance_size = sizeof(MachineState), 362 .instance_init = machine_initfn, 363 .instance_finalize = machine_finalize, 364 }; 365 366 static void machine_register_types(void) 367 { 368 type_register_static(&machine_info); 369 } 370 371 type_init(machine_register_types) 372