diff mbox series

[v1,5/9] s390x: topology: implementating Store Topology System Information

Message ID 1626281596-31061-6-git-send-email-pmorel@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series s390x: CPU Topology | expand

Commit Message

Pierre Morel July 14, 2021, 4:53 p.m. UTC
The handling of STSI is enhenced with the interception of the
function code 15 for storing CPU topology.

Using the objects built during the pluging of CPU, we build the
SYSIB 15_1_x structures.

Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
---
 target/s390x/kvm/kvm.c | 222 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 222 insertions(+)
diff mbox series

Patch

diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
index 5b1fdb55c4..d78261c089 100644
--- a/target/s390x/kvm/kvm.c
+++ b/target/s390x/kvm/kvm.c
@@ -52,6 +52,7 @@ 
 #include "hw/s390x/s390-virtio-ccw.h"
 #include "hw/s390x/s390-virtio-hcall.h"
 #include "hw/s390x/pv.h"
+#include "hw/s390x/cpu-topology.h"
 
 #ifndef DEBUG_KVM
 #define DEBUG_KVM  0
@@ -1893,6 +1894,223 @@  static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar)
     }
 }
 
+static int stsi_15_container(void *p, int nl, int id)
+{
+    SysIBTl_container *tle = (SysIBTl_container *)p;
+
+    tle->nl = nl;
+    tle->id = id;
+
+    return sizeof(*tle);
+}
+
+static int stsi_15_cpus(void *p, S390TopologyCores *cd)
+{
+    SysIBTl_cpu *tle = (SysIBTl_cpu *)p;
+
+    tle->nl = 0;
+    tle->dedicated = cd->dedicated;
+    tle->polarity = cd->polarity;
+    tle->type = cd->cputype;
+    tle->origin = cd->origin;
+    tle->mask = cd->mask;
+
+    return sizeof(*tle);
+}
+
+static int set_socket(const MachineState *ms, void *p,
+                      S390TopologySocket *socket, int level, int off)
+{
+    BusChild *kid;
+    int l, len = 0;
+
+    len += stsi_15_container(p, 1, off * ms->smp.sockets + socket->socket_id);
+    p += len;
+
+    QTAILQ_FOREACH_REVERSE(kid, &socket->bus->children, sibling) {
+        l = stsi_15_cpus(p, S390_TOPOLOGY_CORES(kid->child));
+        p += l;
+        len += l;
+    }
+    return len;
+}
+
+static int set_book(const MachineState *ms, void *p,
+                    S390TopologyBook *book, int level, int off)
+{
+    S390CcwMachineState *s390ms = S390_CCW_MACHINE(ms);
+    BusChild *kid;
+    int l, len = 0;
+    int offset = 0;
+
+    if (level >= 3) {
+        len += stsi_15_container(p, 2, off * s390ms->books + book->book_id);
+        p += len;
+    } else {
+        offset = off * s390ms->books + book->book_id;
+    }
+
+    QTAILQ_FOREACH_REVERSE(kid, &book->bus->children, sibling) {
+        l = set_socket(ms, p, S390_TOPOLOGY_SOCKET(kid->child), level,
+                       offset);
+        p += l;
+        len += l;
+    }
+
+    return len;
+}
+
+static int set_drawer(const MachineState *ms, void *p,
+                      S390TopologyDrawer *drawer, int level)
+{
+    BusChild *kid;
+    int l, len = 0;
+    int offset = 0;
+
+    if (level >= 4) {
+        len += stsi_15_container(p, 3, drawer->drawer_id);
+        p += len;
+    } else {
+        offset = drawer->drawer_id;
+    }
+
+    QTAILQ_FOREACH_REVERSE(kid, &drawer->bus->children, sibling) {
+        l = set_book(ms, p, S390_TOPOLOGY_BOOK(kid->child), level, offset);
+        p += l;
+        len += l;
+    }
+
+    return len;
+}
+
+static void insert_stsi_15_1_2(const MachineState *ms, void *p)
+{
+    S390CcwMachineState *s390ms = S390_CCW_MACHINE(ms);
+    S390TopologyDrawer *drawer;
+    S390TopologyNode *node;
+    SysIB_151x *sysib;
+    BusChild *kid;
+    int level = 2;
+    int len, l, nb_sockets;
+
+    sysib = (SysIB_151x *)p;
+    sysib->mnest = level;
+    nb_sockets = ms->smp.sockets * s390ms->books * s390ms->drawers;
+    sysib->mag[TOPOLOGY_NR_MAG2] = nb_sockets;
+    sysib->mag[TOPOLOGY_NR_MAG1] = ms->smp.cores;
+
+    node = s390_get_topology();
+    len = sizeof(SysIB_151x);
+    p += len;
+
+    QTAILQ_FOREACH_REVERSE(kid, &node->bus->children, sibling) {
+        drawer = S390_TOPOLOGY_DRAWER(kid->child);
+        l = set_drawer(ms, p, drawer, level);
+        p += l;
+        len += l;
+    }
+
+    sysib->length = len;
+}
+
+static void insert_stsi_15_1_3(const MachineState *ms, void *p)
+{
+    S390CcwMachineState *s390ms = S390_CCW_MACHINE(ms);
+    S390TopologyDrawer *drawer;
+    S390TopologyNode *node;
+    SysIB_151x *sysib;
+    BusChild *kid;
+    int level = 3;
+    int len, l;
+
+    sysib = (SysIB_151x *)p;
+    sysib->mnest = level;
+    sysib->mag[TOPOLOGY_NR_MAG3] = s390ms->books * s390ms->drawers;
+    sysib->mag[TOPOLOGY_NR_MAG2] = ms->smp.sockets;
+    sysib->mag[TOPOLOGY_NR_MAG1] = ms->smp.cores;
+
+    node = s390_get_topology();
+    len = sizeof(SysIB_151x);
+    p += len;
+
+    QTAILQ_FOREACH_REVERSE(kid, &node->bus->children, sibling) {
+        drawer = S390_TOPOLOGY_DRAWER(kid->child);
+        l = set_drawer(ms, p, drawer, level);
+        p += l;
+        len += l;
+    }
+
+    sysib->length = len;
+}
+
+static void insert_stsi_15_1_4(const MachineState *ms, void *p)
+{
+    S390CcwMachineState *s390ms = S390_CCW_MACHINE(ms);
+    S390TopologyDrawer *drawer;
+    S390TopologyNode *node;
+    SysIB_151x *sysib;
+    BusChild *kid;
+    int level = 4;
+    int len, l;
+
+    sysib = (SysIB_151x *)p;
+    sysib->mnest = level;
+    sysib->mag[TOPOLOGY_NR_MAG4] = s390ms->drawers;
+    sysib->mag[TOPOLOGY_NR_MAG3] = s390ms->books;
+    sysib->mag[TOPOLOGY_NR_MAG2] = ms->smp.sockets;
+    sysib->mag[TOPOLOGY_NR_MAG1] = ms->smp.cores;
+
+    node = s390_get_topology();
+    len = sizeof(SysIB_151x);
+    p += len;
+
+    QTAILQ_FOREACH_REVERSE(kid, &node->bus->children, sibling) {
+        drawer = S390_TOPOLOGY_DRAWER(kid->child);
+        l = set_drawer(ms, p, drawer, level);
+        p += l;
+        len += l;
+    }
+
+    sysib->length = len;
+}
+
+#define SCLP_READ_SCP_INFO_MNEST 2
+static void insert_stsi_15_1_x(S390CPU *cpu, int sel2, __u64 addr, uint8_t ar)
+{
+    const MachineState *machine = MACHINE(qdev_get_machine());
+    void *p;
+
+    if (sel2 > SCLP_READ_SCP_INFO_MNEST) {
+        setcc(cpu, 3);
+        return;
+    }
+
+    p = g_malloc0(4096);
+
+    switch (sel2) {
+    case 2:
+        insert_stsi_15_1_2(machine, p);
+        break;
+    case 3:
+        insert_stsi_15_1_3(machine, p);
+        break;
+    case 4:
+        insert_stsi_15_1_4(machine, p);
+        break;
+    default:
+        setcc(cpu, 3);
+        return;
+    }
+
+    if (s390_is_pv()) {
+        s390_cpu_pv_mem_write(cpu, 0, p, 4096);
+    } else {
+        s390_cpu_virt_mem_write(cpu, addr, ar, p, 4096);
+    }
+    setcc(cpu, 0);
+    g_free(p);
+}
+
 static int handle_stsi(S390CPU *cpu)
 {
     CPUState *cs = CPU(cpu);
@@ -1906,6 +2124,10 @@  static int handle_stsi(S390CPU *cpu)
         /* Only sysib 3.2.2 needs post-handling for now. */
         insert_stsi_3_2_2(cpu, run->s390_stsi.addr, run->s390_stsi.ar);
         return 0;
+    case 15:
+        insert_stsi_15_1_x(cpu, run->s390_stsi.sel2, run->s390_stsi.addr,
+                           run->s390_stsi.ar);
+        return 0;
     default:
         return 0;
     }