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