0001
0002 #include <sys/types.h>
0003 #include <errno.h>
0004 #include <unistd.h>
0005 #include <stdio.h>
0006 #include <stdlib.h>
0007 #include <string.h>
0008 #include <regex.h>
0009
0010 #include "../../../util/debug.h"
0011 #include "../../../util/header.h"
0012 #include "cpuid.h"
0013
0014 void get_cpuid_0(char *vendor, unsigned int *lvl)
0015 {
0016 unsigned int b, c, d;
0017
0018 cpuid(0, 0, lvl, &b, &c, &d);
0019 strncpy(&vendor[0], (char *)(&b), 4);
0020 strncpy(&vendor[4], (char *)(&d), 4);
0021 strncpy(&vendor[8], (char *)(&c), 4);
0022 vendor[12] = '\0';
0023 }
0024
0025 static int
0026 __get_cpuid(char *buffer, size_t sz, const char *fmt)
0027 {
0028 unsigned int a, b, c, d, lvl;
0029 int family = -1, model = -1, step = -1;
0030 int nb;
0031 char vendor[16];
0032
0033 get_cpuid_0(vendor, &lvl);
0034
0035 if (lvl >= 1) {
0036 cpuid(1, 0, &a, &b, &c, &d);
0037
0038 family = (a >> 8) & 0xf;
0039 model = (a >> 4) & 0xf;
0040 step = a & 0xf;
0041
0042
0043 if (family == 0xf)
0044 family += (a >> 20) & 0xff;
0045
0046
0047 if (family >= 0x6)
0048 model += ((a >> 16) & 0xf) << 4;
0049 }
0050 nb = scnprintf(buffer, sz, fmt, vendor, family, model, step);
0051
0052
0053 if (strchr(buffer, '$')) {
0054 buffer[nb-1] = '\0';
0055 return 0;
0056 }
0057 return ENOBUFS;
0058 }
0059
0060 int
0061 get_cpuid(char *buffer, size_t sz)
0062 {
0063 return __get_cpuid(buffer, sz, "%s,%u,%u,%u$");
0064 }
0065
0066 char *
0067 get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
0068 {
0069 char *buf = malloc(128);
0070
0071 if (buf && __get_cpuid(buf, 128, "%s-%u-%X-%X$") < 0) {
0072 free(buf);
0073 return NULL;
0074 }
0075 return buf;
0076 }
0077
0078
0079 static bool is_full_cpuid(const char *id)
0080 {
0081 const char *tmp = id;
0082 int count = 0;
0083
0084 while ((tmp = strchr(tmp, '-')) != NULL) {
0085 count++;
0086 tmp++;
0087 }
0088
0089 if (count == 3)
0090 return true;
0091
0092 return false;
0093 }
0094
0095 int strcmp_cpuid_str(const char *mapcpuid, const char *id)
0096 {
0097 regex_t re;
0098 regmatch_t pmatch[1];
0099 int match;
0100 bool full_mapcpuid = is_full_cpuid(mapcpuid);
0101 bool full_cpuid = is_full_cpuid(id);
0102
0103
0104
0105
0106
0107 if (full_mapcpuid && !full_cpuid) {
0108 pr_info("Invalid CPUID %s. Full CPUID is required, "
0109 "vendor-family-model-stepping\n", id);
0110 return 1;
0111 }
0112
0113 if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
0114
0115 pr_info("Invalid regular expression %s\n", mapcpuid);
0116 return 1;
0117 }
0118
0119 match = !regexec(&re, id, 1, pmatch, 0);
0120 regfree(&re);
0121 if (match) {
0122 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
0123 size_t cpuid_len;
0124
0125
0126
0127
0128 if (!full_mapcpuid && full_cpuid)
0129 cpuid_len = strrchr(id, '-') - id;
0130 else
0131 cpuid_len = strlen(id);
0132
0133
0134 if (match_len == cpuid_len)
0135 return 0;
0136 }
0137
0138 return 1;
0139 }