linux/tools/perf/arch/s390/util/header.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Implementation of get_cpuid().
   4 *
   5 * Copyright IBM Corp. 2014, 2018
   6 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
   7 *            Thomas Richter <tmricht@linux.vnet.ibm.com>
   8 */
   9
  10#include <sys/types.h>
  11#include <errno.h>
  12#include <unistd.h>
  13#include <stdio.h>
  14#include <string.h>
  15#include <linux/ctype.h>
  16#include <linux/kernel.h>
  17#include <linux/zalloc.h>
  18
  19#include "../../util/header.h"
  20
  21#define SYSINFO_MANU    "Manufacturer:"
  22#define SYSINFO_TYPE    "Type:"
  23#define SYSINFO_MODEL   "Model:"
  24#define SRVLVL_CPUMF    "CPU-MF:"
  25#define SRVLVL_VERSION  "version="
  26#define SRVLVL_AUTHORIZATION    "authorization="
  27#define SYSINFO         "/proc/sysinfo"
  28#define SRVLVL          "/proc/service_levels"
  29
  30int get_cpuid(char *buffer, size_t sz)
  31{
  32        char *cp, *line = NULL, *line2;
  33        char type[8], model[33], version[8], manufacturer[32], authorization[8];
  34        int tpsize = 0, mdsize = 0, vssize = 0, mfsize = 0, atsize = 0;
  35        int read;
  36        unsigned long line_sz;
  37        size_t nbytes;
  38        FILE *sysinfo;
  39
  40        /*
  41         * Scan /proc/sysinfo line by line and read out values for
  42         * Manufacturer:, Type: and Model:, for example:
  43         * Manufacturer:    IBM
  44         * Type:            2964
  45         * Model:           702              N96
  46         * The first word is the Model Capacity and the second word is
  47         * Model (can be omitted). Both words have a maximum size of 16
  48         * bytes.
  49         */
  50        memset(manufacturer, 0, sizeof(manufacturer));
  51        memset(type, 0, sizeof(type));
  52        memset(model, 0, sizeof(model));
  53        memset(version, 0, sizeof(version));
  54        memset(authorization, 0, sizeof(authorization));
  55
  56        sysinfo = fopen(SYSINFO, "r");
  57        if (sysinfo == NULL)
  58                return errno;
  59
  60        while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
  61                if (!strncmp(line, SYSINFO_MANU, strlen(SYSINFO_MANU))) {
  62                        line2 = line + strlen(SYSINFO_MANU);
  63
  64                        while ((cp = strtok_r(line2, "\n ", &line2))) {
  65                                mfsize += scnprintf(manufacturer + mfsize,
  66                                                    sizeof(manufacturer) - mfsize, "%s", cp);
  67                        }
  68                }
  69
  70                if (!strncmp(line, SYSINFO_TYPE, strlen(SYSINFO_TYPE))) {
  71                        line2 = line + strlen(SYSINFO_TYPE);
  72
  73                        while ((cp = strtok_r(line2, "\n ", &line2))) {
  74                                tpsize += scnprintf(type + tpsize,
  75                                                    sizeof(type) - tpsize, "%s", cp);
  76                        }
  77                }
  78
  79                if (!strncmp(line, SYSINFO_MODEL, strlen(SYSINFO_MODEL))) {
  80                        line2 = line + strlen(SYSINFO_MODEL);
  81
  82                        while ((cp = strtok_r(line2, "\n ", &line2))) {
  83                                mdsize += scnprintf(model + mdsize, sizeof(model) - mdsize,
  84                                                    "%s%s", model[0] ? "," : "", cp);
  85                        }
  86                        break;
  87                }
  88        }
  89        fclose(sysinfo);
  90
  91        /* Missing manufacturer, type or model information should not happen */
  92        if (!manufacturer[0] || !type[0] || !model[0])
  93                return EINVAL;
  94
  95        /*
  96         * Scan /proc/service_levels and return the CPU-MF counter facility
  97         * version number and authorization level.
  98         * Optional, does not exist on z/VM guests.
  99         */
 100        sysinfo = fopen(SRVLVL, "r");
 101        if (sysinfo == NULL)
 102                goto skip_sysinfo;
 103        while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
 104                if (strncmp(line, SRVLVL_CPUMF, strlen(SRVLVL_CPUMF)))
 105                        continue;
 106
 107                line2 = line + strlen(SRVLVL_CPUMF);
 108                while ((cp = strtok_r(line2, "\n ", &line2))) {
 109                        if (!strncmp(cp, SRVLVL_VERSION,
 110                                     strlen(SRVLVL_VERSION))) {
 111                                char *sep = strchr(cp, '=');
 112
 113                                vssize += scnprintf(version + vssize,
 114                                                    sizeof(version) - vssize, "%s", sep + 1);
 115                        }
 116                        if (!strncmp(cp, SRVLVL_AUTHORIZATION,
 117                                     strlen(SRVLVL_AUTHORIZATION))) {
 118                                char *sep = strchr(cp, '=');
 119
 120                                atsize += scnprintf(authorization + atsize,
 121                                                    sizeof(authorization) - atsize, "%s", sep + 1);
 122                        }
 123                }
 124        }
 125        fclose(sysinfo);
 126
 127skip_sysinfo:
 128        free(line);
 129
 130        if (version[0] && authorization[0] )
 131                nbytes = snprintf(buffer, sz, "%s,%s,%s,%s,%s",
 132                                  manufacturer, type, model, version,
 133                                  authorization);
 134        else
 135                nbytes = snprintf(buffer, sz, "%s,%s,%s", manufacturer, type,
 136                                  model);
 137        return (nbytes >= sz) ? ENOBUFS : 0;
 138}
 139
 140char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
 141{
 142        char *buf = malloc(128);
 143
 144        if (buf && get_cpuid(buf, 128))
 145                zfree(&buf);
 146        return buf;
 147}
 148