* [PATCH v3 0/2] perf jevents: Autogenerate empty-pmu-events.c
@ 2024-07-30 19:17 Ian Rogers
2024-07-30 19:17 ` [PATCH v3 1/2] perf jevents: Use name for special find value Ian Rogers
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Ian Rogers @ 2024-07-30 19:17 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, Kan Liang, John Garry, Jing Zhang,
Xu Yang, Sandipan Das, linux-perf-users, linux-kernel, philip.li,
oliver.sang, Weilin Wang
Rebase of v2 patch set on tmp.perf-tools-next.
https://lore.kernel.org/lkml/20240525013021.436430-1-irogers@google.com/
Review was delayed because of an Intel automatic testing issue,
confirmed not an issue here:
https://lore.kernel.org/lkml/ZqhGNm+WDcsNx05e@xsang-OptiPlex-9020/
v3: Rebase and add John Garry's reviewed-by tag.
v2: Add not found constant.
Ian Rogers (2):
perf jevents: Use name for special find value
perf jevents: Autogenerate empty-pmu-events.c
tools/perf/Makefile.perf | 2 +
tools/perf/pmu-events/Build | 12 +-
tools/perf/pmu-events/empty-pmu-events.c | 894 ++++++++++++++---------
tools/perf/pmu-events/jevents.py | 12 +-
tools/perf/pmu-events/pmu-events.h | 9 +
5 files changed, 574 insertions(+), 355 deletions(-)
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 1/2] perf jevents: Use name for special find value
2024-07-30 19:17 [PATCH v3 0/2] perf jevents: Autogenerate empty-pmu-events.c Ian Rogers
@ 2024-07-30 19:17 ` Ian Rogers
2024-07-31 13:19 ` Arnaldo Carvalho de Melo
2024-07-30 19:17 ` [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c Ian Rogers
2024-07-31 13:05 ` [PATCH v3 0/2] " Arnaldo Carvalho de Melo
2 siblings, 1 reply; 14+ messages in thread
From: Ian Rogers @ 2024-07-30 19:17 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, Kan Liang, John Garry, Jing Zhang,
Xu Yang, Sandipan Das, linux-perf-users, linux-kernel, philip.li,
oliver.sang, Weilin Wang
-1000 was used as a special value added in Commit 3d5045492ab2 ("perf
pmu-events: Add pmu_events_table__find_event()") to show that 1 table
lacked a PMU/event but that didn't terminate the search in other
tables. Add a new constant PMU_EVENTS__NOT_FOUND for this value and
use it.
Signed-off-by: Ian Rogers <irogers@google.com>
Reviewed-by: John Garry <john.g.garry@oracle.com>
---
tools/perf/pmu-events/jevents.py | 6 +++---
tools/perf/pmu-events/pmu-events.h | 9 +++++++++
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index ac9b7ca41856..731776e29f47 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -906,7 +906,7 @@ static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table
do_call:
return fn ? fn(&pe, table, data) : 0;
}
- return -1000;
+ return PMU_EVENTS__NOT_FOUND;
}
int pmu_events_table__for_each_event(const struct pmu_events_table *table,
@@ -944,10 +944,10 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
continue;
ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data);
- if (ret != -1000)
+ if (ret != PMU_EVENTS__NOT_FOUND)
return ret;
}
- return -1000;
+ return PMU_EVENTS__NOT_FOUND;
}
size_t pmu_events_table__num_events(const struct pmu_events_table *table,
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index f5aa96f1685c..5435ad92180c 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -70,6 +70,8 @@ struct pmu_metric {
struct pmu_events_table;
struct pmu_metrics_table;
+#define PMU_EVENTS__NOT_FOUND -1000
+
typedef int (*pmu_event_iter_fn)(const struct pmu_event *pe,
const struct pmu_events_table *table,
void *data);
@@ -82,6 +84,13 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table,
struct perf_pmu *pmu,
pmu_event_iter_fn fn,
void *data);
+/*
+ * Search for table and entry matching with pmu__name_match. Each matching event
+ * has fn called on it. 0 implies to success/continue the search while non-zero
+ * means to terminate. The special value PMU_EVENTS__NOT_FOUND is used to
+ * indicate no event was found in one of the tables which doesn't terminate the
+ * search of all tables.
+ */
int pmu_events_table__find_event(const struct pmu_events_table *table,
struct perf_pmu *pmu,
const char *name,
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-30 19:17 [PATCH v3 0/2] perf jevents: Autogenerate empty-pmu-events.c Ian Rogers
2024-07-30 19:17 ` [PATCH v3 1/2] perf jevents: Use name for special find value Ian Rogers
@ 2024-07-30 19:17 ` Ian Rogers
2024-07-31 13:18 ` Arnaldo Carvalho de Melo
2024-07-31 13:05 ` [PATCH v3 0/2] " Arnaldo Carvalho de Melo
2 siblings, 1 reply; 14+ messages in thread
From: Ian Rogers @ 2024-07-30 19:17 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, Kan Liang, John Garry, Jing Zhang,
Xu Yang, Sandipan Das, linux-perf-users, linux-kernel, philip.li,
oliver.sang, Weilin Wang
empty-pmu-events.c exists so that builds may occur without python
being installed on a system. Manually updating empty-pmu-events.c to
be in sync with jevents.py is a pain, let's use jevents.py to generate
empty-pmu-events.c.
1) change jevents.py so that an arch and model of none cause
generation of a pmu-events.c without any json. Add a SPDX and
autogenerated warning to the start of the file.
2) change Build so that if a generated pmu-events.c for arch none and
model none doesn't match empty-pmu-events.c the build fails with a
cat of the differences. Update Makefile.perf to clean up the files
used for this.
3) update empty-pmu-events.c to match the output of jevents.py with
arch and mode of none.
Signed-off-by: Ian Rogers <irogers@google.com>
Reviewed-by: John Garry <john.g.garry@oracle.com>
---
tools/perf/Makefile.perf | 2 +
tools/perf/pmu-events/Build | 12 +-
tools/perf/pmu-events/empty-pmu-events.c | 894 ++++++++++++++---------
tools/perf/pmu-events/jevents.py | 6 +-
4 files changed, 562 insertions(+), 352 deletions(-)
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 175e4c7898f0..76bb0925849a 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -1252,6 +1252,8 @@ clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(
$(OUTPUT)util/intel-pt-decoder/inat-tables.c \
$(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
$(OUTPUT)pmu-events/pmu-events.c \
+ $(OUTPUT)pmu-events/test-empty-pmu-events.c \
+ $(OUTPUT)pmu-events/empty-pmu-events.log \
$(OUTPUT)pmu-events/metric_test.log \
$(OUTPUT)$(fadvise_advice_array) \
$(OUTPUT)$(fsconfig_arrays) \
diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
index 1d18bb89402e..c3fa43c49706 100644
--- a/tools/perf/pmu-events/Build
+++ b/tools/perf/pmu-events/Build
@@ -11,6 +11,8 @@ METRIC_TEST_PY = pmu-events/metric_test.py
EMPTY_PMU_EVENTS_C = pmu-events/empty-pmu-events.c
PMU_EVENTS_C = $(OUTPUT)pmu-events/pmu-events.c
METRIC_TEST_LOG = $(OUTPUT)pmu-events/metric_test.log
+TEST_EMPTY_PMU_EVENTS_C = $(OUTPUT)pmu-events/test-empty-pmu-events.c
+EMPTY_PMU_EVENTS_TEST_LOG = $(OUTPUT)pmu-events/empty-pmu-events.log
ifeq ($(JEVENTS_ARCH),)
JEVENTS_ARCH=$(SRCARCH)
@@ -31,7 +33,15 @@ $(METRIC_TEST_LOG): $(METRIC_TEST_PY) $(METRIC_PY)
$(call rule_mkdir)
$(Q)$(call echo-cmd,test)$(PYTHON) $< 2> $@ || (cat $@ && false)
-$(PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG)
+$(TEST_EMPTY_PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG)
+ $(call rule_mkdir)
+ $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) none none pmu-events/arch $@
+
+$(EMPTY_PMU_EVENTS_TEST_LOG): $(EMPTY_PMU_EVENTS_C) $(TEST_EMPTY_PMU_EVENTS_C)
+ $(call rule_mkdir)
+ $(Q)$(call echo-cmd,test)diff -u $? 2> $@ || (cat $@ && false)
+
+$(PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) $(EMPTY_PMU_EVENTS_TEST_LOG)
$(call rule_mkdir)
$(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) pmu-events/arch $@
endif
diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index 13727421d424..c592079982fb 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -1,196 +1,193 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * An empty pmu-events.c file used when there is no architecture json files in
- * arch or when the jevents.py script cannot be run.
- *
- * The test cpu/soc is provided for testing.
- */
-#include "pmu-events/pmu-events.h"
+
+/* SPDX-License-Identifier: GPL-2.0 */
+/* THIS FILE WAS AUTOGENERATED BY jevents.py arch=none model=none ! */
+
+#include <pmu-events/pmu-events.h>
#include "util/header.h"
#include "util/pmu.h"
#include <string.h>
#include <stddef.h>
-static const struct pmu_event pmu_events__test_soc_cpu[] = {
- {
- .name = "l3_cache_rd",
- .event = "event=0x40",
- .desc = "L3 cache access, read",
- .topic = "cache",
- .long_desc = "Attributable Level 3 cache access, read",
- },
- {
- .name = "segment_reg_loads.any",
- .event = "event=0x6,period=200000,umask=0x80",
- .desc = "Number of segment register loads",
- .topic = "other",
- },
- {
- .name = "dispatch_blocked.any",
- .event = "event=0x9,period=200000,umask=0x20",
- .desc = "Memory cluster signals to block micro-op dispatch for any reason",
- .topic = "other",
- },
- {
- .name = "eist_trans",
- .event = "event=0x3a,period=200000,umask=0x0",
- .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
- .topic = "other",
- },
- {
- .name = "uncore_hisi_ddrc.flux_wcmd",
- .event = "event=0x2",
- .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
- .topic = "uncore",
- .long_desc = "DDRC write commands",
- .pmu = "hisi_sccl,ddrc",
- },
- {
- .name = "unc_cbo_xsnp_response.miss_eviction",
- .event = "event=0x22,umask=0x81",
- .desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox ",
- .topic = "uncore",
- .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
- .pmu = "uncore_cbox",
- },
- {
- .name = "event-hyphen",
- .event = "event=0xe0,umask=0x00",
- .desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox ",
- .topic = "uncore",
- .long_desc = "UNC_CBO_HYPHEN",
- .pmu = "uncore_cbox",
- },
- {
- .name = "event-two-hyph",
- .event = "event=0xc0,umask=0x00",
- .desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox ",
- .topic = "uncore",
- .long_desc = "UNC_CBO_TWO_HYPH",
- .pmu = "uncore_cbox",
- },
- {
- .name = "uncore_hisi_l3c.rd_hit_cpipe",
- .event = "event=0x7",
- .desc = "Total read hits. Unit: hisi_sccl,l3c ",
- .topic = "uncore",
- .long_desc = "Total read hits",
- .pmu = "hisi_sccl,l3c",
- },
- {
- .name = "uncore_imc_free_running.cache_miss",
- .event = "event=0x12",
- .desc = "Total cache misses. Unit: uncore_imc_free_running ",
- .topic = "uncore",
- .long_desc = "Total cache misses",
- .pmu = "uncore_imc_free_running",
- },
- {
- .name = "uncore_imc.cache_hits",
- .event = "event=0x34",
- .desc = "Total cache hits. Unit: uncore_imc ",
- .topic = "uncore",
- .long_desc = "Total cache hits",
- .pmu = "uncore_imc",
- },
- {
- .name = "bp_l1_btb_correct",
- .event = "event=0x8a",
- .desc = "L1 BTB Correction",
- .topic = "branch",
- },
- {
- .name = "bp_l2_btb_correct",
- .event = "event=0x8b",
- .desc = "L2 BTB Correction",
- .topic = "branch",
- },
- {
- .name = 0,
- .event = 0,
- .desc = 0,
- },
+struct compact_pmu_event {
+ int offset;
};
-static const struct pmu_metric pmu_metrics__test_soc_cpu[] = {
- {
- .metric_expr = "1 / IPC",
- .metric_name = "CPI",
- },
- {
- .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread",
- .metric_name = "IPC",
- .metric_group = "group1",
- },
- {
- .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * "
- "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))",
- .metric_name = "Frontend_Bound_SMT",
- },
- {
- .metric_expr = "l1d\\-loads\\-misses / inst_retired.any",
- .metric_name = "dcache_miss_cpi",
- },
- {
- .metric_expr = "l1i\\-loads\\-misses / inst_retired.any",
- .metric_name = "icache_miss_cycles",
- },
- {
- .metric_expr = "(dcache_miss_cpi + icache_miss_cycles)",
- .metric_name = "cache_miss_cycles",
- .metric_group = "group1",
- },
- {
- .metric_expr = "l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit",
- .metric_name = "DCache_L2_All_Hits",
- },
- {
- .metric_expr = "max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + "
- "l2_rqsts.pf_miss + l2_rqsts.rfo_miss",
- .metric_name = "DCache_L2_All_Miss",
- },
- {
- .metric_expr = "DCache_L2_All_Hits + DCache_L2_All_Miss",
- .metric_name = "DCache_L2_All",
- },
- {
- .metric_expr = "d_ratio(DCache_L2_All_Hits, DCache_L2_All)",
- .metric_name = "DCache_L2_Hits",
- },
- {
- .metric_expr = "d_ratio(DCache_L2_All_Miss, DCache_L2_All)",
- .metric_name = "DCache_L2_Misses",
- },
- {
- .metric_expr = "ipc + M2",
- .metric_name = "M1",
- },
- {
- .metric_expr = "ipc + M1",
- .metric_name = "M2",
- },
- {
- .metric_expr = "1/M3",
- .metric_name = "M3",
- },
- {
- .metric_expr = "64 * l1d.replacement / 1000000000 / duration_time",
- .metric_name = "L1D_Cache_Fill_BW",
- },
- {
- .metric_expr = 0,
- .metric_name = 0,
- },
+struct pmu_table_entry {
+ const struct compact_pmu_event *entries;
+ uint32_t num_entries;
+ struct compact_pmu_event pmu_name;
+};
+
+static const char *const big_c_string =
+/* offset=0 */ "default_core\000"
+/* offset=13 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000"
+/* offset=72 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000"
+/* offset=131 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000"
+/* offset=226 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000"
+/* offset=325 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000"
+/* offset=455 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000"
+/* offset=570 */ "hisi_sccl,ddrc\000"
+/* offset=585 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000"
+/* offset=671 */ "uncore_cbox\000"
+/* offset=683 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000"
+/* offset=914 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000"
+/* offset=979 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000"
+/* offset=1050 */ "hisi_sccl,l3c\000"
+/* offset=1064 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000"
+/* offset=1144 */ "uncore_imc_free_running\000"
+/* offset=1168 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000"
+/* offset=1263 */ "uncore_imc\000"
+/* offset=1274 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000"
+/* offset=1352 */ "uncore_sys_ddr_pmu\000"
+/* offset=1371 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000"
+/* offset=1444 */ "uncore_sys_ccn_pmu\000"
+/* offset=1463 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000"
+/* offset=1537 */ "uncore_sys_cmn_pmu\000"
+/* offset=1556 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000"
+/* offset=1696 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
+/* offset=1718 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
+/* offset=1781 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
+/* offset=1947 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
+/* offset=2011 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
+/* offset=2078 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
+/* offset=2149 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
+/* offset=2243 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
+/* offset=2377 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
+/* offset=2441 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
+/* offset=2509 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
+/* offset=2579 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
+/* offset=2601 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
+/* offset=2623 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
+/* offset=2643 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
+;
+
+static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
+{ 13 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000 */
+{ 72 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000 */
+{ 325 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000 */
+{ 455 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000 */
+{ 131 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000 */
+{ 226 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000 */
+};
+static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
+{ 585 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000 */
+};
+static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
+{ 1064 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000 */
+};
+static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
+{ 914 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000 */
+{ 979 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000 */
+{ 683 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000 */
+};
+static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
+{ 1274 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000 */
+};
+static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
+{ 1168 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000 */
+
+};
+
+const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
+{
+ .entries = pmu_events__test_soc_cpu_default_core,
+ .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
+ .pmu_name = { 0 /* default_core\000 */ },
+},
+{
+ .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
+ .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
+ .pmu_name = { 570 /* hisi_sccl,ddrc\000 */ },
+},
+{
+ .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
+ .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
+ .pmu_name = { 1050 /* hisi_sccl,l3c\000 */ },
+},
+{
+ .entries = pmu_events__test_soc_cpu_uncore_cbox,
+ .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
+ .pmu_name = { 671 /* uncore_cbox\000 */ },
+},
+{
+ .entries = pmu_events__test_soc_cpu_uncore_imc,
+ .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
+ .pmu_name = { 1263 /* uncore_imc\000 */ },
+},
+{
+ .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
+ .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
+ .pmu_name = { 1144 /* uncore_imc_free_running\000 */ },
+},
};
+static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
+{ 1696 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
+{ 2377 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
+{ 2149 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
+{ 2243 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
+{ 2441 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
+{ 2509 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
+{ 1781 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
+{ 1718 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
+{ 2643 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
+{ 2579 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
+{ 2601 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
+{ 2623 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
+{ 2078 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
+{ 1947 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
+{ 2011 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
+
+};
+
+const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
+{
+ .entries = pmu_metrics__test_soc_cpu_default_core,
+ .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
+ .pmu_name = { 0 /* default_core\000 */ },
+},
+};
+
+static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
+{ 1463 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000 */
+};
+static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
+{ 1556 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000 */
+};
+static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
+{ 1371 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000 */
+
+};
+
+const struct pmu_table_entry pmu_events__test_soc_sys[] = {
+{
+ .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
+ .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
+ .pmu_name = { 1444 /* uncore_sys_ccn_pmu\000 */ },
+},
+{
+ .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
+ .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
+ .pmu_name = { 1537 /* uncore_sys_cmn_pmu\000 */ },
+},
+{
+ .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
+ .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
+ .pmu_name = { 1352 /* uncore_sys_ddr_pmu\000 */ },
+},
+};
+
+
/* Struct used to make the PMU event table implementation opaque to callers. */
struct pmu_events_table {
- const struct pmu_event *entries;
+ const struct pmu_table_entry *pmus;
+ uint32_t num_pmus;
};
/* Struct used to make the PMU metric table implementation opaque to callers. */
struct pmu_metrics_table {
- const struct pmu_metric *entries;
+ const struct pmu_table_entry *pmus;
+ uint32_t num_pmus;
};
/*
@@ -202,92 +199,191 @@ struct pmu_metrics_table {
* The cpuid can contain any character other than the comma.
*/
struct pmu_events_map {
- const char *arch;
- const char *cpuid;
- const struct pmu_events_table event_table;
- const struct pmu_metrics_table metric_table;
+ const char *arch;
+ const char *cpuid;
+ struct pmu_events_table event_table;
+ struct pmu_metrics_table metric_table;
};
/*
* Global table mapping each known CPU for the architecture to its
* table of PMU events.
*/
-static const struct pmu_events_map pmu_events_map[] = {
- {
- .arch = "testarch",
- .cpuid = "testcpu",
- .event_table = { pmu_events__test_soc_cpu },
- .metric_table = { pmu_metrics__test_soc_cpu },
- },
- {
- .arch = 0,
- .cpuid = 0,
- .event_table = { 0 },
- .metric_table = { 0 },
- },
-};
-
-static const struct pmu_event pmu_events__test_soc_sys[] = {
- {
- .name = "sys_ddr_pmu.write_cycles",
- .event = "event=0x2b",
- .desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
- .compat = "v8",
- .topic = "uncore",
- .pmu = "uncore_sys_ddr_pmu",
- },
- {
- .name = "sys_ccn_pmu.read_cycles",
- .event = "config=0x2c",
- .desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
- .compat = "0x01",
- .topic = "uncore",
- .pmu = "uncore_sys_ccn_pmu",
- },
- {
- .name = "sys_cmn_pmu.hnf_cache_miss",
- .event = "eventid=0x1,type=0x5",
- .desc = "Counts total cache misses in first lookup result (high priority). Unit: uncore_sys_cmn_pmu ",
- .compat = "(434|436|43c|43a).*",
- .topic = "uncore",
- .pmu = "uncore_sys_cmn_pmu",
- },
- {
- .name = 0,
- .event = 0,
- .desc = 0,
- },
+const struct pmu_events_map pmu_events_map[] = {
+{
+ .arch = "testarch",
+ .cpuid = "testcpu",
+ .event_table = {
+ .pmus = pmu_events__test_soc_cpu,
+ .num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu),
+ },
+ .metric_table = {
+ .pmus = pmu_metrics__test_soc_cpu,
+ .num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
+ }
+},
+{
+ .arch = 0,
+ .cpuid = 0,
+ .event_table = { 0, 0 },
+ .metric_table = { 0, 0 },
+}
};
struct pmu_sys_events {
const char *name;
- const struct pmu_events_table table;
+ struct pmu_events_table event_table;
+ struct pmu_metrics_table metric_table;
};
static const struct pmu_sys_events pmu_sys_event_tables[] = {
{
- .table = { pmu_events__test_soc_sys },
+ .event_table = {
+ .pmus = pmu_events__test_soc_sys,
+ .num_pmus = ARRAY_SIZE(pmu_events__test_soc_sys)
+ },
.name = "pmu_events__test_soc_sys",
},
{
- .table = { 0 }
+ .event_table = { 0, 0 },
+ .metric_table = { 0, 0 },
},
};
-int pmu_events_table__for_each_event(const struct pmu_events_table *table, struct perf_pmu *pmu,
- pmu_event_iter_fn fn, void *data)
+static void decompress_event(int offset, struct pmu_event *pe)
+{
+ const char *p = &big_c_string[offset];
+
+ pe->name = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pe->topic = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pe->desc = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pe->event = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pe->compat = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pe->deprecated = *p - '0';
+ p++;
+ pe->perpkg = *p - '0';
+ p++;
+ pe->unit = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pe->long_desc = (*p == '\0' ? NULL : p);
+}
+
+static void decompress_metric(int offset, struct pmu_metric *pm)
{
- for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
- int ret;
+ const char *p = &big_c_string[offset];
+
+ pm->metric_name = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pm->metric_group = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pm->metric_expr = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pm->metric_threshold = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pm->desc = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pm->long_desc = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pm->unit = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pm->compat = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pm->metricgroup_no_group = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pm->default_metricgroup_name = (*p == '\0' ? NULL : p);
+ while (*p++);
+ pm->aggr_mode = *p - '0';
+ p++;
+ pm->event_grouping = *p - '0';
+}
- if (pmu && !pmu__name_match(pmu, pe->pmu))
+static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table,
+ const struct pmu_table_entry *pmu,
+ pmu_event_iter_fn fn,
+ void *data)
+{
+ int ret;
+ struct pmu_event pe = {
+ .pmu = &big_c_string[pmu->pmu_name.offset],
+ };
+
+ for (uint32_t i = 0; i < pmu->num_entries; i++) {
+ decompress_event(pmu->entries[i].offset, &pe);
+ if (!pe.name)
continue;
+ ret = fn(&pe, table, data);
+ if (ret)
+ return ret;
+ }
+ return 0;
+ }
+
+static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table,
+ const struct pmu_table_entry *pmu,
+ const char *name,
+ pmu_event_iter_fn fn,
+ void *data)
+{
+ struct pmu_event pe = {
+ .pmu = &big_c_string[pmu->pmu_name.offset],
+ };
+ int low = 0, high = pmu->num_entries - 1;
- ret = fn(pe, table, data);
- if (ret)
- return ret;
- }
- return 0;
+ while (low <= high) {
+ int cmp, mid = (low + high) / 2;
+
+ decompress_event(pmu->entries[mid].offset, &pe);
+
+ if (!pe.name && !name)
+ goto do_call;
+
+ if (!pe.name && name) {
+ low = mid + 1;
+ continue;
+ }
+ if (pe.name && !name) {
+ high = mid - 1;
+ continue;
+ }
+
+ cmp = strcasecmp(pe.name, name);
+ if (cmp < 0) {
+ low = mid + 1;
+ continue;
+ }
+ if (cmp > 0) {
+ high = mid - 1;
+ continue;
+ }
+ do_call:
+ return fn ? fn(&pe, table, data) : 0;
+ }
+ return PMU_EVENTS__NOT_FOUND;
+}
+
+int pmu_events_table__for_each_event(const struct pmu_events_table *table,
+ struct perf_pmu *pmu,
+ pmu_event_iter_fn fn,
+ void *data)
+{
+ for (size_t i = 0; i < table->num_pmus; i++) {
+ const struct pmu_table_entry *table_pmu = &table->pmus[i];
+ const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
+ int ret;
+
+ if (pmu && !pmu__name_match(pmu, pmu_name))
+ continue;
+
+ ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
+ if (pmu || ret)
+ return ret;
+ }
+ return 0;
}
int pmu_events_table__find_event(const struct pmu_events_table *table,
@@ -296,14 +392,19 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
pmu_event_iter_fn fn,
void *data)
{
- for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
- if (pmu && !pmu__name_match(pmu, pe->pmu))
+ for (size_t i = 0; i < table->num_pmus; i++) {
+ const struct pmu_table_entry *table_pmu = &table->pmus[i];
+ const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
+ int ret;
+
+ if (!pmu__name_match(pmu, pmu_name))
continue;
- if (!strcasecmp(pe->name, name))
- return fn(pe, table, data);
- }
- return -1000;
+ ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data);
+ if (ret != PMU_EVENTS__NOT_FOUND)
+ return ret;
+ }
+ return PMU_EVENTS__NOT_FOUND;
}
size_t pmu_events_table__num_events(const struct pmu_events_table *table,
@@ -311,160 +412,253 @@ size_t pmu_events_table__num_events(const struct pmu_events_table *table,
{
size_t count = 0;
- for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
- if (pmu && !pmu__name_match(pmu, pe->pmu))
- continue;
+ for (size_t i = 0; i < table->num_pmus; i++) {
+ const struct pmu_table_entry *table_pmu = &table->pmus[i];
+ const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
- count++;
- }
+ if (pmu__name_match(pmu, pmu_name))
+ count += table_pmu->num_entries;
+ }
return count;
}
-int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
- void *data)
+static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
+ const struct pmu_table_entry *pmu,
+ pmu_metric_iter_fn fn,
+ void *data)
+{
+ int ret;
+ struct pmu_metric pm = {
+ .pmu = &big_c_string[pmu->pmu_name.offset],
+ };
+
+ for (uint32_t i = 0; i < pmu->num_entries; i++) {
+ decompress_metric(pmu->entries[i].offset, &pm);
+ if (!pm.metric_expr)
+ continue;
+ ret = fn(&pm, table, data);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table,
+ pmu_metric_iter_fn fn,
+ void *data)
{
- for (const struct pmu_metric *pm = &table->entries[0]; pm->metric_expr; pm++) {
- int ret = fn(pm, table, data);
+ for (size_t i = 0; i < table->num_pmus; i++) {
+ int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i],
+ fn, data);
+
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
- if (ret)
- return ret;
- }
- return 0;
+static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
+{
+ static struct {
+ const struct pmu_events_map *map;
+ struct perf_pmu *pmu;
+ } last_result;
+ static struct {
+ const struct pmu_events_map *map;
+ char *cpuid;
+ } last_map_search;
+ static bool has_last_result, has_last_map_search;
+ const struct pmu_events_map *map = NULL;
+ char *cpuid = NULL;
+ size_t i;
+
+ if (has_last_result && last_result.pmu == pmu)
+ return last_result.map;
+
+ cpuid = perf_pmu__getcpuid(pmu);
+
+ /*
+ * On some platforms which uses cpus map, cpuid can be NULL for
+ * PMUs other than CORE PMUs.
+ */
+ if (!cpuid)
+ goto out_update_last_result;
+
+ if (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) {
+ map = last_map_search.map;
+ free(cpuid);
+ } else {
+ i = 0;
+ for (;;) {
+ map = &pmu_events_map[i++];
+
+ if (!map->arch) {
+ map = NULL;
+ break;
+ }
+
+ if (!strcmp_cpuid_str(map->cpuid, cpuid))
+ break;
+ }
+ free(last_map_search.cpuid);
+ last_map_search.cpuid = cpuid;
+ last_map_search.map = map;
+ has_last_map_search = true;
+ }
+out_update_last_result:
+ last_result.pmu = pmu;
+ last_result.map = map;
+ has_last_result = true;
+ return map;
}
const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu)
{
- const struct pmu_events_table *table = NULL;
- char *cpuid = perf_pmu__getcpuid(pmu);
- int i;
+ const struct pmu_events_map *map = map_for_pmu(pmu);
- /* on some platforms which uses cpus map, cpuid can be NULL for
- * PMUs other than CORE PMUs.
- */
- if (!cpuid)
- return NULL;
+ if (!map)
+ return NULL;
- i = 0;
- for (;;) {
- const struct pmu_events_map *map = &pmu_events_map[i++];
+ if (!pmu)
+ return &map->event_table;
- if (!map->cpuid)
- break;
+ for (size_t i = 0; i < map->event_table.num_pmus; i++) {
+ const struct pmu_table_entry *table_pmu = &map->event_table.pmus[i];
+ const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
- if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
- table = &map->event_table;
- break;
- }
- }
- free(cpuid);
- return table;
+ if (pmu__name_match(pmu, pmu_name))
+ return &map->event_table;
+ }
+ return NULL;
}
const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pmu)
{
- const struct pmu_metrics_table *table = NULL;
- char *cpuid = perf_pmu__getcpuid(pmu);
- int i;
+ const struct pmu_events_map *map = map_for_pmu(pmu);
- /* on some platforms which uses cpus map, cpuid can be NULL for
- * PMUs other than CORE PMUs.
- */
- if (!cpuid)
- return NULL;
+ if (!map)
+ return NULL;
- i = 0;
- for (;;) {
- const struct pmu_events_map *map = &pmu_events_map[i++];
+ if (!pmu)
+ return &map->metric_table;
- if (!map->cpuid)
- break;
+ for (size_t i = 0; i < map->metric_table.num_pmus; i++) {
+ const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i];
+ const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
- if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
- table = &map->metric_table;
- break;
- }
- }
- free(cpuid);
- return table;
+ if (pmu__name_match(pmu, pmu_name))
+ return &map->metric_table;
+ }
+ return NULL;
}
const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid)
{
- for (const struct pmu_events_map *tables = &pmu_events_map[0];
- tables->arch;
- tables++) {
- if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
- return &tables->event_table;
- }
- return NULL;
+ for (const struct pmu_events_map *tables = &pmu_events_map[0];
+ tables->arch;
+ tables++) {
+ if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
+ return &tables->event_table;
+ }
+ return NULL;
}
const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid)
{
- for (const struct pmu_events_map *tables = &pmu_events_map[0];
- tables->arch;
- tables++) {
- if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
- return &tables->metric_table;
- }
- return NULL;
+ for (const struct pmu_events_map *tables = &pmu_events_map[0];
+ tables->arch;
+ tables++) {
+ if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
+ return &tables->metric_table;
+ }
+ return NULL;
}
int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
{
- for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->arch; tables++) {
- int ret = pmu_events_table__for_each_event(&tables->event_table,
- /*pmu=*/ NULL, fn, data);
-
- if (ret)
- return ret;
- }
- return 0;
+ for (const struct pmu_events_map *tables = &pmu_events_map[0];
+ tables->arch;
+ tables++) {
+ int ret = pmu_events_table__for_each_event(&tables->event_table,
+ /*pmu=*/ NULL, fn, data);
+
+ if (ret)
+ return ret;
+ }
+ return 0;
}
int pmu_for_each_core_metric(pmu_metric_iter_fn fn, void *data)
{
- for (const struct pmu_events_map *tables = &pmu_events_map[0];
- tables->arch;
- tables++) {
- int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
-
- if (ret)
- return ret;
- }
- return 0;
+ for (const struct pmu_events_map *tables = &pmu_events_map[0];
+ tables->arch;
+ tables++) {
+ int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
+
+ if (ret)
+ return ret;
+ }
+ return 0;
}
const struct pmu_events_table *find_sys_events_table(const char *name)
{
- for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
- tables->name;
- tables++) {
- if (!strcmp(tables->name, name))
- return &tables->table;
- }
- return NULL;
+ for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
+ tables->name;
+ tables++) {
+ if (!strcmp(tables->name, name))
+ return &tables->event_table;
+ }
+ return NULL;
}
int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
{
- for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
- tables->name;
- tables++) {
- int ret = pmu_events_table__for_each_event(&tables->table, /*pmu=*/ NULL, fn, data);
-
- if (ret)
- return ret;
- }
- return 0;
+ for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
+ tables->name;
+ tables++) {
+ int ret = pmu_events_table__for_each_event(&tables->event_table,
+ /*pmu=*/ NULL, fn, data);
+
+ if (ret)
+ return ret;
+ }
+ return 0;
}
-int pmu_for_each_sys_metric(pmu_metric_iter_fn fn __maybe_unused, void *data __maybe_unused)
+int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data)
{
- return 0;
+ for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
+ tables->name;
+ tables++) {
+ int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
+
+ if (ret)
+ return ret;
+ }
+ return 0;
}
-const char *describe_metricgroup(const char *group __maybe_unused)
+static const int metricgroups[][2] = {
+
+};
+
+const char *describe_metricgroup(const char *group)
{
- return NULL;
+ int low = 0, high = (int)ARRAY_SIZE(metricgroups) - 1;
+
+ while (low <= high) {
+ int mid = (low + high) / 2;
+ const char *mgroup = &big_c_string[metricgroups[mid][0]];
+ int cmp = strcmp(mgroup, group);
+
+ if (cmp == 0) {
+ return &big_c_string[metricgroups[mid][1]];
+ } else if (cmp < 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+ return NULL;
}
diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index 731776e29f47..fcf0158438b5 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -1256,6 +1256,10 @@ such as "arm/cortex-a34".''',
'output_file', type=argparse.FileType('w', encoding='utf-8'), nargs='?', default=sys.stdout)
_args = ap.parse_args()
+ _args.output_file.write(f"""
+/* SPDX-License-Identifier: GPL-2.0 */
+/* THIS FILE WAS AUTOGENERATED BY jevents.py arch={_args.arch} model={_args.model} ! */
+""")
_args.output_file.write("""
#include <pmu-events/pmu-events.h>
#include "util/header.h"
@@ -1281,7 +1285,7 @@ struct pmu_table_entry {
if item.name == _args.arch or _args.arch == 'all' or item.name == 'test':
archs.append(item.name)
- if len(archs) < 2:
+ if len(archs) < 2 and _args.arch != 'none':
raise IOError(f'Missing architecture directory \'{_args.arch}\'')
archs.sort()
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3 0/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-30 19:17 [PATCH v3 0/2] perf jevents: Autogenerate empty-pmu-events.c Ian Rogers
2024-07-30 19:17 ` [PATCH v3 1/2] perf jevents: Use name for special find value Ian Rogers
2024-07-30 19:17 ` [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c Ian Rogers
@ 2024-07-31 13:05 ` Arnaldo Carvalho de Melo
2 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-07-31 13:05 UTC (permalink / raw)
To: Ian Rogers
Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
John Garry, Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users,
linux-kernel, philip.li, oliver.sang, Weilin Wang
On Tue, Jul 30, 2024 at 12:17:42PM -0700, Ian Rogers wrote:
> Rebase of v2 patch set on tmp.perf-tools-next.
> https://lore.kernel.org/lkml/20240525013021.436430-1-irogers@google.com/
>
> Review was delayed because of an Intel automatic testing issue,
> confirmed not an issue here:
> https://lore.kernel.org/lkml/ZqhGNm+WDcsNx05e@xsang-OptiPlex-9020/
Thanks, applied to tmp.perf-tools-next,
- Arnaldo
> v3: Rebase and add John Garry's reviewed-by tag.
> v2: Add not found constant.
> Ian Rogers (2):
> perf jevents: Use name for special find value
> perf jevents: Autogenerate empty-pmu-events.c
>
> tools/perf/Makefile.perf | 2 +
> tools/perf/pmu-events/Build | 12 +-
> tools/perf/pmu-events/empty-pmu-events.c | 894 ++++++++++++++---------
> tools/perf/pmu-events/jevents.py | 12 +-
> tools/perf/pmu-events/pmu-events.h | 9 +
> 5 files changed, 574 insertions(+), 355 deletions(-)
>
> --
> 2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-30 19:17 ` [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c Ian Rogers
@ 2024-07-31 13:18 ` Arnaldo Carvalho de Melo
2024-07-31 14:08 ` Ian Rogers
0 siblings, 1 reply; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-07-31 13:18 UTC (permalink / raw)
To: Ian Rogers, John Garry
Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users, linux-kernel,
philip.li, oliver.sang, Weilin Wang
On Tue, Jul 30, 2024 at 12:17:44PM -0700, Ian Rogers wrote:
> empty-pmu-events.c exists so that builds may occur without python
> being installed on a system. Manually updating empty-pmu-events.c to
> be in sync with jevents.py is a pain, let's use jevents.py to generate
> empty-pmu-events.c.
What am I missing here?
If it exists so that we can build on a system without python how can we
use python to generate it?
Now having python in the system is a requirement and thus we don't need
empty-pmu-events.c anymore?
Can you guys please clarify that?
- Arnaldo
> 1) change jevents.py so that an arch and model of none cause
> generation of a pmu-events.c without any json. Add a SPDX and
> autogenerated warning to the start of the file.
> > 2) change Build so that if a generated pmu-events.c for arch none and
> model none doesn't match empty-pmu-events.c the build fails with a
> cat of the differences. Update Makefile.perf to clean up the files
> used for this.
>
> 3) update empty-pmu-events.c to match the output of jevents.py with
> arch and mode of none.
>
> Signed-off-by: Ian Rogers <irogers@google.com>
> Reviewed-by: John Garry <john.g.garry@oracle.com>
> ---
> tools/perf/Makefile.perf | 2 +
> tools/perf/pmu-events/Build | 12 +-
> tools/perf/pmu-events/empty-pmu-events.c | 894 ++++++++++++++---------
> tools/perf/pmu-events/jevents.py | 6 +-
> 4 files changed, 562 insertions(+), 352 deletions(-)
>
> diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
> index 175e4c7898f0..76bb0925849a 100644
> --- a/tools/perf/Makefile.perf
> +++ b/tools/perf/Makefile.perf
> @@ -1252,6 +1252,8 @@ clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(
> $(OUTPUT)util/intel-pt-decoder/inat-tables.c \
> $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
> $(OUTPUT)pmu-events/pmu-events.c \
> + $(OUTPUT)pmu-events/test-empty-pmu-events.c \
> + $(OUTPUT)pmu-events/empty-pmu-events.log \
> $(OUTPUT)pmu-events/metric_test.log \
> $(OUTPUT)$(fadvise_advice_array) \
> $(OUTPUT)$(fsconfig_arrays) \
> diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
> index 1d18bb89402e..c3fa43c49706 100644
> --- a/tools/perf/pmu-events/Build
> +++ b/tools/perf/pmu-events/Build
> @@ -11,6 +11,8 @@ METRIC_TEST_PY = pmu-events/metric_test.py
> EMPTY_PMU_EVENTS_C = pmu-events/empty-pmu-events.c
> PMU_EVENTS_C = $(OUTPUT)pmu-events/pmu-events.c
> METRIC_TEST_LOG = $(OUTPUT)pmu-events/metric_test.log
> +TEST_EMPTY_PMU_EVENTS_C = $(OUTPUT)pmu-events/test-empty-pmu-events.c
> +EMPTY_PMU_EVENTS_TEST_LOG = $(OUTPUT)pmu-events/empty-pmu-events.log
>
> ifeq ($(JEVENTS_ARCH),)
> JEVENTS_ARCH=$(SRCARCH)
> @@ -31,7 +33,15 @@ $(METRIC_TEST_LOG): $(METRIC_TEST_PY) $(METRIC_PY)
> $(call rule_mkdir)
> $(Q)$(call echo-cmd,test)$(PYTHON) $< 2> $@ || (cat $@ && false)
>
> -$(PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG)
> +$(TEST_EMPTY_PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG)
> + $(call rule_mkdir)
> + $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) none none pmu-events/arch $@
> +
> +$(EMPTY_PMU_EVENTS_TEST_LOG): $(EMPTY_PMU_EVENTS_C) $(TEST_EMPTY_PMU_EVENTS_C)
> + $(call rule_mkdir)
> + $(Q)$(call echo-cmd,test)diff -u $? 2> $@ || (cat $@ && false)
> +
> +$(PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) $(EMPTY_PMU_EVENTS_TEST_LOG)
> $(call rule_mkdir)
> $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) pmu-events/arch $@
> endif
> diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
> index 13727421d424..c592079982fb 100644
> --- a/tools/perf/pmu-events/empty-pmu-events.c
> +++ b/tools/perf/pmu-events/empty-pmu-events.c
> @@ -1,196 +1,193 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * An empty pmu-events.c file used when there is no architecture json files in
> - * arch or when the jevents.py script cannot be run.
> - *
> - * The test cpu/soc is provided for testing.
> - */
> -#include "pmu-events/pmu-events.h"
> +
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* THIS FILE WAS AUTOGENERATED BY jevents.py arch=none model=none ! */
> +
> +#include <pmu-events/pmu-events.h>
> #include "util/header.h"
> #include "util/pmu.h"
> #include <string.h>
> #include <stddef.h>
>
> -static const struct pmu_event pmu_events__test_soc_cpu[] = {
> - {
> - .name = "l3_cache_rd",
> - .event = "event=0x40",
> - .desc = "L3 cache access, read",
> - .topic = "cache",
> - .long_desc = "Attributable Level 3 cache access, read",
> - },
> - {
> - .name = "segment_reg_loads.any",
> - .event = "event=0x6,period=200000,umask=0x80",
> - .desc = "Number of segment register loads",
> - .topic = "other",
> - },
> - {
> - .name = "dispatch_blocked.any",
> - .event = "event=0x9,period=200000,umask=0x20",
> - .desc = "Memory cluster signals to block micro-op dispatch for any reason",
> - .topic = "other",
> - },
> - {
> - .name = "eist_trans",
> - .event = "event=0x3a,period=200000,umask=0x0",
> - .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
> - .topic = "other",
> - },
> - {
> - .name = "uncore_hisi_ddrc.flux_wcmd",
> - .event = "event=0x2",
> - .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
> - .topic = "uncore",
> - .long_desc = "DDRC write commands",
> - .pmu = "hisi_sccl,ddrc",
> - },
> - {
> - .name = "unc_cbo_xsnp_response.miss_eviction",
> - .event = "event=0x22,umask=0x81",
> - .desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox ",
> - .topic = "uncore",
> - .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
> - .pmu = "uncore_cbox",
> - },
> - {
> - .name = "event-hyphen",
> - .event = "event=0xe0,umask=0x00",
> - .desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox ",
> - .topic = "uncore",
> - .long_desc = "UNC_CBO_HYPHEN",
> - .pmu = "uncore_cbox",
> - },
> - {
> - .name = "event-two-hyph",
> - .event = "event=0xc0,umask=0x00",
> - .desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox ",
> - .topic = "uncore",
> - .long_desc = "UNC_CBO_TWO_HYPH",
> - .pmu = "uncore_cbox",
> - },
> - {
> - .name = "uncore_hisi_l3c.rd_hit_cpipe",
> - .event = "event=0x7",
> - .desc = "Total read hits. Unit: hisi_sccl,l3c ",
> - .topic = "uncore",
> - .long_desc = "Total read hits",
> - .pmu = "hisi_sccl,l3c",
> - },
> - {
> - .name = "uncore_imc_free_running.cache_miss",
> - .event = "event=0x12",
> - .desc = "Total cache misses. Unit: uncore_imc_free_running ",
> - .topic = "uncore",
> - .long_desc = "Total cache misses",
> - .pmu = "uncore_imc_free_running",
> - },
> - {
> - .name = "uncore_imc.cache_hits",
> - .event = "event=0x34",
> - .desc = "Total cache hits. Unit: uncore_imc ",
> - .topic = "uncore",
> - .long_desc = "Total cache hits",
> - .pmu = "uncore_imc",
> - },
> - {
> - .name = "bp_l1_btb_correct",
> - .event = "event=0x8a",
> - .desc = "L1 BTB Correction",
> - .topic = "branch",
> - },
> - {
> - .name = "bp_l2_btb_correct",
> - .event = "event=0x8b",
> - .desc = "L2 BTB Correction",
> - .topic = "branch",
> - },
> - {
> - .name = 0,
> - .event = 0,
> - .desc = 0,
> - },
> +struct compact_pmu_event {
> + int offset;
> };
>
> -static const struct pmu_metric pmu_metrics__test_soc_cpu[] = {
> - {
> - .metric_expr = "1 / IPC",
> - .metric_name = "CPI",
> - },
> - {
> - .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread",
> - .metric_name = "IPC",
> - .metric_group = "group1",
> - },
> - {
> - .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * "
> - "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))",
> - .metric_name = "Frontend_Bound_SMT",
> - },
> - {
> - .metric_expr = "l1d\\-loads\\-misses / inst_retired.any",
> - .metric_name = "dcache_miss_cpi",
> - },
> - {
> - .metric_expr = "l1i\\-loads\\-misses / inst_retired.any",
> - .metric_name = "icache_miss_cycles",
> - },
> - {
> - .metric_expr = "(dcache_miss_cpi + icache_miss_cycles)",
> - .metric_name = "cache_miss_cycles",
> - .metric_group = "group1",
> - },
> - {
> - .metric_expr = "l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit",
> - .metric_name = "DCache_L2_All_Hits",
> - },
> - {
> - .metric_expr = "max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + "
> - "l2_rqsts.pf_miss + l2_rqsts.rfo_miss",
> - .metric_name = "DCache_L2_All_Miss",
> - },
> - {
> - .metric_expr = "DCache_L2_All_Hits + DCache_L2_All_Miss",
> - .metric_name = "DCache_L2_All",
> - },
> - {
> - .metric_expr = "d_ratio(DCache_L2_All_Hits, DCache_L2_All)",
> - .metric_name = "DCache_L2_Hits",
> - },
> - {
> - .metric_expr = "d_ratio(DCache_L2_All_Miss, DCache_L2_All)",
> - .metric_name = "DCache_L2_Misses",
> - },
> - {
> - .metric_expr = "ipc + M2",
> - .metric_name = "M1",
> - },
> - {
> - .metric_expr = "ipc + M1",
> - .metric_name = "M2",
> - },
> - {
> - .metric_expr = "1/M3",
> - .metric_name = "M3",
> - },
> - {
> - .metric_expr = "64 * l1d.replacement / 1000000000 / duration_time",
> - .metric_name = "L1D_Cache_Fill_BW",
> - },
> - {
> - .metric_expr = 0,
> - .metric_name = 0,
> - },
> +struct pmu_table_entry {
> + const struct compact_pmu_event *entries;
> + uint32_t num_entries;
> + struct compact_pmu_event pmu_name;
> +};
> +
> +static const char *const big_c_string =
> +/* offset=0 */ "default_core\000"
> +/* offset=13 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000"
> +/* offset=72 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000"
> +/* offset=131 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000"
> +/* offset=226 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000"
> +/* offset=325 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000"
> +/* offset=455 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000"
> +/* offset=570 */ "hisi_sccl,ddrc\000"
> +/* offset=585 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000"
> +/* offset=671 */ "uncore_cbox\000"
> +/* offset=683 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000"
> +/* offset=914 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000"
> +/* offset=979 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000"
> +/* offset=1050 */ "hisi_sccl,l3c\000"
> +/* offset=1064 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000"
> +/* offset=1144 */ "uncore_imc_free_running\000"
> +/* offset=1168 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000"
> +/* offset=1263 */ "uncore_imc\000"
> +/* offset=1274 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000"
> +/* offset=1352 */ "uncore_sys_ddr_pmu\000"
> +/* offset=1371 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000"
> +/* offset=1444 */ "uncore_sys_ccn_pmu\000"
> +/* offset=1463 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000"
> +/* offset=1537 */ "uncore_sys_cmn_pmu\000"
> +/* offset=1556 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000"
> +/* offset=1696 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> +/* offset=1718 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> +/* offset=1781 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> +/* offset=1947 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> +/* offset=2011 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> +/* offset=2078 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> +/* offset=2149 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> +/* offset=2243 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> +/* offset=2377 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> +/* offset=2441 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> +/* offset=2509 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> +/* offset=2579 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> +/* offset=2601 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> +/* offset=2623 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> +/* offset=2643 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> +;
> +
> +static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
> +{ 13 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000 */
> +{ 72 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000 */
> +{ 325 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000 */
> +{ 455 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000 */
> +{ 131 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000 */
> +{ 226 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000 */
> +};
> +static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
> +{ 585 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000 */
> +};
> +static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
> +{ 1064 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000 */
> +};
> +static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
> +{ 914 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000 */
> +{ 979 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000 */
> +{ 683 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000 */
> +};
> +static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
> +{ 1274 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000 */
> +};
> +static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
> +{ 1168 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000 */
> +
> +};
> +
> +const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
> +{
> + .entries = pmu_events__test_soc_cpu_default_core,
> + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
> + .pmu_name = { 0 /* default_core\000 */ },
> +},
> +{
> + .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
> + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
> + .pmu_name = { 570 /* hisi_sccl,ddrc\000 */ },
> +},
> +{
> + .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
> + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
> + .pmu_name = { 1050 /* hisi_sccl,l3c\000 */ },
> +},
> +{
> + .entries = pmu_events__test_soc_cpu_uncore_cbox,
> + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
> + .pmu_name = { 671 /* uncore_cbox\000 */ },
> +},
> +{
> + .entries = pmu_events__test_soc_cpu_uncore_imc,
> + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
> + .pmu_name = { 1263 /* uncore_imc\000 */ },
> +},
> +{
> + .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
> + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
> + .pmu_name = { 1144 /* uncore_imc_free_running\000 */ },
> +},
> };
>
> +static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
> +{ 1696 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> +{ 2377 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> +{ 2149 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> +{ 2243 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> +{ 2441 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> +{ 2509 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> +{ 1781 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> +{ 1718 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> +{ 2643 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> +{ 2579 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> +{ 2601 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> +{ 2623 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> +{ 2078 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> +{ 1947 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> +{ 2011 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> +
> +};
> +
> +const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
> +{
> + .entries = pmu_metrics__test_soc_cpu_default_core,
> + .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
> + .pmu_name = { 0 /* default_core\000 */ },
> +},
> +};
> +
> +static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
> +{ 1463 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000 */
> +};
> +static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
> +{ 1556 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000 */
> +};
> +static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
> +{ 1371 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000 */
> +
> +};
> +
> +const struct pmu_table_entry pmu_events__test_soc_sys[] = {
> +{
> + .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
> + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
> + .pmu_name = { 1444 /* uncore_sys_ccn_pmu\000 */ },
> +},
> +{
> + .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
> + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
> + .pmu_name = { 1537 /* uncore_sys_cmn_pmu\000 */ },
> +},
> +{
> + .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
> + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
> + .pmu_name = { 1352 /* uncore_sys_ddr_pmu\000 */ },
> +},
> +};
> +
> +
> /* Struct used to make the PMU event table implementation opaque to callers. */
> struct pmu_events_table {
> - const struct pmu_event *entries;
> + const struct pmu_table_entry *pmus;
> + uint32_t num_pmus;
> };
>
> /* Struct used to make the PMU metric table implementation opaque to callers. */
> struct pmu_metrics_table {
> - const struct pmu_metric *entries;
> + const struct pmu_table_entry *pmus;
> + uint32_t num_pmus;
> };
>
> /*
> @@ -202,92 +199,191 @@ struct pmu_metrics_table {
> * The cpuid can contain any character other than the comma.
> */
> struct pmu_events_map {
> - const char *arch;
> - const char *cpuid;
> - const struct pmu_events_table event_table;
> - const struct pmu_metrics_table metric_table;
> + const char *arch;
> + const char *cpuid;
> + struct pmu_events_table event_table;
> + struct pmu_metrics_table metric_table;
> };
>
> /*
> * Global table mapping each known CPU for the architecture to its
> * table of PMU events.
> */
> -static const struct pmu_events_map pmu_events_map[] = {
> - {
> - .arch = "testarch",
> - .cpuid = "testcpu",
> - .event_table = { pmu_events__test_soc_cpu },
> - .metric_table = { pmu_metrics__test_soc_cpu },
> - },
> - {
> - .arch = 0,
> - .cpuid = 0,
> - .event_table = { 0 },
> - .metric_table = { 0 },
> - },
> -};
> -
> -static const struct pmu_event pmu_events__test_soc_sys[] = {
> - {
> - .name = "sys_ddr_pmu.write_cycles",
> - .event = "event=0x2b",
> - .desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
> - .compat = "v8",
> - .topic = "uncore",
> - .pmu = "uncore_sys_ddr_pmu",
> - },
> - {
> - .name = "sys_ccn_pmu.read_cycles",
> - .event = "config=0x2c",
> - .desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
> - .compat = "0x01",
> - .topic = "uncore",
> - .pmu = "uncore_sys_ccn_pmu",
> - },
> - {
> - .name = "sys_cmn_pmu.hnf_cache_miss",
> - .event = "eventid=0x1,type=0x5",
> - .desc = "Counts total cache misses in first lookup result (high priority). Unit: uncore_sys_cmn_pmu ",
> - .compat = "(434|436|43c|43a).*",
> - .topic = "uncore",
> - .pmu = "uncore_sys_cmn_pmu",
> - },
> - {
> - .name = 0,
> - .event = 0,
> - .desc = 0,
> - },
> +const struct pmu_events_map pmu_events_map[] = {
> +{
> + .arch = "testarch",
> + .cpuid = "testcpu",
> + .event_table = {
> + .pmus = pmu_events__test_soc_cpu,
> + .num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu),
> + },
> + .metric_table = {
> + .pmus = pmu_metrics__test_soc_cpu,
> + .num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
> + }
> +},
> +{
> + .arch = 0,
> + .cpuid = 0,
> + .event_table = { 0, 0 },
> + .metric_table = { 0, 0 },
> +}
> };
>
> struct pmu_sys_events {
> const char *name;
> - const struct pmu_events_table table;
> + struct pmu_events_table event_table;
> + struct pmu_metrics_table metric_table;
> };
>
> static const struct pmu_sys_events pmu_sys_event_tables[] = {
> {
> - .table = { pmu_events__test_soc_sys },
> + .event_table = {
> + .pmus = pmu_events__test_soc_sys,
> + .num_pmus = ARRAY_SIZE(pmu_events__test_soc_sys)
> + },
> .name = "pmu_events__test_soc_sys",
> },
> {
> - .table = { 0 }
> + .event_table = { 0, 0 },
> + .metric_table = { 0, 0 },
> },
> };
>
> -int pmu_events_table__for_each_event(const struct pmu_events_table *table, struct perf_pmu *pmu,
> - pmu_event_iter_fn fn, void *data)
> +static void decompress_event(int offset, struct pmu_event *pe)
> +{
> + const char *p = &big_c_string[offset];
> +
> + pe->name = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pe->topic = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pe->desc = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pe->event = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pe->compat = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pe->deprecated = *p - '0';
> + p++;
> + pe->perpkg = *p - '0';
> + p++;
> + pe->unit = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pe->long_desc = (*p == '\0' ? NULL : p);
> +}
> +
> +static void decompress_metric(int offset, struct pmu_metric *pm)
> {
> - for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
> - int ret;
> + const char *p = &big_c_string[offset];
> +
> + pm->metric_name = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pm->metric_group = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pm->metric_expr = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pm->metric_threshold = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pm->desc = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pm->long_desc = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pm->unit = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pm->compat = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pm->metricgroup_no_group = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pm->default_metricgroup_name = (*p == '\0' ? NULL : p);
> + while (*p++);
> + pm->aggr_mode = *p - '0';
> + p++;
> + pm->event_grouping = *p - '0';
> +}
>
> - if (pmu && !pmu__name_match(pmu, pe->pmu))
> +static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table,
> + const struct pmu_table_entry *pmu,
> + pmu_event_iter_fn fn,
> + void *data)
> +{
> + int ret;
> + struct pmu_event pe = {
> + .pmu = &big_c_string[pmu->pmu_name.offset],
> + };
> +
> + for (uint32_t i = 0; i < pmu->num_entries; i++) {
> + decompress_event(pmu->entries[i].offset, &pe);
> + if (!pe.name)
> continue;
> + ret = fn(&pe, table, data);
> + if (ret)
> + return ret;
> + }
> + return 0;
> + }
> +
> +static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table,
> + const struct pmu_table_entry *pmu,
> + const char *name,
> + pmu_event_iter_fn fn,
> + void *data)
> +{
> + struct pmu_event pe = {
> + .pmu = &big_c_string[pmu->pmu_name.offset],
> + };
> + int low = 0, high = pmu->num_entries - 1;
>
> - ret = fn(pe, table, data);
> - if (ret)
> - return ret;
> - }
> - return 0;
> + while (low <= high) {
> + int cmp, mid = (low + high) / 2;
> +
> + decompress_event(pmu->entries[mid].offset, &pe);
> +
> + if (!pe.name && !name)
> + goto do_call;
> +
> + if (!pe.name && name) {
> + low = mid + 1;
> + continue;
> + }
> + if (pe.name && !name) {
> + high = mid - 1;
> + continue;
> + }
> +
> + cmp = strcasecmp(pe.name, name);
> + if (cmp < 0) {
> + low = mid + 1;
> + continue;
> + }
> + if (cmp > 0) {
> + high = mid - 1;
> + continue;
> + }
> + do_call:
> + return fn ? fn(&pe, table, data) : 0;
> + }
> + return PMU_EVENTS__NOT_FOUND;
> +}
> +
> +int pmu_events_table__for_each_event(const struct pmu_events_table *table,
> + struct perf_pmu *pmu,
> + pmu_event_iter_fn fn,
> + void *data)
> +{
> + for (size_t i = 0; i < table->num_pmus; i++) {
> + const struct pmu_table_entry *table_pmu = &table->pmus[i];
> + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> + int ret;
> +
> + if (pmu && !pmu__name_match(pmu, pmu_name))
> + continue;
> +
> + ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
> + if (pmu || ret)
> + return ret;
> + }
> + return 0;
> }
>
> int pmu_events_table__find_event(const struct pmu_events_table *table,
> @@ -296,14 +392,19 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
> pmu_event_iter_fn fn,
> void *data)
> {
> - for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
> - if (pmu && !pmu__name_match(pmu, pe->pmu))
> + for (size_t i = 0; i < table->num_pmus; i++) {
> + const struct pmu_table_entry *table_pmu = &table->pmus[i];
> + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> + int ret;
> +
> + if (!pmu__name_match(pmu, pmu_name))
> continue;
>
> - if (!strcasecmp(pe->name, name))
> - return fn(pe, table, data);
> - }
> - return -1000;
> + ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data);
> + if (ret != PMU_EVENTS__NOT_FOUND)
> + return ret;
> + }
> + return PMU_EVENTS__NOT_FOUND;
> }
>
> size_t pmu_events_table__num_events(const struct pmu_events_table *table,
> @@ -311,160 +412,253 @@ size_t pmu_events_table__num_events(const struct pmu_events_table *table,
> {
> size_t count = 0;
>
> - for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
> - if (pmu && !pmu__name_match(pmu, pe->pmu))
> - continue;
> + for (size_t i = 0; i < table->num_pmus; i++) {
> + const struct pmu_table_entry *table_pmu = &table->pmus[i];
> + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
>
> - count++;
> - }
> + if (pmu__name_match(pmu, pmu_name))
> + count += table_pmu->num_entries;
> + }
> return count;
> }
>
> -int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
> - void *data)
> +static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
> + const struct pmu_table_entry *pmu,
> + pmu_metric_iter_fn fn,
> + void *data)
> +{
> + int ret;
> + struct pmu_metric pm = {
> + .pmu = &big_c_string[pmu->pmu_name.offset],
> + };
> +
> + for (uint32_t i = 0; i < pmu->num_entries; i++) {
> + decompress_metric(pmu->entries[i].offset, &pm);
> + if (!pm.metric_expr)
> + continue;
> + ret = fn(&pm, table, data);
> + if (ret)
> + return ret;
> + }
> + return 0;
> +}
> +
> +int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table,
> + pmu_metric_iter_fn fn,
> + void *data)
> {
> - for (const struct pmu_metric *pm = &table->entries[0]; pm->metric_expr; pm++) {
> - int ret = fn(pm, table, data);
> + for (size_t i = 0; i < table->num_pmus; i++) {
> + int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i],
> + fn, data);
> +
> + if (ret)
> + return ret;
> + }
> + return 0;
> +}
>
> - if (ret)
> - return ret;
> - }
> - return 0;
> +static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> +{
> + static struct {
> + const struct pmu_events_map *map;
> + struct perf_pmu *pmu;
> + } last_result;
> + static struct {
> + const struct pmu_events_map *map;
> + char *cpuid;
> + } last_map_search;
> + static bool has_last_result, has_last_map_search;
> + const struct pmu_events_map *map = NULL;
> + char *cpuid = NULL;
> + size_t i;
> +
> + if (has_last_result && last_result.pmu == pmu)
> + return last_result.map;
> +
> + cpuid = perf_pmu__getcpuid(pmu);
> +
> + /*
> + * On some platforms which uses cpus map, cpuid can be NULL for
> + * PMUs other than CORE PMUs.
> + */
> + if (!cpuid)
> + goto out_update_last_result;
> +
> + if (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) {
> + map = last_map_search.map;
> + free(cpuid);
> + } else {
> + i = 0;
> + for (;;) {
> + map = &pmu_events_map[i++];
> +
> + if (!map->arch) {
> + map = NULL;
> + break;
> + }
> +
> + if (!strcmp_cpuid_str(map->cpuid, cpuid))
> + break;
> + }
> + free(last_map_search.cpuid);
> + last_map_search.cpuid = cpuid;
> + last_map_search.map = map;
> + has_last_map_search = true;
> + }
> +out_update_last_result:
> + last_result.pmu = pmu;
> + last_result.map = map;
> + has_last_result = true;
> + return map;
> }
>
> const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu)
> {
> - const struct pmu_events_table *table = NULL;
> - char *cpuid = perf_pmu__getcpuid(pmu);
> - int i;
> + const struct pmu_events_map *map = map_for_pmu(pmu);
>
> - /* on some platforms which uses cpus map, cpuid can be NULL for
> - * PMUs other than CORE PMUs.
> - */
> - if (!cpuid)
> - return NULL;
> + if (!map)
> + return NULL;
>
> - i = 0;
> - for (;;) {
> - const struct pmu_events_map *map = &pmu_events_map[i++];
> + if (!pmu)
> + return &map->event_table;
>
> - if (!map->cpuid)
> - break;
> + for (size_t i = 0; i < map->event_table.num_pmus; i++) {
> + const struct pmu_table_entry *table_pmu = &map->event_table.pmus[i];
> + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
>
> - if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
> - table = &map->event_table;
> - break;
> - }
> - }
> - free(cpuid);
> - return table;
> + if (pmu__name_match(pmu, pmu_name))
> + return &map->event_table;
> + }
> + return NULL;
> }
>
> const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pmu)
> {
> - const struct pmu_metrics_table *table = NULL;
> - char *cpuid = perf_pmu__getcpuid(pmu);
> - int i;
> + const struct pmu_events_map *map = map_for_pmu(pmu);
>
> - /* on some platforms which uses cpus map, cpuid can be NULL for
> - * PMUs other than CORE PMUs.
> - */
> - if (!cpuid)
> - return NULL;
> + if (!map)
> + return NULL;
>
> - i = 0;
> - for (;;) {
> - const struct pmu_events_map *map = &pmu_events_map[i++];
> + if (!pmu)
> + return &map->metric_table;
>
> - if (!map->cpuid)
> - break;
> + for (size_t i = 0; i < map->metric_table.num_pmus; i++) {
> + const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i];
> + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
>
> - if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
> - table = &map->metric_table;
> - break;
> - }
> - }
> - free(cpuid);
> - return table;
> + if (pmu__name_match(pmu, pmu_name))
> + return &map->metric_table;
> + }
> + return NULL;
> }
>
> const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid)
> {
> - for (const struct pmu_events_map *tables = &pmu_events_map[0];
> - tables->arch;
> - tables++) {
> - if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> - return &tables->event_table;
> - }
> - return NULL;
> + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> + tables->arch;
> + tables++) {
> + if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> + return &tables->event_table;
> + }
> + return NULL;
> }
>
> const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid)
> {
> - for (const struct pmu_events_map *tables = &pmu_events_map[0];
> - tables->arch;
> - tables++) {
> - if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> - return &tables->metric_table;
> - }
> - return NULL;
> + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> + tables->arch;
> + tables++) {
> + if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> + return &tables->metric_table;
> + }
> + return NULL;
> }
>
> int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
> {
> - for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->arch; tables++) {
> - int ret = pmu_events_table__for_each_event(&tables->event_table,
> - /*pmu=*/ NULL, fn, data);
> -
> - if (ret)
> - return ret;
> - }
> - return 0;
> + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> + tables->arch;
> + tables++) {
> + int ret = pmu_events_table__for_each_event(&tables->event_table,
> + /*pmu=*/ NULL, fn, data);
> +
> + if (ret)
> + return ret;
> + }
> + return 0;
> }
>
> int pmu_for_each_core_metric(pmu_metric_iter_fn fn, void *data)
> {
> - for (const struct pmu_events_map *tables = &pmu_events_map[0];
> - tables->arch;
> - tables++) {
> - int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
> -
> - if (ret)
> - return ret;
> - }
> - return 0;
> + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> + tables->arch;
> + tables++) {
> + int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
> +
> + if (ret)
> + return ret;
> + }
> + return 0;
> }
>
> const struct pmu_events_table *find_sys_events_table(const char *name)
> {
> - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> - tables->name;
> - tables++) {
> - if (!strcmp(tables->name, name))
> - return &tables->table;
> - }
> - return NULL;
> + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> + tables->name;
> + tables++) {
> + if (!strcmp(tables->name, name))
> + return &tables->event_table;
> + }
> + return NULL;
> }
>
> int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
> {
> - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> - tables->name;
> - tables++) {
> - int ret = pmu_events_table__for_each_event(&tables->table, /*pmu=*/ NULL, fn, data);
> -
> - if (ret)
> - return ret;
> - }
> - return 0;
> + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> + tables->name;
> + tables++) {
> + int ret = pmu_events_table__for_each_event(&tables->event_table,
> + /*pmu=*/ NULL, fn, data);
> +
> + if (ret)
> + return ret;
> + }
> + return 0;
> }
>
> -int pmu_for_each_sys_metric(pmu_metric_iter_fn fn __maybe_unused, void *data __maybe_unused)
> +int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data)
> {
> - return 0;
> + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> + tables->name;
> + tables++) {
> + int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
> +
> + if (ret)
> + return ret;
> + }
> + return 0;
> }
>
> -const char *describe_metricgroup(const char *group __maybe_unused)
> +static const int metricgroups[][2] = {
> +
> +};
> +
> +const char *describe_metricgroup(const char *group)
> {
> - return NULL;
> + int low = 0, high = (int)ARRAY_SIZE(metricgroups) - 1;
> +
> + while (low <= high) {
> + int mid = (low + high) / 2;
> + const char *mgroup = &big_c_string[metricgroups[mid][0]];
> + int cmp = strcmp(mgroup, group);
> +
> + if (cmp == 0) {
> + return &big_c_string[metricgroups[mid][1]];
> + } else if (cmp < 0) {
> + low = mid + 1;
> + } else {
> + high = mid - 1;
> + }
> + }
> + return NULL;
> }
> diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> index 731776e29f47..fcf0158438b5 100755
> --- a/tools/perf/pmu-events/jevents.py
> +++ b/tools/perf/pmu-events/jevents.py
> @@ -1256,6 +1256,10 @@ such as "arm/cortex-a34".''',
> 'output_file', type=argparse.FileType('w', encoding='utf-8'), nargs='?', default=sys.stdout)
> _args = ap.parse_args()
>
> + _args.output_file.write(f"""
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* THIS FILE WAS AUTOGENERATED BY jevents.py arch={_args.arch} model={_args.model} ! */
> +""")
> _args.output_file.write("""
> #include <pmu-events/pmu-events.h>
> #include "util/header.h"
> @@ -1281,7 +1285,7 @@ struct pmu_table_entry {
> if item.name == _args.arch or _args.arch == 'all' or item.name == 'test':
> archs.append(item.name)
>
> - if len(archs) < 2:
> + if len(archs) < 2 and _args.arch != 'none':
> raise IOError(f'Missing architecture directory \'{_args.arch}\'')
>
> archs.sort()
> --
> 2.46.0.rc2.264.g509ed76dc8-goog
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 1/2] perf jevents: Use name for special find value
2024-07-30 19:17 ` [PATCH v3 1/2] perf jevents: Use name for special find value Ian Rogers
@ 2024-07-31 13:19 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-07-31 13:19 UTC (permalink / raw)
To: Ian Rogers
Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Adrian Hunter, Kan Liang,
John Garry, Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users,
linux-kernel, philip.li, oliver.sang, Weilin Wang
On Tue, Jul 30, 2024 at 12:17:43PM -0700, Ian Rogers wrote:
> -1000 was used as a special value added in Commit 3d5045492ab2 ("perf
> pmu-events: Add pmu_events_table__find_event()") to show that 1 table
> lacked a PMU/event but that didn't terminate the search in other
> tables. Add a new constant PMU_EVENTS__NOT_FOUND for this value and
> use it.
Applied this one.
- Arnaldo
> Signed-off-by: Ian Rogers <irogers@google.com>
> Reviewed-by: John Garry <john.g.garry@oracle.com>
> ---
> tools/perf/pmu-events/jevents.py | 6 +++---
> tools/perf/pmu-events/pmu-events.h | 9 +++++++++
> 2 files changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> index ac9b7ca41856..731776e29f47 100755
> --- a/tools/perf/pmu-events/jevents.py
> +++ b/tools/perf/pmu-events/jevents.py
> @@ -906,7 +906,7 @@ static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table
> do_call:
> return fn ? fn(&pe, table, data) : 0;
> }
> - return -1000;
> + return PMU_EVENTS__NOT_FOUND;
> }
>
> int pmu_events_table__for_each_event(const struct pmu_events_table *table,
> @@ -944,10 +944,10 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
> continue;
>
> ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data);
> - if (ret != -1000)
> + if (ret != PMU_EVENTS__NOT_FOUND)
> return ret;
> }
> - return -1000;
> + return PMU_EVENTS__NOT_FOUND;
> }
>
> size_t pmu_events_table__num_events(const struct pmu_events_table *table,
> diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
> index f5aa96f1685c..5435ad92180c 100644
> --- a/tools/perf/pmu-events/pmu-events.h
> +++ b/tools/perf/pmu-events/pmu-events.h
> @@ -70,6 +70,8 @@ struct pmu_metric {
> struct pmu_events_table;
> struct pmu_metrics_table;
>
> +#define PMU_EVENTS__NOT_FOUND -1000
> +
> typedef int (*pmu_event_iter_fn)(const struct pmu_event *pe,
> const struct pmu_events_table *table,
> void *data);
> @@ -82,6 +84,13 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table,
> struct perf_pmu *pmu,
> pmu_event_iter_fn fn,
> void *data);
> +/*
> + * Search for table and entry matching with pmu__name_match. Each matching event
> + * has fn called on it. 0 implies to success/continue the search while non-zero
> + * means to terminate. The special value PMU_EVENTS__NOT_FOUND is used to
> + * indicate no event was found in one of the tables which doesn't terminate the
> + * search of all tables.
> + */
> int pmu_events_table__find_event(const struct pmu_events_table *table,
> struct perf_pmu *pmu,
> const char *name,
> --
> 2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-31 13:18 ` Arnaldo Carvalho de Melo
@ 2024-07-31 14:08 ` Ian Rogers
2024-07-31 15:33 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 14+ messages in thread
From: Ian Rogers @ 2024-07-31 14:08 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: John Garry, Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
Kan Liang, Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users,
linux-kernel, philip.li, oliver.sang, Weilin Wang
On Wed, Jul 31, 2024 at 6:18 AM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> On Tue, Jul 30, 2024 at 12:17:44PM -0700, Ian Rogers wrote:
> > empty-pmu-events.c exists so that builds may occur without python
> > being installed on a system. Manually updating empty-pmu-events.c to
> > be in sync with jevents.py is a pain, let's use jevents.py to generate
> > empty-pmu-events.c.
>
> What am I missing here?
>
> If it exists so that we can build on a system without python how can we
> use python to generate it?
>
> Now having python in the system is a requirement and thus we don't need
> empty-pmu-events.c anymore?
>
> Can you guys please clarify that?
The requirement for python hasn't changed.
Case 1: no python or NO_JEVENTS=1
Build happens using empty-pmu-events.c that is checked in, no python
is required.
Case 2: python
pmu-events.c is created by jevents.py (requiring python) and then built.
This change adds a step where the empty-pmu-events.c is created using
jevents.py and that file is diffed against the checked in version.
This stops the checked in empty-pmu-events.c diverging if changes are
made to jevents.py. If the diff causes the build to fail then you just
copy the diff empty-pmu-events.c over the checked in one.
Thanks,
Ian
> - Arnaldo
>
> > 1) change jevents.py so that an arch and model of none cause
> > generation of a pmu-events.c without any json. Add a SPDX and
> > autogenerated warning to the start of the file.
> > > 2) change Build so that if a generated pmu-events.c for arch none and
> > model none doesn't match empty-pmu-events.c the build fails with a
> > cat of the differences. Update Makefile.perf to clean up the files
> > used for this.
> >
> > 3) update empty-pmu-events.c to match the output of jevents.py with
> > arch and mode of none.
> >
> > Signed-off-by: Ian Rogers <irogers@google.com>
> > Reviewed-by: John Garry <john.g.garry@oracle.com>
> > ---
> > tools/perf/Makefile.perf | 2 +
> > tools/perf/pmu-events/Build | 12 +-
> > tools/perf/pmu-events/empty-pmu-events.c | 894 ++++++++++++++---------
> > tools/perf/pmu-events/jevents.py | 6 +-
> > 4 files changed, 562 insertions(+), 352 deletions(-)
> >
> > diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
> > index 175e4c7898f0..76bb0925849a 100644
> > --- a/tools/perf/Makefile.perf
> > +++ b/tools/perf/Makefile.perf
> > @@ -1252,6 +1252,8 @@ clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(
> > $(OUTPUT)util/intel-pt-decoder/inat-tables.c \
> > $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
> > $(OUTPUT)pmu-events/pmu-events.c \
> > + $(OUTPUT)pmu-events/test-empty-pmu-events.c \
> > + $(OUTPUT)pmu-events/empty-pmu-events.log \
> > $(OUTPUT)pmu-events/metric_test.log \
> > $(OUTPUT)$(fadvise_advice_array) \
> > $(OUTPUT)$(fsconfig_arrays) \
> > diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
> > index 1d18bb89402e..c3fa43c49706 100644
> > --- a/tools/perf/pmu-events/Build
> > +++ b/tools/perf/pmu-events/Build
> > @@ -11,6 +11,8 @@ METRIC_TEST_PY = pmu-events/metric_test.py
> > EMPTY_PMU_EVENTS_C = pmu-events/empty-pmu-events.c
> > PMU_EVENTS_C = $(OUTPUT)pmu-events/pmu-events.c
> > METRIC_TEST_LOG = $(OUTPUT)pmu-events/metric_test.log
> > +TEST_EMPTY_PMU_EVENTS_C = $(OUTPUT)pmu-events/test-empty-pmu-events.c
> > +EMPTY_PMU_EVENTS_TEST_LOG = $(OUTPUT)pmu-events/empty-pmu-events.log
> >
> > ifeq ($(JEVENTS_ARCH),)
> > JEVENTS_ARCH=$(SRCARCH)
> > @@ -31,7 +33,15 @@ $(METRIC_TEST_LOG): $(METRIC_TEST_PY) $(METRIC_PY)
> > $(call rule_mkdir)
> > $(Q)$(call echo-cmd,test)$(PYTHON) $< 2> $@ || (cat $@ && false)
> >
> > -$(PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG)
> > +$(TEST_EMPTY_PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG)
> > + $(call rule_mkdir)
> > + $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) none none pmu-events/arch $@
> > +
> > +$(EMPTY_PMU_EVENTS_TEST_LOG): $(EMPTY_PMU_EVENTS_C) $(TEST_EMPTY_PMU_EVENTS_C)
> > + $(call rule_mkdir)
> > + $(Q)$(call echo-cmd,test)diff -u $? 2> $@ || (cat $@ && false)
> > +
> > +$(PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) $(EMPTY_PMU_EVENTS_TEST_LOG)
> > $(call rule_mkdir)
> > $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) pmu-events/arch $@
> > endif
> > diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
> > index 13727421d424..c592079982fb 100644
> > --- a/tools/perf/pmu-events/empty-pmu-events.c
> > +++ b/tools/perf/pmu-events/empty-pmu-events.c
> > @@ -1,196 +1,193 @@
> > -// SPDX-License-Identifier: GPL-2.0
> > -/*
> > - * An empty pmu-events.c file used when there is no architecture json files in
> > - * arch or when the jevents.py script cannot be run.
> > - *
> > - * The test cpu/soc is provided for testing.
> > - */
> > -#include "pmu-events/pmu-events.h"
> > +
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/* THIS FILE WAS AUTOGENERATED BY jevents.py arch=none model=none ! */
> > +
> > +#include <pmu-events/pmu-events.h>
> > #include "util/header.h"
> > #include "util/pmu.h"
> > #include <string.h>
> > #include <stddef.h>
> >
> > -static const struct pmu_event pmu_events__test_soc_cpu[] = {
> > - {
> > - .name = "l3_cache_rd",
> > - .event = "event=0x40",
> > - .desc = "L3 cache access, read",
> > - .topic = "cache",
> > - .long_desc = "Attributable Level 3 cache access, read",
> > - },
> > - {
> > - .name = "segment_reg_loads.any",
> > - .event = "event=0x6,period=200000,umask=0x80",
> > - .desc = "Number of segment register loads",
> > - .topic = "other",
> > - },
> > - {
> > - .name = "dispatch_blocked.any",
> > - .event = "event=0x9,period=200000,umask=0x20",
> > - .desc = "Memory cluster signals to block micro-op dispatch for any reason",
> > - .topic = "other",
> > - },
> > - {
> > - .name = "eist_trans",
> > - .event = "event=0x3a,period=200000,umask=0x0",
> > - .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
> > - .topic = "other",
> > - },
> > - {
> > - .name = "uncore_hisi_ddrc.flux_wcmd",
> > - .event = "event=0x2",
> > - .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
> > - .topic = "uncore",
> > - .long_desc = "DDRC write commands",
> > - .pmu = "hisi_sccl,ddrc",
> > - },
> > - {
> > - .name = "unc_cbo_xsnp_response.miss_eviction",
> > - .event = "event=0x22,umask=0x81",
> > - .desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox ",
> > - .topic = "uncore",
> > - .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
> > - .pmu = "uncore_cbox",
> > - },
> > - {
> > - .name = "event-hyphen",
> > - .event = "event=0xe0,umask=0x00",
> > - .desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox ",
> > - .topic = "uncore",
> > - .long_desc = "UNC_CBO_HYPHEN",
> > - .pmu = "uncore_cbox",
> > - },
> > - {
> > - .name = "event-two-hyph",
> > - .event = "event=0xc0,umask=0x00",
> > - .desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox ",
> > - .topic = "uncore",
> > - .long_desc = "UNC_CBO_TWO_HYPH",
> > - .pmu = "uncore_cbox",
> > - },
> > - {
> > - .name = "uncore_hisi_l3c.rd_hit_cpipe",
> > - .event = "event=0x7",
> > - .desc = "Total read hits. Unit: hisi_sccl,l3c ",
> > - .topic = "uncore",
> > - .long_desc = "Total read hits",
> > - .pmu = "hisi_sccl,l3c",
> > - },
> > - {
> > - .name = "uncore_imc_free_running.cache_miss",
> > - .event = "event=0x12",
> > - .desc = "Total cache misses. Unit: uncore_imc_free_running ",
> > - .topic = "uncore",
> > - .long_desc = "Total cache misses",
> > - .pmu = "uncore_imc_free_running",
> > - },
> > - {
> > - .name = "uncore_imc.cache_hits",
> > - .event = "event=0x34",
> > - .desc = "Total cache hits. Unit: uncore_imc ",
> > - .topic = "uncore",
> > - .long_desc = "Total cache hits",
> > - .pmu = "uncore_imc",
> > - },
> > - {
> > - .name = "bp_l1_btb_correct",
> > - .event = "event=0x8a",
> > - .desc = "L1 BTB Correction",
> > - .topic = "branch",
> > - },
> > - {
> > - .name = "bp_l2_btb_correct",
> > - .event = "event=0x8b",
> > - .desc = "L2 BTB Correction",
> > - .topic = "branch",
> > - },
> > - {
> > - .name = 0,
> > - .event = 0,
> > - .desc = 0,
> > - },
> > +struct compact_pmu_event {
> > + int offset;
> > };
> >
> > -static const struct pmu_metric pmu_metrics__test_soc_cpu[] = {
> > - {
> > - .metric_expr = "1 / IPC",
> > - .metric_name = "CPI",
> > - },
> > - {
> > - .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread",
> > - .metric_name = "IPC",
> > - .metric_group = "group1",
> > - },
> > - {
> > - .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * "
> > - "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))",
> > - .metric_name = "Frontend_Bound_SMT",
> > - },
> > - {
> > - .metric_expr = "l1d\\-loads\\-misses / inst_retired.any",
> > - .metric_name = "dcache_miss_cpi",
> > - },
> > - {
> > - .metric_expr = "l1i\\-loads\\-misses / inst_retired.any",
> > - .metric_name = "icache_miss_cycles",
> > - },
> > - {
> > - .metric_expr = "(dcache_miss_cpi + icache_miss_cycles)",
> > - .metric_name = "cache_miss_cycles",
> > - .metric_group = "group1",
> > - },
> > - {
> > - .metric_expr = "l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit",
> > - .metric_name = "DCache_L2_All_Hits",
> > - },
> > - {
> > - .metric_expr = "max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + "
> > - "l2_rqsts.pf_miss + l2_rqsts.rfo_miss",
> > - .metric_name = "DCache_L2_All_Miss",
> > - },
> > - {
> > - .metric_expr = "DCache_L2_All_Hits + DCache_L2_All_Miss",
> > - .metric_name = "DCache_L2_All",
> > - },
> > - {
> > - .metric_expr = "d_ratio(DCache_L2_All_Hits, DCache_L2_All)",
> > - .metric_name = "DCache_L2_Hits",
> > - },
> > - {
> > - .metric_expr = "d_ratio(DCache_L2_All_Miss, DCache_L2_All)",
> > - .metric_name = "DCache_L2_Misses",
> > - },
> > - {
> > - .metric_expr = "ipc + M2",
> > - .metric_name = "M1",
> > - },
> > - {
> > - .metric_expr = "ipc + M1",
> > - .metric_name = "M2",
> > - },
> > - {
> > - .metric_expr = "1/M3",
> > - .metric_name = "M3",
> > - },
> > - {
> > - .metric_expr = "64 * l1d.replacement / 1000000000 / duration_time",
> > - .metric_name = "L1D_Cache_Fill_BW",
> > - },
> > - {
> > - .metric_expr = 0,
> > - .metric_name = 0,
> > - },
> > +struct pmu_table_entry {
> > + const struct compact_pmu_event *entries;
> > + uint32_t num_entries;
> > + struct compact_pmu_event pmu_name;
> > +};
> > +
> > +static const char *const big_c_string =
> > +/* offset=0 */ "default_core\000"
> > +/* offset=13 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000"
> > +/* offset=72 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000"
> > +/* offset=131 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000"
> > +/* offset=226 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000"
> > +/* offset=325 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000"
> > +/* offset=455 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000"
> > +/* offset=570 */ "hisi_sccl,ddrc\000"
> > +/* offset=585 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000"
> > +/* offset=671 */ "uncore_cbox\000"
> > +/* offset=683 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000"
> > +/* offset=914 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000"
> > +/* offset=979 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000"
> > +/* offset=1050 */ "hisi_sccl,l3c\000"
> > +/* offset=1064 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000"
> > +/* offset=1144 */ "uncore_imc_free_running\000"
> > +/* offset=1168 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000"
> > +/* offset=1263 */ "uncore_imc\000"
> > +/* offset=1274 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000"
> > +/* offset=1352 */ "uncore_sys_ddr_pmu\000"
> > +/* offset=1371 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000"
> > +/* offset=1444 */ "uncore_sys_ccn_pmu\000"
> > +/* offset=1463 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000"
> > +/* offset=1537 */ "uncore_sys_cmn_pmu\000"
> > +/* offset=1556 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000"
> > +/* offset=1696 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> > +/* offset=1718 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> > +/* offset=1781 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> > +/* offset=1947 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > +/* offset=2011 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > +/* offset=2078 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> > +/* offset=2149 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> > +/* offset=2243 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> > +/* offset=2377 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> > +/* offset=2441 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > +/* offset=2509 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > +/* offset=2579 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> > +/* offset=2601 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> > +/* offset=2623 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> > +/* offset=2643 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> > +;
> > +
> > +static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
> > +{ 13 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000 */
> > +{ 72 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000 */
> > +{ 325 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000 */
> > +{ 455 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000 */
> > +{ 131 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000 */
> > +{ 226 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000 */
> > +};
> > +static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
> > +{ 585 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000 */
> > +};
> > +static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
> > +{ 1064 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000 */
> > +};
> > +static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
> > +{ 914 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000 */
> > +{ 979 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000 */
> > +{ 683 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000 */
> > +};
> > +static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
> > +{ 1274 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000 */
> > +};
> > +static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
> > +{ 1168 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000 */
> > +
> > +};
> > +
> > +const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
> > +{
> > + .entries = pmu_events__test_soc_cpu_default_core,
> > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
> > + .pmu_name = { 0 /* default_core\000 */ },
> > +},
> > +{
> > + .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
> > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
> > + .pmu_name = { 570 /* hisi_sccl,ddrc\000 */ },
> > +},
> > +{
> > + .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
> > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
> > + .pmu_name = { 1050 /* hisi_sccl,l3c\000 */ },
> > +},
> > +{
> > + .entries = pmu_events__test_soc_cpu_uncore_cbox,
> > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
> > + .pmu_name = { 671 /* uncore_cbox\000 */ },
> > +},
> > +{
> > + .entries = pmu_events__test_soc_cpu_uncore_imc,
> > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
> > + .pmu_name = { 1263 /* uncore_imc\000 */ },
> > +},
> > +{
> > + .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
> > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
> > + .pmu_name = { 1144 /* uncore_imc_free_running\000 */ },
> > +},
> > };
> >
> > +static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
> > +{ 1696 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> > +{ 2377 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> > +{ 2149 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> > +{ 2243 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> > +{ 2441 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > +{ 2509 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > +{ 1781 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> > +{ 1718 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> > +{ 2643 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> > +{ 2579 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> > +{ 2601 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> > +{ 2623 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> > +{ 2078 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> > +{ 1947 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > +{ 2011 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > +
> > +};
> > +
> > +const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
> > +{
> > + .entries = pmu_metrics__test_soc_cpu_default_core,
> > + .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
> > + .pmu_name = { 0 /* default_core\000 */ },
> > +},
> > +};
> > +
> > +static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
> > +{ 1463 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000 */
> > +};
> > +static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
> > +{ 1556 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000 */
> > +};
> > +static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
> > +{ 1371 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000 */
> > +
> > +};
> > +
> > +const struct pmu_table_entry pmu_events__test_soc_sys[] = {
> > +{
> > + .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
> > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
> > + .pmu_name = { 1444 /* uncore_sys_ccn_pmu\000 */ },
> > +},
> > +{
> > + .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
> > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
> > + .pmu_name = { 1537 /* uncore_sys_cmn_pmu\000 */ },
> > +},
> > +{
> > + .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
> > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
> > + .pmu_name = { 1352 /* uncore_sys_ddr_pmu\000 */ },
> > +},
> > +};
> > +
> > +
> > /* Struct used to make the PMU event table implementation opaque to callers. */
> > struct pmu_events_table {
> > - const struct pmu_event *entries;
> > + const struct pmu_table_entry *pmus;
> > + uint32_t num_pmus;
> > };
> >
> > /* Struct used to make the PMU metric table implementation opaque to callers. */
> > struct pmu_metrics_table {
> > - const struct pmu_metric *entries;
> > + const struct pmu_table_entry *pmus;
> > + uint32_t num_pmus;
> > };
> >
> > /*
> > @@ -202,92 +199,191 @@ struct pmu_metrics_table {
> > * The cpuid can contain any character other than the comma.
> > */
> > struct pmu_events_map {
> > - const char *arch;
> > - const char *cpuid;
> > - const struct pmu_events_table event_table;
> > - const struct pmu_metrics_table metric_table;
> > + const char *arch;
> > + const char *cpuid;
> > + struct pmu_events_table event_table;
> > + struct pmu_metrics_table metric_table;
> > };
> >
> > /*
> > * Global table mapping each known CPU for the architecture to its
> > * table of PMU events.
> > */
> > -static const struct pmu_events_map pmu_events_map[] = {
> > - {
> > - .arch = "testarch",
> > - .cpuid = "testcpu",
> > - .event_table = { pmu_events__test_soc_cpu },
> > - .metric_table = { pmu_metrics__test_soc_cpu },
> > - },
> > - {
> > - .arch = 0,
> > - .cpuid = 0,
> > - .event_table = { 0 },
> > - .metric_table = { 0 },
> > - },
> > -};
> > -
> > -static const struct pmu_event pmu_events__test_soc_sys[] = {
> > - {
> > - .name = "sys_ddr_pmu.write_cycles",
> > - .event = "event=0x2b",
> > - .desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
> > - .compat = "v8",
> > - .topic = "uncore",
> > - .pmu = "uncore_sys_ddr_pmu",
> > - },
> > - {
> > - .name = "sys_ccn_pmu.read_cycles",
> > - .event = "config=0x2c",
> > - .desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
> > - .compat = "0x01",
> > - .topic = "uncore",
> > - .pmu = "uncore_sys_ccn_pmu",
> > - },
> > - {
> > - .name = "sys_cmn_pmu.hnf_cache_miss",
> > - .event = "eventid=0x1,type=0x5",
> > - .desc = "Counts total cache misses in first lookup result (high priority). Unit: uncore_sys_cmn_pmu ",
> > - .compat = "(434|436|43c|43a).*",
> > - .topic = "uncore",
> > - .pmu = "uncore_sys_cmn_pmu",
> > - },
> > - {
> > - .name = 0,
> > - .event = 0,
> > - .desc = 0,
> > - },
> > +const struct pmu_events_map pmu_events_map[] = {
> > +{
> > + .arch = "testarch",
> > + .cpuid = "testcpu",
> > + .event_table = {
> > + .pmus = pmu_events__test_soc_cpu,
> > + .num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu),
> > + },
> > + .metric_table = {
> > + .pmus = pmu_metrics__test_soc_cpu,
> > + .num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
> > + }
> > +},
> > +{
> > + .arch = 0,
> > + .cpuid = 0,
> > + .event_table = { 0, 0 },
> > + .metric_table = { 0, 0 },
> > +}
> > };
> >
> > struct pmu_sys_events {
> > const char *name;
> > - const struct pmu_events_table table;
> > + struct pmu_events_table event_table;
> > + struct pmu_metrics_table metric_table;
> > };
> >
> > static const struct pmu_sys_events pmu_sys_event_tables[] = {
> > {
> > - .table = { pmu_events__test_soc_sys },
> > + .event_table = {
> > + .pmus = pmu_events__test_soc_sys,
> > + .num_pmus = ARRAY_SIZE(pmu_events__test_soc_sys)
> > + },
> > .name = "pmu_events__test_soc_sys",
> > },
> > {
> > - .table = { 0 }
> > + .event_table = { 0, 0 },
> > + .metric_table = { 0, 0 },
> > },
> > };
> >
> > -int pmu_events_table__for_each_event(const struct pmu_events_table *table, struct perf_pmu *pmu,
> > - pmu_event_iter_fn fn, void *data)
> > +static void decompress_event(int offset, struct pmu_event *pe)
> > +{
> > + const char *p = &big_c_string[offset];
> > +
> > + pe->name = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pe->topic = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pe->desc = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pe->event = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pe->compat = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pe->deprecated = *p - '0';
> > + p++;
> > + pe->perpkg = *p - '0';
> > + p++;
> > + pe->unit = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pe->long_desc = (*p == '\0' ? NULL : p);
> > +}
> > +
> > +static void decompress_metric(int offset, struct pmu_metric *pm)
> > {
> > - for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
> > - int ret;
> > + const char *p = &big_c_string[offset];
> > +
> > + pm->metric_name = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pm->metric_group = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pm->metric_expr = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pm->metric_threshold = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pm->desc = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pm->long_desc = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pm->unit = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pm->compat = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pm->metricgroup_no_group = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pm->default_metricgroup_name = (*p == '\0' ? NULL : p);
> > + while (*p++);
> > + pm->aggr_mode = *p - '0';
> > + p++;
> > + pm->event_grouping = *p - '0';
> > +}
> >
> > - if (pmu && !pmu__name_match(pmu, pe->pmu))
> > +static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table,
> > + const struct pmu_table_entry *pmu,
> > + pmu_event_iter_fn fn,
> > + void *data)
> > +{
> > + int ret;
> > + struct pmu_event pe = {
> > + .pmu = &big_c_string[pmu->pmu_name.offset],
> > + };
> > +
> > + for (uint32_t i = 0; i < pmu->num_entries; i++) {
> > + decompress_event(pmu->entries[i].offset, &pe);
> > + if (!pe.name)
> > continue;
> > + ret = fn(&pe, table, data);
> > + if (ret)
> > + return ret;
> > + }
> > + return 0;
> > + }
> > +
> > +static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table,
> > + const struct pmu_table_entry *pmu,
> > + const char *name,
> > + pmu_event_iter_fn fn,
> > + void *data)
> > +{
> > + struct pmu_event pe = {
> > + .pmu = &big_c_string[pmu->pmu_name.offset],
> > + };
> > + int low = 0, high = pmu->num_entries - 1;
> >
> > - ret = fn(pe, table, data);
> > - if (ret)
> > - return ret;
> > - }
> > - return 0;
> > + while (low <= high) {
> > + int cmp, mid = (low + high) / 2;
> > +
> > + decompress_event(pmu->entries[mid].offset, &pe);
> > +
> > + if (!pe.name && !name)
> > + goto do_call;
> > +
> > + if (!pe.name && name) {
> > + low = mid + 1;
> > + continue;
> > + }
> > + if (pe.name && !name) {
> > + high = mid - 1;
> > + continue;
> > + }
> > +
> > + cmp = strcasecmp(pe.name, name);
> > + if (cmp < 0) {
> > + low = mid + 1;
> > + continue;
> > + }
> > + if (cmp > 0) {
> > + high = mid - 1;
> > + continue;
> > + }
> > + do_call:
> > + return fn ? fn(&pe, table, data) : 0;
> > + }
> > + return PMU_EVENTS__NOT_FOUND;
> > +}
> > +
> > +int pmu_events_table__for_each_event(const struct pmu_events_table *table,
> > + struct perf_pmu *pmu,
> > + pmu_event_iter_fn fn,
> > + void *data)
> > +{
> > + for (size_t i = 0; i < table->num_pmus; i++) {
> > + const struct pmu_table_entry *table_pmu = &table->pmus[i];
> > + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> > + int ret;
> > +
> > + if (pmu && !pmu__name_match(pmu, pmu_name))
> > + continue;
> > +
> > + ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
> > + if (pmu || ret)
> > + return ret;
> > + }
> > + return 0;
> > }
> >
> > int pmu_events_table__find_event(const struct pmu_events_table *table,
> > @@ -296,14 +392,19 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
> > pmu_event_iter_fn fn,
> > void *data)
> > {
> > - for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
> > - if (pmu && !pmu__name_match(pmu, pe->pmu))
> > + for (size_t i = 0; i < table->num_pmus; i++) {
> > + const struct pmu_table_entry *table_pmu = &table->pmus[i];
> > + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> > + int ret;
> > +
> > + if (!pmu__name_match(pmu, pmu_name))
> > continue;
> >
> > - if (!strcasecmp(pe->name, name))
> > - return fn(pe, table, data);
> > - }
> > - return -1000;
> > + ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data);
> > + if (ret != PMU_EVENTS__NOT_FOUND)
> > + return ret;
> > + }
> > + return PMU_EVENTS__NOT_FOUND;
> > }
> >
> > size_t pmu_events_table__num_events(const struct pmu_events_table *table,
> > @@ -311,160 +412,253 @@ size_t pmu_events_table__num_events(const struct pmu_events_table *table,
> > {
> > size_t count = 0;
> >
> > - for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
> > - if (pmu && !pmu__name_match(pmu, pe->pmu))
> > - continue;
> > + for (size_t i = 0; i < table->num_pmus; i++) {
> > + const struct pmu_table_entry *table_pmu = &table->pmus[i];
> > + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> >
> > - count++;
> > - }
> > + if (pmu__name_match(pmu, pmu_name))
> > + count += table_pmu->num_entries;
> > + }
> > return count;
> > }
> >
> > -int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
> > - void *data)
> > +static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
> > + const struct pmu_table_entry *pmu,
> > + pmu_metric_iter_fn fn,
> > + void *data)
> > +{
> > + int ret;
> > + struct pmu_metric pm = {
> > + .pmu = &big_c_string[pmu->pmu_name.offset],
> > + };
> > +
> > + for (uint32_t i = 0; i < pmu->num_entries; i++) {
> > + decompress_metric(pmu->entries[i].offset, &pm);
> > + if (!pm.metric_expr)
> > + continue;
> > + ret = fn(&pm, table, data);
> > + if (ret)
> > + return ret;
> > + }
> > + return 0;
> > +}
> > +
> > +int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table,
> > + pmu_metric_iter_fn fn,
> > + void *data)
> > {
> > - for (const struct pmu_metric *pm = &table->entries[0]; pm->metric_expr; pm++) {
> > - int ret = fn(pm, table, data);
> > + for (size_t i = 0; i < table->num_pmus; i++) {
> > + int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i],
> > + fn, data);
> > +
> > + if (ret)
> > + return ret;
> > + }
> > + return 0;
> > +}
> >
> > - if (ret)
> > - return ret;
> > - }
> > - return 0;
> > +static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> > +{
> > + static struct {
> > + const struct pmu_events_map *map;
> > + struct perf_pmu *pmu;
> > + } last_result;
> > + static struct {
> > + const struct pmu_events_map *map;
> > + char *cpuid;
> > + } last_map_search;
> > + static bool has_last_result, has_last_map_search;
> > + const struct pmu_events_map *map = NULL;
> > + char *cpuid = NULL;
> > + size_t i;
> > +
> > + if (has_last_result && last_result.pmu == pmu)
> > + return last_result.map;
> > +
> > + cpuid = perf_pmu__getcpuid(pmu);
> > +
> > + /*
> > + * On some platforms which uses cpus map, cpuid can be NULL for
> > + * PMUs other than CORE PMUs.
> > + */
> > + if (!cpuid)
> > + goto out_update_last_result;
> > +
> > + if (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) {
> > + map = last_map_search.map;
> > + free(cpuid);
> > + } else {
> > + i = 0;
> > + for (;;) {
> > + map = &pmu_events_map[i++];
> > +
> > + if (!map->arch) {
> > + map = NULL;
> > + break;
> > + }
> > +
> > + if (!strcmp_cpuid_str(map->cpuid, cpuid))
> > + break;
> > + }
> > + free(last_map_search.cpuid);
> > + last_map_search.cpuid = cpuid;
> > + last_map_search.map = map;
> > + has_last_map_search = true;
> > + }
> > +out_update_last_result:
> > + last_result.pmu = pmu;
> > + last_result.map = map;
> > + has_last_result = true;
> > + return map;
> > }
> >
> > const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu)
> > {
> > - const struct pmu_events_table *table = NULL;
> > - char *cpuid = perf_pmu__getcpuid(pmu);
> > - int i;
> > + const struct pmu_events_map *map = map_for_pmu(pmu);
> >
> > - /* on some platforms which uses cpus map, cpuid can be NULL for
> > - * PMUs other than CORE PMUs.
> > - */
> > - if (!cpuid)
> > - return NULL;
> > + if (!map)
> > + return NULL;
> >
> > - i = 0;
> > - for (;;) {
> > - const struct pmu_events_map *map = &pmu_events_map[i++];
> > + if (!pmu)
> > + return &map->event_table;
> >
> > - if (!map->cpuid)
> > - break;
> > + for (size_t i = 0; i < map->event_table.num_pmus; i++) {
> > + const struct pmu_table_entry *table_pmu = &map->event_table.pmus[i];
> > + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> >
> > - if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
> > - table = &map->event_table;
> > - break;
> > - }
> > - }
> > - free(cpuid);
> > - return table;
> > + if (pmu__name_match(pmu, pmu_name))
> > + return &map->event_table;
> > + }
> > + return NULL;
> > }
> >
> > const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pmu)
> > {
> > - const struct pmu_metrics_table *table = NULL;
> > - char *cpuid = perf_pmu__getcpuid(pmu);
> > - int i;
> > + const struct pmu_events_map *map = map_for_pmu(pmu);
> >
> > - /* on some platforms which uses cpus map, cpuid can be NULL for
> > - * PMUs other than CORE PMUs.
> > - */
> > - if (!cpuid)
> > - return NULL;
> > + if (!map)
> > + return NULL;
> >
> > - i = 0;
> > - for (;;) {
> > - const struct pmu_events_map *map = &pmu_events_map[i++];
> > + if (!pmu)
> > + return &map->metric_table;
> >
> > - if (!map->cpuid)
> > - break;
> > + for (size_t i = 0; i < map->metric_table.num_pmus; i++) {
> > + const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i];
> > + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> >
> > - if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
> > - table = &map->metric_table;
> > - break;
> > - }
> > - }
> > - free(cpuid);
> > - return table;
> > + if (pmu__name_match(pmu, pmu_name))
> > + return &map->metric_table;
> > + }
> > + return NULL;
> > }
> >
> > const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid)
> > {
> > - for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > - tables->arch;
> > - tables++) {
> > - if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> > - return &tables->event_table;
> > - }
> > - return NULL;
> > + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > + tables->arch;
> > + tables++) {
> > + if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> > + return &tables->event_table;
> > + }
> > + return NULL;
> > }
> >
> > const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid)
> > {
> > - for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > - tables->arch;
> > - tables++) {
> > - if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> > - return &tables->metric_table;
> > - }
> > - return NULL;
> > + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > + tables->arch;
> > + tables++) {
> > + if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> > + return &tables->metric_table;
> > + }
> > + return NULL;
> > }
> >
> > int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
> > {
> > - for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->arch; tables++) {
> > - int ret = pmu_events_table__for_each_event(&tables->event_table,
> > - /*pmu=*/ NULL, fn, data);
> > -
> > - if (ret)
> > - return ret;
> > - }
> > - return 0;
> > + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > + tables->arch;
> > + tables++) {
> > + int ret = pmu_events_table__for_each_event(&tables->event_table,
> > + /*pmu=*/ NULL, fn, data);
> > +
> > + if (ret)
> > + return ret;
> > + }
> > + return 0;
> > }
> >
> > int pmu_for_each_core_metric(pmu_metric_iter_fn fn, void *data)
> > {
> > - for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > - tables->arch;
> > - tables++) {
> > - int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
> > -
> > - if (ret)
> > - return ret;
> > - }
> > - return 0;
> > + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > + tables->arch;
> > + tables++) {
> > + int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
> > +
> > + if (ret)
> > + return ret;
> > + }
> > + return 0;
> > }
> >
> > const struct pmu_events_table *find_sys_events_table(const char *name)
> > {
> > - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> > - tables->name;
> > - tables++) {
> > - if (!strcmp(tables->name, name))
> > - return &tables->table;
> > - }
> > - return NULL;
> > + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> > + tables->name;
> > + tables++) {
> > + if (!strcmp(tables->name, name))
> > + return &tables->event_table;
> > + }
> > + return NULL;
> > }
> >
> > int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
> > {
> > - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> > - tables->name;
> > - tables++) {
> > - int ret = pmu_events_table__for_each_event(&tables->table, /*pmu=*/ NULL, fn, data);
> > -
> > - if (ret)
> > - return ret;
> > - }
> > - return 0;
> > + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> > + tables->name;
> > + tables++) {
> > + int ret = pmu_events_table__for_each_event(&tables->event_table,
> > + /*pmu=*/ NULL, fn, data);
> > +
> > + if (ret)
> > + return ret;
> > + }
> > + return 0;
> > }
> >
> > -int pmu_for_each_sys_metric(pmu_metric_iter_fn fn __maybe_unused, void *data __maybe_unused)
> > +int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data)
> > {
> > - return 0;
> > + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> > + tables->name;
> > + tables++) {
> > + int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
> > +
> > + if (ret)
> > + return ret;
> > + }
> > + return 0;
> > }
> >
> > -const char *describe_metricgroup(const char *group __maybe_unused)
> > +static const int metricgroups[][2] = {
> > +
> > +};
> > +
> > +const char *describe_metricgroup(const char *group)
> > {
> > - return NULL;
> > + int low = 0, high = (int)ARRAY_SIZE(metricgroups) - 1;
> > +
> > + while (low <= high) {
> > + int mid = (low + high) / 2;
> > + const char *mgroup = &big_c_string[metricgroups[mid][0]];
> > + int cmp = strcmp(mgroup, group);
> > +
> > + if (cmp == 0) {
> > + return &big_c_string[metricgroups[mid][1]];
> > + } else if (cmp < 0) {
> > + low = mid + 1;
> > + } else {
> > + high = mid - 1;
> > + }
> > + }
> > + return NULL;
> > }
> > diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> > index 731776e29f47..fcf0158438b5 100755
> > --- a/tools/perf/pmu-events/jevents.py
> > +++ b/tools/perf/pmu-events/jevents.py
> > @@ -1256,6 +1256,10 @@ such as "arm/cortex-a34".''',
> > 'output_file', type=argparse.FileType('w', encoding='utf-8'), nargs='?', default=sys.stdout)
> > _args = ap.parse_args()
> >
> > + _args.output_file.write(f"""
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/* THIS FILE WAS AUTOGENERATED BY jevents.py arch={_args.arch} model={_args.model} ! */
> > +""")
> > _args.output_file.write("""
> > #include <pmu-events/pmu-events.h>
> > #include "util/header.h"
> > @@ -1281,7 +1285,7 @@ struct pmu_table_entry {
> > if item.name == _args.arch or _args.arch == 'all' or item.name == 'test':
> > archs.append(item.name)
> >
> > - if len(archs) < 2:
> > + if len(archs) < 2 and _args.arch != 'none':
> > raise IOError(f'Missing architecture directory \'{_args.arch}\'')
> >
> > archs.sort()
> > --
> > 2.46.0.rc2.264.g509ed76dc8-goog
> >
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-31 14:08 ` Ian Rogers
@ 2024-07-31 15:33 ` Arnaldo Carvalho de Melo
2024-07-31 15:46 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-07-31 15:33 UTC (permalink / raw)
To: Ian Rogers
Cc: John Garry, Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
Kan Liang, Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users,
linux-kernel, philip.li, oliver.sang, Weilin Wang
On Wed, Jul 31, 2024 at 07:08:18AM -0700, Ian Rogers wrote:
> On Wed, Jul 31, 2024 at 6:18 AM Arnaldo Carvalho de Melo
> <acme@kernel.org> wrote:
> >
> > On Tue, Jul 30, 2024 at 12:17:44PM -0700, Ian Rogers wrote:
> > > empty-pmu-events.c exists so that builds may occur without python
> > > being installed on a system. Manually updating empty-pmu-events.c to
> > > be in sync with jevents.py is a pain, let's use jevents.py to generate
> > > empty-pmu-events.c.
> >
> > What am I missing here?
> >
> > If it exists so that we can build on a system without python how can we
> > use python to generate it?
> >
> > Now having python in the system is a requirement and thus we don't need
> > empty-pmu-events.c anymore?
> >
> > Can you guys please clarify that?
>
> The requirement for python hasn't changed.
>
> Case 1: no python or NO_JEVENTS=1
> Build happens using empty-pmu-events.c that is checked in, no python
> is required.
>
> Case 2: python
> pmu-events.c is created by jevents.py (requiring python) and then built.
> This change adds a step where the empty-pmu-events.c is created using
> jevents.py and that file is diffed against the checked in version.
> This stops the checked in empty-pmu-events.c diverging if changes are
> made to jevents.py. If the diff causes the build to fail then you just
> copy the diff empty-pmu-events.c over the checked in one.
I'll try and add your explanation to the log message, thanks for
clarifying it!
- Arnaldo
> Thanks,
> Ian
>
> > - Arnaldo
> >
> > > 1) change jevents.py so that an arch and model of none cause
> > > generation of a pmu-events.c without any json. Add a SPDX and
> > > autogenerated warning to the start of the file.
> > > > 2) change Build so that if a generated pmu-events.c for arch none and
> > > model none doesn't match empty-pmu-events.c the build fails with a
> > > cat of the differences. Update Makefile.perf to clean up the files
> > > used for this.
> > >
> > > 3) update empty-pmu-events.c to match the output of jevents.py with
> > > arch and mode of none.
> > >
> > > Signed-off-by: Ian Rogers <irogers@google.com>
> > > Reviewed-by: John Garry <john.g.garry@oracle.com>
> > > ---
> > > tools/perf/Makefile.perf | 2 +
> > > tools/perf/pmu-events/Build | 12 +-
> > > tools/perf/pmu-events/empty-pmu-events.c | 894 ++++++++++++++---------
> > > tools/perf/pmu-events/jevents.py | 6 +-
> > > 4 files changed, 562 insertions(+), 352 deletions(-)
> > >
> > > diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
> > > index 175e4c7898f0..76bb0925849a 100644
> > > --- a/tools/perf/Makefile.perf
> > > +++ b/tools/perf/Makefile.perf
> > > @@ -1252,6 +1252,8 @@ clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(
> > > $(OUTPUT)util/intel-pt-decoder/inat-tables.c \
> > > $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
> > > $(OUTPUT)pmu-events/pmu-events.c \
> > > + $(OUTPUT)pmu-events/test-empty-pmu-events.c \
> > > + $(OUTPUT)pmu-events/empty-pmu-events.log \
> > > $(OUTPUT)pmu-events/metric_test.log \
> > > $(OUTPUT)$(fadvise_advice_array) \
> > > $(OUTPUT)$(fsconfig_arrays) \
> > > diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
> > > index 1d18bb89402e..c3fa43c49706 100644
> > > --- a/tools/perf/pmu-events/Build
> > > +++ b/tools/perf/pmu-events/Build
> > > @@ -11,6 +11,8 @@ METRIC_TEST_PY = pmu-events/metric_test.py
> > > EMPTY_PMU_EVENTS_C = pmu-events/empty-pmu-events.c
> > > PMU_EVENTS_C = $(OUTPUT)pmu-events/pmu-events.c
> > > METRIC_TEST_LOG = $(OUTPUT)pmu-events/metric_test.log
> > > +TEST_EMPTY_PMU_EVENTS_C = $(OUTPUT)pmu-events/test-empty-pmu-events.c
> > > +EMPTY_PMU_EVENTS_TEST_LOG = $(OUTPUT)pmu-events/empty-pmu-events.log
> > >
> > > ifeq ($(JEVENTS_ARCH),)
> > > JEVENTS_ARCH=$(SRCARCH)
> > > @@ -31,7 +33,15 @@ $(METRIC_TEST_LOG): $(METRIC_TEST_PY) $(METRIC_PY)
> > > $(call rule_mkdir)
> > > $(Q)$(call echo-cmd,test)$(PYTHON) $< 2> $@ || (cat $@ && false)
> > >
> > > -$(PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG)
> > > +$(TEST_EMPTY_PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG)
> > > + $(call rule_mkdir)
> > > + $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) none none pmu-events/arch $@
> > > +
> > > +$(EMPTY_PMU_EVENTS_TEST_LOG): $(EMPTY_PMU_EVENTS_C) $(TEST_EMPTY_PMU_EVENTS_C)
> > > + $(call rule_mkdir)
> > > + $(Q)$(call echo-cmd,test)diff -u $? 2> $@ || (cat $@ && false)
> > > +
> > > +$(PMU_EVENTS_C): $(JSON) $(JSON_TEST) $(JEVENTS_PY) $(METRIC_PY) $(METRIC_TEST_LOG) $(EMPTY_PMU_EVENTS_TEST_LOG)
> > > $(call rule_mkdir)
> > > $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) pmu-events/arch $@
> > > endif
> > > diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
> > > index 13727421d424..c592079982fb 100644
> > > --- a/tools/perf/pmu-events/empty-pmu-events.c
> > > +++ b/tools/perf/pmu-events/empty-pmu-events.c
> > > @@ -1,196 +1,193 @@
> > > -// SPDX-License-Identifier: GPL-2.0
> > > -/*
> > > - * An empty pmu-events.c file used when there is no architecture json files in
> > > - * arch or when the jevents.py script cannot be run.
> > > - *
> > > - * The test cpu/soc is provided for testing.
> > > - */
> > > -#include "pmu-events/pmu-events.h"
> > > +
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +/* THIS FILE WAS AUTOGENERATED BY jevents.py arch=none model=none ! */
> > > +
> > > +#include <pmu-events/pmu-events.h>
> > > #include "util/header.h"
> > > #include "util/pmu.h"
> > > #include <string.h>
> > > #include <stddef.h>
> > >
> > > -static const struct pmu_event pmu_events__test_soc_cpu[] = {
> > > - {
> > > - .name = "l3_cache_rd",
> > > - .event = "event=0x40",
> > > - .desc = "L3 cache access, read",
> > > - .topic = "cache",
> > > - .long_desc = "Attributable Level 3 cache access, read",
> > > - },
> > > - {
> > > - .name = "segment_reg_loads.any",
> > > - .event = "event=0x6,period=200000,umask=0x80",
> > > - .desc = "Number of segment register loads",
> > > - .topic = "other",
> > > - },
> > > - {
> > > - .name = "dispatch_blocked.any",
> > > - .event = "event=0x9,period=200000,umask=0x20",
> > > - .desc = "Memory cluster signals to block micro-op dispatch for any reason",
> > > - .topic = "other",
> > > - },
> > > - {
> > > - .name = "eist_trans",
> > > - .event = "event=0x3a,period=200000,umask=0x0",
> > > - .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
> > > - .topic = "other",
> > > - },
> > > - {
> > > - .name = "uncore_hisi_ddrc.flux_wcmd",
> > > - .event = "event=0x2",
> > > - .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
> > > - .topic = "uncore",
> > > - .long_desc = "DDRC write commands",
> > > - .pmu = "hisi_sccl,ddrc",
> > > - },
> > > - {
> > > - .name = "unc_cbo_xsnp_response.miss_eviction",
> > > - .event = "event=0x22,umask=0x81",
> > > - .desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox ",
> > > - .topic = "uncore",
> > > - .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
> > > - .pmu = "uncore_cbox",
> > > - },
> > > - {
> > > - .name = "event-hyphen",
> > > - .event = "event=0xe0,umask=0x00",
> > > - .desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox ",
> > > - .topic = "uncore",
> > > - .long_desc = "UNC_CBO_HYPHEN",
> > > - .pmu = "uncore_cbox",
> > > - },
> > > - {
> > > - .name = "event-two-hyph",
> > > - .event = "event=0xc0,umask=0x00",
> > > - .desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox ",
> > > - .topic = "uncore",
> > > - .long_desc = "UNC_CBO_TWO_HYPH",
> > > - .pmu = "uncore_cbox",
> > > - },
> > > - {
> > > - .name = "uncore_hisi_l3c.rd_hit_cpipe",
> > > - .event = "event=0x7",
> > > - .desc = "Total read hits. Unit: hisi_sccl,l3c ",
> > > - .topic = "uncore",
> > > - .long_desc = "Total read hits",
> > > - .pmu = "hisi_sccl,l3c",
> > > - },
> > > - {
> > > - .name = "uncore_imc_free_running.cache_miss",
> > > - .event = "event=0x12",
> > > - .desc = "Total cache misses. Unit: uncore_imc_free_running ",
> > > - .topic = "uncore",
> > > - .long_desc = "Total cache misses",
> > > - .pmu = "uncore_imc_free_running",
> > > - },
> > > - {
> > > - .name = "uncore_imc.cache_hits",
> > > - .event = "event=0x34",
> > > - .desc = "Total cache hits. Unit: uncore_imc ",
> > > - .topic = "uncore",
> > > - .long_desc = "Total cache hits",
> > > - .pmu = "uncore_imc",
> > > - },
> > > - {
> > > - .name = "bp_l1_btb_correct",
> > > - .event = "event=0x8a",
> > > - .desc = "L1 BTB Correction",
> > > - .topic = "branch",
> > > - },
> > > - {
> > > - .name = "bp_l2_btb_correct",
> > > - .event = "event=0x8b",
> > > - .desc = "L2 BTB Correction",
> > > - .topic = "branch",
> > > - },
> > > - {
> > > - .name = 0,
> > > - .event = 0,
> > > - .desc = 0,
> > > - },
> > > +struct compact_pmu_event {
> > > + int offset;
> > > };
> > >
> > > -static const struct pmu_metric pmu_metrics__test_soc_cpu[] = {
> > > - {
> > > - .metric_expr = "1 / IPC",
> > > - .metric_name = "CPI",
> > > - },
> > > - {
> > > - .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread",
> > > - .metric_name = "IPC",
> > > - .metric_group = "group1",
> > > - },
> > > - {
> > > - .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * "
> > > - "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))",
> > > - .metric_name = "Frontend_Bound_SMT",
> > > - },
> > > - {
> > > - .metric_expr = "l1d\\-loads\\-misses / inst_retired.any",
> > > - .metric_name = "dcache_miss_cpi",
> > > - },
> > > - {
> > > - .metric_expr = "l1i\\-loads\\-misses / inst_retired.any",
> > > - .metric_name = "icache_miss_cycles",
> > > - },
> > > - {
> > > - .metric_expr = "(dcache_miss_cpi + icache_miss_cycles)",
> > > - .metric_name = "cache_miss_cycles",
> > > - .metric_group = "group1",
> > > - },
> > > - {
> > > - .metric_expr = "l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit",
> > > - .metric_name = "DCache_L2_All_Hits",
> > > - },
> > > - {
> > > - .metric_expr = "max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + "
> > > - "l2_rqsts.pf_miss + l2_rqsts.rfo_miss",
> > > - .metric_name = "DCache_L2_All_Miss",
> > > - },
> > > - {
> > > - .metric_expr = "DCache_L2_All_Hits + DCache_L2_All_Miss",
> > > - .metric_name = "DCache_L2_All",
> > > - },
> > > - {
> > > - .metric_expr = "d_ratio(DCache_L2_All_Hits, DCache_L2_All)",
> > > - .metric_name = "DCache_L2_Hits",
> > > - },
> > > - {
> > > - .metric_expr = "d_ratio(DCache_L2_All_Miss, DCache_L2_All)",
> > > - .metric_name = "DCache_L2_Misses",
> > > - },
> > > - {
> > > - .metric_expr = "ipc + M2",
> > > - .metric_name = "M1",
> > > - },
> > > - {
> > > - .metric_expr = "ipc + M1",
> > > - .metric_name = "M2",
> > > - },
> > > - {
> > > - .metric_expr = "1/M3",
> > > - .metric_name = "M3",
> > > - },
> > > - {
> > > - .metric_expr = "64 * l1d.replacement / 1000000000 / duration_time",
> > > - .metric_name = "L1D_Cache_Fill_BW",
> > > - },
> > > - {
> > > - .metric_expr = 0,
> > > - .metric_name = 0,
> > > - },
> > > +struct pmu_table_entry {
> > > + const struct compact_pmu_event *entries;
> > > + uint32_t num_entries;
> > > + struct compact_pmu_event pmu_name;
> > > +};
> > > +
> > > +static const char *const big_c_string =
> > > +/* offset=0 */ "default_core\000"
> > > +/* offset=13 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000"
> > > +/* offset=72 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000"
> > > +/* offset=131 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000"
> > > +/* offset=226 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000"
> > > +/* offset=325 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000"
> > > +/* offset=455 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000"
> > > +/* offset=570 */ "hisi_sccl,ddrc\000"
> > > +/* offset=585 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000"
> > > +/* offset=671 */ "uncore_cbox\000"
> > > +/* offset=683 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000"
> > > +/* offset=914 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000"
> > > +/* offset=979 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000"
> > > +/* offset=1050 */ "hisi_sccl,l3c\000"
> > > +/* offset=1064 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000"
> > > +/* offset=1144 */ "uncore_imc_free_running\000"
> > > +/* offset=1168 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000"
> > > +/* offset=1263 */ "uncore_imc\000"
> > > +/* offset=1274 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000"
> > > +/* offset=1352 */ "uncore_sys_ddr_pmu\000"
> > > +/* offset=1371 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000"
> > > +/* offset=1444 */ "uncore_sys_ccn_pmu\000"
> > > +/* offset=1463 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000"
> > > +/* offset=1537 */ "uncore_sys_cmn_pmu\000"
> > > +/* offset=1556 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000"
> > > +/* offset=1696 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000"
> > > +/* offset=1718 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000"
> > > +/* offset=1781 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000"
> > > +/* offset=1947 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > +/* offset=2011 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000"
> > > +/* offset=2078 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000"
> > > +/* offset=2149 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000"
> > > +/* offset=2243 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000"
> > > +/* offset=2377 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000"
> > > +/* offset=2441 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > +/* offset=2509 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000"
> > > +/* offset=2579 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000"
> > > +/* offset=2601 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000"
> > > +/* offset=2623 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000"
> > > +/* offset=2643 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000"
> > > +;
> > > +
> > > +static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
> > > +{ 13 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000 */
> > > +{ 72 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000 */
> > > +{ 325 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000 */
> > > +{ 455 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000 */
> > > +{ 131 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000 */
> > > +{ 226 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000 */
> > > +};
> > > +static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
> > > +{ 585 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000 */
> > > +};
> > > +static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
> > > +{ 1064 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000 */
> > > +};
> > > +static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
> > > +{ 914 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000 */
> > > +{ 979 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000 */
> > > +{ 683 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000 */
> > > +};
> > > +static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
> > > +{ 1274 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000 */
> > > +};
> > > +static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
> > > +{ 1168 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000 */
> > > +
> > > +};
> > > +
> > > +const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
> > > +{
> > > + .entries = pmu_events__test_soc_cpu_default_core,
> > > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core),
> > > + .pmu_name = { 0 /* default_core\000 */ },
> > > +},
> > > +{
> > > + .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
> > > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
> > > + .pmu_name = { 570 /* hisi_sccl,ddrc\000 */ },
> > > +},
> > > +{
> > > + .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
> > > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
> > > + .pmu_name = { 1050 /* hisi_sccl,l3c\000 */ },
> > > +},
> > > +{
> > > + .entries = pmu_events__test_soc_cpu_uncore_cbox,
> > > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
> > > + .pmu_name = { 671 /* uncore_cbox\000 */ },
> > > +},
> > > +{
> > > + .entries = pmu_events__test_soc_cpu_uncore_imc,
> > > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
> > > + .pmu_name = { 1263 /* uncore_imc\000 */ },
> > > +},
> > > +{
> > > + .entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
> > > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
> > > + .pmu_name = { 1144 /* uncore_imc_free_running\000 */ },
> > > +},
> > > };
> > >
> > > +static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
> > > +{ 1696 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */
> > > +{ 2377 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */
> > > +{ 2149 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */
> > > +{ 2243 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */
> > > +{ 2441 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > +{ 2509 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */
> > > +{ 1781 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */
> > > +{ 1718 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */
> > > +{ 2643 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */
> > > +{ 2579 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */
> > > +{ 2601 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */
> > > +{ 2623 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */
> > > +{ 2078 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */
> > > +{ 1947 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > +{ 2011 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */
> > > +
> > > +};
> > > +
> > > +const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
> > > +{
> > > + .entries = pmu_metrics__test_soc_cpu_default_core,
> > > + .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core),
> > > + .pmu_name = { 0 /* default_core\000 */ },
> > > +},
> > > +};
> > > +
> > > +static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
> > > +{ 1463 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000 */
> > > +};
> > > +static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
> > > +{ 1556 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000 */
> > > +};
> > > +static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
> > > +{ 1371 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000 */
> > > +
> > > +};
> > > +
> > > +const struct pmu_table_entry pmu_events__test_soc_sys[] = {
> > > +{
> > > + .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
> > > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
> > > + .pmu_name = { 1444 /* uncore_sys_ccn_pmu\000 */ },
> > > +},
> > > +{
> > > + .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
> > > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
> > > + .pmu_name = { 1537 /* uncore_sys_cmn_pmu\000 */ },
> > > +},
> > > +{
> > > + .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
> > > + .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
> > > + .pmu_name = { 1352 /* uncore_sys_ddr_pmu\000 */ },
> > > +},
> > > +};
> > > +
> > > +
> > > /* Struct used to make the PMU event table implementation opaque to callers. */
> > > struct pmu_events_table {
> > > - const struct pmu_event *entries;
> > > + const struct pmu_table_entry *pmus;
> > > + uint32_t num_pmus;
> > > };
> > >
> > > /* Struct used to make the PMU metric table implementation opaque to callers. */
> > > struct pmu_metrics_table {
> > > - const struct pmu_metric *entries;
> > > + const struct pmu_table_entry *pmus;
> > > + uint32_t num_pmus;
> > > };
> > >
> > > /*
> > > @@ -202,92 +199,191 @@ struct pmu_metrics_table {
> > > * The cpuid can contain any character other than the comma.
> > > */
> > > struct pmu_events_map {
> > > - const char *arch;
> > > - const char *cpuid;
> > > - const struct pmu_events_table event_table;
> > > - const struct pmu_metrics_table metric_table;
> > > + const char *arch;
> > > + const char *cpuid;
> > > + struct pmu_events_table event_table;
> > > + struct pmu_metrics_table metric_table;
> > > };
> > >
> > > /*
> > > * Global table mapping each known CPU for the architecture to its
> > > * table of PMU events.
> > > */
> > > -static const struct pmu_events_map pmu_events_map[] = {
> > > - {
> > > - .arch = "testarch",
> > > - .cpuid = "testcpu",
> > > - .event_table = { pmu_events__test_soc_cpu },
> > > - .metric_table = { pmu_metrics__test_soc_cpu },
> > > - },
> > > - {
> > > - .arch = 0,
> > > - .cpuid = 0,
> > > - .event_table = { 0 },
> > > - .metric_table = { 0 },
> > > - },
> > > -};
> > > -
> > > -static const struct pmu_event pmu_events__test_soc_sys[] = {
> > > - {
> > > - .name = "sys_ddr_pmu.write_cycles",
> > > - .event = "event=0x2b",
> > > - .desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
> > > - .compat = "v8",
> > > - .topic = "uncore",
> > > - .pmu = "uncore_sys_ddr_pmu",
> > > - },
> > > - {
> > > - .name = "sys_ccn_pmu.read_cycles",
> > > - .event = "config=0x2c",
> > > - .desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
> > > - .compat = "0x01",
> > > - .topic = "uncore",
> > > - .pmu = "uncore_sys_ccn_pmu",
> > > - },
> > > - {
> > > - .name = "sys_cmn_pmu.hnf_cache_miss",
> > > - .event = "eventid=0x1,type=0x5",
> > > - .desc = "Counts total cache misses in first lookup result (high priority). Unit: uncore_sys_cmn_pmu ",
> > > - .compat = "(434|436|43c|43a).*",
> > > - .topic = "uncore",
> > > - .pmu = "uncore_sys_cmn_pmu",
> > > - },
> > > - {
> > > - .name = 0,
> > > - .event = 0,
> > > - .desc = 0,
> > > - },
> > > +const struct pmu_events_map pmu_events_map[] = {
> > > +{
> > > + .arch = "testarch",
> > > + .cpuid = "testcpu",
> > > + .event_table = {
> > > + .pmus = pmu_events__test_soc_cpu,
> > > + .num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu),
> > > + },
> > > + .metric_table = {
> > > + .pmus = pmu_metrics__test_soc_cpu,
> > > + .num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
> > > + }
> > > +},
> > > +{
> > > + .arch = 0,
> > > + .cpuid = 0,
> > > + .event_table = { 0, 0 },
> > > + .metric_table = { 0, 0 },
> > > +}
> > > };
> > >
> > > struct pmu_sys_events {
> > > const char *name;
> > > - const struct pmu_events_table table;
> > > + struct pmu_events_table event_table;
> > > + struct pmu_metrics_table metric_table;
> > > };
> > >
> > > static const struct pmu_sys_events pmu_sys_event_tables[] = {
> > > {
> > > - .table = { pmu_events__test_soc_sys },
> > > + .event_table = {
> > > + .pmus = pmu_events__test_soc_sys,
> > > + .num_pmus = ARRAY_SIZE(pmu_events__test_soc_sys)
> > > + },
> > > .name = "pmu_events__test_soc_sys",
> > > },
> > > {
> > > - .table = { 0 }
> > > + .event_table = { 0, 0 },
> > > + .metric_table = { 0, 0 },
> > > },
> > > };
> > >
> > > -int pmu_events_table__for_each_event(const struct pmu_events_table *table, struct perf_pmu *pmu,
> > > - pmu_event_iter_fn fn, void *data)
> > > +static void decompress_event(int offset, struct pmu_event *pe)
> > > +{
> > > + const char *p = &big_c_string[offset];
> > > +
> > > + pe->name = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pe->topic = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pe->desc = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pe->event = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pe->compat = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pe->deprecated = *p - '0';
> > > + p++;
> > > + pe->perpkg = *p - '0';
> > > + p++;
> > > + pe->unit = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pe->long_desc = (*p == '\0' ? NULL : p);
> > > +}
> > > +
> > > +static void decompress_metric(int offset, struct pmu_metric *pm)
> > > {
> > > - for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
> > > - int ret;
> > > + const char *p = &big_c_string[offset];
> > > +
> > > + pm->metric_name = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pm->metric_group = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pm->metric_expr = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pm->metric_threshold = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pm->desc = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pm->long_desc = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pm->unit = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pm->compat = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pm->metricgroup_no_group = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pm->default_metricgroup_name = (*p == '\0' ? NULL : p);
> > > + while (*p++);
> > > + pm->aggr_mode = *p - '0';
> > > + p++;
> > > + pm->event_grouping = *p - '0';
> > > +}
> > >
> > > - if (pmu && !pmu__name_match(pmu, pe->pmu))
> > > +static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table,
> > > + const struct pmu_table_entry *pmu,
> > > + pmu_event_iter_fn fn,
> > > + void *data)
> > > +{
> > > + int ret;
> > > + struct pmu_event pe = {
> > > + .pmu = &big_c_string[pmu->pmu_name.offset],
> > > + };
> > > +
> > > + for (uint32_t i = 0; i < pmu->num_entries; i++) {
> > > + decompress_event(pmu->entries[i].offset, &pe);
> > > + if (!pe.name)
> > > continue;
> > > + ret = fn(&pe, table, data);
> > > + if (ret)
> > > + return ret;
> > > + }
> > > + return 0;
> > > + }
> > > +
> > > +static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table,
> > > + const struct pmu_table_entry *pmu,
> > > + const char *name,
> > > + pmu_event_iter_fn fn,
> > > + void *data)
> > > +{
> > > + struct pmu_event pe = {
> > > + .pmu = &big_c_string[pmu->pmu_name.offset],
> > > + };
> > > + int low = 0, high = pmu->num_entries - 1;
> > >
> > > - ret = fn(pe, table, data);
> > > - if (ret)
> > > - return ret;
> > > - }
> > > - return 0;
> > > + while (low <= high) {
> > > + int cmp, mid = (low + high) / 2;
> > > +
> > > + decompress_event(pmu->entries[mid].offset, &pe);
> > > +
> > > + if (!pe.name && !name)
> > > + goto do_call;
> > > +
> > > + if (!pe.name && name) {
> > > + low = mid + 1;
> > > + continue;
> > > + }
> > > + if (pe.name && !name) {
> > > + high = mid - 1;
> > > + continue;
> > > + }
> > > +
> > > + cmp = strcasecmp(pe.name, name);
> > > + if (cmp < 0) {
> > > + low = mid + 1;
> > > + continue;
> > > + }
> > > + if (cmp > 0) {
> > > + high = mid - 1;
> > > + continue;
> > > + }
> > > + do_call:
> > > + return fn ? fn(&pe, table, data) : 0;
> > > + }
> > > + return PMU_EVENTS__NOT_FOUND;
> > > +}
> > > +
> > > +int pmu_events_table__for_each_event(const struct pmu_events_table *table,
> > > + struct perf_pmu *pmu,
> > > + pmu_event_iter_fn fn,
> > > + void *data)
> > > +{
> > > + for (size_t i = 0; i < table->num_pmus; i++) {
> > > + const struct pmu_table_entry *table_pmu = &table->pmus[i];
> > > + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> > > + int ret;
> > > +
> > > + if (pmu && !pmu__name_match(pmu, pmu_name))
> > > + continue;
> > > +
> > > + ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
> > > + if (pmu || ret)
> > > + return ret;
> > > + }
> > > + return 0;
> > > }
> > >
> > > int pmu_events_table__find_event(const struct pmu_events_table *table,
> > > @@ -296,14 +392,19 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
> > > pmu_event_iter_fn fn,
> > > void *data)
> > > {
> > > - for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
> > > - if (pmu && !pmu__name_match(pmu, pe->pmu))
> > > + for (size_t i = 0; i < table->num_pmus; i++) {
> > > + const struct pmu_table_entry *table_pmu = &table->pmus[i];
> > > + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> > > + int ret;
> > > +
> > > + if (!pmu__name_match(pmu, pmu_name))
> > > continue;
> > >
> > > - if (!strcasecmp(pe->name, name))
> > > - return fn(pe, table, data);
> > > - }
> > > - return -1000;
> > > + ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data);
> > > + if (ret != PMU_EVENTS__NOT_FOUND)
> > > + return ret;
> > > + }
> > > + return PMU_EVENTS__NOT_FOUND;
> > > }
> > >
> > > size_t pmu_events_table__num_events(const struct pmu_events_table *table,
> > > @@ -311,160 +412,253 @@ size_t pmu_events_table__num_events(const struct pmu_events_table *table,
> > > {
> > > size_t count = 0;
> > >
> > > - for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
> > > - if (pmu && !pmu__name_match(pmu, pe->pmu))
> > > - continue;
> > > + for (size_t i = 0; i < table->num_pmus; i++) {
> > > + const struct pmu_table_entry *table_pmu = &table->pmus[i];
> > > + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> > >
> > > - count++;
> > > - }
> > > + if (pmu__name_match(pmu, pmu_name))
> > > + count += table_pmu->num_entries;
> > > + }
> > > return count;
> > > }
> > >
> > > -int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
> > > - void *data)
> > > +static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
> > > + const struct pmu_table_entry *pmu,
> > > + pmu_metric_iter_fn fn,
> > > + void *data)
> > > +{
> > > + int ret;
> > > + struct pmu_metric pm = {
> > > + .pmu = &big_c_string[pmu->pmu_name.offset],
> > > + };
> > > +
> > > + for (uint32_t i = 0; i < pmu->num_entries; i++) {
> > > + decompress_metric(pmu->entries[i].offset, &pm);
> > > + if (!pm.metric_expr)
> > > + continue;
> > > + ret = fn(&pm, table, data);
> > > + if (ret)
> > > + return ret;
> > > + }
> > > + return 0;
> > > +}
> > > +
> > > +int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table,
> > > + pmu_metric_iter_fn fn,
> > > + void *data)
> > > {
> > > - for (const struct pmu_metric *pm = &table->entries[0]; pm->metric_expr; pm++) {
> > > - int ret = fn(pm, table, data);
> > > + for (size_t i = 0; i < table->num_pmus; i++) {
> > > + int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i],
> > > + fn, data);
> > > +
> > > + if (ret)
> > > + return ret;
> > > + }
> > > + return 0;
> > > +}
> > >
> > > - if (ret)
> > > - return ret;
> > > - }
> > > - return 0;
> > > +static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu)
> > > +{
> > > + static struct {
> > > + const struct pmu_events_map *map;
> > > + struct perf_pmu *pmu;
> > > + } last_result;
> > > + static struct {
> > > + const struct pmu_events_map *map;
> > > + char *cpuid;
> > > + } last_map_search;
> > > + static bool has_last_result, has_last_map_search;
> > > + const struct pmu_events_map *map = NULL;
> > > + char *cpuid = NULL;
> > > + size_t i;
> > > +
> > > + if (has_last_result && last_result.pmu == pmu)
> > > + return last_result.map;
> > > +
> > > + cpuid = perf_pmu__getcpuid(pmu);
> > > +
> > > + /*
> > > + * On some platforms which uses cpus map, cpuid can be NULL for
> > > + * PMUs other than CORE PMUs.
> > > + */
> > > + if (!cpuid)
> > > + goto out_update_last_result;
> > > +
> > > + if (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) {
> > > + map = last_map_search.map;
> > > + free(cpuid);
> > > + } else {
> > > + i = 0;
> > > + for (;;) {
> > > + map = &pmu_events_map[i++];
> > > +
> > > + if (!map->arch) {
> > > + map = NULL;
> > > + break;
> > > + }
> > > +
> > > + if (!strcmp_cpuid_str(map->cpuid, cpuid))
> > > + break;
> > > + }
> > > + free(last_map_search.cpuid);
> > > + last_map_search.cpuid = cpuid;
> > > + last_map_search.map = map;
> > > + has_last_map_search = true;
> > > + }
> > > +out_update_last_result:
> > > + last_result.pmu = pmu;
> > > + last_result.map = map;
> > > + has_last_result = true;
> > > + return map;
> > > }
> > >
> > > const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu)
> > > {
> > > - const struct pmu_events_table *table = NULL;
> > > - char *cpuid = perf_pmu__getcpuid(pmu);
> > > - int i;
> > > + const struct pmu_events_map *map = map_for_pmu(pmu);
> > >
> > > - /* on some platforms which uses cpus map, cpuid can be NULL for
> > > - * PMUs other than CORE PMUs.
> > > - */
> > > - if (!cpuid)
> > > - return NULL;
> > > + if (!map)
> > > + return NULL;
> > >
> > > - i = 0;
> > > - for (;;) {
> > > - const struct pmu_events_map *map = &pmu_events_map[i++];
> > > + if (!pmu)
> > > + return &map->event_table;
> > >
> > > - if (!map->cpuid)
> > > - break;
> > > + for (size_t i = 0; i < map->event_table.num_pmus; i++) {
> > > + const struct pmu_table_entry *table_pmu = &map->event_table.pmus[i];
> > > + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> > >
> > > - if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
> > > - table = &map->event_table;
> > > - break;
> > > - }
> > > - }
> > > - free(cpuid);
> > > - return table;
> > > + if (pmu__name_match(pmu, pmu_name))
> > > + return &map->event_table;
> > > + }
> > > + return NULL;
> > > }
> > >
> > > const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pmu)
> > > {
> > > - const struct pmu_metrics_table *table = NULL;
> > > - char *cpuid = perf_pmu__getcpuid(pmu);
> > > - int i;
> > > + const struct pmu_events_map *map = map_for_pmu(pmu);
> > >
> > > - /* on some platforms which uses cpus map, cpuid can be NULL for
> > > - * PMUs other than CORE PMUs.
> > > - */
> > > - if (!cpuid)
> > > - return NULL;
> > > + if (!map)
> > > + return NULL;
> > >
> > > - i = 0;
> > > - for (;;) {
> > > - const struct pmu_events_map *map = &pmu_events_map[i++];
> > > + if (!pmu)
> > > + return &map->metric_table;
> > >
> > > - if (!map->cpuid)
> > > - break;
> > > + for (size_t i = 0; i < map->metric_table.num_pmus; i++) {
> > > + const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i];
> > > + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
> > >
> > > - if (!strcmp_cpuid_str(map->cpuid, cpuid)) {
> > > - table = &map->metric_table;
> > > - break;
> > > - }
> > > - }
> > > - free(cpuid);
> > > - return table;
> > > + if (pmu__name_match(pmu, pmu_name))
> > > + return &map->metric_table;
> > > + }
> > > + return NULL;
> > > }
> > >
> > > const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid)
> > > {
> > > - for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > > - tables->arch;
> > > - tables++) {
> > > - if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> > > - return &tables->event_table;
> > > - }
> > > - return NULL;
> > > + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > > + tables->arch;
> > > + tables++) {
> > > + if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> > > + return &tables->event_table;
> > > + }
> > > + return NULL;
> > > }
> > >
> > > const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid)
> > > {
> > > - for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > > - tables->arch;
> > > - tables++) {
> > > - if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> > > - return &tables->metric_table;
> > > - }
> > > - return NULL;
> > > + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > > + tables->arch;
> > > + tables++) {
> > > + if (!strcmp(tables->arch, arch) && !strcmp_cpuid_str(tables->cpuid, cpuid))
> > > + return &tables->metric_table;
> > > + }
> > > + return NULL;
> > > }
> > >
> > > int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
> > > {
> > > - for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->arch; tables++) {
> > > - int ret = pmu_events_table__for_each_event(&tables->event_table,
> > > - /*pmu=*/ NULL, fn, data);
> > > -
> > > - if (ret)
> > > - return ret;
> > > - }
> > > - return 0;
> > > + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > > + tables->arch;
> > > + tables++) {
> > > + int ret = pmu_events_table__for_each_event(&tables->event_table,
> > > + /*pmu=*/ NULL, fn, data);
> > > +
> > > + if (ret)
> > > + return ret;
> > > + }
> > > + return 0;
> > > }
> > >
> > > int pmu_for_each_core_metric(pmu_metric_iter_fn fn, void *data)
> > > {
> > > - for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > > - tables->arch;
> > > - tables++) {
> > > - int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
> > > -
> > > - if (ret)
> > > - return ret;
> > > - }
> > > - return 0;
> > > + for (const struct pmu_events_map *tables = &pmu_events_map[0];
> > > + tables->arch;
> > > + tables++) {
> > > + int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
> > > +
> > > + if (ret)
> > > + return ret;
> > > + }
> > > + return 0;
> > > }
> > >
> > > const struct pmu_events_table *find_sys_events_table(const char *name)
> > > {
> > > - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> > > - tables->name;
> > > - tables++) {
> > > - if (!strcmp(tables->name, name))
> > > - return &tables->table;
> > > - }
> > > - return NULL;
> > > + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> > > + tables->name;
> > > + tables++) {
> > > + if (!strcmp(tables->name, name))
> > > + return &tables->event_table;
> > > + }
> > > + return NULL;
> > > }
> > >
> > > int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
> > > {
> > > - for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> > > - tables->name;
> > > - tables++) {
> > > - int ret = pmu_events_table__for_each_event(&tables->table, /*pmu=*/ NULL, fn, data);
> > > -
> > > - if (ret)
> > > - return ret;
> > > - }
> > > - return 0;
> > > + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> > > + tables->name;
> > > + tables++) {
> > > + int ret = pmu_events_table__for_each_event(&tables->event_table,
> > > + /*pmu=*/ NULL, fn, data);
> > > +
> > > + if (ret)
> > > + return ret;
> > > + }
> > > + return 0;
> > > }
> > >
> > > -int pmu_for_each_sys_metric(pmu_metric_iter_fn fn __maybe_unused, void *data __maybe_unused)
> > > +int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data)
> > > {
> > > - return 0;
> > > + for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
> > > + tables->name;
> > > + tables++) {
> > > + int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
> > > +
> > > + if (ret)
> > > + return ret;
> > > + }
> > > + return 0;
> > > }
> > >
> > > -const char *describe_metricgroup(const char *group __maybe_unused)
> > > +static const int metricgroups[][2] = {
> > > +
> > > +};
> > > +
> > > +const char *describe_metricgroup(const char *group)
> > > {
> > > - return NULL;
> > > + int low = 0, high = (int)ARRAY_SIZE(metricgroups) - 1;
> > > +
> > > + while (low <= high) {
> > > + int mid = (low + high) / 2;
> > > + const char *mgroup = &big_c_string[metricgroups[mid][0]];
> > > + int cmp = strcmp(mgroup, group);
> > > +
> > > + if (cmp == 0) {
> > > + return &big_c_string[metricgroups[mid][1]];
> > > + } else if (cmp < 0) {
> > > + low = mid + 1;
> > > + } else {
> > > + high = mid - 1;
> > > + }
> > > + }
> > > + return NULL;
> > > }
> > > diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> > > index 731776e29f47..fcf0158438b5 100755
> > > --- a/tools/perf/pmu-events/jevents.py
> > > +++ b/tools/perf/pmu-events/jevents.py
> > > @@ -1256,6 +1256,10 @@ such as "arm/cortex-a34".''',
> > > 'output_file', type=argparse.FileType('w', encoding='utf-8'), nargs='?', default=sys.stdout)
> > > _args = ap.parse_args()
> > >
> > > + _args.output_file.write(f"""
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +/* THIS FILE WAS AUTOGENERATED BY jevents.py arch={_args.arch} model={_args.model} ! */
> > > +""")
> > > _args.output_file.write("""
> > > #include <pmu-events/pmu-events.h>
> > > #include "util/header.h"
> > > @@ -1281,7 +1285,7 @@ struct pmu_table_entry {
> > > if item.name == _args.arch or _args.arch == 'all' or item.name == 'test':
> > > archs.append(item.name)
> > >
> > > - if len(archs) < 2:
> > > + if len(archs) < 2 and _args.arch != 'none':
> > > raise IOError(f'Missing architecture directory \'{_args.arch}\'')
> > >
> > > archs.sort()
> > > --
> > > 2.46.0.rc2.264.g509ed76dc8-goog
> > >
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-31 15:33 ` Arnaldo Carvalho de Melo
@ 2024-07-31 15:46 ` Arnaldo Carvalho de Melo
2024-07-31 15:58 ` Ian Rogers
0 siblings, 1 reply; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-07-31 15:46 UTC (permalink / raw)
To: Ian Rogers
Cc: John Garry, Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
Kan Liang, Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users,
linux-kernel, philip.li, oliver.sang, Weilin Wang
On Wed, Jul 31, 2024 at 12:33:50PM -0300, Arnaldo Carvalho de Melo wrote:
> On Wed, Jul 31, 2024 at 07:08:18AM -0700, Ian Rogers wrote:
> > On Wed, Jul 31, 2024 at 6:18 AM Arnaldo Carvalho de Melo
> > <acme@kernel.org> wrote:
> > >
> > > On Tue, Jul 30, 2024 at 12:17:44PM -0700, Ian Rogers wrote:
> > > > empty-pmu-events.c exists so that builds may occur without python
> > > > being installed on a system. Manually updating empty-pmu-events.c to
> > > > be in sync with jevents.py is a pain, let's use jevents.py to generate
> > > > empty-pmu-events.c.
> > >
> > > What am I missing here?
> > >
> > > If it exists so that we can build on a system without python how can we
> > > use python to generate it?
> > >
> > > Now having python in the system is a requirement and thus we don't need
> > > empty-pmu-events.c anymore?
> > >
> > > Can you guys please clarify that?
> >
> > The requirement for python hasn't changed.
> >
> > Case 1: no python or NO_JEVENTS=1
> > Build happens using empty-pmu-events.c that is checked in, no python
> > is required.
> >
> > Case 2: python
> > pmu-events.c is created by jevents.py (requiring python) and then built.
> > This change adds a step where the empty-pmu-events.c is created using
> > jevents.py and that file is diffed against the checked in version.
> > This stops the checked in empty-pmu-events.c diverging if changes are
> > made to jevents.py. If the diff causes the build to fail then you just
> > copy the diff empty-pmu-events.c over the checked in one.
>
> I'll try and add your explanation to the log message, thanks for
> clarifying it!
So, with it in place I'm now noticing:
⬢[acme@toolbox perf-tools-next]$ rm -rf /tmp/build/$(basename $PWD)/ ; mkdir -p /tmp/build/$(basename $PWD)/
⬢[acme@toolbox perf-tools-next]$ alias m='rm -rf ~/libexec/perf-core/ ; make -k CORESIGHT=1 O=/tmp/build/$(basename $PWD)/ -C tools/perf install-bin && perf test python'
⬢[acme@toolbox perf-tools-next]$ m
<SNIP>
GEN /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
MKDIR /tmp/build/perf-tools-next/arch/x86/util/
CC /tmp/build/perf-tools-next/util/annotate.o
CC /tmp/build/perf-tools-next/arch/x86/util/tsc.o
CC /tmp/build/perf-tools-next/arch/x86/tests/hybrid.o
CC /tmp/build/perf-tools-next/util/block-info.o
CC /tmp/build/perf-tools-next/arch/x86/tests/intel-pt-test.o
CC /tmp/build/perf-tools-next/arch/x86/util/pmu.o
MKDIR /tmp/build/perf-tools-next/ui/browsers/
CC /tmp/build/perf-tools-next/ui/browsers/annotate.o
CC /tmp/build/perf-tools-next/builtin-kallsyms.o
CC /tmp/build/perf-tools-next/util/block-range.o
TEST /tmp/build/perf-tools-next/pmu-events/empty-pmu-events.log
--- pmu-events/empty-pmu-events.c 2024-07-31 12:44:14.355042296 -0300
+++ /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c 2024-07-31 12:45:35.048682785 -0300
@@ -380,7 +380,7 @@
continue;
ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
- if (pmu || ret)
+ if (ret)
return ret;
}
return 0;
CC /tmp/build/perf-tools-next/tests/openat-syscall.o
make[3]: *** [pmu-events/Build:42: /tmp/build/perf-tools-next/pmu-events/empty-pmu-events.log] Error 1
make[3]: *** Deleting file '/tmp/build/perf-tools-next/pmu-events/empty-pmu-events.log'
make[2]: *** [Makefile.perf:763: /tmp/build/perf-tools-next/pmu-events/pmu-events-in.o] Error 2
make[2]: *** Waiting for unfinished jobs....
CC /tmp/build/perf-tools-next/arch/x86/util/kvm-stat.o
<SNIP>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-31 15:46 ` Arnaldo Carvalho de Melo
@ 2024-07-31 15:58 ` Ian Rogers
2024-07-31 18:53 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 14+ messages in thread
From: Ian Rogers @ 2024-07-31 15:58 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: John Garry, Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
Kan Liang, Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users,
linux-kernel, philip.li, oliver.sang, Weilin Wang
On Wed, Jul 31, 2024 at 8:46 AM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> On Wed, Jul 31, 2024 at 12:33:50PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Wed, Jul 31, 2024 at 07:08:18AM -0700, Ian Rogers wrote:
> > > On Wed, Jul 31, 2024 at 6:18 AM Arnaldo Carvalho de Melo
> > > <acme@kernel.org> wrote:
> > > >
> > > > On Tue, Jul 30, 2024 at 12:17:44PM -0700, Ian Rogers wrote:
> > > > > empty-pmu-events.c exists so that builds may occur without python
> > > > > being installed on a system. Manually updating empty-pmu-events.c to
> > > > > be in sync with jevents.py is a pain, let's use jevents.py to generate
> > > > > empty-pmu-events.c.
> > > >
> > > > What am I missing here?
> > > >
> > > > If it exists so that we can build on a system without python how can we
> > > > use python to generate it?
> > > >
> > > > Now having python in the system is a requirement and thus we don't need
> > > > empty-pmu-events.c anymore?
> > > >
> > > > Can you guys please clarify that?
> > >
> > > The requirement for python hasn't changed.
> > >
> > > Case 1: no python or NO_JEVENTS=1
> > > Build happens using empty-pmu-events.c that is checked in, no python
> > > is required.
> > >
> > > Case 2: python
> > > pmu-events.c is created by jevents.py (requiring python) and then built.
> > > This change adds a step where the empty-pmu-events.c is created using
> > > jevents.py and that file is diffed against the checked in version.
> > > This stops the checked in empty-pmu-events.c diverging if changes are
> > > made to jevents.py. If the diff causes the build to fail then you just
> > > copy the diff empty-pmu-events.c over the checked in one.
> >
> > I'll try and add your explanation to the log message, thanks for
> > clarifying it!
>
> So, with it in place I'm now noticing:
>
> ⬢[acme@toolbox perf-tools-next]$ rm -rf /tmp/build/$(basename $PWD)/ ; mkdir -p /tmp/build/$(basename $PWD)/
> ⬢[acme@toolbox perf-tools-next]$ alias m='rm -rf ~/libexec/perf-core/ ; make -k CORESIGHT=1 O=/tmp/build/$(basename $PWD)/ -C tools/perf install-bin && perf test python'
> ⬢[acme@toolbox perf-tools-next]$ m
> <SNIP>
> GEN /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
> MKDIR /tmp/build/perf-tools-next/arch/x86/util/
> CC /tmp/build/perf-tools-next/util/annotate.o
> CC /tmp/build/perf-tools-next/arch/x86/util/tsc.o
> CC /tmp/build/perf-tools-next/arch/x86/tests/hybrid.o
> CC /tmp/build/perf-tools-next/util/block-info.o
> CC /tmp/build/perf-tools-next/arch/x86/tests/intel-pt-test.o
> CC /tmp/build/perf-tools-next/arch/x86/util/pmu.o
> MKDIR /tmp/build/perf-tools-next/ui/browsers/
> CC /tmp/build/perf-tools-next/ui/browsers/annotate.o
> CC /tmp/build/perf-tools-next/builtin-kallsyms.o
> CC /tmp/build/perf-tools-next/util/block-range.o
> TEST /tmp/build/perf-tools-next/pmu-events/empty-pmu-events.log
> --- pmu-events/empty-pmu-events.c 2024-07-31 12:44:14.355042296 -0300
> +++ /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c 2024-07-31 12:45:35.048682785 -0300
> @@ -380,7 +380,7 @@
> continue;
>
> ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
> - if (pmu || ret)
> + if (ret)
Right, you need to copy:
/tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
to
tools/perf/pmu-events/empty-pmu-events.c
to fix this.
This change has happened as you are testing with:
https://lore.kernel.org/lkml/20240716132951.1748662-1-kan.liang@linux.intel.com/
which isn't in the git repo yet (therefore, I can't make a patch set
on it). The change is WAI as it is telling you empty-pmu-events.c has
become stale and needs Kan's fix applying to it.
Thanks,
Ian
> return ret;
> }
> return 0;
> CC /tmp/build/perf-tools-next/tests/openat-syscall.o
> make[3]: *** [pmu-events/Build:42: /tmp/build/perf-tools-next/pmu-events/empty-pmu-events.log] Error 1
> make[3]: *** Deleting file '/tmp/build/perf-tools-next/pmu-events/empty-pmu-events.log'
> make[2]: *** [Makefile.perf:763: /tmp/build/perf-tools-next/pmu-events/pmu-events-in.o] Error 2
> make[2]: *** Waiting for unfinished jobs....
> CC /tmp/build/perf-tools-next/arch/x86/util/kvm-stat.o
> <SNIP>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-31 15:58 ` Ian Rogers
@ 2024-07-31 18:53 ` Arnaldo Carvalho de Melo
2024-07-31 20:20 ` Ian Rogers
0 siblings, 1 reply; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-07-31 18:53 UTC (permalink / raw)
To: Ian Rogers
Cc: John Garry, Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
Kan Liang, Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users,
linux-kernel, philip.li, oliver.sang, Weilin Wang
On Wed, Jul 31, 2024 at 08:58:43AM -0700, Ian Rogers wrote:
> On Wed, Jul 31, 2024 at 8:46 AM Arnaldo Carvalho de Melo
> <acme@kernel.org> wrote:
> >
> > On Wed, Jul 31, 2024 at 12:33:50PM -0300, Arnaldo Carvalho de Melo wrote:
> > > On Wed, Jul 31, 2024 at 07:08:18AM -0700, Ian Rogers wrote:
> > > > On Wed, Jul 31, 2024 at 6:18 AM Arnaldo Carvalho de Melo
> > > > <acme@kernel.org> wrote:
> > > > >
> > > > > On Tue, Jul 30, 2024 at 12:17:44PM -0700, Ian Rogers wrote:
> > > > > > empty-pmu-events.c exists so that builds may occur without python
> > > > > > being installed on a system. Manually updating empty-pmu-events.c to
> > > > > > be in sync with jevents.py is a pain, let's use jevents.py to generate
> > > > > > empty-pmu-events.c.
> > > > >
> > > > > What am I missing here?
> > > > >
> > > > > If it exists so that we can build on a system without python how can we
> > > > > use python to generate it?
> > > > >
> > > > > Now having python in the system is a requirement and thus we don't need
> > > > > empty-pmu-events.c anymore?
> > > > >
> > > > > Can you guys please clarify that?
> > > >
> > > > The requirement for python hasn't changed.
> > > >
> > > > Case 1: no python or NO_JEVENTS=1
> > > > Build happens using empty-pmu-events.c that is checked in, no python
> > > > is required.
> > > >
> > > > Case 2: python
> > > > pmu-events.c is created by jevents.py (requiring python) and then built.
> > > > This change adds a step where the empty-pmu-events.c is created using
> > > > jevents.py and that file is diffed against the checked in version.
> > > > This stops the checked in empty-pmu-events.c diverging if changes are
> > > > made to jevents.py. If the diff causes the build to fail then you just
> > > > copy the diff empty-pmu-events.c over the checked in one.
> > >
> > > I'll try and add your explanation to the log message, thanks for
> > > clarifying it!
> >
> > So, with it in place I'm now noticing:
> >
> > ⬢[acme@toolbox perf-tools-next]$ rm -rf /tmp/build/$(basename $PWD)/ ; mkdir -p /tmp/build/$(basename $PWD)/
> > ⬢[acme@toolbox perf-tools-next]$ alias m='rm -rf ~/libexec/perf-core/ ; make -k CORESIGHT=1 O=/tmp/build/$(basename $PWD)/ -C tools/perf install-bin && perf test python'
> > ⬢[acme@toolbox perf-tools-next]$ m
> > <SNIP>
> > GEN /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
> > MKDIR /tmp/build/perf-tools-next/arch/x86/util/
> > CC /tmp/build/perf-tools-next/util/annotate.o
> > CC /tmp/build/perf-tools-next/arch/x86/util/tsc.o
> > CC /tmp/build/perf-tools-next/arch/x86/tests/hybrid.o
> > CC /tmp/build/perf-tools-next/util/block-info.o
> > CC /tmp/build/perf-tools-next/arch/x86/tests/intel-pt-test.o
> > CC /tmp/build/perf-tools-next/arch/x86/util/pmu.o
> > MKDIR /tmp/build/perf-tools-next/ui/browsers/
> > CC /tmp/build/perf-tools-next/ui/browsers/annotate.o
> > CC /tmp/build/perf-tools-next/builtin-kallsyms.o
> > CC /tmp/build/perf-tools-next/util/block-range.o
> > TEST /tmp/build/perf-tools-next/pmu-events/empty-pmu-events.log
> > --- pmu-events/empty-pmu-events.c 2024-07-31 12:44:14.355042296 -0300
> > +++ /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c 2024-07-31 12:45:35.048682785 -0300
> > @@ -380,7 +380,7 @@
> > continue;
> >
> > ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
> > - if (pmu || ret)
> > + if (ret)
>
> Right, you need to copy:
> /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
> to
> tools/perf/pmu-events/empty-pmu-events.c
> to fix this.
>
> This change has happened as you are testing with:
> https://lore.kernel.org/lkml/20240716132951.1748662-1-kan.liang@linux.intel.com/
> which isn't in the git repo yet (therefore, I can't make a patch set
> on it). The change is WAI as it is telling you empty-pmu-events.c has
> become stale and needs Kan's fix applying to it.
ok, I'll remove Kan's patch, publish perf-tools-next and wait for the
now normal flow of patches.
- Arnaldo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-31 18:53 ` Arnaldo Carvalho de Melo
@ 2024-07-31 20:20 ` Ian Rogers
2024-07-31 20:41 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 14+ messages in thread
From: Ian Rogers @ 2024-07-31 20:20 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: John Garry, Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
Kan Liang, Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users,
linux-kernel, philip.li, oliver.sang, Weilin Wang
On Wed, Jul 31, 2024 at 11:53 AM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> On Wed, Jul 31, 2024 at 08:58:43AM -0700, Ian Rogers wrote:
> > On Wed, Jul 31, 2024 at 8:46 AM Arnaldo Carvalho de Melo
> > <acme@kernel.org> wrote:
> > >
> > > On Wed, Jul 31, 2024 at 12:33:50PM -0300, Arnaldo Carvalho de Melo wrote:
> > > > On Wed, Jul 31, 2024 at 07:08:18AM -0700, Ian Rogers wrote:
> > > > > On Wed, Jul 31, 2024 at 6:18 AM Arnaldo Carvalho de Melo
> > > > > <acme@kernel.org> wrote:
> > > > > >
> > > > > > On Tue, Jul 30, 2024 at 12:17:44PM -0700, Ian Rogers wrote:
> > > > > > > empty-pmu-events.c exists so that builds may occur without python
> > > > > > > being installed on a system. Manually updating empty-pmu-events.c to
> > > > > > > be in sync with jevents.py is a pain, let's use jevents.py to generate
> > > > > > > empty-pmu-events.c.
> > > > > >
> > > > > > What am I missing here?
> > > > > >
> > > > > > If it exists so that we can build on a system without python how can we
> > > > > > use python to generate it?
> > > > > >
> > > > > > Now having python in the system is a requirement and thus we don't need
> > > > > > empty-pmu-events.c anymore?
> > > > > >
> > > > > > Can you guys please clarify that?
> > > > >
> > > > > The requirement for python hasn't changed.
> > > > >
> > > > > Case 1: no python or NO_JEVENTS=1
> > > > > Build happens using empty-pmu-events.c that is checked in, no python
> > > > > is required.
> > > > >
> > > > > Case 2: python
> > > > > pmu-events.c is created by jevents.py (requiring python) and then built.
> > > > > This change adds a step where the empty-pmu-events.c is created using
> > > > > jevents.py and that file is diffed against the checked in version.
> > > > > This stops the checked in empty-pmu-events.c diverging if changes are
> > > > > made to jevents.py. If the diff causes the build to fail then you just
> > > > > copy the diff empty-pmu-events.c over the checked in one.
> > > >
> > > > I'll try and add your explanation to the log message, thanks for
> > > > clarifying it!
> > >
> > > So, with it in place I'm now noticing:
> > >
> > > ⬢[acme@toolbox perf-tools-next]$ rm -rf /tmp/build/$(basename $PWD)/ ; mkdir -p /tmp/build/$(basename $PWD)/
> > > ⬢[acme@toolbox perf-tools-next]$ alias m='rm -rf ~/libexec/perf-core/ ; make -k CORESIGHT=1 O=/tmp/build/$(basename $PWD)/ -C tools/perf install-bin && perf test python'
> > > ⬢[acme@toolbox perf-tools-next]$ m
> > > <SNIP>
> > > GEN /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
> > > MKDIR /tmp/build/perf-tools-next/arch/x86/util/
> > > CC /tmp/build/perf-tools-next/util/annotate.o
> > > CC /tmp/build/perf-tools-next/arch/x86/util/tsc.o
> > > CC /tmp/build/perf-tools-next/arch/x86/tests/hybrid.o
> > > CC /tmp/build/perf-tools-next/util/block-info.o
> > > CC /tmp/build/perf-tools-next/arch/x86/tests/intel-pt-test.o
> > > CC /tmp/build/perf-tools-next/arch/x86/util/pmu.o
> > > MKDIR /tmp/build/perf-tools-next/ui/browsers/
> > > CC /tmp/build/perf-tools-next/ui/browsers/annotate.o
> > > CC /tmp/build/perf-tools-next/builtin-kallsyms.o
> > > CC /tmp/build/perf-tools-next/util/block-range.o
> > > TEST /tmp/build/perf-tools-next/pmu-events/empty-pmu-events.log
> > > --- pmu-events/empty-pmu-events.c 2024-07-31 12:44:14.355042296 -0300
> > > +++ /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c 2024-07-31 12:45:35.048682785 -0300
> > > @@ -380,7 +380,7 @@
> > > continue;
> > >
> > > ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
> > > - if (pmu || ret)
> > > + if (ret)
> >
> > Right, you need to copy:
> > /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
> > to
> > tools/perf/pmu-events/empty-pmu-events.c
> > to fix this.
> >
> > This change has happened as you are testing with:
> > https://lore.kernel.org/lkml/20240716132951.1748662-1-kan.liang@linux.intel.com/
> > which isn't in the git repo yet (therefore, I can't make a patch set
> > on it). The change is WAI as it is telling you empty-pmu-events.c has
> > become stale and needs Kan's fix applying to it.
>
> ok, I'll remove Kan's patch, publish perf-tools-next and wait for the
> now normal flow of patches.
I can resend Kan's patch with the empty-pmu-events.c fix applied. I
don't see the changes in tmp.perf-tools-next so I can do it with
cherry picks.
Thanks,
Ian
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-31 20:20 ` Ian Rogers
@ 2024-07-31 20:41 ` Arnaldo Carvalho de Melo
2024-08-01 1:35 ` Ian Rogers
0 siblings, 1 reply; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-07-31 20:41 UTC (permalink / raw)
To: Ian Rogers
Cc: John Garry, Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
Kan Liang, Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users,
linux-kernel, philip.li, oliver.sang, Weilin Wang
On Wed, Jul 31, 2024 at 01:20:06PM -0700, Ian Rogers wrote:
> On Wed, Jul 31, 2024 at 11:53 AM Arnaldo Carvalho de Melo
> <acme@kernel.org> wrote:
> >
> > On Wed, Jul 31, 2024 at 08:58:43AM -0700, Ian Rogers wrote:
> > > On Wed, Jul 31, 2024 at 8:46 AM Arnaldo Carvalho de Melo
> > > <acme@kernel.org> wrote:
> > > >
> > > > On Wed, Jul 31, 2024 at 12:33:50PM -0300, Arnaldo Carvalho de Melo wrote:
> > > > > On Wed, Jul 31, 2024 at 07:08:18AM -0700, Ian Rogers wrote:
> > > > > > On Wed, Jul 31, 2024 at 6:18 AM Arnaldo Carvalho de Melo
> > > > > > <acme@kernel.org> wrote:
> > > > > > >
> > > > > > > On Tue, Jul 30, 2024 at 12:17:44PM -0700, Ian Rogers wrote:
> > > > > > > > empty-pmu-events.c exists so that builds may occur without python
> > > > > > > > being installed on a system. Manually updating empty-pmu-events.c to
> > > > > > > > be in sync with jevents.py is a pain, let's use jevents.py to generate
> > > > > > > > empty-pmu-events.c.
> > > > > > >
> > > > > > > What am I missing here?
> > > > > > >
> > > > > > > If it exists so that we can build on a system without python how can we
> > > > > > > use python to generate it?
> > > > > > >
> > > > > > > Now having python in the system is a requirement and thus we don't need
> > > > > > > empty-pmu-events.c anymore?
> > > > > > >
> > > > > > > Can you guys please clarify that?
> > > > > >
> > > > > > The requirement for python hasn't changed.
> > > > > >
> > > > > > Case 1: no python or NO_JEVENTS=1
> > > > > > Build happens using empty-pmu-events.c that is checked in, no python
> > > > > > is required.
> > > > > >
> > > > > > Case 2: python
> > > > > > pmu-events.c is created by jevents.py (requiring python) and then built.
> > > > > > This change adds a step where the empty-pmu-events.c is created using
> > > > > > jevents.py and that file is diffed against the checked in version.
> > > > > > This stops the checked in empty-pmu-events.c diverging if changes are
> > > > > > made to jevents.py. If the diff causes the build to fail then you just
> > > > > > copy the diff empty-pmu-events.c over the checked in one.
> > > > >
> > > > > I'll try and add your explanation to the log message, thanks for
> > > > > clarifying it!
> > > >
> > > > So, with it in place I'm now noticing:
> > > >
> > > > ⬢[acme@toolbox perf-tools-next]$ rm -rf /tmp/build/$(basename $PWD)/ ; mkdir -p /tmp/build/$(basename $PWD)/
> > > > ⬢[acme@toolbox perf-tools-next]$ alias m='rm -rf ~/libexec/perf-core/ ; make -k CORESIGHT=1 O=/tmp/build/$(basename $PWD)/ -C tools/perf install-bin && perf test python'
> > > > ⬢[acme@toolbox perf-tools-next]$ m
> > > > <SNIP>
> > > > GEN /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
> > > > MKDIR /tmp/build/perf-tools-next/arch/x86/util/
> > > > CC /tmp/build/perf-tools-next/util/annotate.o
> > > > CC /tmp/build/perf-tools-next/arch/x86/util/tsc.o
> > > > CC /tmp/build/perf-tools-next/arch/x86/tests/hybrid.o
> > > > CC /tmp/build/perf-tools-next/util/block-info.o
> > > > CC /tmp/build/perf-tools-next/arch/x86/tests/intel-pt-test.o
> > > > CC /tmp/build/perf-tools-next/arch/x86/util/pmu.o
> > > > MKDIR /tmp/build/perf-tools-next/ui/browsers/
> > > > CC /tmp/build/perf-tools-next/ui/browsers/annotate.o
> > > > CC /tmp/build/perf-tools-next/builtin-kallsyms.o
> > > > CC /tmp/build/perf-tools-next/util/block-range.o
> > > > TEST /tmp/build/perf-tools-next/pmu-events/empty-pmu-events.log
> > > > --- pmu-events/empty-pmu-events.c 2024-07-31 12:44:14.355042296 -0300
> > > > +++ /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c 2024-07-31 12:45:35.048682785 -0300
> > > > @@ -380,7 +380,7 @@
> > > > continue;
> > > >
> > > > ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
> > > > - if (pmu || ret)
> > > > + if (ret)
> > >
> > > Right, you need to copy:
> > > /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
> > > to
> > > tools/perf/pmu-events/empty-pmu-events.c
> > > to fix this.
> > >
> > > This change has happened as you are testing with:
> > > https://lore.kernel.org/lkml/20240716132951.1748662-1-kan.liang@linux.intel.com/
> > > which isn't in the git repo yet (therefore, I can't make a patch set
> > > on it). The change is WAI as it is telling you empty-pmu-events.c has
> > > become stale and needs Kan's fix applying to it.
> >
> > ok, I'll remove Kan's patch, publish perf-tools-next and wait for the
> > now normal flow of patches.
>
> I can resend Kan's patch with the empty-pmu-events.c fix applied. I
> don't see the changes in tmp.perf-tools-next so I can do it with
> cherry picks.
Just force pushed one more time. After a while should be there, there
are still some issues here and there, notably:
root@x1:~# perf test 105 106 118
105: perf all metricgroups test : FAILED!
106: perf all metrics test : FAILED!
118: Miscellaneous Intel PT testing : FAILED!
root@x1:~# perf test 110
110: perf stat --bpf-counters --for-each-cgroup test : FAILED!
root@x1:~#
I'm running out of time today, so I'll probably just push what I have to
perf-tools-next so that we can start getting testing from linux-next and
we can then go on fixing up stuff from there.
- Arnaldo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c
2024-07-31 20:41 ` Arnaldo Carvalho de Melo
@ 2024-08-01 1:35 ` Ian Rogers
0 siblings, 0 replies; 14+ messages in thread
From: Ian Rogers @ 2024-08-01 1:35 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: John Garry, Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Mark Rutland, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
Kan Liang, Jing Zhang, Xu Yang, Sandipan Das, linux-perf-users,
linux-kernel, philip.li, oliver.sang, Weilin Wang
On Wed, Jul 31, 2024 at 1:41 PM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> On Wed, Jul 31, 2024 at 01:20:06PM -0700, Ian Rogers wrote:
> > On Wed, Jul 31, 2024 at 11:53 AM Arnaldo Carvalho de Melo
> > <acme@kernel.org> wrote:
> > >
> > > On Wed, Jul 31, 2024 at 08:58:43AM -0700, Ian Rogers wrote:
> > > > On Wed, Jul 31, 2024 at 8:46 AM Arnaldo Carvalho de Melo
> > > > <acme@kernel.org> wrote:
> > > > >
> > > > > On Wed, Jul 31, 2024 at 12:33:50PM -0300, Arnaldo Carvalho de Melo wrote:
> > > > > > On Wed, Jul 31, 2024 at 07:08:18AM -0700, Ian Rogers wrote:
> > > > > > > On Wed, Jul 31, 2024 at 6:18 AM Arnaldo Carvalho de Melo
> > > > > > > <acme@kernel.org> wrote:
> > > > > > > >
> > > > > > > > On Tue, Jul 30, 2024 at 12:17:44PM -0700, Ian Rogers wrote:
> > > > > > > > > empty-pmu-events.c exists so that builds may occur without python
> > > > > > > > > being installed on a system. Manually updating empty-pmu-events.c to
> > > > > > > > > be in sync with jevents.py is a pain, let's use jevents.py to generate
> > > > > > > > > empty-pmu-events.c.
> > > > > > > >
> > > > > > > > What am I missing here?
> > > > > > > >
> > > > > > > > If it exists so that we can build on a system without python how can we
> > > > > > > > use python to generate it?
> > > > > > > >
> > > > > > > > Now having python in the system is a requirement and thus we don't need
> > > > > > > > empty-pmu-events.c anymore?
> > > > > > > >
> > > > > > > > Can you guys please clarify that?
> > > > > > >
> > > > > > > The requirement for python hasn't changed.
> > > > > > >
> > > > > > > Case 1: no python or NO_JEVENTS=1
> > > > > > > Build happens using empty-pmu-events.c that is checked in, no python
> > > > > > > is required.
> > > > > > >
> > > > > > > Case 2: python
> > > > > > > pmu-events.c is created by jevents.py (requiring python) and then built.
> > > > > > > This change adds a step where the empty-pmu-events.c is created using
> > > > > > > jevents.py and that file is diffed against the checked in version.
> > > > > > > This stops the checked in empty-pmu-events.c diverging if changes are
> > > > > > > made to jevents.py. If the diff causes the build to fail then you just
> > > > > > > copy the diff empty-pmu-events.c over the checked in one.
> > > > > >
> > > > > > I'll try and add your explanation to the log message, thanks for
> > > > > > clarifying it!
> > > > >
> > > > > So, with it in place I'm now noticing:
> > > > >
> > > > > ⬢[acme@toolbox perf-tools-next]$ rm -rf /tmp/build/$(basename $PWD)/ ; mkdir -p /tmp/build/$(basename $PWD)/
> > > > > ⬢[acme@toolbox perf-tools-next]$ alias m='rm -rf ~/libexec/perf-core/ ; make -k CORESIGHT=1 O=/tmp/build/$(basename $PWD)/ -C tools/perf install-bin && perf test python'
> > > > > ⬢[acme@toolbox perf-tools-next]$ m
> > > > > <SNIP>
> > > > > GEN /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
> > > > > MKDIR /tmp/build/perf-tools-next/arch/x86/util/
> > > > > CC /tmp/build/perf-tools-next/util/annotate.o
> > > > > CC /tmp/build/perf-tools-next/arch/x86/util/tsc.o
> > > > > CC /tmp/build/perf-tools-next/arch/x86/tests/hybrid.o
> > > > > CC /tmp/build/perf-tools-next/util/block-info.o
> > > > > CC /tmp/build/perf-tools-next/arch/x86/tests/intel-pt-test.o
> > > > > CC /tmp/build/perf-tools-next/arch/x86/util/pmu.o
> > > > > MKDIR /tmp/build/perf-tools-next/ui/browsers/
> > > > > CC /tmp/build/perf-tools-next/ui/browsers/annotate.o
> > > > > CC /tmp/build/perf-tools-next/builtin-kallsyms.o
> > > > > CC /tmp/build/perf-tools-next/util/block-range.o
> > > > > TEST /tmp/build/perf-tools-next/pmu-events/empty-pmu-events.log
> > > > > --- pmu-events/empty-pmu-events.c 2024-07-31 12:44:14.355042296 -0300
> > > > > +++ /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c 2024-07-31 12:45:35.048682785 -0300
> > > > > @@ -380,7 +380,7 @@
> > > > > continue;
> > > > >
> > > > > ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
> > > > > - if (pmu || ret)
> > > > > + if (ret)
> > > >
> > > > Right, you need to copy:
> > > > /tmp/build/perf-tools-next/pmu-events/test-empty-pmu-events.c
> > > > to
> > > > tools/perf/pmu-events/empty-pmu-events.c
> > > > to fix this.
> > > >
> > > > This change has happened as you are testing with:
> > > > https://lore.kernel.org/lkml/20240716132951.1748662-1-kan.liang@linux.intel.com/
> > > > which isn't in the git repo yet (therefore, I can't make a patch set
> > > > on it). The change is WAI as it is telling you empty-pmu-events.c has
> > > > become stale and needs Kan's fix applying to it.
> > >
> > > ok, I'll remove Kan's patch, publish perf-tools-next and wait for the
> > > now normal flow of patches.
> >
> > I can resend Kan's patch with the empty-pmu-events.c fix applied. I
> > don't see the changes in tmp.perf-tools-next so I can do it with
> > cherry picks.
>
> Just force pushed one more time. After a while should be there, there
> are still some issues here and there, notably:
>
>
> root@x1:~# perf test 105 106 118
> 105: perf all metricgroups test : FAILED!
> 106: perf all metrics test : FAILED!
These tests can be sensitive to the NMI watchdog being enabled.
> 118: Miscellaneous Intel PT testing : FAILED!
I bisected this failure to:
```
Author: Leo Yan <leo.yan@arm.com>
Date: Thu Jul 25 07:46:17 2024 +0100
perf auxtrace: Iterate all AUX events when finish reading
When finished to read AUX trace data from mmaped buffer, based on the
AUX buffer index the core layer needs to search the corresponding PMU
event and re-enable it to continue tracing.
However, current code only searches the first AUX event. It misses to
search other enabled AUX events, thus, it returns failure if the buffer
index does not belong to the first AUX event.
This patch extends the auxtrace_record__read_finish() function to
search for every enabled AUX events, so all the mmaped buffer indexes
can be covered.
Signed-off-by: Leo Yan <leo.yan@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: James Clark <james.clark@linaro.org>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: <coresight@lists.linaro.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: <linux-perf-users@vger.kernel.org>
Link: https://lore.kernel.org/lkml/
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/auxtrace.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
```
> root@x1:~# perf test 110
> 110: perf stat --bpf-counters --for-each-cgroup test : FAILED!
This one flakes if the test machine has load on it.
> root@x1:~#
>
> I'm running out of time today, so I'll probably just push what I have to
> perf-tools-next so that we can start getting testing from linux-next and
> we can then go on fixing up stuff from there.
Thanks,
Ian
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2024-08-01 1:35 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-30 19:17 [PATCH v3 0/2] perf jevents: Autogenerate empty-pmu-events.c Ian Rogers
2024-07-30 19:17 ` [PATCH v3 1/2] perf jevents: Use name for special find value Ian Rogers
2024-07-31 13:19 ` Arnaldo Carvalho de Melo
2024-07-30 19:17 ` [PATCH v3 2/2] perf jevents: Autogenerate empty-pmu-events.c Ian Rogers
2024-07-31 13:18 ` Arnaldo Carvalho de Melo
2024-07-31 14:08 ` Ian Rogers
2024-07-31 15:33 ` Arnaldo Carvalho de Melo
2024-07-31 15:46 ` Arnaldo Carvalho de Melo
2024-07-31 15:58 ` Ian Rogers
2024-07-31 18:53 ` Arnaldo Carvalho de Melo
2024-07-31 20:20 ` Ian Rogers
2024-07-31 20:41 ` Arnaldo Carvalho de Melo
2024-08-01 1:35 ` Ian Rogers
2024-07-31 13:05 ` [PATCH v3 0/2] " Arnaldo Carvalho de Melo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).