]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/core/machine.c
machine: Refactor smp_parse() in vl.c as MachineClass::smp_parse()
[mirror_qemu.git] / hw / core / machine.c
index f8563efb8637aadcb706ea6ddb0eae39d9597070..2be19ec0cd5f9dcc19eebd8f83db9804cb0dcad5 100644 (file)
@@ -11,6 +11,9 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/option.h"
+#include "qapi/qmp/qerror.h"
+#include "sysemu/replay.h"
 #include "qemu/units.h"
 #include "hw/boards.h"
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "sysemu/qtest.h"
 #include "hw/pci/pci.h"
+#include "hw/mem/nvdimm.h"
+
+GlobalProperty hw_compat_4_0[] = {
+    { "VGA",            "edid", "false" },
+    { "secondary-vga",  "edid", "false" },
+    { "bochs-display",  "edid", "false" },
+    { "virtio-vga",     "edid", "false" },
+    { "virtio-gpu-pci", "edid", "false" },
+    { "virtio-device", "use-started", "false" },
+};
+const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
 
 GlobalProperty hw_compat_3_1[] = {
-    {
-        .driver   = "pcie-root-port",
-        .property = "x-speed",
-        .value    = "2_5",
-    },{
-        .driver   = "pcie-root-port",
-        .property = "x-width",
-        .value    = "1",
-    },{
-        .driver   = "memory-backend-file",
-        .property = "x-use-canonical-path-for-ramblock-id",
-        .value    = "true",
-    },{
-        .driver   = "memory-backend-memfd",
-        .property = "x-use-canonical-path-for-ramblock-id",
-        .value    = "true",
-    },
+    { "pcie-root-port", "x-speed", "2_5" },
+    { "pcie-root-port", "x-width", "1" },
+    { "memory-backend-file", "x-use-canonical-path-for-ramblock-id", "true" },
+    { "memory-backend-memfd", "x-use-canonical-path-for-ramblock-id", "true" },
+    { "tpm-crb", "ppi", "false" },
+    { "tpm-tis", "ppi", "false" },
+    { "usb-kbd", "serial", "42" },
+    { "usb-mouse", "serial", "42" },
+    { "usb-tablet", "serial", "42" },
+    { "virtio-blk-device", "discard", "false" },
+    { "virtio-blk-device", "write-zeroes", "false" },
 };
 const size_t hw_compat_3_1_len = G_N_ELEMENTS(hw_compat_3_1);
 
