On Tue, 2022-11-29 at 18:42 +0100, Pierre Morel wrote: > The guest uses the STSI instruction to get information on the > CPU topology. > > Let us implement the STSI instruction for the basis CPU topology > level, level 2. > > Signed-off-by: Pierre Morel <pmorel@xxxxxxxxxxxxx> > --- > target/s390x/cpu.h | 77 +++++++++++++++ > hw/s390x/s390-virtio-ccw.c | 12 +-- > target/s390x/cpu_topology.c | 186 ++++++++++++++++++++++++++++++++++++ > target/s390x/kvm/kvm.c | 6 +- > target/s390x/meson.build | 1 + > 5 files changed, 274 insertions(+), 8 deletions(-) > create mode 100644 target/s390x/cpu_topology.c > > diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h > index 7d6d01325b..dd878ac916 100644 > --- a/target/s390x/cpu.h > +++ b/target/s390x/cpu.h > [...] > +/* Configuration topology */ > +typedef struct SysIB_151x { > + uint8_t reserved0[2]; > + uint16_t length; > + uint8_t mag[S390_TOPOLOGY_MAG]; > + uint8_t reserved1; > + uint8_t mnest; > + uint32_t reserved2; > + char tle[0]; AFAIK [] is preferred over [0]. > +} QEMU_PACKED QEMU_ALIGNED(8) SysIB_151x; > +QEMU_BUILD_BUG_ON(sizeof(SysIB_151x) != 16); [...] > > +/* > + * s390_topology_add_cpu: > + * @topo: pointer to the topology > + * @cpu : pointer to the new CPU > + * > + * The topology pointed by S390CPU, gives us the CPU topology > + * established by the -smp QEMU aruments. > + * The core-id is used to calculate the position of the CPU inside > + * the topology: > + * - the socket, container TLE, containing the CPU, we have one socket > + * for every num_cores cores. > + * - the CPU TLE inside the socket, we have potentionly up to 4 CPU TLE > + * in a container TLE with the assumption that all CPU are identical > + * with the same polarity and entitlement because we have maximum 256 > + * CPUs and each TLE can hold up to 64 identical CPUs. > + * - the bit in the 64 bit CPU TLE core mask > + */ > +static void s390_topology_add_cpu(S390Topology *topo, S390CPU *cpu) > +{ > + int core_id = cpu->env.core_id; > + int bit, origin; > + int socket_id; > + > + cpu->machine_data = topo; > + socket_id = core_id / topo->num_cores; > + /* > + * At the core level, each CPU is represented by a bit in a 64bit > + * uint64_t which represent the presence of a CPU. > + * The firmware assume that all CPU in a CPU TLE have the same > + * type, polarization and are all dedicated or shared. > + * In that case the origin variable represents the offset of the first > + * CPU in the CPU container. > + * More than 64 CPUs per socket are represented in several CPU containers > + * inside the socket container. > + * The only reason to have several S390TopologyCores inside a socket is > + * to have more than 64 CPUs. > + * In that case the origin variable represents the offset of the first CPU > + * in the CPU container. More than 64 CPUs per socket are represented in > + * several CPU containers inside the socket container. > + */ This comment still contains redundant sentences. Did you have a look at my suggestion in v10 patch 1? > + bit = core_id; > + origin = bit / 64; > + bit %= 64; > + bit = 63 - bit; > + > + topo->socket[socket_id].active_count++; > + set_bit(bit, &topo->socket[socket_id].mask[origin]); > +} > + > +/* > + * s390_prepare_topology: > + * @s390ms : pointer to the S390CcwMachite State > + * > + * Calls s390_topology_add_cpu to organize the topology > + * inside the topology device before writing the SYSIB. > + * > + * The topology is currently fixed on boot and do not change does not change > + * even on migration. > + */ > +static void s390_prepare_topology(S390CcwMachineState *s390ms) > +{ > + const MachineState *ms = MACHINE(s390ms); > + static bool done; > + int i; > + > + if (done) { > + return; > + } > + > + for (i = 0; i < ms->possible_cpus->len; i++) { > + if (ms->possible_cpus->cpus[i].cpu) { > + s390_topology_add_cpu(S390_CPU_TOPOLOGY(s390ms->topology), > + S390_CPU(ms->possible_cpus->cpus[i].cpu)); > + } > + } > + > + done = true; > +} > + > [...]