]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: use cache ID, keep caches independent on CPU type
authorKarel Zak <kzak@redhat.com>
Thu, 20 Aug 2020 10:28:52 +0000 (12:28 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 13 Nov 2020 08:19:02 +0000 (09:19 +0100)
The cache is identified by Type, Level and ID, the ID is unique cache
instance identifier (of the type).

This changes forces lscpu allocate more lscpu_cache instances (than
old version), but now we're ready for arbitrary scenario where
different CPU types share caches and the same cache type uses
different size in different instances, etc.

Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/lscpu-topology.c
sys-utils/lscpu.c
sys-utils/lscpu.h

index f54317fcab0dba0d79d2a615489775ebcd5045ed..f4c2ff2a31b67ae5454f9a500632da87f9feeef8 100644 (file)
@@ -49,8 +49,6 @@ void lscpu_cputype_free_topology(struct lscpu_cputype *ct)
        free_cpuset_array(ct->socketmaps, ct->nsockets);
        free_cpuset_array(ct->bookmaps, ct->nbooks);
        free_cpuset_array(ct->drawermaps, ct->ndrawers);
-
-       lscpu_free_caches(ct->caches, ct->ncaches);
 }
 
 void lscpu_free_caches(struct lscpu_cache *caches, size_t n)
@@ -63,7 +61,8 @@ void lscpu_free_caches(struct lscpu_cache *caches, size_t n)
        for (i = 0; i < n; i++) {
                struct lscpu_cache *c = &caches[i];
 
-               DBG(MISC, ul_debug(" freeing #%zu cache [%s]", i, c->name));
+               DBG(MISC, ul_debug(" freeing cache #%zu %s::%d",
+                                       i, c->name, c->id));
 
                free(c->name);
                free(c->type);
@@ -222,48 +221,87 @@ static int cputype_read_topology(struct lscpu_cxt *cxt, struct lscpu_cputype *ct
        return 0;
 }
 
-static int read_caches(struct lscpu_cxt *cxt, struct lscpu_cputype *ct, struct lscpu_cpu *cpu)
+/*
+ * The cache is identifued by type+level+id.
+ */
+static struct lscpu_cache *get_cache(struct lscpu_cxt *cxt,
+                               const char *type, int level, int id)
+{
+       size_t i;
+
+       for (i = 0; i < cxt->ncaches; i++) {
+               struct lscpu_cache *ca = &cxt->caches[i];
+               if (ca->id == id &&
+                   ca->level == level &&
+                   strcmp(ca->type, type) == 0)
+                       return ca;
+       }
+       return NULL;
+}
+
+static struct lscpu_cache *add_cache(struct lscpu_cxt *cxt,
+                               const char *type, int level, int id)
+{
+       struct lscpu_cache *ca;
+
+       cxt->ncaches++;
+       cxt->caches = xrealloc(cxt->caches,
+                              cxt->ncaches * sizeof(*cxt->caches));
+
+       ca = &cxt->caches[cxt->ncaches - 1];
+       memset(ca, 0 , sizeof(*ca));
+
+       ca->id = id;
+       ca->level = level;
+       ca->type = xstrdup(type);
+
+       DBG(GATHER, ul_debugobj(cxt, "add cache %s%d::%d", type, level, id));
+
+       return ca;
+}
+
+static int read_caches(struct lscpu_cxt *cxt, struct lscpu_cpu *cpu)
 {
        char buf[256];
        struct path_cxt *sys = cxt->syscpu;
        int num = cpu->logical_id;
-       size_t i, setsize;
-
-       if (!ct->ncaches) {
-               while (ul_path_accessf(sys, F_OK,
-                                       "cpu%d/cache/index%zu",
-                                       num, ct->ncaches) == 0)
-                       ct->ncaches++;
+       size_t i, ncaches, setsize;
 
-               if (!ct->ncaches)
-                       return 0;
-               ct->caches = xcalloc(ct->ncaches, sizeof(*ct->caches));
-       }
+       ncaches = cxt->ncaches;
+       while (ul_path_accessf(sys, F_OK,
+                               "cpu%d/cache/index%zu",
+                               num, ncaches) == 0)
+               ncaches++;
 
        setsize = CPU_ALLOC_SIZE(cxt->maxcpus);
 
-       for (i = 0; i < ct->ncaches; i++) {
-               struct lscpu_cache *ca = &ct->caches[i];
+       for (i = 0; i < ncaches; i++) {
+               struct lscpu_cache *ca;
                cpu_set_t *map;
+               int id, level;
 
-               if (ul_path_accessf(sys, F_OK, "cpu%d/cache/index%zu", num, i) != 0)
+               if (ul_path_readf_s32(sys, &id, "cpu%d/cache/index%zu/id", num, i) != 0)
+                       continue;
+               if (ul_path_readf_s32(sys, &level, "cpu%d/cache/index%zu/level", num, i) != 0)
+                       continue;
+               if (ul_path_readf_buffer(sys, buf, sizeof(buf),
+                                        "cpu%d/cache/index%zu/type", num, i) <= 0)
                        continue;
 
+               ca = get_cache(cxt, buf, level, id);
+               if (!ca)
+                       ca = add_cache(cxt, buf, level, id);
+
                if (!ca->name) {
                        int type = 0;
 
-                       /* cache type */
-                       if (ul_path_readf_string(sys, &ca->type,
-                                       "cpu%d/cache/index%zu/type", num, i) > 0) {
-                               if (!strcmp(ca->type, "Data"))
-                                       type = 'd';
-                               else if (!strcmp(ca->type, "Instruction"))
-                                       type = 'i';
-                       }
+                       assert(ca->type);
+
+                       if (!strcmp(ca->type, "Data"))
+                               type = 'd';
+                       else if (!strcmp(ca->type, "Instruction"))
+                               type = 'i';
 
-                       /* cache level */
-                       ul_path_readf_s32(sys, &ca->level,
-                                       "cpu%d/cache/index%zu/level", num, i);
                        if (type)
                                snprintf(buf, sizeof(buf), "L%d%c", ca->level, type);
                        else
@@ -306,29 +344,6 @@ static int read_caches(struct lscpu_cxt *cxt, struct lscpu_cputype *ct, struct l
        return 0;
 }
 
-/* Read cache for specified type */
-static int cputype_read_caches(struct lscpu_cxt *cxt, struct lscpu_cputype *ct)
-{
-       size_t i;
-       int rc = 0;
-
-       DBG(TYPE, ul_debugobj(ct, "reading %s/%s/%s topology",
-                               ct->vendor ?: "", ct->model ?: "", ct->modelname ?:""));
-
-       for (i = 0; i < cxt->npossibles; i++) {
-               struct lscpu_cpu *cpu = cxt->cpus[i];
-
-               if (!cpu || cpu->type != ct)
-                       continue;
-               rc = read_caches(cxt, ct, cpu);
-               if (rc)
-                       break;
-       }
-
-       lscpu_sort_caches(ct->caches, ct->ncaches);
-       return rc;
-}
-
 static int read_ids(struct lscpu_cxt *cxt, struct lscpu_cpu *cpu)
 {
        struct path_cxt *sys = cxt->syscpu;
@@ -420,10 +435,8 @@ int lscpu_read_topology(struct lscpu_cxt *cxt)
        size_t i;
        int rc = 0;
 
-       for (i = 0; i < cxt->ncputypes; i++) {
+       for (i = 0; i < cxt->ncputypes; i++)
                rc += cputype_read_topology(cxt, cxt->cputypes[i]);
-               rc += cputype_read_caches(cxt, cxt->cputypes[i]);
-       }
 
        for (i = 0; rc == 0 && i < cxt->npossibles; i++) {
                struct lscpu_cpu *cpu = cxt->cpus[i];
@@ -440,8 +453,12 @@ int lscpu_read_topology(struct lscpu_cxt *cxt)
                        rc = read_configure(cxt, cpu);
                if (!rc)
                        rc = read_mhz(cxt, cpu);
+               if (!rc)
+                       rc = read_caches(cxt, cpu);
        }
 
+       lscpu_sort_caches(cxt->caches, cxt->ncaches);
+
        return rc;
 }
 
index ace20f91d90642f7ec52d788408840634f0cffaf..c4c5af9dddb230be9c1ea84c30ff9dd30884fb2a 100644 (file)
@@ -269,7 +269,9 @@ static void lscpu_free_context(struct lscpu_cxt *cxt)
 
        lscpu_free_virtualization(cxt->virt);
        lscpu_free_architecture(cxt->arch);
+
        lscpu_free_caches(cxt->ecaches, cxt->necaches);
+       lscpu_free_caches(cxt->caches, cxt->ncaches);
 
        free(cxt);
 }
index ac90860f4ca172a58bd3fb1a74463a64fae226c3..d3dd77edea91abc7192317a003f4d4922b702eb7 100644 (file)
@@ -35,6 +35,7 @@ UL_DEBUG_DECLARE_MASK(lscpu);
 #define _PATH_SYS_DMI_TYPE4    "/sys/firmware/dmi/entries/4-0/raw"
 
 struct lscpu_cache {
+       int             id;             /* unique identifier */
        int             nth;            /* cache<number> from cpuinfo */
        char            *name;
        char            *type;
@@ -80,9 +81,6 @@ struct lscpu_cputype {
        int     nbooks_per_drawer;
        int     ndrawers_per_system;
 
-       struct lscpu_cache *caches;
-       size_t ncaches;
-
        /* siblings maps */
        int             ncores;
        cpu_set_t       **coremaps;
@@ -211,6 +209,8 @@ struct lscpu_cxt {
        struct lscpu_vulnerability *vuls;       /* array of CPU vulnerabilities */
        size_t  nvuls;                          /* number of CPU vulnerabilities */
 
+       struct lscpu_cache *caches;
+       size_t ncaches;
 
        struct lscpu_cache *ecaches;
        size_t necaches;                /* extra caches (s390) from /proc/cpuinfo */