diff options
Diffstat (limited to 'hw/core/machine.c')
-rw-r--r-- | hw/core/machine.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/hw/core/machine.c b/hw/core/machine.c index b35dea05bd..2be19ec0cd 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -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" @@ -726,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); @@ -733,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 |