diff options
Diffstat (limited to 'tools/perf/arch/x86/util/header.c')
-rw-r--r-- | tools/perf/arch/x86/util/header.c | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/tools/perf/arch/x86/util/header.c b/tools/perf/arch/x86/util/header.c index fb0d71afee8b..af9a9f2600be 100644 --- a/tools/perf/arch/x86/util/header.c +++ b/tools/perf/arch/x86/util/header.c @@ -4,6 +4,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <regex.h> #include "../../util/header.h" @@ -70,9 +71,72 @@ get_cpuid_str(struct perf_pmu *pmu __maybe_unused) { char *buf = malloc(128); - if (buf && __get_cpuid(buf, 128, "%s-%u-%X$") < 0) { + if (buf && __get_cpuid(buf, 128, "%s-%u-%X-%X$") < 0) { free(buf); return NULL; } return buf; } + +/* Full CPUID format for x86 is vendor-family-model-stepping */ +static bool is_full_cpuid(const char *id) +{ + const char *tmp = id; + int count = 0; + + while ((tmp = strchr(tmp, '-')) != NULL) { + count++; + tmp++; + } + + if (count == 3) + return true; + + return false; +} + +int strcmp_cpuid_str(const char *mapcpuid, const char *id) +{ + regex_t re; + regmatch_t pmatch[1]; + int match; + bool full_mapcpuid = is_full_cpuid(mapcpuid); + bool full_cpuid = is_full_cpuid(id); + + /* + * Full CPUID format is required to identify a platform. + * Error out if the cpuid string is incomplete. + */ + if (full_mapcpuid && !full_cpuid) { + pr_info("Invalid CPUID %s. Full CPUID is required, " + "vendor-family-model-stepping\n", id); + return 1; + } + + if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) { + /* Warn unable to generate match particular string. */ + pr_info("Invalid regular expression %s\n", mapcpuid); + return 1; + } + + match = !regexec(&re, id, 1, pmatch, 0); + regfree(&re); + if (match) { + size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so); + size_t cpuid_len; + + /* If the full CPUID format isn't required, + * ignoring the stepping. + */ + if (!full_mapcpuid && full_cpuid) + cpuid_len = strrchr(id, '-') - id; + else + cpuid_len = strlen(id); + + /* Verify the entire string matched. */ + if (match_len == cpuid_len) + return 0; + } + + return 1; +} |