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_hw_dtb(Object *obj, Error **errp)
 161{
 162    MachineState *ms = MACHINE(obj);
 163
 164    return g_strdup(ms->hw_dtb);
 165}
 166
 167static void machine_set_hw_dtb(Object *obj, const char *value, Error **errp)
 168{
 169    MachineState *ms = MACHINE(obj);
 170
 171    ms->hw_dtb = g_strdup(value);
 172}
 173
 174static char *machine_get_dumpdtb(Object *obj, Error **errp)
 175{
 176    MachineState *ms = MACHINE(obj);
 177
 178    return g_strdup(ms->dumpdtb);
 179}
 180
 181static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
 182{
 183    MachineState *ms = MACHINE(obj);
 184
 185    g_free(ms->dumpdtb);
 186    ms->dumpdtb = g_strdup(value);
 187}
 188
 189static void machine_get_phandle_start(Object *obj, Visitor *v,
 190                                      const char *name, void *opaque,
 191                                      Error **errp)
 192{
 193    MachineState *ms = MACHINE(obj);
 194    int64_t value = ms->phandle_start;
 195
 196    visit_type_int(v, name, &value, errp);
 197}
 198
 199static void machine_set_phandle_start(Object *obj, Visitor *v,
 200                                      const char *name, void *opaque,
 201                                      Error **errp)
 202{
 203    MachineState *ms = MACHINE(obj);
 204    Error *error = NULL;
 205    int64_t value;
 206
 207    visit_type_int(v, name, &value, &error);
 208    if (error) {
 209        error_propagate(errp, error);
 210        return;
 211    }
 212
 213    ms->phandle_start = value;
 214}
 215
 216static char *machine_get_dt_compatible(Object *obj, Error **errp)
 217{
 218    MachineState *ms = MACHINE(obj);
 219
 220    return g_strdup(ms->dt_compatible);
 221}
 222
 223static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp)
 224{
 225    MachineState *ms = MACHINE(obj);
 226
 227    g_free(ms->dt_compatible);
 228    ms->dt_compatible = g_strdup(value);
 229}
 230
 231static bool machine_get_dump_guest_core(Object *obj, Error **errp)
 232{
 233    MachineState *ms = MACHINE(obj);
 234
 235    return ms->dump_guest_core;
 236}
 237
 238static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp)
 239{
 240    MachineState *ms = MACHINE(obj);
 241
 242    ms->dump_guest_core = value;
 243}
 244
 245
 246static bool machine_get_linux(Object *obj, Error **errp)
 247{
 248    MachineState *ms = MACHINE(obj);
 249
 250    return ms->is_linux;
 251}
 252
 253static void machine_set_linux(Object *obj, bool value, Error **errp)
 254{
 255    MachineState *ms = MACHINE(obj);
 256
 257    ms->is_linux = value;
 258}
 259
 260static bool machine_get_mem_merge(Object *obj, Error **errp)
 261{
 262    MachineState *ms = MACHINE(obj);
 263
 264    return ms->mem_merge;
 265}
 266
 267static void machine_set_mem_merge(Object *obj, bool value, Error **errp)
 268{
 269    MachineState *ms = MACHINE(obj);
 270
 271    ms->mem_merge = value;
 272}
 273
 274static bool machine_get_usb(Object *obj, Error **errp)
 275{
 276    MachineState *ms = MACHINE(obj);
 277
 278    return ms->usb;
 279}
 280
 281static void machine_set_usb(Object *obj, bool value, Error **errp)
 282{
 283    MachineState *ms = MACHINE(obj);
 284
 285    ms->usb = value;
 286    ms->usb_disabled = !value;
 287}
 288
 289static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
 290{
 291    MachineState *ms = MACHINE(obj);
 292
 293    return ms->igd_gfx_passthru;
 294}
 295
 296static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
 297{
 298    MachineState *ms = MACHINE(obj);
 299
 300    ms->igd_gfx_passthru = value;
 301}
 302
 303static char *machine_get_firmware(Object *obj, Error **errp)
 304{
 305    MachineState *ms = MACHINE(obj);
 306
 307    return g_strdup(ms->firmware);
 308}
 309
 310static void machine_set_firmware(Object *obj, const char *value, Error **errp)
 311{
 312    MachineState *ms = MACHINE(obj);
 313
 314    g_free(ms->firmware);
 315    ms->firmware = g_strdup(value);
 316}
 317
 318static bool machine_get_iommu(Object *obj, Error **errp)
 319{
 320    MachineState *ms = MACHINE(obj);
 321
 322    return ms->iommu;
 323}
 324
 325static void machine_set_iommu(Object *obj, bool value, Error **errp)
 326{
 327    MachineState *ms = MACHINE(obj);
 328
 329    ms->iommu = value;
 330}
 331
 332static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
 333{
 334    MachineState *ms = MACHINE(obj);
 335
 336    ms->suppress_vmdesc = value;
 337}
 338
 339static bool machine_get_suppress_vmdesc(Object *obj, Error **errp)
 340{
 341    MachineState *ms = MACHINE(obj);
 342
 343    return ms->suppress_vmdesc;
 344}
 345
 346static void machine_set_enforce_config_section(Object *obj, bool value,
 347                                             Error **errp)
 348{
 349    MachineState *ms = MACHINE(obj);
 350
 351    ms->enforce_config_section = value;
 352}
 353
 354static bool machine_get_enforce_config_section(Object *obj, Error **errp)
 355{
 356    MachineState *ms = MACHINE(obj);
 357
 358    return ms->enforce_config_section;
 359}
 360
 361static int error_on_sysbus_device(SysBusDevice *sbdev, void *opaque)
 362{
 363    error_report("Option '-device %s' cannot be handled by this machine",
 364                 object_class_get_name(object_get_class(OBJECT(sbdev))));
 365    exit(1);
 366}
 367
 368static void machine_init_notify(Notifier *notifier, void *data)
 369{
 370    Object *machine = qdev_get_machine();
 371    ObjectClass *oc = object_get_class(machine);
 372    MachineClass *mc = MACHINE_CLASS(oc);
 373
 374    if (mc->has_dynamic_sysbus) {
 375        /* Our machine can handle dynamic sysbus devices, we're all good */
 376        return;
 377    }
 378
 379    /*
 380     * Loop through all dynamically created devices and check whether there
 381     * are sysbus devices among them. If there are, error out.
 382     */
 383    foreach_dynamic_sysbus_device(error_on_sysbus_device, NULL);
 384}
 385
 386static void machine_class_init(ObjectClass *oc, void *data)
 387{
 388    MachineClass *mc = MACHINE_CLASS(oc);
 389
 390    /* Default 128 MB as guest ram size */
 391    mc->default_ram_size = 128 * M_BYTE;
 392    mc->rom_file_has_mr = true;
 393}
 394
 395static void machine_class_base_init(ObjectClass *oc, void *data)
 396{
 397    if (!object_class_is_abstract(oc)) {
 398        MachineClass *mc = MACHINE_CLASS(oc);
 399        const char *cname = object_class_get_name(oc);
 400        assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX));
 401        mc->name = g_strndup(cname,
 402                            strlen(cname) - strlen(TYPE_MACHINE_SUFFIX));
 403    }
 404}
 405
 406static void machine_initfn(Object *obj)
 407{
 408    MachineState *ms = MACHINE(obj);
 409
 410    ms->kernel_irqchip_allowed = true;
 411    ms->kvm_shadow_mem = -1;
 412    ms->dump_guest_core = true;
 413    ms->mem_merge = true;
 414
 415    object_property_add_str(obj, "accel",
 416                            machine_get_accel, machine_set_accel, NULL);
 417    object_property_set_description(obj, "accel",
 418                                    "Accelerator list",
 419                                    NULL);
 420    object_property_add(obj, "kernel-irqchip", "OnOffSplit",
 421                        NULL,
 422                        machine_set_kernel_irqchip,
 423                        NULL, NULL, NULL);
 424    object_property_set_description(obj, "kernel-irqchip",
 425                                    "Configure KVM in-kernel irqchip",
 426                                    NULL);
 427    object_property_add(obj, "kvm-shadow-mem", "int",
 428                        machine_get_kvm_shadow_mem,
 429                        machine_set_kvm_shadow_mem,
 430                        NULL, NULL, NULL);
 431    object_property_set_description(obj, "kvm-shadow-mem",
 432                                    "KVM shadow MMU size",
 433                                    NULL);
 434    object_property_add_str(obj, "kernel",
 435                            machine_get_kernel, machine_set_kernel, NULL);
 436    object_property_set_description(obj, "kernel",
 437                                    "Linux kernel image file",
 438                                    NULL);
 439    object_property_add_str(obj, "initrd",
 440                            machine_get_initrd, machine_set_initrd, NULL);
 441    object_property_set_description(obj, "initrd",
 442                                    "Linux initial ramdisk file",
 443                                    NULL);
 444    object_property_add_str(obj, "append",
 445                            machine_get_append, machine_set_append, NULL);
 446    object_property_set_description(obj, "append",
 447                                    "Linux kernel command line",
 448                                    NULL);
 449    object_property_add_str(obj, "dtb",
 450                            machine_get_dtb, machine_set_dtb, NULL);
 451    object_property_set_description(obj, "dtb",
 452                                    "Linux kernel device tree file",
 453                                    NULL);
 454    object_property_add_str(obj, "hw-dtb",
 455                            machine_get_hw_dtb, machine_set_hw_dtb, NULL);
 456    object_property_set_description(obj, "hw-dtb",
 457                                    "Dump current dtb to a file and quit",
 458                                    NULL);
 459    object_property_add_str(obj, "dumpdtb",
 460                            machine_get_dumpdtb, machine_set_dumpdtb, NULL);
 461    object_property_set_description(obj, "dumpdtb",
 462                                    "Dump current dtb to a file and quit",
 463                                    NULL);
 464    object_property_add(obj, "phandle-start", "int",
 465                        machine_get_phandle_start,
 466                        machine_set_phandle_start,
 467                        NULL, NULL, NULL);
 468    object_property_set_description(obj, "phandle-start",
 469                                    "The first phandle ID we may generate dynamically",
 470                                    NULL);
 471    object_property_add_str(obj, "dt-compatible",
 472                            machine_get_dt_compatible,
 473                            machine_set_dt_compatible,
 474                            NULL);
 475    object_property_set_description(obj, "dt-compatible",
 476                                    "Overrides the \"compatible\" property of the dt root node",
 477                                    NULL);
 478    object_property_add_bool(obj, "dump-guest-core",
 479                             machine_get_dump_guest_core,
 480                             machine_set_dump_guest_core,
 481                             NULL);
 482    object_property_set_description(obj, "dump-guest-core",
 483                                    "Include guest memory in  a core dump",
 484                                    NULL);
 485    object_property_add_bool(obj, "linux",
 486                             machine_get_linux, machine_set_linux, NULL);
 487    object_property_set_description(obj, "linux",
 488                                    "Force a Linux style boot",
 489                                    NULL);
 490    object_property_add_bool(obj, "mem-merge",
 491                             machine_get_mem_merge,
 492                             machine_set_mem_merge, NULL);
 493    object_property_set_description(obj, "mem-merge",
 494                                    "Enable/disable memory merge support",
 495                                    NULL);
 496    object_property_add_bool(obj, "usb",
 497                             machine_get_usb,
 498                             machine_set_usb, NULL);
 499    object_property_set_description(obj, "usb",
 500                                    "Set on/off to enable/disable usb",
 501                                    NULL);
 502    object_property_add_bool(obj, "igd-passthru",
 503                             machine_get_igd_gfx_passthru,
 504                             machine_set_igd_gfx_passthru, NULL);
 505    object_property_set_description(obj, "igd-passthru",
 506                                    "Set on/off to enable/disable igd passthrou",
 507                                    NULL);
 508    object_property_add_str(obj, "firmware",
 509                            machine_get_firmware,
 510                            machine_set_firmware, NULL);
 511    object_property_set_description(obj, "firmware",
 512                                    "Firmware image",
 513                                    NULL);
 514    object_property_add_bool(obj, "iommu",
 515                             machine_get_iommu,
 516                             machine_set_iommu, NULL);
 517    object_property_set_description(obj, "iommu",
 518                                    "Set on/off to enable/disable Intel IOMMU (VT-d)",
 519                                    NULL);
 520    object_property_add_bool(obj, "suppress-vmdesc",
 521                             machine_get_suppress_vmdesc,
 522                             machine_set_suppress_vmdesc, NULL);
 523    object_property_set_description(obj, "suppress-vmdesc",
 524                                    "Set on to disable self-describing migration",
 525                                    NULL);
 526    object_property_add_bool(obj, "enforce-config-section",
 527                             machine_get_enforce_config_section,
 528                             machine_set_enforce_config_section, NULL);
 529    object_property_set_description(obj, "enforce-config-section",
 530                                    "Set on to enforce configuration section migration",
 531                                    NULL);
 532
 533    /* Register notifier when init is done for sysbus sanity checks */
 534    ms->sysbus_notifier.notify = machine_init_notify;
 535    qemu_add_machine_init_done_notifier(&ms->sysbus_notifier);
 536}
 537
 538static void machine_finalize(Object *obj)
 539{
 540    MachineState *ms = MACHINE(obj);
 541
 542    g_free(ms->accel);
 543    g_free(ms->kernel_filename);
 544    g_free(ms->initrd_filename);
 545    g_free(ms->kernel_cmdline);
 546    g_free(ms->dtb);
 547    g_free(ms->dumpdtb);
 548    g_free(ms->dt_compatible);
 549    g_free(ms->firmware);
 550}
 551
 552bool machine_usb(MachineState *machine)
 553{
 554    return machine->usb;
 555}
 556
 557bool machine_kernel_irqchip_allowed(MachineState *machine)
 558{
 559    return machine->kernel_irqchip_allowed;
 560}
 561
 562bool machine_kernel_irqchip_required(MachineState *machine)
 563{
 564    return machine->kernel_irqchip_required;
 565}
 566
 567bool machine_kernel_irqchip_split(MachineState *machine)
 568{
 569    return machine->kernel_irqchip_split;
 570}
 571
 572int machine_kvm_shadow_mem(MachineState *machine)
 573{
 574    return machine->kvm_shadow_mem;
 575}
 576
 577int machine_phandle_start(MachineState *machine)
 578{
 579    return machine->phandle_start;
 580}
 581
 582bool machine_dump_guest_core(MachineState *machine)
 583{
 584    return machine->dump_guest_core;
 585}
 586
 587bool machine_mem_merge(MachineState *machine)
 588{
 589    return machine->mem_merge;
 590}
 591
 592static const TypeInfo machine_info = {
 593    .name = TYPE_MACHINE,
 594    .parent = TYPE_OBJECT,
 595    .abstract = true,
 596    .class_size = sizeof(MachineClass),
 597    .class_init    = machine_class_init,
 598    .class_base_init = machine_class_base_init,
 599    .instance_size = sizeof(MachineState),
 600    .instance_init = machine_initfn,
 601    .instance_finalize = machine_finalize,
 602};
 603
 604static void machine_register_types(void)
 605{
 606    type_register_static(&machine_info);
 607}
 608
 609type_init(machine_register_types)
 610