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