1
2#include <sys/types.h>
3#include <unistd.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <regex.h>
8
9#include "../../util/header.h"
10
11static inline void
12cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
13 unsigned int *d)
14{
15 __asm__ __volatile__ (".byte 0x53\n\tcpuid\n\t"
16 "movl %%ebx, %%esi\n\t.byte 0x5b"
17 : "=a" (*a),
18 "=S" (*b),
19 "=c" (*c),
20 "=d" (*d)
21 : "a" (op));
22}
23
24static int
25__get_cpuid(char *buffer, size_t sz, const char *fmt)
26{
27 unsigned int a, b, c, d, lvl;
28 int family = -1, model = -1, step = -1;
29 int nb;
30 char vendor[16];
31
32 cpuid(0, &lvl, &b, &c, &d);
33 strncpy(&vendor[0], (char *)(&b), 4);
34 strncpy(&vendor[4], (char *)(&d), 4);
35 strncpy(&vendor[8], (char *)(&c), 4);
36 vendor[12] = '\0';
37
38 if (lvl >= 1) {
39 cpuid(1, &a, &b, &c, &d);
40
41 family = (a >> 8) & 0xf;
42 model = (a >> 4) & 0xf;
43 step = a & 0xf;
44
45
46 if (family == 0xf)
47 family += (a >> 20) & 0xff;
48
49
50 if (family >= 0x6)
51 model += ((a >> 16) & 0xf) << 4;
52 }
53 nb = scnprintf(buffer, sz, fmt, vendor, family, model, step);
54
55
56 if (strchr(buffer, '$')) {
57 buffer[nb-1] = '\0';
58 return 0;
59 }
60 return -1;
61}
62
63int
64get_cpuid(char *buffer, size_t sz)
65{
66 return __get_cpuid(buffer, sz, "%s,%u,%u,%u$");
67}
68
69char *
70get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
71{
72 char *buf = malloc(128);
73
74 if (buf && __get_cpuid(buf, 128, "%s-%u-%X-%X$") < 0) {
75 free(buf);
76 return NULL;
77 }
78 return buf;
79}
80
81
82static bool is_full_cpuid(const char *id)
83{
84 const char *tmp = id;
85 int count = 0;
86
87 while ((tmp = strchr(tmp, '-')) != NULL) {
88 count++;
89 tmp++;
90 }
91
92 if (count == 3)
93 return true;
94
95 return false;
96}
97
98int strcmp_cpuid_str(const char *mapcpuid, const char *id)
99{
100 regex_t re;
101 regmatch_t pmatch[1];
102 int match;
103 bool full_mapcpuid = is_full_cpuid(mapcpuid);
104 bool full_cpuid = is_full_cpuid(id);
105
106
107
108
109
110 if (full_mapcpuid && !full_cpuid) {
111 pr_info("Invalid CPUID %s. Full CPUID is required, "
112 "vendor-family-model-stepping\n", id);
113 return 1;
114 }
115
116 if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
117
118 pr_info("Invalid regular expression %s\n", mapcpuid);
119 return 1;
120 }
121
122 match = !regexec(&re, id, 1, pmatch, 0);
123 regfree(&re);
124 if (match) {
125 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
126 size_t cpuid_len;
127
128
129
130
131 if (!full_mapcpuid && full_cpuid)
132 cpuid_len = strrchr(id, '-') - id;
133 else
134 cpuid_len = strlen(id);
135
136
137 if (match_len == cpuid_len)
138 return 0;
139 }
140
141 return 1;
142}
143