@@ -48,269 +56,114 @@ GlobalProperty hw_compat_3_0[] = {};
 const size_t hw_compat_3_0_len = G_N_ELEMENTS(hw_compat_3_0);
 
 GlobalProperty hw_compat_2_12[] = {
-    {
-        .driver   = "migration",
-        .property = "decompress-error-check",
-        .value    = "off",
-    },{
-        .driver   = "hda-audio",
-        .property = "use-timer",
-        .value    = "false",
-    },{
-        .driver   = "cirrus-vga",
-        .property = "global-vmstate",
-        .value    = "true",
-    },{
-        .driver   = "VGA",
-        .property = "global-vmstate",
-        .value    = "true",
-    },{
-        .driver   = "vmware-svga",
-        .property = "global-vmstate",
-        .value    = "true",
-    },{
-        .driver   = "qxl-vga",
-        .property = "global-vmstate",
-        .value    = "true",
-    },
+    { "migration", "decompress-error-check", "off" },
+    { "hda-audio", "use-timer", "false" },
+    { "cirrus-vga", "global-vmstate", "true" },
+    { "VGA", "global-vmstate", "true" },
+    { "vmware-svga", "global-vmstate", "true" },
+    { "qxl-vga", "global-vmstate", "true" },
 };
 const size_t hw_compat_2_12_len = G_N_ELEMENTS(hw_compat_2_12);
 
 GlobalProperty hw_compat_2_11[] = {
-    {
-        .driver   = "hpet",
-        .property = "hpet-offset-saved",
-        .value    = "false",
-    },{
-        .driver   = "virtio-blk-pci",
-        .property = "vectors",
-        .value    = "2",
-    },{
-        .driver   = "vhost-user-blk-pci",
-        .property = "vectors",
-        .value    = "2",
-    },{
-        .driver   = "e1000",
-        .property = "migrate_tso_props",
-        .value    = "off",
-    },
+    { "hpet", "hpet-offset-saved", "false" },
+    { "virtio-blk-pci", "vectors", "2" },
+    { "vhost-user-blk-pci", "vectors", "2" },
+    { "e1000", "migrate_tso_props", "off" },
 };
 const size_t hw_compat_2_11_len = G_N_ELEMENTS(hw_compat_2_11);
 
 GlobalProperty hw_compat_2_10[] = {
-    {
-        .driver   = "virtio-mouse-device",
-        .property = "wheel-axis",
-        .value    = "false",
-    },{
-        .driver   = "virtio-tablet-device",
-        .property = "wheel-axis",
-        .value    = "false",
-    },
+    { "virtio-mouse-device", "wheel-axis", "false" },
+    { "virtio-tablet-device", "wheel-axis", "false" },
 };
 const size_t hw_compat_2_10_len = G_N_ELEMENTS(hw_compat_2_10);
 
 GlobalProperty hw_compat_2_9[] = {
-    {
-        .driver   = "pci-bridge",
-        .property = "shpc",
-        .value    = "off",
-    },{
-        .driver   = "intel-iommu",
-        .property = "pt",
-        .value    = "off",
-    },{
-        .driver   = "virtio-net-device",
-        .property = "x-mtu-bypass-backend",
-        .value    = "off",
-    },{
-        .driver   = "pcie-root-port",
-        .property = "x-migrate-msix",
-        .value    = "false",
-    },
+    { "pci-bridge", "shpc", "off" },
+    { "intel-iommu", "pt", "off" },
+    { "virtio-net-device", "x-mtu-bypass-backend", "off" },
+    { "pcie-root-port", "x-migrate-msix", "false" },
 };
 const size_t hw_compat_2_9_len = G_N_ELEMENTS(hw_compat_2_9);
 
 GlobalProperty hw_compat_2_8[] = {
-    {
-        .driver   = "fw_cfg_mem",
-        .property = "x-file-slots",
-        .value    = stringify(0x10),
-    },{
-        .driver   = "fw_cfg_io",
-        .property = "x-file-slots",
-        .value    = stringify(0x10),
-    },{
-        .driver   = "pflash_cfi01",
-        .property = "old-multiple-chip-handling",
-        .value    = "on",
-    },{
-        .driver   = "pci-bridge",
-        .property = "shpc",
-        .value    = "on",
-    },{
-        .driver   = TYPE_PCI_DEVICE,
-        .property = "x-pcie-extcap-init",
-        .value    = "off",
-    },{
-        .driver   = "virtio-pci",
-        .property = "x-pcie-deverr-init",
-        .value    = "off",
-    },{
-        .driver   = "virtio-pci",
-        .property = "x-pcie-lnkctl-init",
-        .value    = "off",
-    },{
-        .driver   = "virtio-pci",
-        .property = "x-pcie-pm-init",
-        .value    = "off",
-    },{
-        .driver   = "cirrus-vga",
-        .property = "vgamem_mb",
-        .value    = "8",
-    },{
-        .driver   = "isa-cirrus-vga",
-        .property = "vgamem_mb",
-        .value    = "8",
-    },
+    { "fw_cfg_mem", "x-file-slots", "0x10" },
+    { "fw_cfg_io", "x-file-slots", "0x10" },
+    { "pflash_cfi01", "old-multiple-chip-handling", "on" },
+    { "pci-bridge", "shpc", "on" },
+    { TYPE_PCI_DEVICE, "x-pcie-extcap-init", "off" },
+    { "virtio-pci", "x-pcie-deverr-init", "off" },
+    { "virtio-pci", "x-pcie-lnkctl-init", "off" },
+    { "virtio-pci", "x-pcie-pm-init", "off" },
+    { "cirrus-vga", "vgamem_mb", "8" },
+    { "isa-cirrus-vga", "vgamem_mb", "8" },
 };
 const size_t hw_compat_2_8_len = G_N_ELEMENTS(hw_compat_2_8);
 
 GlobalProperty hw_compat_2_7[] = {
-    {
-        .driver   = "virtio-pci",
-        .property = "page-per-vq",
-        .value    = "on",
-    },{
-        .driver   = "virtio-serial-device",
-        .property = "emergency-write",
-        .value    = "off",
-    },{
-        .driver   = "ioapic",
-        .property = "version",
-        .value    = "0x11",
-    },{
-        .driver   = "intel-iommu",
-        .property = "x-buggy-eim",
-        .value    = "true",
-    },{
-        .driver   = "virtio-pci",
-        .property = "x-ignore-backend-features",
-        .value    = "on",
-    },
+    { "virtio-pci", "page-per-vq", "on" },
+    { "virtio-serial-device", "emergency-write", "off" },
+    { "ioapic", "version", "0x11" },
+    { "intel-iommu", "x-buggy-eim", "true" },
+    { "virtio-pci", "x-ignore-backend-features", "on" },
 };
 const size_t hw_compat_2_7_len = G_N_ELEMENTS(hw_compat_2_7);
 
 GlobalProperty hw_compat_2_6[] = {
-    {
-        .driver   = "virtio-mmio",
-        .property = "format_transport_address",
-        .value    = "off",
-    },{
-        .driver   = "virtio-pci",
-        .property = "disable-modern",
-        .value    = "on",
-    },{
-        .driver   = "virtio-pci",
-        .property = "disable-legacy",
-        .value    = "off",
-    },
+    { "virtio-mmio", "format_transport_address", "off" },
+    /*
+     * don't include devices which are modern-only
+     * ie keyboard, mouse, tablet, gpu, vga & crypto
+     */
+    { "virtio-9p-pci", "disable-modern", "on" },
+    { "virtio-9p-pci", "disable-legacy", "off" },
+    { "virtio-balloon-pci", "disable-modern", "on" },
+    { "virtio-balloon-pci", "disable-legacy", "off" },
+    { "virtio-blk-pci", "disable-modern", "on" },
+    { "virtio-blk-pci", "disable-legacy", "off" },
+    { "virtio-input-host-pci", "disable-modern", "on" },
+    { "virtio-input-host-pci", "disable-legacy", "off" },
+    { "virtio-net-pci", "disable-modern", "on" },
+    { "virtio-net-pci", "disable-legacy", "off" },
+    { "virtio-rng-pci", "disable-modern", "on" },
+    { "virtio-rng-pci", "disable-legacy", "off" },
+    { "virtio-scsi-pci", "disable-modern", "on" },
+    { "virtio-scsi-pci", "disable-legacy", "off" },
+    { "virtio-serial-pci", "disable-modern", "on" },
+    { "virtio-serial-pci", "disable-legacy", "off" },
 };
 const size_t hw_compat_2_6_len = G_N_ELEMENTS(hw_compat_2_6);
 
 GlobalProperty hw_compat_2_5[] = {
-    {
-        .driver   = "isa-fdc",
-        .property = "fallback",
-        .value    = "144",
-    },{
-        .driver   = "pvscsi",
-        .property = "x-old-pci-configuration",
-        .value    = "on",
-    },{
-        .driver   = "pvscsi",
-        .property = "x-disable-pcie",
-        .value    = "on",
-    },
-    {
-        .driver   = "vmxnet3",
-        .property = "x-old-msi-offsets",
-        .value    = "on",
-    },{
-        .driver   = "vmxnet3",
-        .property = "x-disable-pcie",
-        .value    = "on",
-    },
+    { "isa-fdc", "fallback", "144" },
+    { "pvscsi", "x-old-pci-configuration", "on" },
+    { "pvscsi", "x-disable-pcie", "on" },
+    { "vmxnet3", "x-old-msi-offsets", "on" },
+    { "vmxnet3", "x-disable-pcie", "on" },
 };
 const size_t hw_compat_2_5_len = G_N_ELEMENTS(hw_compat_2_5);
 
 GlobalProperty hw_compat_2_4[] = {
-    {
-        .driver   = "virtio-blk-device",
-        .property = "scsi",
-        .value    = "true",
-    },{
-        .driver   = "e1000",
-        .property = "extra_mac_registers",
-        .value    = "off",
-    },{
-        .driver   = "virtio-pci",
-        .property = "x-disable-pcie",
-        .value    = "on",
-    },{
-        .driver   = "virtio-pci",
-        .property = "migrate-extra",
-        .value    = "off",
-    },{
-        .driver   = "fw_cfg_mem",
-        .property = "dma_enabled",
-        .value    = "off",
-    },{
-        .driver   = "fw_cfg_io",
-        .property = "dma_enabled",
-        .value    = "off",
-    }
+    { "virtio-blk-device", "scsi", "true" },
+    { "e1000", "extra_mac_registers", "off" },
+    { "virtio-pci", "x-disable-pcie", "on" },
+    { "virtio-pci", "migrate-extra", "off" },
+    { "fw_cfg_mem", "dma_enabled", "off" },
+    { "fw_cfg_io", "dma_enabled", "off" }
 };
 const size_t hw_compat_2_4_len = G_N_ELEMENTS(hw_compat_2_4);
 
 GlobalProperty hw_compat_2_3[] = {
-    {
-        .driver   = "virtio-blk-pci",
-        .property = "any_layout",
-        .value    = "off",
-    },{
-        .driver   = "virtio-balloon-pci",
-        .property = "any_layout",
-        .value    = "off",
-    },{
-        .driver   = "virtio-serial-pci",
-        .property = "any_layout",
-        .value    = "off",
-    },{
-        .driver   = "virtio-9p-pci",
-        .property = "any_layout",
-        .value    = "off",
-    },{
-        .driver   = "virtio-rng-pci",
-        .property = "any_layout",
-        .value    = "off",
-    },{
-        .driver   = TYPE_PCI_DEVICE,
-        .property = "x-pcie-lnksta-dllla",
-        .value    = "off",
-    },{
-        .driver   = "migration",
-        .property = "send-configuration",
-        .value    = "off",
-    },{
-        .driver   = "migration",
-        .property = "send-section-footer",
-        .value    = "off",
-    },{
-        .driver   = "migration",
-        .property = "store-global-state",
-        .value    = "off",
-    },
+    { "virtio-blk-pci", "any_layout", "off" },
+    { "virtio-balloon-pci", "any_layout", "off" },
+    { "virtio-serial-pci", "any_layout", "off" },
+    { "virtio-9p-pci", "any_layout", "off" },
+    { "virtio-rng-pci", "any_layout", "off" },
+    { TYPE_PCI_DEVICE, "x-pcie-lnksta-dllla", "off" },
+    { "migration", "send-configuration", "off" },
+    { "migration", "send-section-footer", "off" },
+    { "migration", "store-global-state", "off" },
 };
 const size_t hw_compat_2_3_len = G_N_ELEMENTS(hw_compat_2_3);
 
