We add the possibility to define the CPU topology to QEMU S390x. This allows the user chose which CPU in the topology is active.
A NUMA node is considered to be a socket and chosing the NUMA node leads to chose the specific socket in a book inside a drawer. Signed-off-by: Pierre Morel <pmo...@linux.ibm.com> --- hw/s390x/s390-virtio-ccw.c | 53 +++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 3708ad3c46..0fd938fe3f 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -84,14 +84,37 @@ out: static void s390_init_cpus(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); - int i; + const CPUArchId *slot; + int i, n = 1; /* initialize possible_cpus */ mc->possible_cpu_arch_ids(machine); s390_topology_setup(machine); - for (i = 0; i < machine->smp.cpus; i++) { + + /* Create CPU0 */ + s390x_new_cpu(machine->cpu_type, 0, &error_fatal); + + /* For NUMA configuration create defined nodes */ + if (machine->numa_state->num_nodes) { + for (i = 1; i < machine->smp.max_cpus; i++) { + slot = &machine->possible_cpus->cpus[i]; + if (slot->props.node_id) { + s390x_new_cpu(machine->cpu_type, i, &error_fatal); + n++; + } + } + } + + /* create all remaining CPUs */ + for (i = 1; n < machine->smp.cpus && i < machine->smp.max_cpus; i++) { + slot = &machine->possible_cpus->cpus[i]; + /* For NUMA configuration skip defined nodes */ + if (machine->numa_state->num_nodes && slot->props.node_id) { + continue; + } s390x_new_cpu(machine->cpu_type, i, &error_fatal); + n++; } } @@ -530,6 +553,7 @@ static const CPUArchIdList *s390_possible_cpu_arch_ids(MachineState *ms) { int i; unsigned int max_cpus = ms->smp.max_cpus; + S390CcwMachineState *s390ms = S390_CCW_MACHINE(ms); if (ms->possible_cpus) { g_assert(ms->possible_cpus && ms->possible_cpus->len == max_cpus); @@ -540,11 +564,20 @@ static const CPUArchIdList *s390_possible_cpu_arch_ids(MachineState *ms) sizeof(CPUArchId) * max_cpus); ms->possible_cpus->len = max_cpus; for (i = 0; i < ms->possible_cpus->len; i++) { - ms->possible_cpus->cpus[i].type = ms->cpu_type; - ms->possible_cpus->cpus[i].vcpus_count = 1; - ms->possible_cpus->cpus[i].arch_id = i; - ms->possible_cpus->cpus[i].props.has_core_id = true; - ms->possible_cpus->cpus[i].props.core_id = i; + CPUArchId *slot = &ms->possible_cpus->cpus[i]; + + slot->type = ms->cpu_type; + slot->vcpus_count = 1; + slot->arch_id = i; + + slot->props.core_id = i; + slot->props.has_core_id = true; + slot->props.socket_id = i / ms->smp.cores; + slot->props.has_socket_id = true; + slot->props.book_id = slot->props.socket_id / ms->smp.sockets; + slot->props.has_book_id = true; + slot->props.drawer_id = slot->props.book_id / s390ms->books; + slot->props.has_drawer_id = true; } return ms->possible_cpus; @@ -635,6 +668,11 @@ static void s390_smp_parse(MachineState *ms, QemuOpts *opts) s390ms->books = books; } +static int64_t s390x_get_default_cpu_node_id(const MachineState *ms, int idx) +{ + return idx / ms->smp.cores; +} + static void ccw_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -666,6 +704,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) nc->nmi_monitor_handler = s390_nmi; mc->default_ram_id = "s390.ram"; mc->smp_parse = s390_smp_parse; + mc->get_default_cpu_node_id = s390x_get_default_cpu_node_id; } static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp) -- 2.25.1