mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
3b54411a44
The perf tools cannot find the proper event list for the Cascadelake server. Because the Cascadelake server and the Skylake server have the same CPU model number, which are used by the perf tools to find the event list. The stepping for Skylake server is up to 4. The stepping for Cascadelake server starts from 5. The stepping can be used to distinguish between them. The stepping is added in get_cpuid_str(). The stepping information for Skylake server is updated in mapfile.csv. A x86 specific strcmp_cpuid_cmp() function is added to handle two CPUID formats in mapfile.csv, "vendor-family-model-stepping" and "vendor-family-model": - If a cpuid-regular-expression from the mapfile.csv using the new stepping format, a cpuid-string generated on the machine must include stepping. Otherwise, it is a mismatch. - If the cpuid-regular-expression using the old non-stepping format, the stepping in the cpuid-string will be ignored. The script, using environment string "PERF_CPUID" without stepping on Skylake server, will be broken. If so, users must fix their scripts. Committer notes: Fixed this build error on centos:6 and debian:7: arch/x86/util/header.c: In function 'is_full_cpuid': arch/x86/util/header.c:82:39: error: declaration of 'cpuid' shadows a global declaration [-Werror=shadow] arch/x86/util/header.c:12:1: error: shadowed declaration is here [-Werror=shadow] arch/x86/util/header.c: In function 'strcmp_cpuid_str': arch/x86/util/header.c:98:56: error: declaration of 'cpuid' shadows a global declaration [-Werror=shadow] arch/x86/util/header.c:12:1: error: shadowed declaration is here [-Werror=shadow] cc1: all warnings being treated as errors Signed-off-by: Kan Liang <kan.liang@linux.intel.com> Reviewed-by: Jiri Olsa <jolsa@kernel.org> Cc: Andi Kleen <ak@linux.intel.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20181114212416.15665-1-kan.liang@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
143 lines
2.9 KiB
C
143 lines
2.9 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <regex.h>
|
|
|
|
#include "../../util/header.h"
|
|
|
|
static inline void
|
|
cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
|
|
unsigned int *d)
|
|
{
|
|
__asm__ __volatile__ (".byte 0x53\n\tcpuid\n\t"
|
|
"movl %%ebx, %%esi\n\t.byte 0x5b"
|
|
: "=a" (*a),
|
|
"=S" (*b),
|
|
"=c" (*c),
|
|
"=d" (*d)
|
|
: "a" (op));
|
|
}
|
|
|
|
static int
|
|
__get_cpuid(char *buffer, size_t sz, const char *fmt)
|
|
{
|
|
unsigned int a, b, c, d, lvl;
|
|
int family = -1, model = -1, step = -1;
|
|
int nb;
|
|
char vendor[16];
|
|
|
|
cpuid(0, &lvl, &b, &c, &d);
|
|
strncpy(&vendor[0], (char *)(&b), 4);
|
|
strncpy(&vendor[4], (char *)(&d), 4);
|
|
strncpy(&vendor[8], (char *)(&c), 4);
|
|
vendor[12] = '\0';
|
|
|
|
if (lvl >= 1) {
|
|
cpuid(1, &a, &b, &c, &d);
|
|
|
|
family = (a >> 8) & 0xf; /* bits 11 - 8 */
|
|
model = (a >> 4) & 0xf; /* Bits 7 - 4 */
|
|
step = a & 0xf;
|
|
|
|
/* extended family */
|
|
if (family == 0xf)
|
|
family += (a >> 20) & 0xff;
|
|
|
|
/* extended model */
|
|
if (family >= 0x6)
|
|
model += ((a >> 16) & 0xf) << 4;
|
|
}
|
|
nb = scnprintf(buffer, sz, fmt, vendor, family, model, step);
|
|
|
|
/* look for end marker to ensure the entire data fit */
|
|
if (strchr(buffer, '$')) {
|
|
buffer[nb-1] = '\0';
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
get_cpuid(char *buffer, size_t sz)
|
|
{
|
|
return __get_cpuid(buffer, sz, "%s,%u,%u,%u$");
|
|
}
|
|
|
|
char *
|
|
get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
|
|
{
|
|
char *buf = malloc(128);
|
|
|
|
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;
|
|
}
|