diff options
-rw-r--r-- | tools/perf/arch/x86/util/header.c | 66 | ||||
-rw-r--r-- | tools/perf/pmu-events/arch/x86/mapfile.csv | 2 | ||||
-rw-r--r-- | tools/perf/util/pmu.c | 2 |
3 files changed, 67 insertions, 3 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; +} diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 7e3cce3bcf3b..183a42c99251 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -31,4 +31,4 @@ GenuineIntel-6-2A,v15,sandybridge,core GenuineIntel-6-2C,v2,westmereep-dp,core GenuineIntel-6-25,v2,westmereep-sp,core GenuineIntel-6-2F,v2,westmereex,core -GenuineIntel-6-55,v1,skylakex,core +GenuineIntel-6-55-[01234],v1,skylakex,core diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 7348eea0248f..c660625d7d4b 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -670,7 +670,7 @@ char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused) * cpuid string generated on this platform. * Otherwise return non-zero. */ -int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid) +int __weak strcmp_cpuid_str(const char *mapcpuid, const char *cpuid) { regex_t re; regmatch_t pmatch[1]; |