To support new epyc mode, we need to know the number of numa nodes in advance to generate apic id correctly. So, split the numa initialization into two. The function parse_numa initializes numa_info and updates nb_numa_nodes. And then parse_numa_node does the numa node initialization.
Signed-off-by: Babu Moger <babu.mo...@amd.com> --- hw/core/numa.c | 106 +++++++++++++++++++++++++++++++++++-------------- include/sysemu/numa.h | 2 + vl.c | 2 + 3 files changed, 80 insertions(+), 30 deletions(-) diff --git a/hw/core/numa.c b/hw/core/numa.c index a11431483c..27fa6b5e1d 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -55,14 +55,10 @@ bool have_numa_distance; NodeInfo numa_info[MAX_NODES]; -static void parse_numa_node(MachineState *ms, NumaNodeOptions *node, +static void parse_numa_info(MachineState *ms, NumaNodeOptions *node, Error **errp) { - Error *err = NULL; uint16_t nodenr; - uint16List *cpus = NULL; - MachineClass *mc = MACHINE_GET_CLASS(ms); - unsigned int max_cpus = ms->smp.max_cpus; if (node->has_nodeid) { nodenr = node->nodeid; @@ -81,29 +77,6 @@ static void parse_numa_node(MachineState *ms, NumaNodeOptions *node, return; } - if (!mc->cpu_index_to_instance_props || !mc->get_default_cpu_node_id) { - error_setg(errp, "NUMA is not supported by this machine-type"); - return; - } - for (cpus = node->cpus; cpus; cpus = cpus->next) { - CpuInstanceProperties props; - if (cpus->value >= max_cpus) { - error_setg(errp, - "CPU index (%" PRIu16 ")" - " should be smaller than maxcpus (%d)", - cpus->value, max_cpus); - return; - } - props = mc->cpu_index_to_instance_props(ms, cpus->value); - props.node_id = nodenr; - props.has_node_id = true; - machine_set_cpu_numa_node(ms, &props, &err); - if (err) { - error_propagate(errp, err); - return; - } - } - have_memdevs = have_memdevs ? : node->has_memdev; have_mem = have_mem ? : node->has_mem; if ((node->has_mem && have_memdevs) || (node->has_memdev && have_mem)) { @@ -177,7 +150,7 @@ void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp) switch (object->type) { case NUMA_OPTIONS_TYPE_NODE: - parse_numa_node(ms, &object->u.node, &err); + parse_numa_info(ms, &object->u.node, &err); if (err) { goto end; } @@ -242,6 +215,73 @@ end: return 0; } +void set_numa_node_options(MachineState *ms, NumaOptions *object, Error **errp) +{ + MachineClass *mc = MACHINE_GET_CLASS(ms); + NumaNodeOptions *node = &object->u.node; + unsigned int max_cpus = ms->smp.max_cpus; + uint16List *cpus = NULL; + Error *err = NULL; + uint16_t nodenr; + + if (node->has_nodeid) { + nodenr = node->nodeid; + } else { + error_setg(errp, "NUMA node information is not available"); + } + + if (!mc->cpu_index_to_instance_props || !mc->get_default_cpu_node_id) { + error_setg(errp, "NUMA is not supported by this machine-type"); + return; + } + + for (cpus = node->cpus; cpus; cpus = cpus->next) { + CpuInstanceProperties props; + if (cpus->value >= max_cpus) { + error_setg(errp, + "CPU index (%" PRIu16 ")" + " should be smaller than maxcpus (%d)", + cpus->value, max_cpus); + return; + } + props = mc->cpu_index_to_instance_props(ms, cpus->value); + props.node_id = nodenr; + props.has_node_id = true; + machine_set_cpu_numa_node(ms, &props, &err); + if (err) { + error_propagate(errp, err); + return; + } + } +} + +static int parse_numa_node(void *opaque, QemuOpts *opts, Error **errp) +{ + NumaOptions *object = NULL; + MachineState *ms = MACHINE(opaque); + Error *err = NULL; + Visitor *v = opts_visitor_new(opts); + + visit_type_NumaOptions(v, NULL, &object, &err); + visit_free(v); + if (err) { + goto end; + } + + if (object->type == NUMA_OPTIONS_TYPE_NODE) { + set_numa_node_options(ms, object, &err); + } + +end: + qapi_free_NumaOptions(object); + if (err) { + error_propagate(errp, err); + return -1; + } + + return 0; +} + /* If all node pair distances are symmetric, then only distances * in one direction are enough. If there is even one asymmetric * pair, though, then all distances must be provided. The @@ -368,7 +408,7 @@ void numa_complete_configuration(MachineState *ms) if (ms->ram_slots > 0 && nb_numa_nodes == 0 && mc->auto_enable_numa_with_memhp) { NumaNodeOptions node = { }; - parse_numa_node(ms, &node, &error_abort); + parse_numa_info(ms, &node, &error_abort); } assert(max_numa_nodeid <= MAX_NODES); @@ -448,6 +488,12 @@ void parse_numa_opts(MachineState *ms) qemu_opts_foreach(qemu_find_opts("numa"), parse_numa, ms, &error_fatal); } +void parse_numa_node_opts(MachineState *ms) +{ + qemu_opts_foreach(qemu_find_opts("numa"), parse_numa_node, + ms, &error_fatal); +} + void numa_cpu_pre_plug(const CPUArchId *slot, DeviceState *dev, Error **errp) { int node_id = object_property_get_int(OBJECT(dev), "node-id", &error_abort); diff --git a/include/sysemu/numa.h b/include/sysemu/numa.h index 01a263eba2..ca109adaa6 100644 --- a/include/sysemu/numa.h +++ b/include/sysemu/numa.h @@ -24,7 +24,9 @@ struct NumaNodeMem { extern NodeInfo numa_info[MAX_NODES]; void set_numa_options(MachineState *ms, NumaOptions *object, Error **errp); +void set_numa_node_options(MachineState *ms, NumaOptions *object, Error **errp); void parse_numa_opts(MachineState *ms); +void parse_numa_node_opts(MachineState *ms); void numa_complete_configuration(MachineState *ms); void query_numa_node_mem(NumaNodeMem node_mem[]); extern QemuOptsList qemu_numa_opts; diff --git a/vl.c b/vl.c index b426b32134..711d2ae5da 100644 --- a/vl.c +++ b/vl.c @@ -4339,6 +4339,8 @@ int main(int argc, char **argv, char **envp) } parse_numa_opts(current_machine); + parse_numa_node_opts(current_machine); + /* do monitor/qmp handling at preconfig state if requested */ main_loop();