Linux Audio

Check our new training course

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