On POWERPC, only a whole CPU core can be assigned to a KVM. Since POWER7/8 support several threads per core, we want all threads of a core to go to the same KVM so every time we run QEMU with -enable-kvm, we have to add -smp X,threads=(4|8)" (4 for POWER7 and 8 for POWER8).
The user rather wants the maximum number of threads enabled, and there is no easy way to know the maximum number supported by the hardware. However the accelerator (KVM) knows this number and we can use it to set the threads number to the maximum. This adds a "threads_max" boolean switch to the "-smp" parameter which tells QEMU to use the smp_threads value. The existing "threads" is not changed to support a "max" string value in order to avoid duplicating the parsing errors handling. This adds smp_threads tweaking into POWERPC's kvm_arch_init(). This moves smp_parse() call in vl.c later to let the accelerator alter the smp_threads value before actual "-smp" option parsing happens. This does not change the default value of smp_threads which remains 1. Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru> --- qemu-options.hx | 7 +++++-- target-ppc/kvm.c | 2 ++ vl.c | 34 +++++++++++++++++++++++----------- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index bcfe9ea..8d582fa 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -73,16 +73,17 @@ Select CPU model (@code{-cpu help} for list and additional feature selection) ETEXI DEF("smp", HAS_ARG, QEMU_OPTION_smp, - "-smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]\n" + "-smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,threads_max=on|off][,sockets=sockets]\n" " set the number of CPUs to 'n' [default=1]\n" " maxcpus= maximum number of total cpus, including\n" " offline CPUs for hotplug, etc\n" " cores= number of CPU cores on one socket\n" " threads= number of threads on one CPU core\n" + " threads_max= set number of threads on one CPU core to maximum supported by accelerator\n" " sockets= number of discrete sockets in the system\n", QEMU_ARCH_ALL) STEXI -@item -smp [cpus=]@var{n}[,cores=@var{cores}][,threads=@var{threads}][,sockets=@var{sockets}][,maxcpus=@var{maxcpus}] +@item -smp [cpus=]@var{n}[,cores=@var{cores}][,threads=@var{threads}][,threads_max=@var{threads_max}][,sockets=@var{sockets}][,maxcpus=@var{maxcpus}] @findex -smp Simulate an SMP system with @var{n} CPUs. On the PC target, up to 255 CPUs are supported. On Sparc32 target, Linux limits the number of usable CPUs @@ -92,6 +93,8 @@ of @var{threads} per cores and the total number of @var{sockets} can be specified. Missing values will be computed. If any on the three values is given, the total number of CPUs @var{n} can be omitted. @var{maxcpus} specifies the maximum number of hotpluggable CPUs. +If the accelerator has a knowledge about the maximum number of threads per +core supported, @var{threads_max} will use the maximum value. ETEXI DEF("numa", HAS_ARG, QEMU_OPTION_numa, diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 781b72f..fa845fa 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -109,6 +109,8 @@ int kvm_arch_init(KVMState *s) "VM to stall at times!\n"); } + smp_threads = kvmppc_smt_threads(); + kvm_ppc_register_host_cpu_type(); return 0; diff --git a/vl.c b/vl.c index c268949..57589aa 100644 --- a/vl.c +++ b/vl.c @@ -1381,6 +1381,9 @@ static QemuOptsList qemu_smp_opts = { .name = "threads", .type = QEMU_OPT_NUMBER, }, { + .name = "threads_max", + .type = QEMU_OPT_BOOL, + }, { .name = "maxcpus", .type = QEMU_OPT_NUMBER, }, @@ -1396,12 +1399,21 @@ static void smp_parse(QemuOpts *opts) 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); + bool threads_max = qemu_opt_get_bool(opts, "threads_max", false); /* compute missing values, prefer sockets over cores over threads */ if (cpus == 0 || sockets == 0) { sockets = sockets > 0 ? sockets : 1; cores = cores > 0 ? cores : 1; - threads = threads > 0 ? threads : 1; + if (threads_max) { + if (threads > 0) { + fprintf(stderr, "Use either threads or threads_max\n"); + exit(1); + } + threads = smp_threads > 0 ? smp_threads : 1; + } else { + threads = threads > 0 ? threads : 1; + } if (cpus == 0) { cpus = cores * threads * sockets; } @@ -3895,16 +3907,6 @@ int main(int argc, char **argv, char **envp) data_dir[data_dir_idx++] = CONFIG_QEMU_DATADIR; } - smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); - - machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */ - if (smp_cpus > machine->max_cpus) { - fprintf(stderr, "Number of SMP cpus requested (%d), exceeds max cpus " - "supported by machine `%s' (%d)\n", smp_cpus, machine->name, - machine->max_cpus); - exit(1); - } - /* * Get the default machine options from the machine if it is not already * specified either by the configuration file or by the command line. @@ -4058,6 +4060,16 @@ int main(int argc, char **argv, char **envp) qtest_init(qtest_chrdev, qtest_log); } + smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); + + machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */ + if (smp_cpus > machine->max_cpus) { + fprintf(stderr, "Number of SMP cpus requested (%d), exceeds max cpus " + "supported by machine `%s' (%d)\n", smp_cpus, machine->name, + machine->max_cpus); + exit(1); + } + machine_opts = qemu_get_machine_opts(); kernel_filename = qemu_opt_get(machine_opts, "kernel"); initrd_filename = qemu_opt_get(machine_opts, "initrd"); -- 1.8.4.rc4