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 "qemu/option.h"
  15#include "qapi/qmp/qerror.h"
  16#include "sysemu/replay.h"
  17#include "qemu/units.h"
  18#include "hw/boards.h"
  19#include "qapi/error.h"
  20#include "qapi/qapi-visit-common.h"
  21#include "qapi/visitor.h"
  22#include "hw/sysbus.h"
  23#include "sysemu/sysemu.h"
  24#include "sysemu/numa.h"
  25#include "qemu/error-report.h"
  26#include "sysemu/qtest.h"
  27#include "hw/pci/pci.h"
  28#include "hw/mem/nvdimm.h"
  29
  30GlobalProperty hw_compat_4_1[] = {
  31    { "virtio-pci", "x-pcie-flr-init", "off" },
  32};
  33const size_t hw_compat_4_1_len = G_N_ELEMENTS(hw_compat_4_1);
  34
  35GlobalProperty hw_compat_4_0[] = {
  36    { "VGA",            "edid", "false" },
  37    { "secondary-vga",  "edid", "false" },
  38    { "bochs-display",  "edid", "false" },
  39    { "virtio-vga",     "edid", "false" },
  40    { "virtio-gpu-device", "edid", "false" },
  41    { "virtio-device", "use-started", "false" },
  42    { "virtio-balloon-device", "qemu-4-0-config-size", "true" },
  43    { "pl031", "migrate-tick-offset", "false" },
  44};
  45const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
  46
  47GlobalProperty hw_compat_3_1[] = {
  48    { "pcie-root-port", "x-speed", "2_5" },
  49    { "pcie-root-port", "x-width", "1" },
  50    { "memory-backend-file", "x-use-canonical-path-for-ramblock-id", "true" },
  51    { "memory-backend-memfd", "x-use-canonical-path-for-ramblock-id", "true" },
  52    { "tpm-crb", "ppi", "false" },
  53    { "tpm-tis", "ppi", "false" },
  54    { "usb-kbd", "serial", "42" },
  55    { "usb-mouse", "serial", "42" },
  56    { "usb-tablet", "serial", "42" },
  57    { "virtio-blk-device", "discard", "false" },
  58    { "virtio-blk-device", "write-zeroes", "false" },
  59    { "virtio-balloon-device", "qemu-4-0-config-size", "false" },
  60    { "pcie-root-port-base", "disable-acs", "true" }, /* Added in 4.1 */
  61};
  62const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1);
  63
  64GlobalProperty hw_compat_3_0[] = {};
  65const size_t hw_compat_3_0_len = G_N_ELEMENTS(hw_compat_3_0);
  66
  67GlobalProperty hw_compat_2_12[] = {
  68    { "migration", "decompress-error-check", "off" },
  69    { "hda-audio", "use-timer", "false" },
  70    { "cirrus-vga", "global-vmstate", "true" },
  71    { "VGA", "global-vmstate", "true" },
  72    { "vmware-svga", "global-vmstate", "true" },
  73    { "qxl-vga", "global-vmstate", "true" },
  74};
  75const size_t hw_compat_2_12_len = G_N_ELEMENTS(hw_compat_2_12);
  76
  77GlobalProperty hw_compat_2_11[] = {
  78    { "hpet", "hpet-offset-saved", "false" },
  79    { "virtio-blk-pci", "vectors", "2" },
  80    { "vhost-user-blk-pci", "vectors", "2" },
  81    { "e1000", "migrate_tso_props", "off" },
  82};
  83const size_t hw_compat_2_11_len = G_N_ELEMENTS(hw_compat_2_11);
  84
  85GlobalProperty hw_compat_2_10[] = {
  86    { "virtio-mouse-device", "wheel-axis", "false" },
  87    { "virtio-tablet-device", "wheel-axis", "false" },
  88};
  89const size_t hw_compat_2_10_len = G_N_ELEMENTS(hw_compat_2_10);
  90
  91GlobalProperty hw_compat_2_9[] = {
  92    { "pci-bridge", "shpc", "off" },
  93    { "intel-iommu", "pt", "off" },
  94    { "virtio-net-device", "x-mtu-bypass-backend", "off" },
  95    { "pcie-root-port", "x-migrate-msix", "false" },
  96};
  97const size_t hw_compat_2_9_len = G_N_ELEMENTS(hw_compat_2_9);
  98
  99GlobalProperty hw_compat_2_8[] = {
 100    { "fw_cfg_mem", "x-file-slots", "0x10" },
 101    { "fw_cfg_io", "x-file-slots", "0x10" },
 102    { "pflash_cfi01", "old-multiple-chip-handling", "on" },
 103    { "pci-bridge", "shpc", "on" },
 104    { TYPE_PCI_DEVICE, "x-pcie-extcap-init", "off" },
 105    { "virtio-pci", "x-pcie-deverr-init", "off" },
 106    { "virtio-pci", "x-pcie-lnkctl-init", "off" },
 107    { "virtio-pci", "x-pcie-pm-init", "off" },
 108    { "cirrus-vga", "vgamem_mb", "8" },
 109    { "isa-cirrus-vga", "vgamem_mb", "8" },
 110};
 111const size_t hw_compat_2_8_len = G_N_ELEMENTS(hw_compat_2_8);
 112
 113GlobalProperty hw_compat_2_7[] = {
 114    { "virtio-pci", "page-per-vq", "on" },
 115    { "virtio-serial-device", "emergency-write", "off" },
 116    { "ioapic", "version", "0x11" },
 117    { "intel-iommu", "x-buggy-eim", "true" },
 118    { "virtio-pci", "x-ignore-backend-features", "on" },
 119};
 120const size_t hw_compat_2_7_len = G_N_ELEMENTS(hw_compat_2_7);
 121
 122GlobalProperty hw_compat_2_6[] = {
 123    { "virtio-mmio", "format_transport_address", "off" },
 124    /* Optional because not all virtio-pci devices support legacy mode */
 125    { "virtio-pci", "disable-modern", "on",  .optional = true },
 126    { "virtio-pci", "disable-legacy", "off", .optional = true },
 127};
 128const size_t hw_compat_2_6_len = G_N_ELEMENTS(hw_compat_2_6);
 129
 130GlobalProperty hw_compat_2_5[] = {
 131    { "isa-fdc", "fallback", "144" },
 132    { "pvscsi", "x-old-pci-configuration", "on" },
 133    { "pvscsi", "x-disable-pcie", "on" },
 134    { "vmxnet3", "x-old-msi-offsets", "on" },
 135    { "vmxnet3", "x-disable-pcie", "on" },
 136};
 137const size_t hw_compat_2_5_len = G_N_ELEMENTS(hw_compat_2_5);
 138
 139GlobalProperty hw_compat_2_4[] = {
 140    { "virtio-blk-device", "scsi", "true" },
 141    { "e1000", "extra_mac_registers", "off" },
 142    { "virtio-pci", "x-disable-pcie", "on" },
 143    { "virtio-pci", "migrate-extra", "off" },
 144    { "fw_cfg_mem", "dma_enabled", "off" },
 145    { "fw_cfg_io", "dma_enabled", "off" }
 146};
 147const size_t hw_compat_2_4_len = G_N_ELEMENTS(hw_compat_2_4);
 148
 149GlobalProperty hw_compat_2_3[] = {
 150    { "virtio-blk-pci", "any_layout", "off" },
 151    { "virtio-balloon-pci", "any_layout", "off" },
 152    { "virtio-serial-pci", "any_layout", "off" },
 153    { "virtio-9p-pci", "any_layout", "off" },
 154    { "virtio-rng-pci", "any_layout", "off" },
 155    { TYPE_PCI_DEVICE, "x-pcie-lnksta-dllla", "off" },
 156    { "migration", "send-configuration", "off" },
 157    { "migration", "send-section-footer", "off" },
 158    { "migration", "store-global-state", "off" },
 159};
 160const size_t hw_compat_2_3_len = G_N_ELEMENTS(hw_compat_2_3);
 161
 162GlobalProperty hw_compat_2_2[] = {};
 163const size_t hw_compat_2_2_len = G_N_ELEMENTS(hw_compat_2_2);
 164
 165GlobalProperty hw_compat_2_1[] = {
 166    { "intel-hda", "old_msi_addr", "on" },
 167    { "VGA", "qemu-extended-regs", "off" },
 168    { "secondary-vga", "qemu-extended-regs", "off" },
 169    { "virtio-scsi-pci", "any_layout", "off" },
 170    { "usb-mouse", "usb_version", "1" },
 171    { "usb-kbd", "usb_version", "1" },
 172    { "virtio-pci", "virtio-pci-bus-master-bug-migration", "on" },
 173};
 174const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
 175
 176static char *machine_get_accel(Object *obj, Error **errp)
 177{
 178    MachineState *ms = MACHINE(obj);
 179
 180    return g_strdup(ms->accel);
 181}
 182
 183static void machine_set_accel(Object *obj, const char *value, Error **errp)
 184{
 185    MachineState *ms = MACHINE(obj);
 186
 187    g_free(ms->accel);
 188    ms->accel = g_strdup(value);
 189}
 190
 191static void machine_set_kernel_irqchip(Object *obj, Visitor *v,
 192                                       const char *name, void *opaque,
 193                                       Error **errp)
 194{
 195    Error *err = NULL;
 196    MachineState *ms = MACHINE(obj);
 197    OnOffSplit mode;
 198
 199    visit_type_OnOffSplit(v, name, &mode, &err);
 200    if (err) {
 201        error_propagate(errp, err);
 202        return;
 203    } else {
 204        switch (mode) {
 205        case ON_OFF_SPLIT_ON:
 206            ms->kernel_irqchip_allowed = true;
 207            ms->kernel_irqchip_required = true;
 208            ms->kernel_irqchip_split = false;
 209            break;
 210        case ON_OFF_SPLIT_OFF:
 211            ms->kernel_irqchip_allowed = false;
 212            ms->kernel_irqchip_required = false;
 213            ms->kernel_irqchip_split = false;
 214            break;
 215        case ON_OFF_SPLIT_SPLIT:
 216            ms->kernel_irqchip_allowed = true;
 217            ms->kernel_irqchip_required = true;
 218            ms->kernel_irqchip_split = true;
 219            break;
 220        default:
 221            /* The value was checked in visit_type_OnOffSplit() above. If
 222             * we get here, then something is wrong in QEMU.
 223             */
 224            abort();
 225        }
 226    }
 227}
 228
 229static void machine_get_kvm_shadow_mem(Object *obj, Visitor *v,
 230                                       const char *name, void *opaque,
 231                                       Error **errp)
 232{
 233    MachineState *ms = MACHINE(obj);
 234    int64_t value = ms->kvm_shadow_mem;
 235
 236    visit_type_int(v, name, &value, errp);
 237}
 238
 239static void machine_set_kvm_shadow_mem(Object *obj, Visitor *v,
 240                                       const char *name, void *opaque,
 241                                       Error **errp)
 242{
 243    MachineState *ms = MACHINE(obj);
 244    Error *error = NULL;
 245    int64_t value;
 246
 247    visit_type_int(v, name, &value, &error);
 248    if (error) {
 249        error_propagate(errp, error);
 250        return;
 251    }
 252
 253    ms->kvm_shadow_mem = value;
 254}
 255
 256static char *machine_get_kernel(Object *obj, Error **errp)
 257{
 258    MachineState *ms = MACHINE(obj);
 259
 260    return g_strdup(ms->kernel_filename);
 261}
 262
 263static void machine_set_kernel(Object *obj, const char *value, Error **errp)
 264{
 265    MachineState *ms = MACHINE(obj);
 266
 267    g_free(ms->kernel_filename);
 268    ms->kernel_filename = g_strdup(value);
 269}
 270
 271static char *machine_get_initrd(Object *obj, Error **errp)
 272{
 273    MachineState *ms = MACHINE(obj);
 274
 275    return g_strdup(ms->initrd_filename);
 276}
 277
 278static void machine_set_initrd(Object *obj, const char *value, Error **errp)
 279{
 280    MachineState *ms = MACHINE(obj);
 281
 282    g_free(ms->initrd_filename);
 283    ms->initrd_filename = g_strdup(value);
 284}
 285
 286static char *machine_get_append(Object *obj, Error **errp)
 287{
 288    MachineState *ms = MACHINE(obj);
 289
 290    return g_strdup(ms->kernel_cmdline);
 291}
 292
 293static void machine_set_append(Object *obj, const char *value, Error **errp)
 294{
 295    MachineState *ms = MACHINE(obj);
 296
 297    g_free(ms->kernel_cmdline);
 298    ms->kernel_cmdline = g_strdup(value);
 299}
 300
 301static char *machine_get_dtb(Object *obj, Error **errp)
 302{
 303    MachineState *ms = MACHINE(obj);
 304
 305    return g_strdup(ms->dtb);
 306}
 307
 308static void machine_set_dtb(Object *obj, const char *value, Error **errp)
 309{
 310    MachineState *ms = MACHINE(obj);
 311
 312    g_free(ms->dtb);
 313    ms->dtb = g_strdup(value);
 314}
 315
 316static char *machine_get_dumpdtb(Object *obj, Error **errp)
 317{
 318    MachineState *ms = MACHINE(obj);
 319
 320    return g_strdup(ms->dumpdtb);
 321}
 322
 323static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
 324{
 325    MachineState *ms = MACHINE(obj);
 326
 327    g_free(ms->dumpdtb);
 328    ms->dumpdtb = g_strdup(value);
 329}
 330
 331static void machine_get_phandle_start(Object *obj, Visitor *v,
 332                                      const char *name, void *opaque,
 333                                      Error **errp)
 334{
 335    MachineState *ms = MACHINE(obj);
 336    int64_t value = ms->phandle_start;
 337
 338    visit_type_int(v, name, &value, errp);
 339}
 340
 341static void machine_set_phandle_start(Object *obj, Visitor *v,
 342                                      const char *name, void *opaque,
 343                                      Error **errp)
 344{
 345    MachineState *ms = MACHINE(obj);
 346    Error *error = NULL;
 347    int64_t value;
 348
 349    visit_type_int(v, name, &value, &error);
 350    if (error) {
 351        error_propagate(errp, error);
 352        return;
 353    }
 354
 355    ms->phandle_start = value;
 356}
 357
 358static char *machine_get_dt_compatible(Object *obj, Error **errp)
 359{
 360    MachineState *ms = MACHINE(obj);
 361
 362    return g_strdup(ms->dt_compatible);
 363}
 364
 365static void machine_set_dt_compatible(Object *obj, const char *value, Error **errp)
 366{
 367    MachineState *ms = MACHINE(obj);
 368
 369    g_free(ms->dt_compatible);
 370    ms->dt_compatible = g_strdup(value);
 371}
 372
 373static bool machine_get_dump_guest_core(Object *obj, Error **errp)
 374{
 375    MachineState *ms = MACHINE(obj);
 376
 377    return ms->dump_guest_core;
 378}
 379
 380static void machine_set_dump_guest_core(Object *obj, bool value, Error **errp)
 381{
 382    MachineState *ms = MACHINE(obj);
 383
 384    ms->dump_guest_core = value;
 385}
 386
 387static bool machine_get_mem_merge(Object *obj, Error **errp)
 388{
 389    MachineState *ms = MACHINE(obj);
 390
 391    return ms->mem_merge;
 392}
 393
 394static void machine_set_mem_merge(Object *obj, bool value, Error **errp)
 395{
 396    MachineState *ms = MACHINE(obj);
 397
 398    ms->mem_merge = value;
 399}
 400
 401static bool machine_get_usb(Object *obj, Error **errp)
 402{
 403    MachineState *ms = MACHINE(obj);
 404
 405    return ms->usb;
 406}
 407
 408static void machine_set_usb(Object *obj, bool value, Error **errp)
 409{
 410    MachineState *ms = MACHINE(obj);
 411
 412    ms->usb = value;
 413    ms->usb_disabled = !value;
 414}
 415
 416static bool machine_get_graphics(Object *obj, Error **errp)
 417{
 418    MachineState *ms = MACHINE(obj);
 419
 420    return ms->enable_graphics;
 421}
 422
 423static void machine_set_graphics(Object *obj, bool value, Error **errp)
 424{
 425    MachineState *ms = MACHINE(obj);
 426
 427    ms->enable_graphics = value;
 428}
 429
 430static bool machine_get_igd_gfx_passthru(Object *obj, Error **errp)
 431{
 432    MachineState *ms = MACHINE(obj);
 433
 434    return ms->igd_gfx_passthru;
 435}
 436
 437static void machine_set_igd_gfx_passthru(Object *obj, bool value, Error **errp)
 438{
 439    MachineState *ms = MACHINE(obj);
 440
 441    ms->igd_gfx_passthru = value;
 442}
 443
 444static char *machine_get_firmware(Object *obj, Error **errp)
 445{
 446    MachineState *ms = MACHINE(obj);
 447
 448    return g_strdup(ms->firmware);
 449}
 450
 451static void machine_set_firmware(Object *obj, const char *value, Error **errp)
 452{
 453    MachineState *ms = MACHINE(obj);
 454
 455    g_free(ms->firmware);
 456    ms->firmware = g_strdup(value);
 457}
 458
 459static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
 460{
 461    MachineState *ms = MACHINE(obj);
 462
 463    ms->suppress_vmdesc = value;
 464}
 465
 466static bool machine_get_suppress_vmdesc(Object *obj, Error **errp)
 467{
 468    MachineState *ms = MACHINE(obj);
 469
 470    return ms->suppress_vmdesc;
 471}
 472
 473static void machine_set_enforce_config_section(Object *obj, bool value,
 474                                             Error **errp)
 475{
 476    MachineState *ms = MACHINE(obj);
 477
 478    warn_report("enforce-config-section is deprecated, please use "
 479                "-global migration.send-configuration=on|off instead");
 480
 481    ms->enforce_config_section = value;
 482}
 483
 484static bool machine_get_enforce_config_section(Object *obj, Error **errp)
 485{
 486    MachineState *ms = MACHINE(obj);
 487
 488    return ms->enforce_config_section;
 489}
 490
 491static char *machine_get_memory_encryption(Object *obj, Error **errp)
 492{
 493    MachineState *ms = MACHINE(obj);
 494
 495    return g_strdup(ms->memory_encryption);
 496}
 497
 498static void machine_set_memory_encryption(Object *obj, const char *value,
 499                                        Error **errp)
 500{
 501    MachineState *ms = MACHINE(obj);
 502
 503    g_free(ms->memory_encryption);
 504    ms->memory_encryption = g_strdup(value);
 505}
 506
 507static bool machine_get_nvdimm(Object *obj, Error **errp)
 508{
 509    MachineState *ms = MACHINE(obj);
 510
 511    return ms->nvdimms_state->is_enabled;
 512}
 513
 514static void machine_set_nvdimm(Object *obj, bool value, Error **errp)
 515{
 516    MachineState *ms = MACHINE(obj);
 517
 518    ms->nvdimms_state->is_enabled = value;
 519}
 520
 521static char *machine_get_nvdimm_persistence(Object *obj, Error **errp)
 522{
 523    MachineState *ms = MACHINE(obj);
 524
 525    return g_strdup(ms->nvdimms_state->persistence_string);
 526}
 527
 528static void machine_set_nvdimm_persistence(Object *obj, const char *value,
 529                                           Error **errp)
 530{
 531    MachineState *ms = MACHINE(obj);
 532    NVDIMMState *nvdimms_state = ms->nvdimms_state;
 533
 534    if (strcmp(value, "cpu") == 0) {
 535        nvdimms_state->persistence = 3;
 536    } else if (strcmp(value, "mem-ctrl") == 0) {
 537        nvdimms_state->persistence = 2;
 538    } else {
 539        error_setg(errp, "-machine nvdimm-persistence=%s: unsupported option",
 540                   value);
 541        return;
 542    }
 543
 544    g_free(nvdimms_state->persistence_string);
 545    nvdimms_state->persistence_string = g_strdup(value);
 546}
 547
 548void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type)
 549{
 550    strList *item = g_new0(strList, 1);
 551
 552    item->value = g_strdup(type);
 553    item->next = mc->allowed_dynamic_sysbus_devices;
 554    mc->allowed_dynamic_sysbus_devices = item;
 555}
 556
 557static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque)
 558{
 559    MachineState *machine = opaque;
 560    MachineClass *mc = MACHINE_GET_CLASS(machine);
 561    bool allowed = false;
 562    strList *wl;
 563
 564    for (wl = mc->allowed_dynamic_sysbus_devices;
 565         !allowed && wl;
 566         wl = wl->next) {
 567        allowed |= !!object_dynamic_cast(OBJECT(sbdev), wl->value);
 568    }
 569
 570    if (!allowed) {
 571        error_report("Option '-device %s' cannot be handled by this machine",
 572                     object_class_get_name(object_get_class(OBJECT(sbdev))));
 573        exit(1);
 574    }
 575}
 576
 577static void machine_init_notify(Notifier *notifier, void *data)
 578{
 579    MachineState *machine = MACHINE(qdev_get_machine());
 580
 581    /*
 582     * Loop through all dynamically created sysbus devices and check if they are
 583     * all allowed.  If a device is not allowed, error out.
 584     */
 585    foreach_dynamic_sysbus_device(validate_sysbus_device, machine);
 586}
 587
 588HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
 589{
 590    int i;
 591    HotpluggableCPUList *head = NULL;
 592    MachineClass *mc = MACHINE_GET_CLASS(machine);
 593
 594    /* force board to initialize possible_cpus if it hasn't been done yet */
 595    mc->possible_cpu_arch_ids(machine);
 596
 597    for (i = 0; i < machine->possible_cpus->len; i++) {
 598        Object *cpu;
 599        HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
 600        HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
 601
 602        cpu_item->type = g_strdup(machine->possible_cpus->cpus[i].type);
 603        cpu_item->vcpus_count = machine->possible_cpus->cpus[i].vcpus_count;
 604        cpu_item->props = g_memdup(&machine->possible_cpus->cpus[i].props,
 605                                   sizeof(*cpu_item->props));
 606
 607        cpu = machine->possible_cpus->cpus[i].cpu;
 608        if (cpu) {
 609            cpu_item->has_qom_path = true;
 610            cpu_item->qom_path = object_get_canonical_path(cpu);
 611        }
 612        list_item->value = cpu_item;
 613        list_item->next = head;
 614        head = list_item;
 615    }
 616    return head;
 617}
 618
 619/**
 620 * machine_set_cpu_numa_node:
 621 * @machine: machine object to modify
 622 * @props: specifies which cpu objects to assign to
 623 *         numa node specified by @props.node_id
 624 * @errp: if an error occurs, a pointer to an area to store the error
 625 *
 626 * Associate NUMA node specified by @props.node_id with cpu slots that
 627 * match socket/core/thread-ids specified by @props. It's recommended to use
 628 * query-hotpluggable-cpus.props values to specify affected cpu slots,
 629 * which would lead to exact 1:1 mapping of cpu slots to NUMA node.
 630 *
 631 * However for CLI convenience it's possible to pass in subset of properties,
 632 * which would affect all cpu slots that match it.
 633 * Ex for pc machine:
 634 *    -smp 4,cores=2,sockets=2 -numa node,nodeid=0 -numa node,nodeid=1 \
 635 *    -numa cpu,node-id=0,socket_id=0 \
 636 *    -numa cpu,node-id=1,socket_id=1
 637 * will assign all child cores of socket 0 to node 0 and
 638 * of socket 1 to node 1.
 639 *
 640 * On attempt of reassigning (already assigned) cpu slot to another NUMA node,
 641 * return error.
 642 * Empty subset is disallowed and function will return with error in this case.
 643 */
 644void machine_set_cpu_numa_node(MachineState *machine,
 645                               const CpuInstanceProperties *props, Error **errp)
 646{
 647    MachineClass *mc = MACHINE_GET_CLASS(machine);
 648    bool match = false;
 649    int i;
 650
 651    if (!mc->possible_cpu_arch_ids) {
 652        error_setg(errp, "mapping of CPUs to NUMA node is not supported");
 653        return;
 654    }
 655
 656    /* disabling node mapping is not supported, forbid it */
 657    assert(props->has_node_id);
 658
 659    /* force board to initialize possible_cpus if it hasn't been done yet */
 660    mc->possible_cpu_arch_ids(machine);
 661
 662    for (i = 0; i < machine->possible_cpus->len; i++) {
 663        CPUArchId *slot = &machine->possible_cpus->cpus[i];
 664
 665        /* reject unsupported by board properties */
 666        if (props->has_thread_id && !slot->props.has_thread_id) {
 667            error_setg(errp, "thread-id is not supported");
 668            return;
 669        }
 670
 671        if (props->has_core_id && !slot->props.has_core_id) {
 672            error_setg(errp, "core-id is not supported");
 673            return;
 674        }
 675
 676        if (props->has_socket_id && !slot->props.has_socket_id) {
 677            error_setg(errp, "socket-id is not supported");
 678            return;
 679        }
 680
 681        if (props->has_die_id && !slot->props.has_die_id) {
 682            error_setg(errp, "die-id is not supported");
 683            return;
 684        }
 685
 686        /* skip slots with explicit mismatch */
 687        if (props->has_thread_id && props->thread_id != slot->props.thread_id) {
 688                continue;
 689        }
 690
 691        if (props->has_core_id && props->core_id != slot->props.core_id) {
 692                continue;
 693        }
 694
 695        if (props->has_die_id && props->die_id != slot->props.die_id) {
 696                continue;
 697        }
 698
 699        if (props->has_socket_id && props->socket_id != slot->props.socket_id) {
 700                continue;
 701        }
 702
 703        /* reject assignment if slot is already assigned, for compatibility
 704         * of legacy cpu_index mapping with SPAPR core based mapping do not
 705         * error out if cpu thread and matched core have the same node-id */
 706        if (slot->props.has_node_id &&
 707            slot->props.node_id != props->node_id) {
 708            error_setg(errp, "CPU is already assigned to node-id: %" PRId64,
 709                       slot->props.node_id);
 710            return;
 711        }
 712
 713        /* assign slot to node as it's matched '-numa cpu' key */
 714        match = true;
 715        slot->props.node_id = props->node_id;
 716        slot->props.has_node_id = props->has_node_id;
 717    }
 718
 719    if (!match) {
 720        error_setg(errp, "no match found");
 721    }
 722}
 723
 724static void smp_parse(MachineState *ms, QemuOpts *opts)
 725{
 726    if (opts) {
 727        unsigned cpus    = qemu_opt_get_number(opts, "cpus", 0);
 728        unsigned sockets = qemu_opt_get_number(opts, "sockets", 0);
 729        unsigned cores   = qemu_opt_get_number(opts, "cores", 0);
 730        unsigned threads = qemu_opt_get_number(opts, "threads", 0);
 731
 732        /* compute missing values, prefer sockets over cores over threads */
 733        if (cpus == 0 || sockets == 0) {
 734            cores = cores > 0 ? cores : 1;
 735            threads = threads > 0 ? threads : 1;
 736            if (cpus == 0) {
 737                sockets = sockets > 0 ? sockets : 1;
 738                cpus = cores * threads * sockets;
 739            } else {
 740                ms->smp.max_cpus =
 741                        qemu_opt_get_number(opts, "maxcpus", cpus);
 742                sockets = ms->smp.max_cpus / (cores * threads);
 743            }
 744        } else if (cores == 0) {
 745            threads = threads > 0 ? threads : 1;
 746            cores = cpus / (sockets * threads);
 747            cores = cores > 0 ? cores : 1;
 748        } else if (threads == 0) {
 749            threads = cpus / (cores * sockets);
 750            threads = threads > 0 ? threads : 1;
 751        } else if (sockets * cores * threads < cpus) {
 752            error_report("cpu topology: "
 753                         "sockets (%u) * cores (%u) * threads (%u) < "
 754                         "smp_cpus (%u)",
 755                         sockets, cores, threads, cpus);
 756            exit(1);
 757        }
 758
 759        ms->smp.max_cpus =
 760                qemu_opt_get_number(opts, "maxcpus", cpus);
 761
 762        if (ms->smp.max_cpus < cpus) {
 763            error_report("maxcpus must be equal to or greater than smp");
 764            exit(1);
 765        }
 766
 767        if (sockets * cores * threads > ms->smp.max_cpus) {
 768            error_report("cpu topology: "
 769                         "sockets (%u) * cores (%u) * threads (%u) > "
 770                         "maxcpus (%u)",
 771                         sockets, cores, threads,
 772                         ms->smp.max_cpus);
 773            exit(1);
 774        }
 775
 776        if (sockets * cores * threads != ms->smp.max_cpus) {
 777            warn_report("Invalid CPU topology deprecated: "
 778                        "sockets (%u) * cores (%u) * threads (%u) "
 779                        "!= maxcpus (%u)",
 780                        sockets, cores, threads,
 781                        ms->smp.max_cpus);
 782        }
 783
 784        ms->smp.cpus = cpus;
 785        ms->smp.cores = cores;
 786        ms->smp.threads = threads;
 787    }
 788
 789    if (ms->smp.cpus > 1) {
 790        Error *blocker = NULL;
 791        error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp");
 792        replay_add_blocker(blocker);
 793    }
 794}
 795
 796static void machine_class_init(ObjectClass *oc, void *data)
 797{
 798    MachineClass *mc = MACHINE_CLASS(oc);
 799
 800    /* Default 128 MB as guest ram size */
 801    mc->default_ram_size = 128 * MiB;
 802    mc->rom_file_has_mr = true;
 803    mc->smp_parse = smp_parse;
 804
 805    /* numa node memory size aligned on 8MB by default.
 806     * On Linux, each node's border has to be 8MB aligned
 807     */
 808    mc->numa_mem_align_shift = 23;
 809    mc->numa_auto_assign_ram = numa_default_auto_assign_ram;
 810
 811    object_class_property_add_str(oc, "accel",
 812        machine_get_accel, machine_set_accel, &error_abort);
 813    object_class_property_set_description(oc, "accel",
 814        "Accelerator list", &error_abort);
 815
 816    object_class_property_add(oc, "kernel-irqchip", "on|off|split",
 817        NULL, machine_set_kernel_irqchip,
 818        NULL, NULL, &error_abort);
 819    object_class_property_set_description(oc, "kernel-irqchip",
 820        "Configure KVM in-kernel irqchip", &error_abort);
 821
 822    object_class_property_add(oc, "kvm-shadow-mem", "int",
 823        machine_get_kvm_shadow_mem, machine_set_kvm_shadow_mem,
 824        NULL, NULL, &error_abort);
 825    object_class_property_set_description(oc, "kvm-shadow-mem",
 826        "KVM shadow MMU size", &error_abort);
 827
 828    object_class_property_add_str(oc, "kernel",
 829        machine_get_kernel, machine_set_kernel, &error_abort);
 830    object_class_property_set_description(oc, "kernel",
 831        "Linux kernel image file", &error_abort);
 832
 833    object_class_property_add_str(oc, "initrd",
 834        machine_get_initrd, machine_set_initrd, &error_abort);
 835    object_class_property_set_description(oc, "initrd",
 836        "Linux initial ramdisk file", &error_abort);
 837
 838    object_class_property_add_str(oc, "append",
 839        machine_get_append, machine_set_append, &error_abort);
 840    object_class_property_set_description(oc, "append",
 841        "Linux kernel command line", &error_abort);
 842
 843    object_class_property_add_str(oc, "dtb",
 844        machine_get_dtb, machine_set_dtb, &error_abort);
 845    object_class_property_set_description(oc, "dtb",
 846        "Linux kernel device tree file", &error_abort);
 847
 848    object_class_property_add_str(oc, "dumpdtb",
 849        machine_get_dumpdtb, machine_set_dumpdtb, &error_abort);
 850    object_class_property_set_description(oc, "dumpdtb",
 851        "Dump current dtb to a file and quit", &error_abort);
 852
 853    object_class_property_add(oc, "phandle-start", "int",
 854        machine_get_phandle_start, machine_set_phandle_start,
 855        NULL, NULL, &error_abort);
 856    object_class_property_set_description(oc, "phandle-start",
 857            "The first phandle ID we may generate dynamically", &error_abort);
 858
 859    object_class_property_add_str(oc, "dt-compatible",
 860        machine_get_dt_compatible, machine_set_dt_compatible, &error_abort);
 861    object_class_property_set_description(oc, "dt-compatible",
 862        "Overrides the \"compatible\" property of the dt root node",
 863        &error_abort);
 864
 865    object_class_property_add_bool(oc, "dump-guest-core",
 866        machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort);
 867    object_class_property_set_description(oc, "dump-guest-core",
 868        "Include guest memory in a core dump", &error_abort);
 869
 870    object_class_property_add_bool(oc, "mem-merge",
 871        machine_get_mem_merge, machine_set_mem_merge, &error_abort);
 872    object_class_property_set_description(oc, "mem-merge",
 873        "Enable/disable memory merge support", &error_abort);
 874
 875    object_class_property_add_bool(oc, "usb",
 876        machine_get_usb, machine_set_usb, &error_abort);
 877    object_class_property_set_description(oc, "usb",
 878        "Set on/off to enable/disable usb", &error_abort);
 879
 880    object_class_property_add_bool(oc, "graphics",
 881        machine_get_graphics, machine_set_graphics, &error_abort);
 882    object_class_property_set_description(oc, "graphics",
 883        "Set on/off to enable/disable graphics emulation", &error_abort);
 884
 885    object_class_property_add_bool(oc, "igd-passthru",
 886        machine_get_igd_gfx_passthru, machine_set_igd_gfx_passthru,
 887        &error_abort);
 888    object_class_property_set_description(oc, "igd-passthru",
 889        "Set on/off to enable/disable igd passthrou", &error_abort);
 890
 891    object_class_property_add_str(oc, "firmware",
 892        machine_get_firmware, machine_set_firmware,
 893        &error_abort);
 894    object_class_property_set_description(oc, "firmware",
 895        "Firmware image", &error_abort);
 896
 897    object_class_property_add_bool(oc, "suppress-vmdesc",
 898        machine_get_suppress_vmdesc, machine_set_suppress_vmdesc,
 899        &error_abort);
 900    object_class_property_set_description(oc, "suppress-vmdesc",
 901        "Set on to disable self-describing migration", &error_abort);
 902
 903    object_class_property_add_bool(oc, "enforce-config-section",
 904        machine_get_enforce_config_section, machine_set_enforce_config_section,
 905        &error_abort);
 906    object_class_property_set_description(oc, "enforce-config-section",
 907        "Set on to enforce configuration section migration", &error_abort);
 908
 909    object_class_property_add_str(oc, "memory-encryption",
 910        machine_get_memory_encryption, machine_set_memory_encryption,
 911        &error_abort);
 912    object_class_property_set_description(oc, "memory-encryption",
 913        "Set memory encryption object to use", &error_abort);
 914}
 915
 916static void machine_class_base_init(ObjectClass *oc, void *data)
 917{
 918    if (!object_class_is_abstract(oc)) {
 919        MachineClass *mc = MACHINE_CLASS(oc);
 920        const char *cname = object_class_get_name(oc);
 921        assert(g_str_has_suffix(cname, TYPE_MACHINE_SUFFIX));
 922        mc->name = g_strndup(cname,
 923                            strlen(cname) - strlen(TYPE_MACHINE_SUFFIX));
 924        mc->compat_props = g_ptr_array_new();
 925    }
 926}
 927
 928static void machine_initfn(Object *obj)
 929{
 930    MachineState *ms = MACHINE(obj);
 931    MachineClass *mc = MACHINE_GET_CLASS(obj);
 932
 933    ms->kernel_irqchip_allowed = true;
 934    ms->kernel_irqchip_split = mc->default_kernel_irqchip_split;
 935    ms->kvm_shadow_mem = -1;
 936    ms->dump_guest_core = true;
 937    ms->mem_merge = true;
 938    ms->enable_graphics = true;
 939
 940    if (mc->nvdimm_supported) {
 941        Object *obj = OBJECT(ms);
 942
 943        ms->nvdimms_state = g_new0(NVDIMMState, 1);
 944        object_property_add_bool(obj, "nvdimm",
 945                                 machine_get_nvdimm, machine_set_nvdimm,
 946                                 &error_abort);
 947        object_property_set_description(obj, "nvdimm",
 948                                        "Set on/off to enable/disable "
 949                                        "NVDIMM instantiation", NULL);
 950
 951        object_property_add_str(obj, "nvdimm-persistence",
 952                                machine_get_nvdimm_persistence,
 953                                machine_set_nvdimm_persistence,
 954                                &error_abort);
 955        object_property_set_description(obj, "nvdimm-persistence",
 956                                        "Set NVDIMM persistence"
 957                                        "Valid values are cpu, mem-ctrl",
 958                                        NULL);
 959    }
 960
 961    if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) {
 962        ms->numa_state = g_new0(NumaState, 1);
 963    }
 964
 965    /* Register notifier when init is done for sysbus sanity checks */
 966    ms->sysbus_notifier.notify = machine_init_notify;
 967    qemu_add_machine_init_done_notifier(&ms->sysbus_notifier);
 968}
 969
 970static void machine_finalize(Object *obj)
 971{
 972    MachineState *ms = MACHINE(obj);
 973
 974    g_free(ms->accel);
 975    g_free(ms->kernel_filename);
 976    g_free(ms->initrd_filename);
 977    g_free(ms->kernel_cmdline);
 978    g_free(ms->dtb);
 979    g_free(ms->dumpdtb);
 980    g_free(ms->dt_compatible);
 981    g_free(ms->firmware);
 982    g_free(ms->device_memory);
 983    g_free(ms->nvdimms_state);
 984    g_free(ms->numa_state);
 985}
 986
 987bool machine_usb(MachineState *machine)
 988{
 989    return machine->usb;
 990}
 991
 992bool machine_kernel_irqchip_allowed(MachineState *machine)
 993{
 994    return machine->kernel_irqchip_allowed;
 995}
 996
 997bool machine_kernel_irqchip_required(MachineState *machine)
 998{
 999    return machine->kernel_irqchip_required;
1000}
1001
1002bool machine_kernel_irqchip_split(MachineState *machine)
1003{
1004    return machine->kernel_irqchip_split;
1005}
1006
1007int machine_kvm_shadow_mem(MachineState *machine)
1008{
1009    return machine->kvm_shadow_mem;
1010}
1011
1012int machine_phandle_start(MachineState *machine)
1013{
1014    return machine->phandle_start;
1015}
1016
1017bool machine_dump_guest_core(MachineState *machine)
1018{
1019    return machine->dump_guest_core;
1020}
1021
1022bool machine_mem_merge(MachineState *machine)
1023{
1024    return machine->mem_merge;
1025}
1026
1027static char *cpu_slot_to_string(const CPUArchId *cpu)
1028{
1029    GString *s = g_string_new(NULL);
1030    if (cpu->props.has_socket_id) {
1031        g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id);
1032    }
1033    if (cpu->props.has_die_id) {
1034        g_string_append_printf(s, "die-id: %"PRId64, cpu->props.die_id);
1035    }
1036    if (cpu->props.has_core_id) {
1037        if (s->len) {
1038            g_string_append_printf(s, ", ");
1039        }
1040        g_string_append_printf(s, "core-id: %"PRId64, cpu->props.core_id);
1041    }
1042    if (cpu->props.has_thread_id) {
1043        if (s->len) {
1044            g_string_append_printf(s, ", ");
1045        }
1046        g_string_append_printf(s, "thread-id: %"PRId64, cpu->props.thread_id);
1047    }
1048    return g_string_free(s, false);
1049}
1050
1051static void machine_numa_finish_cpu_init(MachineState *machine)
1052{
1053    int i;
1054    bool default_mapping;
1055    GString *s = g_string_new(NULL);
1056    MachineClass *mc = MACHINE_GET_CLASS(machine);
1057    const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(machine);
1058
1059    assert(machine->numa_state->num_nodes);
1060    for (i = 0; i < possible_cpus->len; i++) {
1061        if (possible_cpus->cpus[i].props.has_node_id) {
1062            break;
1063        }
1064    }
1065    default_mapping = (i == possible_cpus->len);
1066
1067    for (i = 0; i < possible_cpus->len; i++) {
1068        const CPUArchId *cpu_slot = &possible_cpus->cpus[i];
1069
1070        if (!cpu_slot->props.has_node_id) {
1071            /* fetch default mapping from board and enable it */
1072            CpuInstanceProperties props = cpu_slot->props;
1073
1074            props.node_id = mc->get_default_cpu_node_id(machine, i);
1075            if (!default_mapping) {
1076                /* record slots with not set mapping,
1077                 * TODO: make it hard error in future */
1078                char *cpu_str = cpu_slot_to_string(cpu_slot);
1079                g_string_append_printf(s, "%sCPU %d [%s]",
1080                                       s->len ? ", " : "", i, cpu_str);
1081                g_free(cpu_str);
1082
1083                /* non mapped cpus used to fallback to node 0 */
1084                props.node_id = 0;
1085            }
1086
1087            props.has_node_id = true;
1088            machine_set_cpu_numa_node(machine, &props, &error_fatal);
1089        }
1090    }
1091    if (s->len && !qtest_enabled()) {
1092        warn_report("CPU(s) not present in any NUMA nodes: %s",
1093                    s->str);
1094        warn_report("All CPU(s) up to maxcpus should be described "
1095                    "in NUMA config, ability to start up with partial NUMA "
1096                    "mappings is obsoleted and will be removed in future");
1097    }
1098    g_string_free(s, true);
1099}
1100
1101void machine_run_board_init(MachineState *machine)
1102{
1103    MachineClass *machine_class = MACHINE_GET_CLASS(machine);
1104
1105    if (machine->numa_state) {
1106        numa_complete_configuration(machine);
1107        if (machine->numa_state->num_nodes) {
1108            machine_numa_finish_cpu_init(machine);
1109        }
1110    }
1111
1112    /* If the machine supports the valid_cpu_types check and the user
1113     * specified a CPU with -cpu check here that the user CPU is supported.
1114     */
1115    if (machine_class->valid_cpu_types && machine->cpu_type) {
1116        ObjectClass *class = object_class_by_name(machine->cpu_type);
1117        int i;
1118
1119        for (i = 0; machine_class->valid_cpu_types[i]; i++) {
1120            if (object_class_dynamic_cast(class,
1121                                          machine_class->valid_cpu_types[i])) {
1122                /* The user specificed CPU is in the valid field, we are
1123                 * good to go.
1124                 */
1125                break;
1126            }
1127        }
1128
1129        if (!machine_class->valid_cpu_types[i]) {
1130            /* The user specified CPU is not valid */
1131            error_report("Invalid CPU type: %s", machine->cpu_type);
1132            error_printf("The valid types are: %s",
1133                         machine_class->valid_cpu_types[0]);
1134            for (i = 1; machine_class->valid_cpu_types[i]; i++) {
1135                error_printf(", %s", machine_class->valid_cpu_types[i]);
1136            }
1137            error_printf("\n");
1138
1139            exit(1);
1140        }
1141    }
1142
1143    machine_class->init(machine);
1144}
1145
1146static const TypeInfo machine_info = {
1147    .name = TYPE_MACHINE,
1148    .parent = TYPE_OBJECT,
1149    .abstract = true,
1150    .class_size = sizeof(MachineClass),
1151    .class_init    = machine_class_init,
1152    .class_base_init = machine_class_base_init,
1153    .instance_size = sizeof(MachineState),
1154    .instance_init = machine_initfn,
1155    .instance_finalize = machine_finalize,
1156};
1157
1158static void machine_register_types(void)
1159{
1160    type_register_static(&machine_info);
1161}
1162
1163type_init(machine_register_types)
1164