brintos

brintos / linux-shallow public Read only

0
0
Text · 2.8 KiB · a51444a Raw
140 lines · c
1// SPDX-License-Identifier: GPL-2.02#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 int26__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 60int61get_cpuid(char *buffer, size_t sz)62{63	return __get_cpuid(buffer, sz, "%s,%u,%u,%u$");64}65 66char *67get_cpuid_str(struct perf_pmu *pmu __maybe_unused)68{69	char *buf = malloc(128);70 71	if (buf && __get_cpuid(buf, 128, "%s-%u-%X-%X$") < 0) {72		free(buf);73		return NULL;74	}75	return buf;76}77 78/* Full CPUID format for x86 is vendor-family-model-stepping */79static bool is_full_cpuid(const char *id)80{81	const char *tmp = id;82	int count = 0;83 84	while ((tmp = strchr(tmp, '-')) != NULL) {85		count++;86		tmp++;87	}88 89	if (count == 3)90		return true;91 92	return false;93}94 95int strcmp_cpuid_str(const char *mapcpuid, const char *id)96{97	regex_t re;98	regmatch_t pmatch[1];99	int match;100	bool full_mapcpuid = is_full_cpuid(mapcpuid);101	bool full_cpuid = is_full_cpuid(id);102 103	/*104	 * Full CPUID format is required to identify a platform.105	 * Error out if the cpuid string is incomplete.106	 */107	if (full_mapcpuid && !full_cpuid) {108		pr_info("Invalid CPUID %s. Full CPUID is required, "109			"vendor-family-model-stepping\n", id);110		return 1;111	}112 113	if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {114		/* Warn unable to generate match particular string. */115		pr_info("Invalid regular expression %s\n", mapcpuid);116		return 1;117	}118 119	match = !regexec(&re, id, 1, pmatch, 0);120	regfree(&re);121	if (match) {122		size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);123		size_t cpuid_len;124 125		/* If the full CPUID format isn't required,126		 * ignoring the stepping.127		 */128		if (!full_mapcpuid && full_cpuid)129			cpuid_len = strrchr(id, '-') - id;130		else131			cpuid_len = strlen(id);132 133		/* Verify the entire string matched. */134		if (match_len == cpuid_len)135			return 0;136	}137 138	return 1;139}140