@@ -318,35 +171,13 @@ GlobalProperty hw_compat_2_2[] = {};
 const size_t hw_compat_2_2_len = G_N_ELEMENTS(hw_compat_2_2);
 
 GlobalProperty hw_compat_2_1[] = {
-    {
-        .driver   = "intel-hda",
-        .property = "old_msi_addr",
-        .value    = "on",
-    },{
-        .driver   = "VGA",
-        .property = "qemu-extended-regs",
-        .value    = "off",
-    },{
-        .driver   = "secondary-vga",
-        .property = "qemu-extended-regs",
-        .value    = "off",
-    },{
-        .driver   = "virtio-scsi-pci",
-        .property = "any_layout",
-        .value    = "off",
-    },{
-        .driver   = "usb-mouse",
-        .property = "usb_version",
-        .value    = stringify(1),
-    },{
-        .driver   = "usb-kbd",
-        .property = "usb_version",
-        .value    = stringify(1),
-    },{
-        .driver   = "virtio-pci",
-        .property = "virtio-pci-bus-master-bug-migration",
-        .value    = "on",
-    },
+    { "intel-hda", "old_msi_addr", "on" },
+    { "VGA", "qemu-extended-regs", "off" },
+    { "secondary-vga", "qemu-extended-regs", "off" },
+    { "virtio-scsi-pci", "any_layout", "off" },
+    { "usb-mouse", "usb_version", "1" },
+    { "usb-kbd", "usb_version", "1" },
+    { "virtio-pci", "virtio-pci-bus-master-bug-migration", "on" },
 };
 const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
 
