Commit 4689f567 authored by John Garry's avatar John Garry Committed by Arnaldo Carvalho de Melo
Browse files

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: default avatarJohn Garry <john.garry@huawei.com>
Acked-by: default avatarKajol 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 4853f1ca
Loading
Loading
Loading
Loading
+85 −1
Original line number Diff line number Diff line
@@ -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 @@ static int json_events(const char *fn,
		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;
	}
+6 −0
Original line number Diff line number Diff line
@@ -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