mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
perf jevents: Add support for system events tables
Process the JSONs to find support for "system" events, which are not tied to a specific CPUID. A "COMPAT" property is now used to match against the namespace ID from the kernel PMU driver. The generated pmu-events.c will now have 2 tables: a. CPU events, as before. b. New pmu_sys_event_tables[] table, which will have events matched to specific SoCs. It will look like this: struct pmu_event pme_hisilicon_hip09_sys[] = { { .name = "cycles", .compat = "0x00030736", .event = "event=0", .desc = "Clock cycles", .topic = "smmu v3 pmcg", .long_desc = "Clock cycles", }, { .name = "smmuv3_pmcg.l1_tlb", .compat = "0x00030736", .event = "event=0x8a", .desc = "SMMUv3 PMCG l1_tlb. Unit: smmuv3_pmcg ", .topic = "smmu v3 pmcg", .long_desc = "SMMUv3 PMCG l1_tlb", .pmu = "smmuv3_pmcg", }, ... }; struct pmu_event pme_arm_cortex_a53[] = { { .name = "ext_mem_req", .event = "event=0xc0", .desc = "External memory request", .topic = "memory", }, { .name = "ext_mem_req_nc", .event = "event=0xc1", .desc = "Non-cacheable external memory request", .topic = "memory", }, ... }; struct pmu_event pme_hisilicon_hip09_cpu[] = { { .name = "l2d_cache_refill_wr", .event = "event=0x53", .desc = "L2D cache refill, write", .topic = "core imp def", .long_desc = "Attributable Level 2 data cache refill, write", }, ... }; struct pmu_events_map pmu_events_map[] = { { .cpuid = "0x00000000410fd030", .version = "v1", .type = "core", .table = pme_arm_cortex_a53 }, { .cpuid = "0x00000000480fd010", .version = "v1", .type = "core", .table = pme_hisilicon_hip09_cpu }, { .table = 0 }, }; struct pmu_event pme_hisilicon_hip09_cpu[] = { { .name = "uncore_hisi_l3c.rd_cpipe", .event = "event=0", .desc = "Total read accesses. Unit: hisi_sccl,l3c ", .topic = "uncore l3c", .long_desc = "Total read accesses", .pmu = "hisi_sccl,l3c", }, { .name = "uncore_hisi_l3c.wr_cpipe", .event = "event=0x1", .desc = "Total write accesses. Unit: hisi_sccl,l3c ", .topic = "uncore l3c", .long_desc = "Total write accesses", .pmu = "hisi_sccl,l3c", }, ... }; struct pmu_sys_events pmu_sys_event_tables[] = { { .table = pme_hisilicon_hip09_sys, }, ... }; Committer notes: Added the fix for architectures without PMU events, provided by John after I reported the build failing in such systems. Link: https://lore.kernel.org/lkml/650baaf2-36b6-a9e2-ff49-963ef864c1f3@huawei.com/ Signed-off-by: John Garry <john.garry@huawei.com> Acked-by: Kajol Jain <kjain@linux.ibm.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Joakim Zhang <qiangqing.zhang@nxp.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Kim Phillips <kim.phillips@amd.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Shaokun Zhang <zhangshaokun@hisilicon.com> Cc: Will Deacon <will@kernel.org> Cc: linux-arm-kernel@lists.infradead.org Cc: linuxarm@huawei.com Link: http://lore.kernel.org/lkml/1607080216-36968-3-git-send-email-john.garry@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
4853f1caa4
commit
4689f56796
@ -55,6 +55,7 @@ char *prog;
|
||||
|
||||
struct json_event {
|
||||
char *name;
|
||||
char *compat;
|
||||
char *event;
|
||||
char *desc;
|
||||
char *long_desc;
|
||||
@ -82,6 +83,23 @@ enum aggr_mode_class convert(const char *aggr_mode)
|
||||
|
||||
typedef int (*func)(void *data, struct json_event *je);
|
||||
|
||||
static LIST_HEAD(sys_event_tables);
|
||||
|
||||
struct sys_event_table {
|
||||
struct list_head list;
|
||||
char *soc_id;
|
||||
};
|
||||
|
||||
static void free_sys_event_tables(void)
|
||||
{
|
||||
struct sys_event_table *et, *next;
|
||||
|
||||
list_for_each_entry_safe(et, next, &sys_event_tables, list) {
|
||||
free(et->soc_id);
|
||||
free(et);
|
||||
}
|
||||
}
|
||||
|
||||
int eprintf(int level, int var, const char *fmt, ...)
|
||||
{
|
||||
|
||||
@ -360,6 +378,8 @@ static int print_events_table_entry(void *data, struct json_event *je)
|
||||
if (je->event)
|
||||
fprintf(outfp, "\t.event = \"%s\",\n", je->event);
|
||||
fprintf(outfp, "\t.desc = \"%s\",\n", je->desc);
|
||||
if (je->compat)
|
||||
fprintf(outfp, "\t.compat = \"%s\",\n", je->compat);
|
||||
fprintf(outfp, "\t.topic = \"%s\",\n", topic);
|
||||
if (je->long_desc && je->long_desc[0])
|
||||
fprintf(outfp, "\t.long_desc = \"%s\",\n", je->long_desc);
|
||||
@ -390,6 +410,7 @@ struct event_struct {
|
||||
struct list_head list;
|
||||
char *name;
|
||||
char *event;
|
||||
char *compat;
|
||||
char *desc;
|
||||
char *long_desc;
|
||||
char *pmu;
|
||||
@ -583,6 +604,8 @@ static int json_events(const char *fn,
|
||||
free(code);
|
||||
} else if (json_streq(map, field, "EventName")) {
|
||||
addfield(map, &je.name, "", "", val);
|
||||
} else if (json_streq(map, field, "Compat")) {
|
||||
addfield(map, &je.compat, "", "", val);
|
||||
} else if (json_streq(map, field, "BriefDescription")) {
|
||||
addfield(map, &je.desc, "", "", val);
|
||||
fixdesc(je.desc);
|
||||
@ -683,6 +706,7 @@ free_strings:
|
||||
free(event);
|
||||
free(je.desc);
|
||||
free(je.name);
|
||||
free(je.compat);
|
||||
free(je.long_desc);
|
||||
free(extra_desc);
|
||||
free(je.pmu);
|
||||
@ -747,6 +771,15 @@ static char *file_name_to_table_name(char *fname)
|
||||
return tblname;
|
||||
}
|
||||
|
||||
static bool is_sys_dir(char *fname)
|
||||
{
|
||||
size_t len = strlen(fname), len2 = strlen("/sys");
|
||||
|
||||
if (len2 > len)
|
||||
return false;
|
||||
return !strcmp(fname+len-len2, "/sys");
|
||||
}
|
||||
|
||||
static void print_mapping_table_prefix(FILE *outfp)
|
||||
{
|
||||
fprintf(outfp, "struct pmu_events_map pmu_events_map[] = {\n");
|
||||
@ -781,6 +814,33 @@ static void print_mapping_test_table(FILE *outfp)
|
||||
fprintf(outfp, "},\n");
|
||||
}
|
||||
|
||||
static void print_system_event_mapping_table_prefix(FILE *outfp)
|
||||
{
|
||||
fprintf(outfp, "\nstruct pmu_sys_events pmu_sys_event_tables[] = {");
|
||||
}
|
||||
|
||||
static void print_system_event_mapping_table_suffix(FILE *outfp)
|
||||
{
|
||||
fprintf(outfp, "\n\t{\n\t\t.table = 0\n\t},");
|
||||
fprintf(outfp, "\n};\n");
|
||||
}
|
||||
|
||||
static int process_system_event_tables(FILE *outfp)
|
||||
{
|
||||
struct sys_event_table *sys_event_table;
|
||||
|
||||
print_system_event_mapping_table_prefix(outfp);
|
||||
|
||||
list_for_each_entry(sys_event_table, &sys_event_tables, list) {
|
||||
fprintf(outfp, "\n\t{\n\t\t.table = %s,\n\t},",
|
||||
sys_event_table->soc_id);
|
||||
}
|
||||
|
||||
print_system_event_mapping_table_suffix(outfp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_mapfile(FILE *outfp, char *fpath)
|
||||
{
|
||||
int n = 16384;
|
||||
@ -886,6 +946,8 @@ static void create_empty_mapping(const char *output_file)
|
||||
fprintf(outfp, "#include \"pmu-events/pmu-events.h\"\n");
|
||||
print_mapping_table_prefix(outfp);
|
||||
print_mapping_table_suffix(outfp);
|
||||
print_system_event_mapping_table_prefix(outfp);
|
||||
print_system_event_mapping_table_suffix(outfp);
|
||||
fclose(outfp);
|
||||
}
|
||||
|
||||
@ -1026,6 +1088,22 @@ static int process_one_file(const char *fpath, const struct stat *sb,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_sys_dir(bname)) {
|
||||
struct sys_event_table *sys_event_table;
|
||||
|
||||
sys_event_table = malloc(sizeof(*sys_event_table));
|
||||
if (!sys_event_table)
|
||||
return -1;
|
||||
|
||||
sys_event_table->soc_id = strdup(tblname);
|
||||
if (!sys_event_table->soc_id) {
|
||||
free(sys_event_table);
|
||||
return -1;
|
||||
}
|
||||
list_add_tail(&sys_event_table->list,
|
||||
&sys_event_tables);
|
||||
}
|
||||
|
||||
print_events_table_prefix(eventsfp, tblname);
|
||||
return 0;
|
||||
}
|
||||
@ -1185,10 +1263,16 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
rc = process_mapfile(eventsfp, mapfile);
|
||||
fclose(eventsfp);
|
||||
if (rc) {
|
||||
pr_info("%s: Error processing mapfile %s\n", prog, mapfile);
|
||||
/* Make build fail */
|
||||
ret = 1;
|
||||
goto err_close_eventsfp;
|
||||
}
|
||||
|
||||
rc = process_system_event_tables(eventsfp);
|
||||
fclose(eventsfp);
|
||||
if (rc) {
|
||||
ret = 1;
|
||||
goto err_out;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ enum aggr_mode_class {
|
||||
*/
|
||||
struct pmu_event {
|
||||
const char *name;
|
||||
const char *compat;
|
||||
const char *event;
|
||||
const char *desc;
|
||||
const char *topic;
|
||||
@ -43,10 +44,15 @@ struct pmu_events_map {
|
||||
struct pmu_event *table;
|
||||
};
|
||||
|
||||
struct pmu_sys_events {
|
||||
struct pmu_event *table;
|
||||
};
|
||||
|
||||
/*
|
||||
* Global table mapping each known CPU for the architecture to its
|
||||
* table of PMU events.
|
||||
*/
|
||||
extern struct pmu_events_map pmu_events_map[];
|
||||
extern struct pmu_sys_events pmu_sys_event_tables[];
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user