summaryrefslogtreecommitdiff
path: root/tools/perf/pmu-events
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/pmu-events')
-rw-r--r--tools/perf/pmu-events/Build12
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/ampereone/instruction.json3
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power10/frontend.json5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power10/others.json100
-rw-r--r--tools/perf/pmu-events/empty-pmu-events.c894
-rwxr-xr-xtools/perf/pmu-events/jevents.py16
-rw-r--r--tools/perf/pmu-events/pmu-events.h9
7 files changed, 676 insertions, 363 deletions
diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
index 1d18bb89402e..d941bc9d16e9 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/arch/arm64/ampere/ampereone/instruction.json b/tools/perf/pmu-events/arch/arm64/ampere/ampereone/instruction.json
index 18d1f2f76a23..9fe697d12fe0 100644
--- a/tools/perf/pmu-events/arch/arm64/ampere/ampereone/instruction.json
+++ b/tools/perf/pmu-events/arch/arm64/ampere/ampereone/instruction.json
@@ -78,9 +78,6 @@
"ArchStdEvent": "OP_RETIRED"
},
{
- "ArchStdEvent": "OP_SPEC"
- },
- {
"PublicDescription": "Operation speculatively executed, NOP",
"EventCode": "0x100",
"EventName": "NOP_SPEC",
diff --git a/tools/perf/pmu-events/arch/powerpc/power10/frontend.json b/tools/perf/pmu-events/arch/powerpc/power10/frontend.json
index 5977f5e64212..53660c279286 100644
--- a/tools/perf/pmu-events/arch/powerpc/power10/frontend.json
+++ b/tools/perf/pmu-events/arch/powerpc/power10/frontend.json
@@ -75,6 +75,11 @@
"BriefDescription": "Cycles in which an instruction or group of instructions were cancelled after being issued. This event increments once per occurrence, regardless of how many instructions are included in the issue group."
},
{
+ "EventCode": "0x44054",
+ "EventName": "PM_VECTOR_LD_CMPL",
+ "BriefDescription": "Vector load instruction completed."
+ },
+ {
"EventCode": "0x44056",
"EventName": "PM_VECTOR_ST_CMPL",
"BriefDescription": "Vector store instruction completed."
diff --git a/tools/perf/pmu-events/arch/powerpc/power10/others.json b/tools/perf/pmu-events/arch/powerpc/power10/others.json
index fcf8a8ebe7bd..3789304cb363 100644
--- a/tools/perf/pmu-events/arch/powerpc/power10/others.json
+++ b/tools/perf/pmu-events/arch/powerpc/power10/others.json
@@ -95,11 +95,6 @@
"BriefDescription": "Counts all instruction cache reloads includes demand, prefetch, prefetch turned into demand and demand turned into prefetch."
},
{
- "EventCode": "0x44054",
- "EventName": "PM_VECTOR_LD_CMPL",
- "BriefDescription": "Vector load instruction completed."
- },
- {
"EventCode": "0x4D05E",
"EventName": "PM_BR_CMPL",
"BriefDescription": "A branch completed. All branches are included."
@@ -108,5 +103,100 @@
"EventCode": "0x400F0",
"EventName": "PM_LD_DEMAND_MISS_L1_FIN",
"BriefDescription": "Load missed L1, counted at finish time."
+ },
+ {
+ "EventCode": "0x00000038BC",
+ "EventName": "PM_ISYNC_CMPL",
+ "BriefDescription": "Isync completion count per thread."
+ },
+ {
+ "EventCode": "0x000000C088",
+ "EventName": "PM_LD0_32B_FIN",
+ "BriefDescription": "256-bit load finished in the LD0 load execution unit."
+ },
+ {
+ "EventCode": "0x000000C888",
+ "EventName": "PM_LD1_32B_FIN",
+ "BriefDescription": "256-bit load finished in the LD1 load execution unit."
+ },
+ {
+ "EventCode": "0x000000C090",
+ "EventName": "PM_LD0_UNALIGNED_FIN",
+ "BriefDescription": "Load instructions in LD0 port that are either unaligned, or treated as unaligned and require an additional recycle through the pipeline using the load gather buffer. This typically adds about 10 cycles to the latency of the instruction. This includes loads that cross the 128 byte boundary, octword loads that are not aligned, and a special forward progress case of a load that does not hit in the L1 and crosses the 32 byte boundary and is launched NTC. Counted at finish time."
+ },
+ {
+ "EventCode": "0x000000C890",
+ "EventName": "PM_LD1_UNALIGNED_FIN",
+ "BriefDescription": "Load instructions in LD1 port that are either unaligned, or treated as unaligned and require an additional recycle through the pipeline using the load gather buffer. This typically adds about 10 cycles to the latency of the instruction. This includes loads that cross the 128 byte boundary, octword loads that are not aligned, and a special forward progress case of a load that does not hit in the L1 and crosses the 32 byte boundary and is launched NTC. Counted at finish time."
+ },
+ {
+ "EventCode": "0x000000C0A4",
+ "EventName": "PM_ST0_UNALIGNED_FIN",
+ "BriefDescription": "Store instructions in ST0 port that are either unaligned, or treated as unaligned and require an additional recycle through the pipeline. This typically adds about 10 cycles to the latency of the instruction. This only includes stores that cross the 128 byte boundary. Counted at finish time."
+ },
+ {
+ "EventCode": "0x000000C8A4",
+ "EventName": "PM_ST1_UNALIGNED_FIN",
+ "BriefDescription": "Store instructions in ST1 port that are either unaligned, or treated as unaligned and require an additional recycle through the pipeline. This typically adds about 10 cycles to the latency of the instruction. This only includes stores that cross the 128 byte boundary. Counted at finish time."
+ },
+ {
+ "EventCode": "0x000000C8B8",
+ "EventName": "PM_STCX_SUCCESS_CMPL",
+ "BriefDescription": "STCX instructions that completed successfully. Specifically, counts only when a pass status is returned from the nest."
+ },
+ {
+ "EventCode": "0x000000D0B4",
+ "EventName": "PM_DC_PREF_STRIDED_CONF",
+ "BriefDescription": "A demand load referenced a line in an active strided prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software."
+ },
+ {
+ "EventCode": "0x000000F880",
+ "EventName": "PM_SNOOP_TLBIE_CYC",
+ "BriefDescription": "Cycles in which TLBIE snoops are executed in the LSU."
+ },
+ {
+ "EventCode": "0x000000F084",
+ "EventName": "PM_SNOOP_TLBIE_CACHE_WALK_CYC",
+ "BriefDescription": "TLBIE snoop cycles in which the data cache is being walked."
+ },
+ {
+ "EventCode": "0x000000F884",
+ "EventName": "PM_SNOOP_TLBIE_WAIT_ST_CYC",
+ "BriefDescription": "TLBIE snoop cycles in which older stores are still draining."
+ },
+ {
+ "EventCode": "0x000000F088",
+ "EventName": "PM_SNOOP_TLBIE_WAIT_LD_CYC",
+ "BriefDescription": "TLBIE snoop cycles in which older loads are still draining."
+ },
+ {
+ "EventCode": "0x000000F08C",
+ "EventName": "PM_SNOOP_TLBIE_WAIT_MMU_CYC",
+ "BriefDescription": "TLBIE snoop cycles in which the Load-Store unit is waiting for the MMU to finish invalidation."
+ },
+ {
+ "EventCode": "0x0000004884",
+ "EventName": "PM_NO_FETCH_IBUF_FULL_CYC",
+ "BriefDescription": "Cycles in which no instructions are fetched because there is no room in the instruction buffers."
+ },
+ {
+ "EventCode": "0x00000048B4",
+ "EventName": "PM_BR_TKN_UNCOND_FIN",
+ "BriefDescription": "An unconditional branch finished. All unconditional branches are taken."
+ },
+ {
+ "EventCode": "0x0B0000016080",
+ "EventName": "PM_L2_TLBIE_SLBIE_START",
+ "BriefDescription": "NCU Master received a TLBIE/SLBIEG/SLBIAG operation from the core. Event count should be multiplied by 2 since the data is coming from a 2:1 clock domain and the data is time sliced across all 4 threads."
+ },
+ {
+ "EventCode": "0x0B0000016880",
+ "EventName": "PM_L2_TLBIE_SLBIE_DELAY",
+ "BriefDescription": "Cycles when a TLBIE/SLBIEG/SLBIAG command was held in a hottemp condition by the NCU Master. Multiply this count by 1000 to obtain the total number of cycles. This can be divided by PM_L2_TLBIE_SLBIE_SENT to obtain the average time a TLBIE/SLBIEG/SLBIAG command was held. Event count should be multiplied by 2 since the data is coming from a 2:1 clock domain and the data is time sliced across all 4 threads."
+ },
+ {
+ "EventCode": "0x0B0000026880",
+ "EventName": "PM_L2_SNP_TLBIE_SLBIE_DELAY",
+ "BriefDescription": "Cycles when a TLBIE/SLBIEG/SLBIAG that targets this thread's LPAR was in flight while in a hottemp condition. Multiply this count by 1000 to obtain the total number of cycles. This can be divided by PM_L2_SNP_TLBIE_SLBIE_START to obtain the overall efficiency. Note: 'inflight' means SnpTLB has been sent to core(ie doesn't include when SnpTLB is in NCU waiting to be launched serially behind different SnpTLB). The NCU Snooper gets in a 'hottemp' delay window when it detects it is above its TLBIE/SLBIE threshold for process SnpTLBIE/SLBIE with this core. Event count should be multiplied by 2 since the data is coming from a 2:1 clock domain and the data is time sliced across all 4 threads."
}
]
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 ac9b7ca41856..1d96b2204e52 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -503,8 +503,11 @@ def print_pending_events() -> None:
first = True
last_pmu = None
+ last_name = None
pmus = set()
for event in sorted(_pending_events, key=event_cmp_key):
+ if last_pmu and last_pmu == event.pmu:
+ assert event.name != last_name, f"Duplicate event: {last_pmu}/{last_name}/ in {_pending_events_tblname}"
if event.pmu != last_pmu:
if not first:
_args.output_file.write('};\n')
@@ -516,6 +519,7 @@ def print_pending_events() -> None:
pmus.add((event.pmu, pmu_name))
_args.output_file.write(event.to_c_string(metric=False))
+ last_name = event.name
_pending_events = []
_args.output_file.write(f"""
@@ -906,7 +910,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 +948,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,
@@ -1256,6 +1260,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 +1289,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()
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,