perf vendor events: Use more flexible pattern matching for CPU identification for mapfile.csv

The powerpc cpuid information includes chip revision information.
Changes between chip revisions are usually minor bug fixes and usually
do not affect the operation of the performance monitoring hardware.

The original mapfile.csv matching requires enumerating every possible
cpuid string.  When a new minor chip revision is produced a new entry
has to be added to the mapfile.csv and the code recompiled to allow perf
to have the implementation specific perf events for this new minor
revision.  For users of various distibutions of Linux having to wait for
a new release of the kernel's perf tool to be built with these trivial
patches is inconvenient.

Using regular expressions rather than exactly string matching of the
entire cpuid string allows developers to write mapfile.csv files that do
not require patches and recompiles for each of these minor version
changes.  If special cases need to be made for some particular versions,
they can be placed earlier in the mapfile.csv file before the more
general matches.

Signed-off-by: William Cohen <wcohen@redhat.com>
Tested-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Shriya <shriyak@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/20171204145728.16792-1-wcohen@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
William Cohen 2017-12-04 09:57:28 -05:00 committed by Arnaldo Carvalho de Melo
parent 0125195268
commit fbc2844e84
4 changed files with 60 additions and 16 deletions

View file

@ -13,13 +13,5 @@
# #
# Power8 entries # Power8 entries
004b0000,1,power8,core 004[bcd][[:xdigit:]]{4},1,power8,core
004b0201,1,power8,core 004e[[:xdigit:]]{4},1,power9,core
004c0000,1,power8,core
004d0000,1,power8,core
004d0100,1,power8,core
004d0200,1,power8,core
004c0100,1,power8,core
004e0100,1,power9,core
004e0200,1,power9,core
004e1200,1,power9,core

1 # Format:
13 #
14 # Power8 entries
15 004b0000,1,power8,core 004[bcd][[:xdigit:]]{4},1,power8,core
16 004b0201,1,power8,core 004e[[:xdigit:]]{4},1,power9,core
17
004d0000,1,power8,core
004d0100,1,power8,core
004d0200,1,power8,core
004c0100,1,power8,core
004e0100,1,power9,core
004e0200,1,power9,core
004e1200,1,power9,core

View file

@ -23,10 +23,7 @@ GenuineIntel-6-1E,v2,nehalemep,core
GenuineIntel-6-1F,v2,nehalemep,core GenuineIntel-6-1F,v2,nehalemep,core
GenuineIntel-6-1A,v2,nehalemep,core GenuineIntel-6-1A,v2,nehalemep,core
GenuineIntel-6-2E,v2,nehalemex,core GenuineIntel-6-2E,v2,nehalemex,core
GenuineIntel-6-4E,v24,skylake,core GenuineIntel-6-[4589]E,v24,skylake,core
GenuineIntel-6-5E,v24,skylake,core
GenuineIntel-6-8E,v24,skylake,core
GenuineIntel-6-9E,v24,skylake,core
GenuineIntel-6-37,v13,silvermont,core GenuineIntel-6-37,v13,silvermont,core
GenuineIntel-6-4D,v13,silvermont,core GenuineIntel-6-4D,v13,silvermont,core
GenuineIntel-6-4C,v13,silvermont,core GenuineIntel-6-4C,v13,silvermont,core

1 Family-model Version Filename EventType
23 GenuineIntel-6-1F v2 nehalemep core
24 GenuineIntel-6-1A v2 nehalemep core
25 GenuineIntel-6-2E v2 nehalemex core
26 GenuineIntel-6-4E GenuineIntel-6-[4589]E v24 skylake core
GenuineIntel-6-5E v24 skylake core
GenuineIntel-6-8E v24 skylake core
GenuineIntel-6-9E v24 skylake core
27 GenuineIntel-6-37 v13 silvermont core
28 GenuineIntel-6-4D v13 silvermont core
29 GenuineIntel-6-4C v13 silvermont core

View file

@ -116,6 +116,43 @@ static void fixdesc(char *s)
*e = 0; *e = 0;
} }
/* Add escapes for '\' so they are proper C strings. */
static char *fixregex(char *s)
{
int len = 0;
int esc_count = 0;
char *fixed = NULL;
char *p, *q;
/* Count the number of '\' in string */
for (p = s; *p; p++) {
++len;
if (*p == '\\')
++esc_count;
}
if (esc_count == 0)
return s;
/* allocate space for a new string */
fixed = (char *) malloc(len + 1);
if (!fixed)
return NULL;
/* copy over the characters */
q = fixed;
for (p = s; *p; p++) {
if (*p == '\\') {
*q = '\\';
++q;
}
*q = *p;
++q;
}
*q = '\0';
return fixed;
}
static struct msrmap { static struct msrmap {
const char *num; const char *num;
const char *pname; const char *pname;
@ -648,7 +685,7 @@ static int process_mapfile(FILE *outfp, char *fpath)
} }
line[strlen(line)-1] = '\0'; line[strlen(line)-1] = '\0';
cpuid = strtok_r(p, ",", &save); cpuid = fixregex(strtok_r(p, ",", &save));
version = strtok_r(NULL, ",", &save); version = strtok_r(NULL, ",", &save);
fname = strtok_r(NULL, ",", &save); fname = strtok_r(NULL, ",", &save);
type = strtok_r(NULL, ",", &save); type = strtok_r(NULL, ",", &save);

View file

@ -12,6 +12,7 @@
#include <dirent.h> #include <dirent.h>
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include <locale.h> #include <locale.h>
#include <regex.h>
#include "util.h" #include "util.h"
#include "pmu.h" #include "pmu.h"
#include "parse-events.h" #include "parse-events.h"
@ -609,15 +610,32 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
i = 0; i = 0;
for (;;) { for (;;) {
regex_t re;
regmatch_t pmatch[1];
int match;
map = &pmu_events_map[i++]; map = &pmu_events_map[i++];
if (!map->table) { if (!map->table) {
map = NULL; map = NULL;
break; break;
} }
if (!strcmp(map->cpuid, cpuid)) if (regcomp(&re, map->cpuid, REG_EXTENDED) != 0) {
/* Warn unable to generate match particular string. */
pr_info("Invalid regular expression %s\n", map->cpuid);
break; break;
} }
match = !regexec(&re, cpuid, 1, pmatch, 0);
regfree(&re);
if (match) {
size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
/* Verify the entire string matched. */
if (match_len == strlen(cpuid))
break;
}
}
free(cpuid); free(cpuid);
return map; return map;
} }