1 // SPDX-License-Identifier: GPL-2.0-only
3 * Implementation of get_cpuid().
5 * Copyright IBM Corp. 2014, 2018
6 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
7 * Thomas Richter <tmricht@linux.vnet.ibm.com>
10 #include <sys/types.h>
15 #include <linux/ctype.h>
16 #include <linux/kernel.h>
17 #include <linux/zalloc.h>
19 #include "../../util/header.h"
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"
30 int get_cpuid(char *buffer
, size_t sz
, struct perf_cpu cpu __maybe_unused
)
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;
36 unsigned long line_sz
;
41 * Scan /proc/sysinfo line by line and read out values for
42 * Manufacturer:, Type: and Model:, for example:
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
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
));
56 sysinfo
= fopen(SYSINFO
, "r");
60 while ((read
= getline(&line
, &line_sz
, sysinfo
)) != -1) {
61 if (!strncmp(line
, SYSINFO_MANU
, strlen(SYSINFO_MANU
))) {
62 line2
= line
+ strlen(SYSINFO_MANU
);
64 while ((cp
= strtok_r(line2
, "\n ", &line2
))) {
65 mfsize
+= scnprintf(manufacturer
+ mfsize
,
66 sizeof(manufacturer
) - mfsize
, "%s", cp
);
70 if (!strncmp(line
, SYSINFO_TYPE
, strlen(SYSINFO_TYPE
))) {
71 line2
= line
+ strlen(SYSINFO_TYPE
);
73 while ((cp
= strtok_r(line2
, "\n ", &line2
))) {
74 tpsize
+= scnprintf(type
+ tpsize
,
75 sizeof(type
) - tpsize
, "%s", cp
);
79 if (!strncmp(line
, SYSINFO_MODEL
, strlen(SYSINFO_MODEL
))) {
80 line2
= line
+ strlen(SYSINFO_MODEL
);
82 while ((cp
= strtok_r(line2
, "\n ", &line2
))) {
83 mdsize
+= scnprintf(model
+ mdsize
, sizeof(model
) - mdsize
,
84 "%s%s", model
[0] ? "," : "", cp
);
91 /* Missing manufacturer, type or model information should not happen */
92 if (!manufacturer
[0] || !type
[0] || !model
[0])
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.
100 sysinfo
= fopen(SRVLVL
, "r");
103 while ((read
= getline(&line
, &line_sz
, sysinfo
)) != -1) {
104 if (strncmp(line
, SRVLVL_CPUMF
, strlen(SRVLVL_CPUMF
)))
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
, '=');
113 vssize
+= scnprintf(version
+ vssize
,
114 sizeof(version
) - vssize
, "%s", sep
+ 1);
116 if (!strncmp(cp
, SRVLVL_AUTHORIZATION
,
117 strlen(SRVLVL_AUTHORIZATION
))) {
118 char *sep
= strchr(cp
, '=');
120 atsize
+= scnprintf(authorization
+ atsize
,
121 sizeof(authorization
) - atsize
, "%s", sep
+ 1);
130 if (version
[0] && authorization
[0] )
131 nbytes
= snprintf(buffer
, sz
, "%s,%s,%s,%s,%s",
132 manufacturer
, type
, model
, version
,
135 nbytes
= snprintf(buffer
, sz
, "%s,%s,%s", manufacturer
, type
,
137 return (nbytes
>= sz
) ? ENOBUFS
: 0;
140 char *get_cpuid_str(struct perf_cpu cpu
)
142 char *buf
= malloc(128);
144 if (buf
&& get_cpuid(buf
, 128, cpu
))