aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2018-10-05 08:28:07 -0400
committerWill Deacon <will.deacon@arm.com>2018-11-21 08:16:33 -0500
commit342e53bd8548e07c6a734d2d3a6437ad6e6d3b09 (patch)
treeafafbc66fd14730b6713497135d23b2198dfc71f
parentd3adeed7289220fdc78ee4400efbcd4cf1556215 (diff)
arm64: perf: Add support for Armv8.1 PMCEID register format
Armv8.1 allocated the upper 32-bits of the PMCEID registers to describe the common architectural and microarchitecture events beginning at 0x4000. Add support for these registers to our probing code, so that we can advertise the SPE events when they are supported by the CPU. Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm64/kernel/perf_event.c25
-rw-r--r--include/linux/perf/arm_pmu.h4
2 files changed, 21 insertions, 8 deletions
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index ac1c5c41501d..1a783df6f234 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -183,12 +183,10 @@
183#define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_ACCESS 0xEC 183#define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_ACCESS 0xEC
184#define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS 0xED 184#define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS 0xED
185 185
186/* PMUv3 HW events mapping. */
187
188/* 186/*
189 * ARMv8 Architectural defined events, not all of these may 187 * ARMv8 Architectural defined events, not all of these may
190 * be supported on any given implementation. Undefined events will 188 * be supported on any given implementation. Unsupported events will
191 * be disabled at run-time. 189 * be disabled at run-time based on the PMCEID registers.
192 */ 190 */
193static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { 191static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
194 PERF_MAP_ALL_UNSUPPORTED, 192 PERF_MAP_ALL_UNSUPPORTED,
@@ -434,7 +432,13 @@ armv8pmu_event_attr_is_visible(struct kobject *kobj,
434 432
435 pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr); 433 pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr);
436 434
437 if (test_bit(pmu_attr->id, cpu_pmu->pmceid_bitmap)) 435 if (pmu_attr->id < ARMV8_PMUV3_MAX_COMMON_EVENTS &&
436 test_bit(pmu_attr->id, cpu_pmu->pmceid_bitmap))
437 return attr->mode;
438
439 pmu_attr->id -= ARMV8_PMUV3_EXT_COMMON_EVENT_BASE;
440 if (pmu_attr->id < ARMV8_PMUV3_MAX_COMMON_EVENTS &&
441 test_bit(pmu_attr->id, cpu_pmu->pmceid_ext_bitmap))
438 return attr->mode; 442 return attr->mode;
439 443
440 return 0; 444 return 0;
@@ -1061,6 +1065,7 @@ static void __armv8pmu_probe_pmu(void *info)
1061 struct armv8pmu_probe_info *probe = info; 1065 struct armv8pmu_probe_info *probe = info;
1062 struct arm_pmu *cpu_pmu = probe->pmu; 1066 struct arm_pmu *cpu_pmu = probe->pmu;
1063 u64 dfr0; 1067 u64 dfr0;
1068 u64 pmceid_raw[2];
1064 u32 pmceid[2]; 1069 u32 pmceid[2];
1065 int pmuver; 1070 int pmuver;
1066 1071
@@ -1079,11 +1084,17 @@ static void __armv8pmu_probe_pmu(void *info)
1079 /* Add the CPU cycles counter */ 1084 /* Add the CPU cycles counter */
1080 cpu_pmu->num_events += 1; 1085 cpu_pmu->num_events += 1;
1081 1086
1082 pmceid[0] = read_sysreg(pmceid0_el0); 1087 pmceid[0] = pmceid_raw[0] = read_sysreg(pmceid0_el0);
1083 pmceid[1] = read_sysreg(pmceid1_el0); 1088 pmceid[1] = pmceid_raw[1] = read_sysreg(pmceid1_el0);
1084 1089
1085 bitmap_from_arr32(cpu_pmu->pmceid_bitmap, 1090 bitmap_from_arr32(cpu_pmu->pmceid_bitmap,
1086 pmceid, ARMV8_PMUV3_MAX_COMMON_EVENTS); 1091 pmceid, ARMV8_PMUV3_MAX_COMMON_EVENTS);
1092
1093 pmceid[0] = pmceid_raw[0] >> 32;
1094 pmceid[1] = pmceid_raw[1] >> 32;
1095
1096 bitmap_from_arr32(cpu_pmu->pmceid_ext_bitmap,
1097 pmceid, ARMV8_PMUV3_MAX_COMMON_EVENTS);
1087} 1098}
1088 1099
1089static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu) 1100static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu)
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index bf309ff6f244..4641e850b204 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -102,8 +102,10 @@ struct arm_pmu {
102 int (*filter_match)(struct perf_event *event); 102 int (*filter_match)(struct perf_event *event);
103 int num_events; 103 int num_events;
104 bool secure_access; /* 32-bit ARM only */ 104 bool secure_access; /* 32-bit ARM only */
105#define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40 105#define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40
106 DECLARE_BITMAP(pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS); 106 DECLARE_BITMAP(pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
107#define ARMV8_PMUV3_EXT_COMMON_EVENT_BASE 0x4000
108 DECLARE_BITMAP(pmceid_ext_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
107 struct platform_device *plat_device; 109 struct platform_device *plat_device;
108 struct pmu_hw_events __percpu *hw_events; 110 struct pmu_hw_events __percpu *hw_events;
109 struct hlist_node node; 111 struct hlist_node node;