@@ -681,6 +512,47 @@ static void machine_set_memory_encryption(Object *obj, const char *value,
     ms->memory_encryption = g_strdup(value);
 }
 
+static bool machine_get_nvdimm(Object *obj, Error **errp)
+{
+    MachineState *ms = MACHINE(obj);
+
+    return ms->nvdimms_state->is_enabled;
+}
+
+static void machine_set_nvdimm(Object *obj, bool value, Error **errp)
+{
+    MachineState *ms = MACHINE(obj);
+
+    ms->nvdimms_state->is_enabled = value;
+}
+
+static char *machine_get_nvdimm_persistence(Object *obj, Error **errp)
+{
+    MachineState *ms = MACHINE(obj);
+
+    return g_strdup(ms->nvdimms_state->persistence_string);
+}
+
+static void machine_set_nvdimm_persistence(Object *obj, const char *value,
+                                           Error **errp)
+{
+    MachineState *ms = MACHINE(obj);
+    NVDIMMState *nvdimms_state = ms->nvdimms_state;
+
+    if (strcmp(value, "cpu") == 0) {
+        nvdimms_state->persistence = 3;
+    } else if (strcmp(value, "mem-ctrl") == 0) {
+        nvdimms_state->persistence = 2;
+    } else {
+        error_setg(errp, "-machine nvdimm-persistence=%s: unsupported option",
+                   value);
+        return;
+    }
+
+    g_free(nvdimms_state->persistence_string);
+    nvdimms_state->persistence_string = g_strdup(value);
+}
+
 void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type)
 {
     strList *item = g_new0(strList, 1);
@@ -814,6 +686,11 @@ void machine_set_cpu_numa_node(MachineState *machine,
             return;
         }
 
+        if (props->has_die_id && !slot->props.has_die_id) {
+            error_setg(errp, "die-id is not supported");
+            return;
+        }
+
         /* skip slots with explicit mismatch */
         if (props->has_thread_id && props->thread_id != slot->props.thread_id) {
                 continue;
@@ -823,6 +700,10 @@ void machine_set_cpu_numa_node(MachineState *machine,
                 continue;
         }
 
+        if (props->has_die_id && props->die_id != slot->props.die_id) {
+                continue;
+        }
+
         if (props->has_socket_id && props->socket_id != slot->props.socket_id) {
                 continue;
         }
@@ -848,6 +729,78 @@ void machine_set_cpu_numa_node(MachineState *machine,
     }
 }
 
+static void smp_parse(MachineState *ms, QemuOpts *opts)
+{
+    if (opts) {
+        unsigned cpus    = qemu_opt_get_number(opts, "cpus", 0);
+        unsigned sockets = qemu_opt_get_number(opts, "sockets", 0);
+        unsigned cores   = qemu_opt_get_number(opts, "cores", 0);
+        unsigned threads = qemu_opt_get_number(opts, "threads", 0);
+
+        /* compute missing values, prefer sockets over cores over threads */
+        if (cpus == 0 || sockets == 0) {
+            cores = cores > 0 ? cores : 1;
+            threads = threads > 0 ? threads : 1;
+            if (cpus == 0) {
+                sockets = sockets > 0 ? sockets : 1;
+                cpus = cores * threads * sockets;
+            } else {
+                ms->smp.max_cpus =
+                        qemu_opt_get_number(opts, "maxcpus", cpus);
+                sockets = ms->smp.max_cpus / (cores * threads);
+            }
+        } else if (cores == 0) {
+            threads = threads > 0 ? threads : 1;
+            cores = cpus / (sockets * threads);
+            cores = cores > 0 ? cores : 1;
+        } else if (threads == 0) {
+            threads = cpus / (cores * sockets);
+            threads = threads > 0 ? threads : 1;
+        } else if (sockets * cores * threads < cpus) {
+            error_report("cpu topology: "
+                         "sockets (%u) * cores (%u) * threads (%u) < "
+                         "smp_cpus (%u)",
+                         sockets, cores, threads, cpus);
+            exit(1);
+        }
+
+        ms->smp.max_cpus =
+                qemu_opt_get_number(opts, "maxcpus", cpus);
+
+        if (ms->smp.max_cpus < cpus) {
+            error_report("maxcpus must be equal to or greater than smp");
+            exit(1);
+        }
+
+        if (sockets * cores * threads > ms->smp.max_cpus) {
+            error_report("cpu topology: "
+                         "sockets (%u) * cores (%u) * threads (%u) > "
+                         "maxcpus (%u)",
+                         sockets, cores, threads,
+                         ms->smp.max_cpus);
+            exit(1);
+        }
+
+        if (sockets * cores * threads != ms->smp.max_cpus) {
+            warn_report("Invalid CPU topology deprecated: "
+                        "sockets (%u) * cores (%u) * threads (%u) "
+                        "!= maxcpus (%u)",
+                        sockets, cores, threads,
+                        ms->smp.max_cpus);
+        }
+
+        ms->smp.cpus = cpus;
+        ms->smp.cores = cores;
+        ms->smp.threads = threads;
+    }
+
+    if (ms->smp.cpus > 1) {
+        Error *blocker = NULL;
+        error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp");
+        replay_add_blocker(blocker);
+    }
+}
+
 static void machine_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
@@ -855,6 +808,7 @@ static void machine_class_init(ObjectClass *oc, void *data)
     /* Default 128 MB as guest ram size */
     mc->default_ram_size = 128 * MiB;
     mc->rom_file_has_mr = true;
+    mc->smp_parse = smp_parse;
 
     /* numa node memory size aligned on 8MB by default.
      * On Linux, each node's border has to be 8MB aligned
@@ -919,7 +873,7 @@ static void machine_class_init(ObjectClass *oc, void *data)
     object_class_property_add_bool(oc, "dump-guest-core",
         machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort);
     object_class_property_set_description(oc, "dump-guest-core",
-        "Include guest memory in  a core dump", &error_abort);
+        "Include guest memory in a core dump", &error_abort);
 
     object_class_property_add_bool(oc, "mem-merge",
         machine_get_mem_merge, machine_set_mem_merge, &error_abort);
@@ -991,6 +945,28 @@ static void machine_initfn(Object *obj)
     ms->mem_merge = true;
     ms->enable_graphics = true;
 
+    if (mc->nvdimm_supported) {
+        Object *obj = OBJECT(ms);
+
+        ms->nvdimms_state = g_new0(NVDIMMState, 1);
+        object_property_add_bool(obj, "nvdimm",
+                                 machine_get_nvdimm, machine_set_nvdimm,
+                                 &error_abort);
+        object_property_set_description(obj, "nvdimm",
+                                        "Set on/off to enable/disable "
+                                        "NVDIMM instantiation", NULL);
+
+        object_property_add_str(obj, "nvdimm-persistence",
+                                machine_get_nvdimm_persistence,
+                                machine_set_nvdimm_persistence,
+                                &error_abort);
+        object_property_set_description(obj, "nvdimm-persistence",
+                                        "Set NVDIMM persistence"
+                                        "Valid values are cpu, mem-ctrl",
+                                        NULL);
+    }
+
+
     /* Register notifier when init is done for sysbus sanity checks */
     ms->sysbus_notifier.notify = machine_init_notify;
     qemu_add_machine_init_done_notifier(&ms->sysbus_notifier);
@@ -1009,6 +985,7 @@ static void machine_finalize(Object *obj)
     g_free(ms->dt_compatible);
     g_free(ms->firmware);
     g_free(ms->device_memory);
+    g_free(ms->nvdimms_state);
 }
 
 bool machine_usb(MachineState *machine)
@@ -1057,6 +1034,9 @@ static char *cpu_slot_to_string(const CPUArchId *cpu)
     if (cpu->props.has_socket_id) {
         g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id);
     }
+    if (cpu->props.has_die_id) {
+        g_string_append_printf(s, "die-id: %"PRId64, cpu->props.die_id);
+    }
     if (cpu->props.has_core_id) {
         if (s->len) {
             g_string_append_printf(s, ", ");