From: Zhao Liu <zhao1....@intel.com> Add "-hybrid" command parsing.
And now we have reason to move MachineState.topo initialization to its original place [1], because we can't know whcih topologies should be initialized before collecting all commands. If "-hybrid" is set, initialize MachineState.topo as hybrid topology. Otherwise, use smp topology as default. [1]: 8b0e484 (machine: move SMP initialization from vl.c) Signed-off-by: Zhao Liu <zhao1....@intel.com> --- hw/core/machine-topo.c | 41 ++++++++++++++++++++++++++++++++++++++++- hw/core/machine.c | 11 ----------- include/hw/boards.h | 1 + qemu-options.hx | 7 +++++++ softmmu/vl.c | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 12 deletions(-) diff --git a/hw/core/machine-topo.c b/hw/core/machine-topo.c index 9e37de04ce75..f38b8c683026 100644 --- a/hw/core/machine-topo.c +++ b/hw/core/machine-topo.c @@ -177,6 +177,33 @@ unsigned int machine_topo_get_threads_per_socket(const MachineState *ms) return ms->topo.max_cpus / sockets; } +void machine_init_topology_default(MachineState *ms, bool smp) +{ + MachineClass *mc = MACHINE_GET_CLASS(ms); + + if (smp) { + /* default to mc->default_cpus */ + ms->topo.cpus = mc->default_cpus; + ms->topo.max_cpus = mc->default_cpus; + + ms->topo.topo_type = CPU_TOPO_TYPE_SMP; + ms->topo.smp.sockets = 1; + ms->topo.smp.dies = 1; + ms->topo.smp.clusters = 1; + ms->topo.smp.cores = 1; + ms->topo.smp.threads = 1; + } else { + ms->topo.cpus = 0; + ms->topo.max_cpus = 0; + + ms->topo.topo_type = CPU_TOPO_TYPE_HYBRID; + ms->topo.hybrid.sockets = 1; + ms->topo.hybrid.dies = 1; + ms->topo.hybrid.clusters = 1; + ms->topo.hybrid.cluster_list = NULL; + } +} + /* * Report information of a machine's supported CPU topology hierarchy. * Topology members will be ordered from the largest to the smallest @@ -231,6 +258,12 @@ void machine_parse_smp_config(MachineState *ms, const SMPConfiguration *config, Error **errp) { MachineClass *mc = MACHINE_GET_CLASS(ms); + + if (!machine_topo_is_smp(ms)) { + error_setg(errp, "Cannot set smp and hybrid at the same time"); + return; + } + unsigned cpus = config->has_cpus ? config->cpus : 0; unsigned sockets = config->has_sockets ? config->sockets : 0; unsigned dies = config->has_dies ? config->dies : 0; @@ -608,8 +641,14 @@ static int parse_hybrid(void *opaque, QemuOpts *opts, Error **errp) g_autoptr(HybridOptions) config = NULL; MachineState *ms = MACHINE(opaque); Error *err = NULL; - Visitor *v = opts_visitor_new(opts); + Visitor *v; + + if (machine_topo_is_smp(ms)) { + error_setg(errp, "Cannot set hybrid and smp at the same time"); + return -1; + } + v = opts_visitor_new(opts); visit_type_HybridOptions(v, NULL, &config, errp); visit_free(v); if (!config) { diff --git a/hw/core/machine.c b/hw/core/machine.c index 08a0c117ce1b..212749f984d6 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1093,17 +1093,6 @@ static void machine_initfn(Object *obj) "Table (HMAT)"); } - /* default to mc->default_cpus */ - ms->topo.cpus = mc->default_cpus; - ms->topo.max_cpus = mc->default_cpus; - - ms->topo.topo_type = CPU_TOPO_TYPE_SMP; - ms->topo.smp.sockets = 1; - ms->topo.smp.dies = 1; - ms->topo.smp.clusters = 1; - ms->topo.smp.cores = 1; - ms->topo.smp.threads = 1; - machine_copy_boot_config(ms, &(BootConfiguration){ 0 }); } diff --git a/include/hw/boards.h b/include/hw/boards.h index 0395990139bc..c93bb1206244 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -41,6 +41,7 @@ void parse_hybrid_opts(MachineState *ms); void machine_free_hybrid_topology(MachineState *ms); void machine_validate_hybrid_topology(MachineState *ms, Error **errp); void machine_consolidate_hybrid_topology(MachineState *ms); +void machine_init_topology_default(MachineState *ms, bool smp); /** * machine_class_allow_dynamic_sysbus_dev: Add type to list of valid devices diff --git a/qemu-options.hx b/qemu-options.hx index 3caf9da4c3af..8987972a8d5f 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -5605,6 +5605,13 @@ SRST (qemu) qom-set /objects/iothread1 poll-max-ns 100000 ERST +DEF("hybrid", HAS_ARG, QEMU_OPTION_hybrid, + "-hybrid socket,sockets=n" + "-hybrid die,dies=n" + "-hybrid cluster,clusters=n" + "-hybrid core,cores=n,coretype=core_type[,threads=threads][,clusterid=cluster]", + QEMU_ARCH_ALL) + HXCOMM This is the last statement. Insert new options before this line! diff --git a/softmmu/vl.c b/softmmu/vl.c index 0547ad390f52..ce5e021006f8 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -500,6 +500,13 @@ static QemuOptsList qemu_action_opts = { }, }; +static QemuOptsList qemu_hybrid_opts = { + .name = "hybrid", + .implied_opt_name = "type", + .head = QTAILQ_HEAD_INITIALIZER(qemu_hybrid_opts.head), + .desc = { { 0 } } /* validated with OptsVisitor */ +}; + const char *qemu_get_vm_name(void) { return qemu_name; @@ -2010,6 +2017,17 @@ static void parse_memory_options(void) loc_pop(&loc); } +static void qemu_machine_init_topology(MachineState *machine) +{ + bool is_smp = true; + QemuOptsList *list = qemu_find_opts("hybrid"); + + if (!QTAILQ_EMPTY(&list->head)) { + is_smp = false; + } + machine_init_topology_default(machine, is_smp); +} + static void qemu_create_machine(QDict *qdict) { MachineClass *machine_class = select_machine(qdict, &error_fatal); @@ -2038,6 +2056,12 @@ static void qemu_create_machine(QDict *qdict) qemu_set_hw_version(machine_class->hw_version); } + /* + * Initialize cpu topology. If hybrid is set, initialize as hybrid + * topology. Otherwise, initialize as smp topology. + */ + qemu_machine_init_topology(current_machine); + /* * Get the default machine options from the machine if it is not already * specified either by the configuration file or by the command line. @@ -2667,6 +2691,7 @@ void qemu_init(int argc, char **argv) qemu_add_opts(&qemu_semihosting_config_opts); qemu_add_opts(&qemu_fw_cfg_opts); qemu_add_opts(&qemu_action_opts); + qemu_add_opts(&qemu_hybrid_opts); module_call_init(MODULE_INIT_OPTS); error_init(argv[0]); @@ -3489,6 +3514,13 @@ void qemu_init(int argc, char **argv) case QEMU_OPTION_nouserconfig: /* Nothing to be parsed here. Especially, do not error out below. */ break; + case QEMU_OPTION_hybrid: + opts = qemu_opts_parse_noisily(qemu_find_opts("hybrid"), + optarg, true); + if (!opts) { + exit(1); + } + break; default: if (os_parse_cmd_args(popt->index, optarg)) { error_report("Option not supported in this build"); @@ -3598,6 +3630,7 @@ void qemu_init(int argc, char **argv) qemu_resolve_machine_memdev(); parse_numa_opts(current_machine); + parse_hybrid_opts(current_machine); if (vmstate_dump_file) { /* dump and exit */ -- 2.34.1